changeset 27242:61701d1317a1

maint: Merge stable to default.
author John W. Eaton <jwe@octave.org>
date Fri, 12 Jul 2019 12:14:43 -0400
parents 733431da9742 (diff) 940c1b6e3453 (current diff)
children c6807f5cc48b
files
diffstat 787 files changed, 36493 insertions(+), 24054 deletions(-) [+]
line wrap: on
line diff
--- a/.dir-locals.el	Wed Jul 10 20:02:44 2019 -0700
+++ b/.dir-locals.el	Fri Jul 12 12:14:43 2019 -0400
@@ -1,11 +1,6 @@
 ((nil .
       ((c-file-style . "gnu")
        (indent-tabs-mode . nil)
-       (fill-column . 72)
-       (eval . (when (and (buffer-file-name)
-                          (string-match-p "\\.h\\'" (buffer-file-name))
-                          (not (string-match-p "/gnulib/" (buffer-file-name))))
-                 (c++-mode)
-                 (c-set-style "gnu")))))
+       (fill-column . 72)))
  (change-log-mode . ((indent-tabs-mode . t)))
  (makefile-mode . ((indent-tabs-mode . t))))
--- a/.hgignore	Wed Jul 10 20:02:44 2019 -0700
+++ b/.hgignore	Fri Jul 12 12:14:43 2019 -0400
@@ -28,6 +28,11 @@
 ^Makefile\.in$
 ^INSTALL$
 
+## CMake associated files
+# Octave doesn't use CMake, but some IDEs use this index file to indicate
+# what files are part of a project (e.g., CLion).  Ignore it (bug #55901).
+^CMakeLists.txt$
+
 ## Emacs associated files
 (^|/)TAGS$
 (^|/)semantic.cache$
@@ -60,7 +65,6 @@
 .*\.Plo$
 .*\.Po$
 
-
 ## DLDFCN associated files
 ^libinterp/dldfcn/module\.mk$
 (^|/)libinterp/dldfcn/PKG_ADD$
--- a/CITATION	Wed Jul 10 20:02:44 2019 -0700
+++ b/CITATION	Fri Jul 12 12:14:43 2019 -0400
@@ -15,5 +15,5 @@
   }
 
 We have invested a lot of time and effort in creating GNU Octave, please
-cite it when using it.  See also `citation pkgname' for citing Octave
+cite it when using it.  See also 'citation pkgname' for citing Octave
 packages.
--- a/NEWS	Wed Jul 10 20:02:44 2019 -0700
+++ b/NEWS	Fri Jul 12 12:14:43 2019 -0400
@@ -1,324 +1,151 @@
-Summary of important user-visible changes for version 5 (2019-02-23):
---------------------------------------------------------------------
+Summary of important user-visible changes for version 6 (yyyy-mm-dd):
+----------------------------------------------------------------------
 
 ### General improvements
 
-- The Octave plotting system now supports high resolution screens,
-  i.e., those with greater than 96 DPI which are referred to as
-  HiDPI/Retina monitors.
-
-- Unicode character support for files and folders in Windows.
+- The `edit` function option `"editinplace"` now defaults to `true` and
+  the option `"home"` now defaults to the empty matrix `[]`.  Files will
+  no longer be copied to the user's HOME directory for editing.  The old
+  behavior can be restored by setting `"editinplace"` to `false` and
+  `"home"` to `"~/octave"`.
 
-- A new core function `movfun` will apply a function to a sliding
-  window of arbitrary size on a dataset and accumulate the results.
-  Many common cases have been implemented using the naming
-  scheme `movXXX` where `XXX` is the function that will be applied.
-  For example, the moving average over a dataset is `movmean`.
-  New moving window functions:
-
-  `movfun`  `movslice`
-  `movmad`  `movmax`   `movmean`  `movmedian`  `movmin`  `movprod`
-  `movstd`  `movsum`   `movvar`
+#### Graphics backend
 
-- The `fsolve` function has been tweaked to use larger step sizes when
-  calculating the Jacobian of a function with finite differences.
-  This leads to faster convergence.
-
-- The `ranks` function has been recoded for performance and is now 25X
-  faster.  In addition, it now supports a third argument that specifies
-  how to resolve the ranking of tie values.
+- Graphic primitives now accept a color property value of `"none"`
+  which is useful when a particular primitive needs to be hidden
+  (for example, the Y-axis of an axes object with `"ycolor" = "none"`)
+  without hiding the entire primitive `"visibility" = "off"`.
 
-- The function `randi` has been recoded to produce an unbiased (all
-  results are equally likely) sample of integers.  This may produce
-  different results in existing code.  If it is necessary to reproduce
-  the exact random integer sequence as in previous versions use
-
-  `ri = imin + floor ((imax - imin + 1) * rand ());`
-
-- The function `isdefinite` now returns `true` or `false` rather than
-  `-1`, `0`, or `1`.  To test for a positive semi-definite matrix (old
-  output of `0`) check whether the following two conditions hold:
+- A new property `"FontSmoothing"` has been added to text and axes
+  objects that controls whether anti-aliasing is used during the
+  rendering of characters.  The default is "on" which produces smooth,
+  more visually appealing text.
 
-    `isdefinite (A) => 0`  and  `isdefinite (A + 5*TOL, TOL) => 1`
-
-- The `intmax`, `intmin`, and `flintmax` functions now accept a variable
-  as input.  Existing code to query the range of an existing variable can
-  be simplified by removing the call to `class` that was previously
-  required.  For example defining the variable `x = int8 (3)` in the
-  workspace, calls like
+- The figure property `"windowscrollwheelfcn"`is now implemented.
+  This makes it possible to provide a callback function to be executed when
+  users manipulate the mouse wheel on a given figure.
 
-    `range = [ intmin(class(x)), intmax(class(x)) ]`
-
-  can in Octave 5 be simplified to `range = [ intmin(x), intmax(x) ]`.
-
-- The path handling functions no longer perform variable or brace
-  expansion on path elements and Octave's load-path is no longer
-  subject to these expansions.
+- The figure properties `"pointer"`, `"pointershapecdata"`, and
+  `"pointershapehotspot"` are now implemented.  This makes it possible
+  to change the shape of the cursor (pointer in Matlab-speak) displayed
+  in a plot window.
 
-- A new printing device is available, `"-ddumb"`, which produces ASCII
-  art for plots.  This device is only available with the gnuplot toolkit.
-
-- The `msgbox` function has changed in two respects: the default WindowStyle
-  is now `"non-modal"`, and the default interpreter for the message is now
-  `"tex"`.  Both WindowStyle and Interpreter can be controlled by passing an
-  option struct argument.
-
-### Dependencies
+- The appearance of patterned lines `"LineStyle" = ":"|"--"|"-."` has
+  been improved for small widths (`"LineWidth"` less than 1.5 pixels)
+  which is a common scenario.
 
-- The GUI requires Qt libraries.  The minimum Qt4 version supported is
-  Qt4.8.  Qt5 of any version is preferred.
+- Printing to EPS files now uses a tight bounding box (`"-tight"`
+  argument to print) by default.  This makes more sense for EPS
+  files which are normally embedded within other documents, and is
+  Matlab compatible.  If necessary use the `"-loose"` option to
+  reproduce figures as they appeared in previous versions of Octave.
 
-- The OSMesa library is no longer used.  To print invisible figures
-  when using OpenGL graphics, the Qt `QOFFSCREENSURFACE` feature must be
-  available and you must use the qt graphics toolkit.
-
-- The FFTW library is now required to perform FFT calculations.
-  The FFTPACK sources have been removed from Octave.
-
+- The following print devices are no longer officially supported: cdr,
+  corel, aifm, ill, cgm, hpgl, mf and dxf.  A warning will be thrown
+  when using those devices, and the code for supporting those formats
+  will eventually be removed from a future version of Octave.
 
 ### Matlab compatibility
 
-- The determination of an object's dimensions, size, and shape by the
-  functions `ndims`, `rows`, `columns`, `isscalar`, `isvector`,
-  `isrow`, `iscolumn`, `ismatrix`, and `issquare` now fully depends
-  on the function size.  Thus, any user-defined object can ensure correct
-  treatment by the aforementioned functions by properly overloading the
-  `size` function.
+- The function `unique` now returns column index vectors for the second
+  and third outputs.  When duplicate values are present, the default
+  index to return is now the `"first"` occurrence.  The previous Octave
+  behavior, or Matlab behavior from releases prior to R2012b, can be
+  obtained by using the `"legacy"` flag.
 
-- 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.
-
-- The `issorted` function now uses a direction option of `"ascend"`
-  or `"descend"`.  Change all uses of `"ascending"` and `"descending"`
-  in existing code to the new options.
+- The function `setdiff` with the `"rows"` argument now returns Matlab
+  compatible results.  The previous Octave behavior, or Matlab behavior
+  from releases prior to R2012b, can be obtained by using the `"legacy"`
+  flag.
 
-- The `strncmp` and `strncmpi` functions now return `true` if the two
-  input strings match, even though the number of characters specified
-  by `n` exceeds the string length.  For Example:
-
-    `strncmp ("abc", "abc", 100)`
-
-  returns `true` in Octave 5 and `false` in older versions of Octave.
+- The functions `intersect`, `setxor`, `union`, now accept a `"legacy"`
+  flag which changes the index values (second and third outputs) as well
+  as the orientation of all outputs to match Matlab releases prior to
+  R2012b.
 
-- The `str2func` function no longer accepts a second `"global"` argument.
-  This argument was typically used to allow functions that accept
-  function names as arguments to avoid conflicts with subfunctions or
-  nested functions.  Instead, it's best to avoid this situation
-  entirely and require users to pass function handles rather than
-  function names.
+- Complex RESTful web services can now be accessed by the `webread` and
+  `webwrite` functions alongside with the `weboptions` structure.  One
+  major feature is the support for cookies to enable RESTful
+  communication with the web service.
 
-- Using `clear` with no arguments now removes only local variables
-  from the current workspace.  Global variables will no longer be
-  visible, but they continue to exist in the global workspace and
-  possibly other workspaces such as the base workspace.
+  Additionally, the system web browser can be opened by the `web` function.
+
+- The interpreter now supports handles to nested functions.
+
+- The graphics properties `"LineWidth"` and `"MarkerSize"` are now
+  measured in points, *not* pixels.  Compared to previous versions
+  of Octave, some lines and markers will appear 4/3 larger.
 
 
-#### Nonlinear Equations
-
-Several default solver options have been changed to be Matlab compatible.
-This *may* result in existing code producing different results.
-
-- `fsolve`
-
-  Option         |   New Default    | Old Default
-  ---------------|------------------|-------------
-  `FinDiffType`  |    `"forward"`   |  `"central"`
-  `MaxFunEvals`  | `100*length(x0)` |    `Inf`
-  `TolFun`       |     `1e-6`       |    `1e-7`
-  `TolX`         |     `1e-6`       |    `1e-7`
-  `Updating`     |     `"off"`      |    `"on"`
-
-- `fminsearch`
-
-  Option   | New Default | Old Default
-  ---------|-------------|------------
-  `TolFun` |   `1e-7`    |   `1e-4`
-
-- `fminbnd`
-
-  Option         | New Default | Old Default
-  ---------------|-------------|------------
-  `MaxFunEvals`  |     `500`   |   `Inf`
-  `MaxIter`      |     `500`   |   `Inf`
-  `TolX`         |    `1e-4`   |   `1e-8`
-
-- `fminunc`
-
-  Option         |   New Default    | Old Default
-  ---------------|------------------|------------
-  `FinDiffType`  |   `"forward"`    | `"central"`
-  `MaxFunEvals`  | `100*length(x0)` |   `Inf`
-  `TolX`         |     `1e-6`       |   `1e-7`
-  `TolFun`       |     `1e-6`       |   `1e-7`
-
-
-#### Graphic objects
-
-- 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 `[]`.
-
-- Patch and surface graphic objects now use the `"FaceNormals"` property
-  for flat lighting.
+### Alphabetical list of new functions added in Octave 6
 
-- `"FaceNormals"` and `"VertexNormals"` for patch and surface graphic
-  objects are now calculated only when necessary to improve graphics
-  performance.  In order for any normals to be calculated the
-  `"FaceLighting"` property must be set to `"flat"` (FaceNormals) or
-  `"gouraud"` (VertexNormals), **and** a light object must be present
-  in the axes.
-
-- The `"Margin"` property of `text`-objects has a new default of `3`
-  rather than `2`.
-
-- Printing to raster formats (bitmaps like PNG or JPEG) now uses an
-  OpenGL-based method by default.  The print options `"-opengl"`
-  (raster) and `"-painters"` (vector) have been added ("qt" toolkit
-  only).  The figure property `"renderer"` specifies which renderer to
-  use.  When the property `"renderermode"` is `"auto"` Octave will select
-  `"-opengl"` for a raster output format and `"-painters"` for a vector
-  output format.
-
-- A new print option `"-RGBImage"` has been added which captures the
-  pixels of a figure as an image.  This is similar to screen capture
-  tools, except that print formatting options can be used to, for
-  example, change the resolution or display the image in black and
-  white.
-
-- Two new print options for page-based formats (PDF, PostScript) have
-  been added.  The `"-fillpage"` option will stretch the plot to occupy
-  the entire page with 0.25 inch margins all around.  The `"-bestfit"`
-  option will expand the plot to take up as much room as possible on
-  the page without distorting the original aspect ratio of the plot.
-
-- Printing using the `"-dtiff"` output device will now create compressed
-  images using LZW compression.  To produce uncompressed images use the
-  `"-dtiffn"` device.
-
-
-### Legacy functions
-
-The following functions have been declared legacy functions which
-means they are obsolete and should not be used in any new code.
-Unlike deprecated functions, however, their removal from Octave has
-not yet been scheduled.
-
-  Function               | Replacement
-  -----------------------|------------------
-  `findstr`              | `strfind`
-  `flipdim`              | `flip`
-  `isdir`                | `isfolder` or `dir_in_loadpath`
-  `isequalwithequalnans` | `isequaln`
-  `isstr`                | `ischar`
-  `setstr`               | `char`
-  `strmatch`             | `strncmp` or `strcmp`
-  `strread`              | `textscan`
-  `textread`             | `textscan`
+- `lightangle`
+- `newline`
+- `verLessThan`
+- `web`
+- `weboptions`
+- `webread`
+- `webwrite`
 
 
 ### Deprecated functions and properties
 
-The following functions and graphics properties have been deprecated
-in Octave 5 and will be removed from Octave 7 (or whatever version
-is the second major release after 5):
-
-- Functions
-
-  Function                 | Replacement
-  -------------------------|-------------------
-  `output_max_field_width` | `output_precision`
-  `is_keyword`             | `iskeyword`
-
-- Graphics properties
-
-  Object           | Property      | Value
-  -----------------|---------------|------------
-  `text`           | `fontangle`   | `"oblique"`
-  `uibuttongroup`  | `fontangle`   | `"oblique"`
-  `uicontrol`      | `fontangle`   | `"oblique"`
-  `uipanel`        | `fontangle`   | `"oblique"`
-  `uitable`        | `fontangle`   | `"oblique"`
-
-- Specifying `legend` position with a numeric argument is deprecated.
-  Use a string argument instead.
-
-- The environment variable used by `mkoctfile` for linker flags is now
-  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` is deprecated, and a warning
-  is emitted if is used, but it will continue to work.
-
-
-### Removed functions and properties
-
-The following functions and properties were deprecated in Octave 4.2
-and have been removed from Octave 5.
+The following functions and properties have been deprecated in Octave 6
+and will be removed from Octave 8 (or whatever version is the second
+major release after 6):
 
 - Functions
 
   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`
+  `runtests`             | `oruntests`
 
 - Properties
 
-  Object      | Property          | Value
-  ------------|-------------------|---------
-  `axes`      | `xaxislocation`   | `"zero"`
-              | `yaxislocation`   | `"zero"`
-  `hggroup`   | `erasemode`       |
-  `image`     | `erasemode`       |
-  `line`      | `erasemode`       |
-  `patch`     | `erasemode`       |
-  `patch`     | `normalmode`      |
-  `surface`   | `erasemode`       |
-  `surface`   | `normalmode`      |
-  `text`      | `erasemode`       |
+  Object           | Property      | Value
+  -----------------|---------------|------------
+                   |               |
 
 
-### Alphabetical list of new functions added in 5
+### Removed functions and properties
+
+The following functions and properties were deprecated in Octave 4.4
+and have been removed from Octave 6.
+
+- Functions
+
+  Function             | Replacement
+  ---------------------|------------------
+  `chop`               | `sprintf` for visual results
+  `desktop`            | `isguirunning`
+  `tmpnam`             | `tempname`
+  `toascii`            | `double`
+  `java2mat`           | `__java2mat__`
+
+- Properties
 
-- `clearvars`
-- `isfile`
-- `isfolder`
-- `matlab.lang.makeUniqueStrings`
-- `matlab.lang.makeValidName`
-- `movegui`
-- `movfun`
-- `movie`
-- `movmad`
-- `movmax`
-- `movmean`
-- `movmedian`
-- `movmin`
-- `movprod`
-- `movslice`
-- `movstd`
-- `movsum`
-- `movvar`
-- `openfig`
-- `ordeig`
-- `savefig`
-- `uitable`
+  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"`
+  `uitable`            | `fontweight`              | `"demi"` and `"light"`
 
 
 ### Old release news
 
-- [Octave 4.4.x](etc/NEWS.4)
-- [Octave 4.2.x](etc/NEWS.4)
-- [Octave 4.0.x](etc/NEWS.4)
-- [Octave 3.8.x](etc/NEWS.3)
-- [Octave 3.6.x](etc/NEWS.3)
-- [Octave 3.4.x](etc/NEWS.3)
-- [Octave 3.2.x](etc/NEWS.3)
-- [Octave 3.0.x](etc/NEWS.3)
+- [Octave 5.x](etc/NEWS.5)
+- [Octave 4.x](etc/NEWS.4)
+- [Octave 3.x](etc/NEWS.3)
 - [Octave 2.x](etc/NEWS.2)
 - [Octave 1.x](etc/NEWS.1)
--- a/build-aux/subst-config-vals.in.sh	Wed Jul 10 20:02:44 2019 -0700
+++ b/build-aux/subst-config-vals.in.sh	Fri Jul 12 12:14:43 2019 -0400
@@ -211,6 +211,9 @@
 SUNDIALS_NVECSERIAL_CPPFLAGS="@SUNDIALS_NVECSERIAL_CPPFLAGS@"
 SUNDIALS_NVECSERIAL_LDFLAGS="@SUNDIALS_NVECSERIAL_LDFLAGS@"
 SUNDIALS_NVECSERIAL_LIBS="@SUNDIALS_NVECSERIAL_LIBS@"
+SUNDIALS_SUNLINSOLKLU_CPPFLAGS="@SUNDIALS_SUNLINSOLKLU_CPPFLAGS@"
+SUNDIALS_SUNLINSOLKLU_LDFLAGS="@SUNDIALS_SUNLINSOLKLU_LDFLAGS@"
+SUNDIALS_SUNLINSOLKLU_LIBS="@SUNDIALS_SUNLINSOLKLU_LIBS@"
 TERM_LIBS="@TERM_LIBS@"
 UMFPACK_CPPFLAGS="@UMFPACK_CPPFLAGS@"
 UMFPACK_LDFLAGS="@UMFPACK_LDFLAGS@"
@@ -380,6 +383,9 @@
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%|\"${SUNDIALS_NVECSERIAL_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%|\"${SUNDIALS_NVECSERIAL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%|\"${SUNDIALS_NVECSERIAL_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%|\"${SUNDIALS_SUNLINSOLKLU_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%|\"${SUNDIALS_SUNLINSOLKLU_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%|\"${SUNDIALS_SUNLINSOLKLU_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_TERM_LIBS%|\"${TERM_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_CPPFLAGS%|\"${UMFPACK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_LDFLAGS%|\"${UMFPACK_LDFLAGS}\"|" \
--- a/build-aux/subst-cross-config-vals.in.sh	Wed Jul 10 20:02:44 2019 -0700
+++ b/build-aux/subst-cross-config-vals.in.sh	Fri Jul 12 12:14:43 2019 -0400
@@ -215,6 +215,9 @@
 SUNDIALS_NVECSERIAL_CPPFLAGS="@SUNDIALS_NVECSERIAL_CPPFLAGS@"
 SUNDIALS_NVECSERIAL_LDFLAGS="@SUNDIALS_NVECSERIAL_LDFLAGS@"
 SUNDIALS_NVECSERIAL_LIBS="@SUNDIALS_NVECSERIAL_LIBS@"
+SUNDIALS_SUNLINSOLKLU_CPPFLAGS="@SUNDIALS_SUNLINSOLKLU_CPPFLAGS@"
+SUNDIALS_SUNLINSOLKLU_LDFLAGS="@SUNDIALS_SUNLINSOLKLU_LDFLAGS@"
+SUNDIALS_SUNLINSOLKLU_LIBS="@SUNDIALS_SUNLINSOLKLU_LIBS@"
 TERM_LIBS="@TERM_LIBS@"
 UMFPACK_CPPFLAGS="@UMFPACK_CPPFLAGS@"
 UMFPACK_LDFLAGS="@UMFPACK_LDFLAGS@"
@@ -384,6 +387,9 @@
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%|\"${SUNDIALS_NVECSERIAL_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%|\"${SUNDIALS_NVECSERIAL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%|\"${SUNDIALS_NVECSERIAL_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%|\"${SUNDIALS_SUNLINSOLKLU_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%|\"${SUNDIALS_SUNLINSOLKLU_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%|\"${SUNDIALS_SUNLINSOLKLU_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_TERM_LIBS%|\"${TERM_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_CPPFLAGS%|\"${UMFPACK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_LDFLAGS%|\"${UMFPACK_LDFLAGS}\"|" \
--- a/build-aux/update-bug-status.sh	Wed Jul 10 20:02:44 2019 -0700
+++ b/build-aux/update-bug-status.sh	Fri Jul 12 12:14:43 2019 -0400
@@ -23,7 +23,7 @@
 done | sort -u)
 
 fixed_bug_numbers=$(for num in $bug_numbers; do
-  status=$(wget -q -O - https://octave.org/testfailure/?$num | sed -n 's/.*>Status:<\/span><\/span>&nbsp;<\/td><td valign="middle" width="35%">\([^<]*\)<.*/\1/p');
+  status=$(wget -q -O - https://octave.org/testfailure/?$num | tr -d '\n' | sed -n 's/.*>Status:<\/span><\/span>&nbsp;<\/td> *<td valign="middle" width="35%">\([^<]*\)<.*/\1/p');
   if [ "$status" = "Fixed" ]; then echo "$num"; fi
 done)
 
--- a/configure.ac	Wed Jul 10 20:02:44 2019 -0700
+++ b/configure.ac	Fri Jul 12 12:14:43 2019 -0400
@@ -20,7 +20,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [5.1.1], [https://octave.org/bugs.html], [octave],
+AC_INIT([GNU Octave], [6.0.0], [https://octave.org/bugs.html], [octave],
         [https://www.gnu.org/software/octave/])
 
 ### Declare version numbers
@@ -32,9 +32,9 @@
 ## explains how to update these numbers for release and development
 ## versions.
 
-OCTAVE_MAJOR_VERSION=5
-OCTAVE_MINOR_VERSION=1
-OCTAVE_PATCH_VERSION=1
+OCTAVE_MAJOR_VERSION=6
+OCTAVE_MINOR_VERSION=0
+OCTAVE_PATCH_VERSION=0
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -56,7 +56,7 @@
 dnl FIXME: Since we also set libtool versions for liboctave and libinterp,
 dnl perhaps we should be computing the "api version" from those versions numbers
 dnl in some way instead of setting it independently here.
-OCTAVE_API_VERSION="api-v53"
+OCTAVE_API_VERSION="api-v53+"
 
 AC_SUBST(OCTAVE_MAJOR_VERSION)
 AC_SUBST(OCTAVE_MINOR_VERSION)
@@ -850,9 +850,7 @@
 RDYNAMIC_FLAG=
 DL_API_MSG=""
 dlopen_api=no
-shl_load_api=no
 loadlibrary_api=no
-dyld_api=no
 
 case $lt_cv_dlopen in
   dlopen)
@@ -862,24 +860,12 @@
       [Define to 1 if system has dlopen, dlsym, dlerror, and dlclose for dynamic linking.])
     OCTAVE_CXX_FLAG([-rdynamic], [RDYNAMIC_FLAG=-rdynamic])
   ;;
-  shl_load)
-    shl_load_api=yes
-    DL_API_MSG="shl_load"
-    AC_DEFINE(HAVE_SHL_LOAD_API, 1,
-      [Define to 1 if system has shl_load and shl_findsym for dynamic linking.])
-  ;;
   LoadLibrary)
     loadlibrary_api=yes
     DL_API_MSG="LoadLibrary"
     AC_DEFINE(HAVE_LOADLIBRARY_API, 1,
       [Define to 1 if system has LoadLibrary for dynamic linking.])
   ;;
-  dyld)
-    dyld_api=yes
-    DL_API_MSG="dyld"
-    AC_DEFINE(HAVE_DYLD_API, 1,
-      [Define to 1 if system has dyld for dynamic linking.])
-  ;;
   *)
     AC_MSG_ERROR([Octave requires some way to perform dynamic linking.])
   ;;
@@ -2206,46 +2192,85 @@
 ### Check for SUNDIALS NVECTOR serial library and header.
 
 OCTAVE_CHECK_LIB(sundials_nvecserial, [SUNDIALS NVECTOR],
-  [SUNDIALS NVECTOR serial library not found.  Solvers ode15i and ode15s will be disabled.],
+  [SUNDIALS NVECTOR serial library not found.  The solvers ode15i and ode15s will be disabled.],
   [nvector/nvector_serial.h nvector_serial.h ], [N_VNew_Serial],
-  [], [don't use SUNDIALS NVECTOR library, solvers ode15i and ode15s will be disabled])
+  [], [don't use SUNDIALS NVECTOR library, disable solvers ode15i and ode15s])
 
 ### Check for SUNDIALS IDA library and header.
 
 save_LIBS="$LIBS"
 LIBS="$SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
 OCTAVE_CHECK_LIB(sundials_ida, [SUNDIALS IDA],
-  [SUNDIALS IDA library not found.  Solvers ode15i and ode15s will be disabled.],
+  [SUNDIALS IDA library not found.  The solvers ode15i and ode15s will be disabled.],
   [ida/ida.h ida.h], [IDAInit],
-  [], [don't use SUNDIALS IDA library, solvers ode15i and ode15s will be disabled],
-  [warn_sundials_ida=
-   OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE
-   OCTAVE_CHECK_SUNDIALS_IDA_DENSE
-   OCTAVE_CHECK_SUNDIALS_IDAKLU])
+  [], [don't use SUNDIALS IDA library, disable solvers ode15i and ode15s])
+LIBS="$save_LIBS"
+
+### Check for SUNDIALS library features, some required, some optional.
+
+LIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS $BLAS_LIBS $FLIBS $LIBS"
+if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida"; then
+  dnl Any of the following tests could determine that SUNDIALS is incompatible
+  dnl and should be disabled. In that event, they all populate the same
+  dnl variable with appropriate warning messages, and further tests should be
+  dnl skipped if a warning message has already been generated that SUNDIALS is
+  dnl disabled.
+  warn_sundials_disabled=
+  if test -z "$warn_sundials_disabled"; then
+    OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API
+  fi
+  if test -z "$warn_sundials_disabled"; then
+    OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE
+  fi
+  if test -z "$warn_sundials_disabled"; then
+    OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE
+  fi
+  dnl The following tests determine whether certain optional features are
+  dnl present in the SUNDIALS libraries, but will not disable using SUNDIALS.
+  if test -z "$warn_sundials_disabled"; then
+    OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU
+  fi
+fi
 LIBS="$save_LIBS"
 
 dnl Define this way instead of with an #if in oct-conf-post.h so that
 dnl the build features script will get the correct value.
+dnl
+dnl The test on the sunlinsol_klu.h header is a bit of a kluge.
+dnl How can we do a better job here?  Do we need to disable sundials
+dnl any tests fail, or can we fix __ode15__.cc so that it still partially
+dnl works when some things are missing (for example, KLU)?
 if test -n "$SUNDIALS_IDA_LIBS" \
     && test -n "$SUNDIALS_NVECSERIAL_LIBS" \
-    && test $octave_cv_sundials_ida_dense = yes \
-    && test $octave_cv_sundials_realtype_is_double = yes; then
+    && test "x$octave_cv_sundials_sunlinsol_dense" = xyes \
+    && test "x$octave_cv_sundials_realtype_is_double" = xyes \
+    && test "x$octave_have_sundials_compatible_api" = xyes; then
   AC_DEFINE(HAVE_SUNDIALS, 1, [Define to 1 if SUNDIALS is available.])
 
   ## Collections of options needed to build with SUNDIALS and its dependencies.
-  SUNDIALS_XCPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS"
-  SUNDIALS_XLDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS"
-  SUNDIALS_XLIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS"
+  SUNDIALS_XCPPFLAGS="$SUNDIALS_IDA_CPPFLAGS $SUNDIALS_SUNLINSOLKLU_CPPFLAGS $SUNDIALS_NVECSERIAL_CPPFLAGS $KLU_CPPFLAGS"
+  SUNDIALS_XLDFLAGS="$SUNDIALS_IDA_LDFLAGS $SUNDIALS_SUNLINSOLKLU_LDFLAGS $SUNDIALS_NVECSERIAL_LDFLAGS $KLU_LDFLAGS"
+  SUNDIALS_XLIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_SUNLINSOLKLU_LIBS $SUNDIALS_NVECSERIAL_LIBS $KLU_LIBS"
 else
   SUNDIALS_IDA_CPPFLAGS=
   SUNDIALS_IDA_LDFLAGS=
   SUNDIALS_IDA_LIBS=
+  SUNDIALS_SUNLINSOLKLU_CPPFLAGS=
+  SUNDIALS_SUNLINSOLKLU_LDFLAGS=
+  SUNDIALS_SUNLINSOLKLU_LIBS=
   SUNDIALS_NVECSERIAL_CPPFLAGS=
   SUNDIALS_NVECSERIAL_LDFLAGS=
   SUNDIALS_NVECSERIAL_LIBS=
   SUNDIALS_XCPPFLAGS=
   SUNDIALS_XLDFLAGS=
   SUNDIALS_XLIBS=
+  dnl Emit a fallback warning message in case SUNDIALS has been disabled for
+  dnl some reason that hasn't already generated one of these known warnings.
+  if test -z "$warn_sundials_nvecserial" && test -z "$warn_sundials_ida" \
+      && test -z "$warn_sundials_disabled"; then
+    warn_sundials_disabled="SUNDIALS libraries are missing some feature.  The solvers ode15i and ode15s will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
+  fi
 fi
 
 AC_SUBST(SUNDIALS_XCPPFLAGS)
@@ -2594,7 +2619,7 @@
 esac
 
 GCC_EXTRA_FLAGS="-Wall -W $GCC_WSHADOW_OPTION -Wformat -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wcast-align -Wcast-qual"
-GXX_EXTRA_FLAGS="-Wall -W $GCC_WSHADOW_OPTION -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual"
+GXX_EXTRA_FLAGS="-Wall -W $GCC_WSHADOW_OPTION -Woverloaded-virtual -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual"
 
 try_extra_warning_flags=yes
 AC_ARG_ENABLE([extra-warning-flags],
@@ -3066,6 +3091,9 @@
   SUNDIALS NVECTOR CPPFLAGS:     $SUNDIALS_NVECSERIAL_CPPFLAGS
   SUNDIALS NVECTOR LDFLAGS:      $SUNDIALS_NVECSERIAL_LDFLAGS
   SUNDIALS NVECTOR libraries:    $SUNDIALS_NVECSERIAL_LIBS
+  SUNLINSOL KLU CPPFLAGS:        $SUNDIALS_SUNLINSOLKLU_CPPFLAGS
+  SUNLINSOL KLU LDFLAGS:         $SUNDIALS_SUNLINSOLKLU_LDFLAGS
+  SUNLINSOL KLU libraries:       $SUNDIALS_SUNLINSOLKLU_LIBS
   TERM libraries:                $TERM_LIBS
   UMFPACK CPPFLAGS:              $UMFPACK_CPPFLAGS
   UMFPACK LDFLAGS:               $UMFPACK_LDFLAGS
--- a/doc/interpreter/TODO	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/TODO	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,7 @@
     (???)
 
   * If Octave crashes, it now attempts to save all user-defined
-    variables in a file named `octave-core' in the current directory
+    variables in a file named 'octave-core' in the current directory
     before exiting.
     (???)
 
@@ -39,7 +39,7 @@
     that are not yet available in the public release of Info.
     (install)
 
-  * If it is present, Octave will now use an `ls-R' database file to
+  * If it is present, Octave will now use an 'ls-R' database file to
     speed up recursive path searching.  Octave looks for a file called
     ls-R in the directory specified by the environment variable
     OCTAVE_DB_DIR.  If that is not set but the environment variable
--- a/doc/interpreter/contributors.in	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/contributors.in	Fri Jul 12 12:14:43 2019 -0400
@@ -43,6 +43,7 @@
 Remy Bruno
 Clemens Buchacher
 Ansgar Burchard
+Antonius Burgers
 Marco Caliari
 Daniel Calvelo
 John C. Campbell
@@ -430,6 +431,7 @@
 Alexander Wilms
 Joe Winegarden
 Georg Wiora
+Eddy Xiao
 Sahil Yadav
 Fook Fah Yap
 Sean Young
--- a/doc/interpreter/genpropdoc.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/genpropdoc.m	Fri Jul 12 12:14:43 2019 -0400
@@ -503,11 +503,24 @@
 @code{screenpixelsperinch} property of the root object.";
 
       case "pointer"
-        s.doc = doc_unused;
+        s.doc = "Name of the mouse pointer shape associated with the canvas \
+of the figure.  When __prop__ is \"custom\", the shape is determined by \
+the @code{pointershapecdata} property.\n\n\
+__prop__ has no effect when the figure is in zoom, pan, or rotate mode. \
+In this case, Octave automatically uses a pointer shape appropriate \
+to the mode.";
+
       case "pointershapecdata"
-        s.doc = doc_unused;
+        s.doc ="m-by-m matrix defining a custom pointer.  Each \
+element defines a pixel with the element (1,1) representing the \
+top-left pixel.  A value of 1 is colored black, a value of 2 is colored white, \
+and all other values are rendered as transparent.";
+        s.valid = "16-by-16 or 32-by-32 Matrix";
+
       case "pointershapehotspot"
-        s.doc = doc_unused;
+        s.doc ="For custom pointers only __prop__ defines the row and column \
+of the pixel in @code{pointershapecdata} that is used as the pointer location.";
+        s.valid = valid_2elvec;
 
       case "position"
         s.doc = "Specify the position and size of the figure canvas.  \
@@ -536,7 +549,19 @@
         s.valid = valid_fcn;
 
       case "selectiontype"
-        ## FIXME: docstring explaining what "{normal}|open|alt|extend" mean.
+        s.doc = "Selection type of the latest mouse click.\n\n\
+__prop__ may take different values depending on the combination of mouse \
+button and keyboard modifier that were used:\n\
+@table @code\n\
+@item normal:\n\
+Left-click.\n\
+@item alt:\n\
+Right-click or Ctrl+Left-click.\n\
+@item extend:\n\
+Shitf+Left-click, Middle click, or combined Left-click and Right-click.\n\
+@item open:\n\
+Double Left-click.\n\
+@end table";
 
       case "sizechangedfcn"
         s.doc = "Callback triggered when the figure window size is changed.\
@@ -581,7 +606,21 @@
         s.valid = valid_fcn;
 
       case "windowscrollwheelfcn"
-        s.doc = doc_unused;
+        s.doc = "Function that is executed when a user manipulates \
+the mouse wheel over this figure.  \
+The function is called with two input arguments.  The first \
+argument holds the handle of the calling figure.  The second argument holds \
+an event structure which has the following members:\n\
+@table @code\n\
+@item VerticalScrollCount:\n\
+The number of wheel steps, typically 1 when scrolling down and -1 when \
+scrolling up.\n\
+@item VerticalScrollAmount:\n\
+The number of lines a wheel step should scroll.  This value is always 3.\n\
+@item EventName:\n\
+The event name which is \"WindowScrollWheel\".\n\
+@end table\
+\n\n__fcnmsg__";
         s.valid = valid_fcn;
 
       case "windowstyle"
@@ -696,12 +735,12 @@
         s.doc = doc_fontsize;
         s.valid = "scalar";
 
+      case "fontsmoothing"
+        s.doc = "Control whether any text associated with __objname__ is anti-aliased.";
+
       case "fontunits"
         s.doc = doc_fontunits;
 
-      case "fontsmoothing"
-        s.doc = doc_unused;
-
       case "fontweight"
         s.doc = doc_fontweight;
 
@@ -1082,6 +1121,9 @@
         s.doc = doc_fontname;
         s.valid = valid_string;
 
+      case "fontsmoothing"
+        s.doc = "Control whether anti-aliasing is used when rendering text.";
+
       case "fontsize"
         s.doc = doc_fontsize;
         s.valid = "scalar";
--- a/doc/interpreter/macros.texi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/macros.texi	Fri Jul 12 12:14:43 2019 -0400
@@ -46,9 +46,14 @@
 @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.
+@c for HTML.  We use a simple blank line to produce the correct
+@c behavior.
+@c
+@c We use @xseealso now because Texinfo introduced its own @seealso
+@c command.  But instead of modifying all source files, we'll have the
+@c munge-texi script convert @seealso to @xseealso.
 
-@macro seealso {args}
+@macro xseealso {args}
 @iftex
 @vskip 2pt
 @end iftex
--- a/doc/interpreter/mk-doc-cache.pl	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/mk-doc-cache.pl	Fri Jul 12 12:14:43 2019 -0400
@@ -71,6 +71,8 @@
           next if $in_header;
           next if $line =~ /$tex_delim_pat/;
 
+          $line =~ s/\@seealso/\@xseealso/g;
+
           ## escape {}@ characters for texinfo
           $line =~ s/([{}\@])/\@$1/g
             if $line =~ m/^$doc_delim/;
--- a/doc/interpreter/munge-texi.pl	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/munge-texi.pl	Fri Jul 12 12:14:43 2019 -0400
@@ -73,6 +73,8 @@
 
 TXI_LINE: while (<STDIN>)
 {
+  s/\@seealso/\@xseealso/g;
+
   if (/^\s*\@DOCSTRING\((\S+)\)/)
   {
     $func = $1;
@@ -139,7 +141,9 @@
         $repl .= "\@ref{XREF$node,,$func}, ";
       }
       substr($repl,-2) = "";   # Remove last ', '
-      $_ = "\@seealso{$repl}$rest_of_line";
+      # write out @xseealso because we have our own macro that conflicts
+      # with the one introduced in Texinfo 6.
+      $_ = "\@xseealso{$repl}$rest_of_line";
     }
 
     $docstring .= $_;
--- a/doc/interpreter/oop.txi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/oop.txi	Fri Jul 12 12:14:43 2019 -0400
@@ -900,6 +900,8 @@
 By default, in the example @var{prop4}, properties are not constant and have
 public read and write access.
 
+@DOCSTRING(properties)
+
 @node Methods
 @subsection Methods
 
--- a/doc/interpreter/plot.txi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/plot.txi	Fri Jul 12 12:14:43 2019 -0400
@@ -459,6 +459,8 @@
 
 @DOCSTRING(camlight)
 
+@DOCSTRING(lightangle)
+
 @DOCSTRING(meshgrid)
 
 @DOCSTRING(ndgrid)
--- a/doc/interpreter/strings.txi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/strings.txi	Fri Jul 12 12:14:43 2019 -0400
@@ -248,7 +248,12 @@
 the overhead of a function call and the input validation of the associated
 function.
 
-Nevertheless, there are several other functions for concatenating string
+The @code{newline} function can be used to join strings such that they appear
+as multiple lines of text when displayed.
+
+@DOCSTRING(newline)
+
+In addition, there are several other functions for concatenating string
 objects which can be useful in specific circumstances: @code{char},
 @code{strvcat}, @code{strcat}, and @code{cstrcat}.  Finally, the general
 purpose concatenation functions can be used: see @ref{XREFcat,,cat},
--- a/doc/interpreter/system.txi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/system.txi	Fri Jul 12 12:14:43 2019 -0400
@@ -533,6 +533,8 @@
 
 @DOCSTRING(compare_versions)
 
+@DOCSTRING(verLessThan)
+
 @DOCSTRING(license)
 
 @DOCSTRING(getrusage)
--- a/doc/interpreter/testfun.txi	Wed Jul 10 20:02:44 2019 -0700
+++ b/doc/interpreter/testfun.txi	Fri Jul 12 12:14:43 2019 -0400
@@ -470,8 +470,8 @@
 
 @DOCSTRING(example)
 
+@DOCSTRING(oruntests)
+
 @DOCSTRING(rundemos)
 
-@DOCSTRING(runtests)
-
 @DOCSTRING(speed)
--- a/etc/HACKING.md	Wed Jul 10 20:02:44 2019 -0700
+++ b/etc/HACKING.md	Fri Jul 12 12:14:43 2019 -0400
@@ -343,7 +343,7 @@
 
 The rules for updating these version numbers are:
 
-  * Start with version information of ‘0:0:0’ for each libtool library.
+  * Start with version information of `0:0:0` for each libtool library.
 
   * Update the version information only immediately before a public
     release of your software.  More frequent updates are unnecessary,
@@ -351,7 +351,7 @@
     faster.
 
   * If the library source code has changed at all since the last update,
-    then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+    then increment revision (`c:r:a` becomes `c:r+1:a`).
 
   * If any interfaces have been added, removed, or changed since the
     last update, increment current, and set revision to 0.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.5	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,324 @@
+Summary of important user-visible changes for version 5 (2019-02-23):
+--------------------------------------------------------------------
+
+### General improvements
+
+- The Octave plotting system now supports high resolution screens,
+  i.e., those with greater than 96 DPI which are referred to as
+  HiDPI/Retina monitors.
+
+- Unicode character support for files and folders in Windows.
+
+- A new core function `movfun` will apply a function to a sliding
+  window of arbitrary size on a dataset and accumulate the results.
+  Many common cases have been implemented using the naming
+  scheme `movXXX` where `XXX` is the function that will be applied.
+  For example, the moving average over a dataset is `movmean`.
+  New moving window functions:
+
+  `movfun`  `movslice`
+  `movmad`  `movmax`   `movmean`  `movmedian`  `movmin`  `movprod`
+  `movstd`  `movsum`   `movvar`
+
+- The `fsolve` function has been tweaked to use larger step sizes when
+  calculating the Jacobian of a function with finite differences.
+  This leads to faster convergence.
+
+- The `ranks` function has been recoded for performance and is now 25X
+  faster.  In addition, it now supports a third argument that specifies
+  how to resolve the ranking of tie values.
+
+- The function `randi` has been recoded to produce an unbiased (all
+  results are equally likely) sample of integers.  This may produce
+  different results in existing code.  If it is necessary to reproduce
+  the exact random integer sequence as in previous versions use
+
+  `ri = imin + floor ((imax - imin + 1) * rand ());`
+
+- The function `isdefinite` now returns `true` or `false` rather than
+  `-1`, `0`, or `1`.  To test for a positive semi-definite matrix (old
+  output of `0`) check whether the following two conditions hold:
+
+    `isdefinite (A) => 0`  and  `isdefinite (A + 5*TOL, TOL) => 1`
+
+- The `intmax`, `intmin`, and `flintmax` functions now accept a variable
+  as input.  Existing code to query the range of an existing variable can
+  be simplified by removing the call to `class` that was previously
+  required.  For example defining the variable `x = int8 (3)` in the
+  workspace, calls like
+
+    `range = [ intmin(class(x)), intmax(class(x)) ]`
+
+  can in Octave 5 be simplified to `range = [ intmin(x), intmax(x) ]`.
+
+- The path handling functions no longer perform variable or brace
+  expansion on path elements and Octave's load-path is no longer
+  subject to these expansions.
+
+- A new printing device is available, `"-ddumb"`, which produces ASCII
+  art for plots.  This device is only available with the gnuplot toolkit.
+
+- The `msgbox` function has changed in two respects: the default WindowStyle
+  is now `"non-modal"`, and the default interpreter for the message is now
+  `"tex"`.  Both WindowStyle and Interpreter can be controlled by passing an
+  option struct argument.
+
+### Dependencies
+
+- The GUI requires Qt libraries.  The minimum Qt4 version supported is
+  Qt4.8.  Qt5 of any version is preferred.
+
+- The OSMesa library is no longer used.  To print invisible figures
+  when using OpenGL graphics, the Qt `QOFFSCREENSURFACE` feature must be
+  available and you must use the qt graphics toolkit.
+
+- The FFTW library is now required to perform FFT calculations.
+  The FFTPACK sources have been removed from Octave.
+
+
+### Matlab compatibility
+
+- The determination of an object's dimensions, size, and shape by the
+  functions `ndims`, `rows`, `columns`, `isscalar`, `isvector`,
+  `isrow`, `iscolumn`, `ismatrix`, and `issquare` now fully depends
+  on the function size.  Thus, any user-defined object can ensure correct
+  treatment by the aforementioned functions by properly overloading the
+  `size` function.
+
+- 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.
+
+- The `issorted` function now uses a direction option of `"ascend"`
+  or `"descend"`.  Change all uses of `"ascending"` and `"descending"`
+  in existing code to the new options.
+
+- The `strncmp` and `strncmpi` functions now return `true` if the two
+  input strings match, even though the number of characters specified
+  by `n` exceeds the string length.  For Example:
+
+    `strncmp ("abc", "abc", 100)`
+
+  returns `true` in Octave 5 and `false` in older versions of Octave.
+
+- The `str2func` function no longer accepts a second `"global"` argument.
+  This argument was typically used to allow functions that accept
+  function names as arguments to avoid conflicts with subfunctions or
+  nested functions.  Instead, it's best to avoid this situation
+  entirely and require users to pass function handles rather than
+  function names.
+
+- Using `clear` with no arguments now removes only local variables
+  from the current workspace.  Global variables will no longer be
+  visible, but they continue to exist in the global workspace and
+  possibly other workspaces such as the base workspace.
+
+
+#### Nonlinear Equations
+
+Several default solver options have been changed to be Matlab compatible.
+This *may* result in existing code producing different results.
+
+- `fsolve`
+
+  Option         |   New Default    | Old Default
+  ---------------|------------------|-------------
+  `FinDiffType`  |    `"forward"`   |  `"central"`
+  `MaxFunEvals`  | `100*length(x0)` |    `Inf`
+  `TolFun`       |     `1e-6`       |    `1e-7`
+  `TolX`         |     `1e-6`       |    `1e-7`
+  `Updating`     |     `"off"`      |    `"on"`
+
+- `fminsearch`
+
+  Option   | New Default | Old Default
+  ---------|-------------|------------
+  `TolFun` |   `1e-7`    |   `1e-4`
+
+- `fminbnd`
+
+  Option         | New Default | Old Default
+  ---------------|-------------|------------
+  `MaxFunEvals`  |     `500`   |   `Inf`
+  `MaxIter`      |     `500`   |   `Inf`
+  `TolX`         |    `1e-4`   |   `1e-8`
+
+- `fminunc`
+
+  Option         |   New Default    | Old Default
+  ---------------|------------------|------------
+  `FinDiffType`  |   `"forward"`    | `"central"`
+  `MaxFunEvals`  | `100*length(x0)` |   `Inf`
+  `TolX`         |     `1e-6`       |   `1e-7`
+  `TolFun`       |     `1e-6`       |   `1e-7`
+
+
+#### Graphic objects
+
+- 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 `[]`.
+
+- Patch and surface graphic objects now use the `"FaceNormals"` property
+  for flat lighting.
+
+- `"FaceNormals"` and `"VertexNormals"` for patch and surface graphic
+  objects are now calculated only when necessary to improve graphics
+  performance.  In order for any normals to be calculated the
+  `"FaceLighting"` property must be set to `"flat"` (FaceNormals) or
+  `"gouraud"` (VertexNormals), **and** a light object must be present
+  in the axes.
+
+- The `"Margin"` property of `text`-objects has a new default of `3`
+  rather than `2`.
+
+- Printing to raster formats (bitmaps like PNG or JPEG) now uses an
+  OpenGL-based method by default.  The print options `"-opengl"`
+  (raster) and `"-painters"` (vector) have been added ("qt" toolkit
+  only).  The figure property `"renderer"` specifies which renderer to
+  use.  When the property `"renderermode"` is `"auto"` Octave will select
+  `"-opengl"` for a raster output format and `"-painters"` for a vector
+  output format.
+
+- A new print option `"-RGBImage"` has been added which captures the
+  pixels of a figure as an image.  This is similar to screen capture
+  tools, except that print formatting options can be used to, for
+  example, change the resolution or display the image in black and
+  white.
+
+- Two new print options for page-based formats (PDF, PostScript) have
+  been added.  The `"-fillpage"` option will stretch the plot to occupy
+  the entire page with 0.25 inch margins all around.  The `"-bestfit"`
+  option will expand the plot to take up as much room as possible on
+  the page without distorting the original aspect ratio of the plot.
+
+- Printing using the `"-dtiff"` output device will now create compressed
+  images using LZW compression.  To produce uncompressed images use the
+  `"-dtiffn"` device.
+
+
+### Legacy functions
+
+The following functions have been declared legacy functions which
+means they are obsolete and should not be used in any new code.
+Unlike deprecated functions, however, their removal from Octave has
+not yet been scheduled.
+
+  Function               | Replacement
+  -----------------------|------------------
+  `findstr`              | `strfind`
+  `flipdim`              | `flip`
+  `isdir`                | `isfolder` or `dir_in_loadpath`
+  `isequalwithequalnans` | `isequaln`
+  `isstr`                | `ischar`
+  `setstr`               | `char`
+  `strmatch`             | `strncmp` or `strcmp`
+  `strread`              | `textscan`
+  `textread`             | `textscan`
+
+
+### Deprecated functions and properties
+
+The following functions and graphics properties have been deprecated
+in Octave 5 and will be removed from Octave 7 (or whatever version
+is the second major release after 5):
+
+- Functions
+
+  Function                 | Replacement
+  -------------------------|-------------------
+  `output_max_field_width` | `output_precision`
+  `is_keyword`             | `iskeyword`
+
+- Graphics properties
+
+  Object           | Property      | Value
+  -----------------|---------------|------------
+  `text`           | `fontangle`   | `"oblique"`
+  `uibuttongroup`  | `fontangle`   | `"oblique"`
+  `uicontrol`      | `fontangle`   | `"oblique"`
+  `uipanel`        | `fontangle`   | `"oblique"`
+  `uitable`        | `fontangle`   | `"oblique"`
+
+- Specifying `legend` position with a numeric argument is deprecated.
+  Use a string argument instead.
+
+- The environment variable used by `mkoctfile` for linker flags is now
+  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` is deprecated, and a warning
+  is emitted if is used, but it will continue to work.
+
+
+### Removed functions and properties
+
+The following functions and properties were deprecated in Octave 4.2
+and have been removed from Octave 5.
+
+- Functions
+
+  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`
+
+- Properties
+
+  Object      | Property          | Value
+  ------------|-------------------|---------
+  `axes`      | `xaxislocation`   | `"zero"`
+              | `yaxislocation`   | `"zero"`
+  `hggroup`   | `erasemode`       |
+  `image`     | `erasemode`       |
+  `line`      | `erasemode`       |
+  `patch`     | `erasemode`       |
+  `patch`     | `normalmode`      |
+  `surface`   | `erasemode`       |
+  `surface`   | `normalmode`      |
+  `text`      | `erasemode`       |
+
+
+### Alphabetical list of new functions added in 5
+
+- `clearvars`
+- `isfile`
+- `isfolder`
+- `matlab.lang.makeUniqueStrings`
+- `matlab.lang.makeValidName`
+- `movegui`
+- `movfun`
+- `movie`
+- `movmad`
+- `movmax`
+- `movmean`
+- `movmedian`
+- `movmin`
+- `movprod`
+- `movslice`
+- `movstd`
+- `movsum`
+- `movvar`
+- `openfig`
+- `ordeig`
+- `savefig`
+- `uitable`
+
+
+### Old release news
+
+- [Octave 4.4.x](etc/NEWS.4)
+- [Octave 4.2.x](etc/NEWS.4)
+- [Octave 4.0.x](etc/NEWS.4)
+- [Octave 3.8.x](etc/NEWS.3)
+- [Octave 3.6.x](etc/NEWS.3)
+- [Octave 3.4.x](etc/NEWS.3)
+- [Octave 3.2.x](etc/NEWS.3)
+- [Octave 3.0.x](etc/NEWS.3)
+- [Octave 2.x](etc/NEWS.2)
+- [Octave 1.x](etc/NEWS.1)
--- a/etc/RELEASE.BUG_FIX_LIST	Wed Jul 10 20:02:44 2019 -0700
+++ b/etc/RELEASE.BUG_FIX_LIST	Fri Jul 12 12:14:43 2019 -0400
@@ -1,4 +1,4 @@
-The following bugs must be fixed prior to the next release.  See also the [[5.0.0 Release Checklist]].
+The following bugs must be fixed prior to the next release.  See also the [[6.0.0 Release Checklist]].
 
 <p>Sign up for a bug by filling in the Owner field so people won't duplicate each other's work.</p>
 
@@ -21,4 +21,4 @@
 == Other Bugs ==
 
 == Potentially excluded bugs ==
-These bugs have been provisionally decided not to be blockers for 5.0.0.  That doesn't mean they can't be fixed, if someone wants to fix them.
+These bugs have been provisionally decided not to be blockers for 6.0.0.  That doesn't mean they can't be fixed, if someone wants to fix them.
--- a/etc/RELEASE.CHECKLIST	Wed Jul 10 20:02:44 2019 -0700
+++ b/etc/RELEASE.CHECKLIST	Fri Jul 12 12:14:43 2019 -0400
@@ -3,7 +3,7 @@
    The format of the file is wiki markup and can be directly used as a page
    on wiki.octave.org. >
 <!----------------------------------------------------------------------------->
-==5.0.0 Release Tasks==
+==6.0.0 Release Tasks==
 
 <!----------------------------------------------------------------------------->
 # Update gnulib to latest version
@@ -23,7 +23,7 @@
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Clear all bugs identified as must-fix
-#* See [[Bug Fix List - 5.0 Release]]
+#* See [[Bug Fix List - 6.0 Release]]
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # GPL License activities
@@ -67,6 +67,11 @@
 #* Submit call for translations for GUI strings
 #: Completion Date:
 <!----------------------------------------------------------------------------->
+# Update shared library and oct file API version numbers
+#* Increment oct file API version number (configure.ac:OCTAVE_API_VERSION, increment number and drop "+" suffix)
+#* Increment libtool versioning (liboctave/module.mk:%canon_reldir%_%canon_reldir%_current, libinterp/module.mk:%canon_reldir%_liboctinterp_current, libgui/module.mk:%canon_reldir%_liboctgui_current)
+#: Completion Date:
+<!----------------------------------------------------------------------------->
 # Verify build process and create release candidates
 #* Update configure.ac with new version information
 #** Update AC_INIT, OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, OCTAVE_PATCH_VERSION, OCTAVE_RELEASE_DATE
@@ -84,7 +89,6 @@
 # Final 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)
@@ -98,6 +102,7 @@
 <!----------------------------------------------------------------------------->
 # Post-Release
 #* Update configure.ac (AC_INIT, OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, OCTAVE_PATCH_VERSION) to next release cycle
+#* Update oct file API version number (configure.ac:OCTAVE_API_VERSION, add "+" suffix)
 #* 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
--- a/etc/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/etc/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -9,6 +9,7 @@
   %reldir%/NEWS.2 \
   %reldir%/NEWS.3 \
   %reldir%/NEWS.4 \
+  %reldir%/NEWS.5 \
   %reldir%/PROJECTS \
   %reldir%/gdbinit
 
--- a/examples/code/funcdemo.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/examples/code/funcdemo.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1,7 +1,7 @@
 #include <octave/oct.h>
 #include <octave/parse.h>
 
-DEFUN_DLD (funcdemo, args, nargout, "Function Demo")
+DEFMETHOD_DLD (funcdemo, interp, args, nargout, "Function Demo")
 {
   int nargin = args.length ();
 
@@ -15,18 +15,9 @@
 
   octave_value_list retval;
 
-  if (args(0).is_function_handle () || args(0).is_inline_function ())
-    {
-      octave_function *fcn = args(0).function_value ();
-
-      retval = feval (fcn, newargs, nargout);
-    }
-  else if (args(0).is_string ())
-    {
-      std::string fcn = args(0).string_value ();
-
-      retval = feval (fcn, newargs, nargout);
-    }
+  if (args(0).is_function_handle () || args(0).is_inline_function ()
+      || args(0).is_string ())
+    retval = interp.feval (args(0), newargs, nargout);
   else
     error ("funcdemo: INPUT must be string, inline, or function handle");
 
--- a/examples/code/make_int.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/examples/code/make_int.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -12,7 +12,6 @@
 #include <octave/str-vec.h>
 
 #include <octave/defun-dld.h>
-#include <octave/errwarn.h>
 #include <octave/interpreter.h>
 #include <octave/ops.h>
 #include <octave/ov-base.h>
@@ -161,12 +160,7 @@
   const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);
   const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);
 
-  int d = v2.integer_value ();
-
-  if (d == 0)
-    warn_divide_by_zero ();
-
-  return new octave_integer (v1.integer_value () / d);
+  return new octave_integer (v1.integer_value () / v2.integer_value ());
 }
 
 
@@ -175,12 +169,7 @@
   const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return new octave_scalar (v1.double_value () / d);
+  return new octave_scalar (v1.double_value () / v2.double_value ());
 }
 
 DEFBINOP (ldiv, integer, integer)
@@ -188,12 +177,7 @@
   const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);
   const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);
 
-  int d = v1.integer_value ();
-
-  if (d == 0)
-    warn_divide_by_zero ();
-
-  return new octave_integer (v2.integer_value () / d);
+  return new octave_integer (v2.integer_value () / v1.integer_value ());
 }
 
 DEFBINOP_OP (lt, integer, integer, <)
@@ -210,12 +194,7 @@
   const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);
   const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);
 
-  int d = v2.integer_value ();
-
-  if (d == 0)
-    warn_divide_by_zero ();
-
-  return new octave_integer (v1.integer_value () / d);
+  return new octave_integer (v1.integer_value () / v2.integer_value ());
 }
 
 DEFBINOP (el_ldiv, integer, integer)
@@ -223,12 +202,7 @@
   const octave_integer& v1 = dynamic_cast<const octave_integer&> (a1);
   const octave_integer& v2 = dynamic_cast<const octave_integer&> (a2);
 
-  int d = v1.integer_value ();
-
-  if (d == 0)
-    warn_divide_by_zero ();
-
-  return new octave_integer (v2.integer_value () / d);
+  return new octave_integer (v2.integer_value () / v1.integer_value ());
 }
 
 DEFBINOP_OP (el_and, integer, integer, &&)
--- a/examples/code/oregonator.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/examples/code/oregonator.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1,7 +1,7 @@
 #include <octave/oct.h>
 
 DEFUN_DLD (oregonator, args, ,
-           "The `oregonator'.\n\
+           "The 'oregonator'.\n\
 \n\
 Reference:\n\
 \n\
--- a/examples/code/oregonator.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/examples/code/oregonator.m	Fri Jul 12 12:14:43 2019 -0400
@@ -1,4 +1,4 @@
-## The `oregonator'.
+## The 'oregonator'.
 ##
 ## Reference:
 ##
--- a/libgui/graphics/BaseControl.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/BaseControl.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -93,6 +93,7 @@
   BaseControl::BaseControl (const graphics_object& go, QWidget *w)
     : Object (go, w), m_normalizedFont (false), m_keyPressHandlerDefined (false)
   {
+    qObject ()->setObjectName ("UIControl");
     init (w);
   }
 
@@ -123,6 +124,12 @@
   { }
 
   void
+  BaseControl::redraw (void)
+  {
+    update (uicontrol::properties::ID_POSITION);
+  }
+
+  void
   BaseControl::update (int pId)
   {
     uicontrol::properties& up = properties<uicontrol> ();
--- a/libgui/graphics/BaseControl.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/BaseControl.h	Fri Jul 12 12:14:43 2019 -0400
@@ -43,6 +43,7 @@
 
   protected:
     void init (QWidget *w, bool callBase = false);
+    void redraw (void);
     void update (int pId);
 
   private:
--- a/libgui/graphics/ButtonGroup.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/ButtonGroup.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -378,6 +378,9 @@
   void
   ButtonGroup::redraw (void)
   {
+    update (uibuttongroup::properties::ID_POSITION);
+
+    // FIXME: is it really necessary to update the opengl canvas here?
     Canvas *canvas = m_container->canvas (m_handle);
 
     if (canvas)
--- a/libgui/graphics/Canvas.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Canvas.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -41,8 +41,11 @@
 
 #include "annotation-dialog.h"
 
+#include "interpreter-private.h"
+#include "interpreter.h"
 #include "oct-opengl.h"
 #include "octave-qt-link.h"
+#include "resource-manager.h"
 
 #include "builtin-defun-decls.h"
 
@@ -70,33 +73,113 @@
   }
 
   void
-  Canvas::setCursor (MouseMode mode)
+  Canvas::setCursor (MouseMode mode, std::string fallback,
+                     QImage cdata, Matrix hotspot)
   {
     QWidget *w = qWidget ();
-
+    QCursor cursor = Qt::ArrowCursor;
     if (w)
       {
-        static QCursor origCursor = w->cursor ();
-
         switch (mode)
           {
+          case NoMode:
+            {
+              cursor = Qt::ArrowCursor;
+
+              if (fallback == "arrow")
+                cursor = Qt::ArrowCursor;
+              else if (fallback == "botl")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("bottom_left_corner").pixmap (22,22),
+                                  5, 16);
+              else if (fallback == "botr")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("bottom_right_corner").pixmap (22, 22),
+                                  16, 16);
+              else if (fallback == "bottom")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("bottom_side").pixmap (22, 22),
+                                  11, 16);
+              else if (fallback == "circle")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("circle").pixmap (22, 22),
+                                  10, 10);
+              else if (fallback == "cross" || fallback == "crosshair")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("cross").pixmap (22, 22), 10, 10);
+              else if (fallback == "custom")
+                {
+                  if (hotspot(0) > cdata.width () || hotspot(0) < 1.0
+                      || hotspot(1) > cdata.height () || hotspot(1) < 1.0)
+                    hotspot = Matrix (1, 2, 1);
+
+                  cursor = QCursor (QPixmap::fromImage (cdata),
+                                    static_cast<int> (hotspot(1) - 1),
+                                    static_cast<int> (hotspot(0) - 1));
+                }
+              else if (fallback == "fleur")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("fleur").pixmap (22, 22), 10, 4);
+              else if (fallback == "hand")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("hand2").pixmap (22, 22), 7, 3);
+              else if (fallback == "ibeam")
+                cursor = Qt::IBeamCursor;
+              else if (fallback == "left")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("left_side").pixmap (22, 22), 4, 10);
+              else if (fallback == "right")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("right_side").pixmap (22, 22),
+                                  17, 10);
+              else if (fallback == "top")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("top_side").pixmap (22, 22), 11, 4);
+              else if (fallback == "topl")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("top_left_corner").pixmap (22, 22),
+                                  4, 4);
+              else if (fallback == "topr")
+                cursor = QCursor (octave::resource_manager::icon
+                                  ("top_right_corner").pixmap (22, 22),
+                                  16, 4);
+              else if (fallback == "watch")
+                cursor = Qt::BusyCursor;
+            }
+            break;
+          case SelectMode:
+            cursor = Qt::ArrowCursor;
+            break;
+
           case PanMode:
+            cursor = QCursor (octave::resource_manager::icon ("figure-pan")
+                              .pixmap (22, 22));
+            break;
+
           case RotateMode:
-            w->setCursor (Qt::OpenHandCursor);
+            cursor = QCursor (octave::resource_manager::icon ("figure-rotate")
+                              .pixmap (22, 22));
+            break;
+
+          case TextMode:
+            cursor = Qt::IBeamCursor;
             break;
 
           case ZoomInMode:
-            w->setCursor (QPixmap (":/images/zoom-in.png"));
+            cursor = QCursor (octave::resource_manager::icon ("figure-zoom-in")
+                              .pixmap (22, 22), 9, 9);
             break;
 
           case ZoomOutMode:
-            w->setCursor (QPixmap (":/images/zoom-out.png"));
+            cursor = QCursor (octave::resource_manager::icon ("figure-zoom-out")
+                              .pixmap (22, 22), 9, 9);
             break;
 
           default:
-            w->setCursor (origCursor);
+            cursor = Qt::ArrowCursor;
             break;
           }
+        w->setCursor (cursor);
       }
   }
 
@@ -186,78 +269,14 @@
   void
   Canvas::annotation_callback (const octave_value_list& args)
   {
-    Ffeval (ovl ("annotation").append (args));
+    octave::interpreter& interp
+      = octave::__get_interpreter__ ("Canvas::annotation_callback");
+
+    interp.feval ("annotation", args);
 
     redraw ();
   }
 
-  void
-  Canvas::canvasToggleAxes (const graphics_handle& handle)
-  {
-    gh_manager::auto_lock lock;
-
-    graphics_object go = gh_manager::get_object (handle);
-
-    if (go.valid_object ())
-      {
-        figure::properties& fp = Utils::properties<figure> (go);
-
-        graphics_handle ah = fp.get_currentaxes ();
-
-        graphics_object ax = gh_manager::get_object (ah);
-
-        if (ax.valid_object ())
-          {
-            axes::properties& ap = Utils::properties<axes> (ax);
-
-            if (ap.handlevisibility_is ("on"))
-              {
-                ap.set_visible (! ap.is_visible ());
-
-                redraw (true);
-              }
-          }
-      }
-  }
-
-  void
-  Canvas::canvasToggleGrid (const graphics_handle& handle)
-  {
-    gh_manager::auto_lock lock;
-
-    graphics_object go = gh_manager::get_object (handle);
-
-    if (go.valid_object ())
-      {
-        figure::properties& fp = Utils::properties<figure> (go);
-
-        graphics_handle ah = fp.get_currentaxes ();
-
-        graphics_object ax = gh_manager::get_object (ah);
-
-        if (ax.valid_object ())
-          {
-            axes::properties& ap = Utils::properties<axes> (ax);
-
-            std::string tmp;
-
-            // If any grid is off, then turn them all on.  If they are all
-            // on, then turn them off.
-
-            std::string state = ((ap.get_xgrid () == "off"
-                                  || ap.get_ygrid () == "off"
-                                  || ap.get_zgrid () == "off")
-                                 ? "on" : "off");
-
-            ap.set_xgrid (state);
-            ap.set_ygrid (state);
-            ap.set_zgrid (state);
-
-            redraw (true);
-          }
-      }
-  }
-
   static void
   autoscale_axes (axes::properties& ap)
   {
@@ -272,32 +291,6 @@
   }
 
   void
-  Canvas::canvasAutoAxes (const graphics_handle& handle)
-  {
-    gh_manager::auto_lock lock;
-
-    graphics_object go = gh_manager::get_object (handle);
-
-    if (go.valid_object ())
-      {
-        figure::properties& fp = Utils::properties<figure> (go);
-
-        graphics_handle ah = fp.get_currentaxes ();
-
-        graphics_object ax = gh_manager::get_object (ah);
-
-        if (ax.valid_object ())
-          {
-            axes::properties& ap = Utils::properties<axes> (ax);
-
-            autoscale_axes (ap);
-
-            redraw (true);
-          }
-      }
-  }
-
-  void
   Canvas::canvasPaintEvent (void)
   {
     if (! m_redrawBlocked)
@@ -639,14 +632,15 @@
               currentObj = graphics_object ();
           }
 
-        if (axesObj)
-          {
-            if (axesObj.get_properties ().handlevisibility_is ("on")
-                && axesObj.get_properties ().get_tag () != "legend"
-                && axesObj.get_properties ().get_tag () != "colorbar")
-              Utils::properties<figure> (figObj)
-              .set_currentaxes (axesObj.get_handle ().as_octave_value ());
-          }
+        // Make selected axes current
+        bool valid_axes = axesObj.valid_object ()
+          && axesObj.get_properties ().handlevisibility_is ("on")
+          && axesObj.get_properties ().get_tag () != "legend"
+          && axesObj.get_properties ().get_tag () != "colorbar";
+
+        if (valid_axes)
+          Utils::properties<figure> (figObj)
+            .set_currentaxes (axesObj.get_handle ().as_octave_value ());
 
         Figure *fig = dynamic_cast<Figure *> (Backend::toolkitObject (figObj));
 
@@ -670,9 +664,10 @@
                 fprop.set_currentobject (Matrix ());
 
               // Update figure "selectiontype" and "currentpoint"
-              gh_manager::post_set (
-                                    figObj.get_handle (), "selectiontype",
-                                    Utils::figureSelectionType (event, isdblclick), false);
+              gh_manager::post_set (figObj.get_handle (), "selectiontype",
+                                    Utils::figureSelectionType (event,
+                                                                isdblclick),
+                                    false);
 
               updateCurrentPoint (figObj, obj, event);
 
@@ -718,7 +713,7 @@
           case RotateMode:
           case ZoomInMode:
           case ZoomOutMode:
-            if (axesObj && axesObj.get_properties ().handlevisibility_is ("on"))
+            if (valid_axes)
               {
                 bool redraw_figure = true;
 
@@ -912,6 +907,8 @@
       {
         std::string mode;
 
+        graphics_object figObj (obj.get_ancestor ("figure"));
+
         graphics_object axesObj;
 
         Matrix children = obj.get_properties ().get_children ();
@@ -937,8 +934,6 @@
           {
             MouseMode newMouseMode = NoMode;
 
-            graphics_object figObj (obj.get_ancestor ("figure"));
-
             Figure *fig = dynamic_cast<Figure *> (Backend::toolkitObject (figObj));
 
             if (fig)
@@ -1012,6 +1007,13 @@
             if (redrawFigure)
               redraw (false);
           }
+        
+        if (! figObj.get ("windowscrollwheelfcn").isempty ())
+          {
+            octave_scalar_map eventData = Utils::makeScrollEventStruct (event);
+            gh_manager::post_callback (m_handle, "windowscrollwheelfcn",
+                                       eventData);
+          }
       }
   }
 
@@ -1028,13 +1030,14 @@
             graphics_object figObj (obj.get_ancestor ("figure"));
 
             updateCurrentPoint (figObj, obj);
-          }
 
-        octave_scalar_map eventData = Utils::makeKeyEventStruct (event);
+            octave_scalar_map eventData = Utils::makeKeyEventStruct (event);
 
-        gh_manager::post_set (m_handle, "currentcharacter",
-                              eventData.getfield ("Character"), false);
-        gh_manager::post_callback (m_handle, "keypressfcn", eventData);
+            gh_manager::post_set (figObj.get_handle (), "currentcharacter",
+                                  eventData.getfield ("Character"), false);
+            gh_manager::post_callback (figObj.get_handle (), "keypressfcn",
+                                       eventData);
+          }
 
         return true;
       }
@@ -1047,8 +1050,15 @@
   {
     if (! event->isAutoRepeat () && (m_eventMask & KeyRelease))
       {
-        gh_manager::post_callback (m_handle, "keyreleasefcn",
-                                   Utils::makeKeyEventStruct (event));
+        gh_manager::auto_lock lock;
+        graphics_object obj = gh_manager::get_object (m_handle);
+
+        if (obj.valid_object ())
+          {
+            graphics_object figObj (obj.get_ancestor ("figure"));
+            gh_manager::post_callback (figObj.get_handle (), "keyreleasefcn",
+                                       Utils::makeKeyEventStruct (event));
+          }
 
         return true;
       }
--- a/libgui/graphics/Canvas.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Canvas.h	Fri Jul 12 12:14:43 2019 -0400
@@ -63,17 +63,14 @@
     void clearEventMask (int m) { m_eventMask &= (~m); }
     void setEventMask (int m) { m_eventMask = m; }
 
-    void setCursor (MouseMode mode);
+    void setCursor (MouseMode mode, std::string fallback,
+                    QImage cdata, Matrix hotspot);
 
     virtual QWidget * qWidget (void) = 0;
 
     static Canvas * create (const std::string& name, QWidget *parent,
                             const graphics_handle& handle);
 
-    virtual void toggleAxes (const graphics_handle& handle) = 0;
-    virtual void toggleGrid (const graphics_handle& handle) = 0;
-    virtual void autoAxes (const graphics_handle& handle) = 0;
-
     virtual uint8NDArray getPixels (void) { return do_getPixels (m_handle); };
 
   protected:
--- a/libgui/graphics/Figure.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Figure.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include <QAction>
 #include <QActionEvent>
-#include <QActionGroup>
 #include <QApplication>
 #include <QClipboard>
 #include <QEvent>
@@ -50,7 +49,6 @@
 #include "Container.h"
 #include "Figure.h"
 #include "FigureWindow.h"
-#include "MouseModeActionGroup.h"
 #include "QtHandlesUtils.h"
 
 #include "file-ops.h"
@@ -83,6 +81,29 @@
     return r;
   }
 
+  static QImage
+  pointer_to_qimage (const Matrix& cdata)
+  {
+    QImage retval (cdata.rows (), cdata.columns (), QImage::Format_ARGB32);
+    QColor tmp ("White");
+    QColor black ("Black");
+    QColor white ("White");
+    for (octave_idx_type ii = 0; ii < cdata.rows (); ii++)
+      for (octave_idx_type jj = 0; jj < cdata.columns (); jj++)
+        {
+          if (cdata(ii,jj) == 1.0)
+            tmp = black;
+          else if (cdata(ii,jj) == 2.0)
+            tmp = white;
+          else
+            tmp.setAlpha (0);
+
+          retval.setPixel (jj, ii, tmp.rgba ());
+        }
+
+    return retval;
+  }
+
   Figure*
   Figure::create (const graphics_object& go)
   {
@@ -92,42 +113,31 @@
   Figure::Figure (const graphics_object& go, FigureWindow *win)
     : Object (go, win), m_blockUpdates (false), m_figureToolBar (nullptr),
       m_menuBar (nullptr), m_innerRect (), m_outerRect (),
-      m_mouseModeGroup (nullptr), m_previousHeight (0), m_resizable (true)
+      m_previousHeight (0), m_resizable (true)
   {
     m_container = new Container (win);
     win->setCentralWidget (m_container);
 
     figure::properties& fp = properties<figure> ();
 
-    // Register for the signal that indicates when a window has moved
-    // to a different screen
-    connect (win, SIGNAL (figureWindowShown ()),
-             this, SLOT (figureWindowShown ()));
+    // Adjust figure position
+    m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
+    m_outerRect = boundingBoxToRect (fp.get_boundingbox (false));
+
+    set_geometry (m_innerRect);
+
+    // Menubar
+    m_menuBar = new MenuBar (win);
+    win->setMenuBar (m_menuBar);
+    m_menuBar->addReceiver (this);
 
     // Status bar
     m_statusBar = win->statusBar ();
-    int boffset = 0;
-
-    // Toolbar and menubar
-    createFigureToolBarAndMenuBar ();
-    int toffset = 0;
+    m_statusBar->setVisible (false);
 
     if (fp.toolbar_is ("figure")
         || (fp.toolbar_is ("auto") && fp.menubar_is ("figure")))
-      {
-        toffset += m_figureToolBar->sizeHint ().height ();
-        boffset += m_statusBar->sizeHint ().height ();
-      }
-    else
-      {
-        m_figureToolBar->hide ();
-        m_statusBar->hide ();
-      }
-
-    m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
-    m_outerRect = boundingBoxToRect (fp.get_boundingbox (false));
-
-    set_geometry (m_innerRect.adjusted (0, -toffset, 0, boffset));
+      showFigureStatusBar (true);
 
     // Enable mouse tracking unconditionally
     enableMouseTracking ();
@@ -149,12 +159,20 @@
     // Handle resizing constraints
     update (figure::properties::ID_RESIZE);
 
+    // Custom pointer data
+    update (figure::properties::ID_POINTERSHAPECDATA);
+
     // Visibility
     update (figure::properties::ID_VISIBLE);
 
     connect (this, SIGNAL (asyncUpdate (void)),
              this, SLOT (updateContainer (void)));
 
+    // Register for the signal that indicates when a window has moved
+    // to a different screen
+    connect (win, SIGNAL (figureWindowShown ()),
+             this, SLOT (figureWindowShown ()));
+
     win->addReceiver (this);
     m_container->addReceiver (this);
   }
@@ -162,55 +180,6 @@
   Figure::~Figure (void)
   { }
 
-  static std::string
-  mouse_mode_to_string (MouseMode mode)
-  {
-    switch (mode)
-      {
-      case NoMode:
-        return "none";
-
-      case RotateMode:
-        return "rotate";
-
-      case ZoomInMode:
-        return "zoom in";
-
-      case ZoomOutMode:
-        return "zoom out";
-
-      case PanMode:
-        return "pan";
-
-      case TextMode:
-        return "text";
-
-      default:
-        break;
-      }
-
-    return "none";
-  }
-
-  static MouseMode
-  mouse_mode_from_string (const std::string& mode)
-  {
-    if (mode == "none")
-      return NoMode;
-    else if (mode == "rotate")
-      return RotateMode;
-    else if (mode == "zoom in")
-      return ZoomInMode;
-    else if (mode == "zoom out")
-      return ZoomOutMode;
-    else if (mode == "pan")
-      return PanMode;
-    else if (mode == "text")
-      return TextMode;
-    else
-      return NoMode;
-  }
-
   QString
   Figure::fileName (void)
   {
@@ -251,49 +220,18 @@
         mode += ' ' + direction;
       }
 
-    return mouse_mode_from_string (mode);
-  }
-
-  void
-  Figure::createFigureToolBarAndMenuBar (void)
-  {
-    QMainWindow *win = qWidget<QMainWindow> ();
-
-    m_figureToolBar = win->addToolBar (tr ("Figure ToolBar"));
-    m_figureToolBar->setMovable (false);
-    m_figureToolBar->setFloatable (false);
-
-    m_mouseModeGroup = new MouseModeActionGroup (win);
-    connect (m_mouseModeGroup, SIGNAL (modeChanged (MouseMode)),
-             SLOT (setMouseMode (MouseMode)));
-    m_figureToolBar->addActions (m_mouseModeGroup->actions ());
-
-    QAction *toggle_axes = m_figureToolBar->addAction (tr ("Axes"));
-    connect (toggle_axes, SIGNAL (triggered (void)),
-             this, SLOT (toggleAxes (void)));
+    if (mode == "rotate")
+      return RotateMode;
+    else if (mode == "zoom in")
+      return ZoomInMode;
+    else if (mode == "zoom out")
+      return ZoomOutMode;
+    else if (mode == "pan")
+      return PanMode;
+    else if (mode == "text")
+      return TextMode;
 
-    QAction *toggle_grid = m_figureToolBar->addAction (tr ("Grid"));
-    connect (toggle_grid, SIGNAL (triggered (void)),
-             this, SLOT (toggleGrid (void)));
-
-    QAction *auto_axes = m_figureToolBar->addAction (tr ("Autoscale"));
-    connect (auto_axes, SIGNAL (triggered (void)),
-             this, SLOT (autoAxes (void)));
-
-    m_menuBar = new MenuBar (win);
-    win->setMenuBar (m_menuBar);
-    m_menuBar->addReceiver (this);
-  }
-
-  void
-  Figure::updateFigureToolBarAndMenuBar (void)
-  {
-    if (m_mouseModeGroup)
-      {
-        m_blockUpdates = true;
-        m_mouseModeGroup->setMode (mouseMode ());
-        m_blockUpdates = false;
-      }
+    return NoMode;
   }
 
   void
@@ -307,6 +245,11 @@
         win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
       }
 
+    // Unlock window if it is maximized or full-screen
+    int state = win->windowState ();
+    if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized)
+      win->setWindowState (Qt::WindowNoState);
+
     win->setGeometry (r);
 
     if (! m_resizable)
@@ -330,20 +273,20 @@
     if (canvas)
       canvas->redraw ();
 
-    foreach (QFrame *frame,
-             qWidget<QWidget> ()->findChildren<QFrame*> ())
+    foreach (QObject *qobj,
+             qWidget<QWidget> ()->findChildren<QObject*> ())
       {
-        if (frame->objectName () == "UIPanel"
-            || frame->objectName () == "UIButtonGroup")
+        if (qobj->objectName () == "UIPanel"
+            || qobj->objectName () == "UIButtonGroup"
+            || qobj->objectName () == "UIControl"
+            || qobj->objectName () == "UITable")
           {
-            Object *obj = Object::fromQObject (frame);
+            Object *obj = Object::fromQObject (qobj);
 
             if (obj)
               obj->slotRedraw ();
           }
       }
-
-    updateFigureToolBarAndMenuBar ();
   }
 
   void
@@ -388,7 +331,6 @@
     if (canvas)
       canvas->blockRedraw (true);
 
-    m_menuBar->removeReceiver (this);
     m_container->removeReceiver (this);
     qWidget<FigureWindow> ()->removeReceiver (this);
   }
@@ -468,18 +410,14 @@
           }
         break;
 
+      case figure::properties::ID_MENUBAR:
       case figure::properties::ID_TOOLBAR:
         if (fp.toolbar_is ("none"))
-          showFigureToolBar (false);
+          showFigureStatusBar (false);
         else if (fp.toolbar_is ("figure"))
-          showFigureToolBar (true);
+          showFigureStatusBar (true);
         else  // "auto"
-          showFigureToolBar (fp.menubar_is ("figure"));
-        break;
-
-      case figure::properties::ID_MENUBAR:
-        if (fp.toolbar_is ("auto"))
-          showFigureToolBar (fp.menubar_is ("figure"));
+          showFigureStatusBar (fp.menubar_is ("figure"));
         break;
 
       case figure::properties::ID_KEYPRESSFCN:
@@ -487,6 +425,25 @@
           m_container->canvas (m_handle)->clearEventMask (Canvas::KeyPress);
         else
           m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress);
+        // Signal the change to uipanels as well
+        foreach (QObject *qobj,
+                 qWidget<QWidget> ()->findChildren<QObject*> ())
+          {
+            if (qobj->objectName () == "UIPanel")
+              {
+                Object *obj = Object::fromQObject (qobj);
+
+                if (obj)
+                  {
+                    if (fp.get_keypressfcn ().isempty ())
+                      obj->innerContainer ()->canvas (m_handle)->
+                        clearEventMask (Canvas::KeyPress);
+                    else
+                      obj->innerContainer ()->canvas (m_handle)->
+                        addEventMask (Canvas::KeyPress);
+                  }
+              }
+          }
         break;
 
       case figure::properties::ID_KEYRELEASEFCN:
@@ -495,6 +452,26 @@
         else
           m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease);
         break;
+        // Signal the change to uipanels as well
+        foreach (QObject *qobj,
+                 qWidget<QWidget> ()->findChildren<QObject*> ())
+          {
+            if (qobj->objectName () == "UIPanel")
+              {
+                Object *obj = Object::fromQObject (qobj);
+
+                if (obj)
+                  {
+                    if (fp.get_keypressfcn ().isempty ())
+                      obj->innerContainer ()->canvas (m_handle)->
+                        clearEventMask (Canvas::KeyRelease);
+                    else
+                      obj->innerContainer ()->canvas (m_handle)->
+                        addEventMask (Canvas::KeyRelease);
+                  }
+              }
+          }
+        break;
 
       case figure::properties::ID_WINDOWSTYLE:
         if (fp.windowstyle_is ("modal"))
@@ -514,8 +491,22 @@
 
         break;
 
+      case figure::properties::ID_POINTERSHAPECDATA:
+        m_pointer_cdata =
+          pointer_to_qimage (fp.get_pointershapecdata ().matrix_value ());
+        if (fp.get_pointer () != "custom")
+          break;
+        OCTAVE_FALLTHROUGH;
+
+      case figure::properties::ID_POINTER:
+      case figure::properties::ID_POINTERSHAPEHOTSPOT:
       case figure::properties::ID___MOUSE_MODE__:
-        m_container->canvas (m_handle)->setCursor (mouseMode ());
+      case figure::properties::ID___ZOOM_MODE__:
+        m_container->canvas (m_handle)->setCursor (mouseMode (),
+                                                   fp.get_pointer (),
+                                                   m_pointer_cdata,
+                                                   fp.get_pointershapehotspot ()
+                                                   .matrix_value());
         break;
 
       default:
@@ -526,22 +517,21 @@
   }
 
   void
-  Figure::showFigureToolBar (bool visible)
+  Figure::showFigureStatusBar (bool visible)
   {
-    if ((! m_figureToolBar->isHidden ()) != visible)
+    if (m_statusBar
+        && (! m_statusBar->isHidden ()) != visible)
       {
-        int dy1 = m_figureToolBar->sizeHint ().height ();
-        int dy2 = m_statusBar->sizeHint ().height ();
+        int dy = m_statusBar->sizeHint ().height ();
         QRect r = qWidget<QWidget> ()->geometry ();
 
         if (! visible)
-          r.adjust (0, dy1, 0, -dy2);
+          r.adjust (0, 0, 0, -dy);
         else
-          r.adjust (0, -dy1, 0, dy2);
+          r.adjust (0, 0, 0, dy);
 
         m_blockUpdates = true;
         set_geometry (r);
-        m_figureToolBar->setVisible (visible);
         m_statusBar->setVisible (visible);
         m_blockUpdates = false;
 
@@ -584,14 +574,6 @@
     return qWidget<QMainWindow> ()->menuBar ();
   }
 
-  struct UpdateBoundingBoxData
-  {
-    Matrix m_bbox;
-    bool m_internal;
-    graphics_handle m_handle;
-    Figure *m_figure;
-  };
-
   void
   Figure::updateBoundingBox (bool internal, int flags)
   {
@@ -779,35 +761,19 @@
   }
 
   void
-  Figure::setMouseMode (MouseMode mode)
-  {
-    if (m_blockUpdates)
-      return;
-
-    gh_manager::auto_lock lock;
-
-    figure::properties& fp = properties<figure> ();
-
-    fp.set___mouse_mode__ (mouse_mode_to_string (mode));
-
-    Canvas *canvas = m_container->canvas (m_handle);
-
-    if (canvas)
-      canvas->setCursor (mode);
-  }
-
-  void
-  Figure::addCustomToolBar (QToolBar *bar, bool visible)
+  Figure::addCustomToolBar (QToolBar *bar, bool visible, bool isdefault)
   {
     QMainWindow *win = qWidget<QMainWindow> ();
 
+    if (isdefault)
+      m_figureToolBar = bar;
+
     if (! visible)
       win->addToolBar (bar);
     else
       {
         QSize sz = bar->sizeHint ();
         QRect r = win->geometry ();
-        //qDebug () << "Figure::addCustomToolBar:" << r;
 
         r.adjust (0, -sz.height (), 0, 0);
 
@@ -817,7 +783,6 @@
         win->addToolBar (bar);
         m_blockUpdates = false;
 
-        //qDebug () << "Figure::addCustomToolBar:" << win->geometry ();
         updateBoundingBox (false);
       }
   }
@@ -853,33 +818,6 @@
   }
 
   void
-  Figure::toggleAxes (void)
-  {
-    Canvas *canvas = m_container->canvas (m_handle);
-
-    if (canvas)
-      canvas->toggleAxes (m_handle);
-  }
-
-  void
-  Figure::toggleGrid (void)
-  {
-    Canvas *canvas = m_container->canvas (m_handle);
-
-    if (canvas)
-      canvas->toggleGrid (m_handle);
-  }
-
-  void
-  Figure::autoAxes (void)
-  {
-    Canvas *canvas = m_container->canvas (m_handle);
-
-    if (canvas)
-      canvas->autoAxes (m_handle);
-  }
-
-  void
   Figure::figureWindowShown ()
   {
 #if defined (HAVE_QSCREEN_DEVICEPIXELRATIO)
--- a/libgui/graphics/Figure.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Figure.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,15 +39,13 @@
 
   enum MouseMode
   {
-    // NOTE: These values must match the order of the buttons in the
-    // MouseModeActionGroup object.
-
-    NoMode      = 0,
-    RotateMode  = 1,
-    ZoomInMode  = 2,
-    ZoomOutMode = 3,
-    PanMode     = 4,
-    TextMode    = 5
+    NoMode,
+    RotateMode,
+    ZoomInMode,
+    ZoomOutMode,
+    PanMode,
+    SelectMode,
+    TextMode
   };
 
   class Container;
@@ -55,8 +53,6 @@
   class MenuBar;
   class ToolBar;
 
-  class MouseModeActionGroup;
-
   class Figure :
   public Object,
   public MenuContainer,
@@ -101,22 +97,16 @@
     void beingDeleted (void);
 
   private:
-    void createFigureToolBarAndMenuBar (void);
-    void showFigureToolBar (bool visible);
-    void addCustomToolBar (QToolBar *bar, bool visible);
+    void showFigureStatusBar (bool visible);
+    void addCustomToolBar (QToolBar *bar, bool visible, bool isdefault);
     void showCustomToolBar (QToolBar *bar, bool visible);
-    void updateFigureToolBarAndMenuBar (void);
     void set_geometry (QRect r);
 
     void enableMouseTracking (void);
 
   private slots:
-    void setMouseMode (MouseMode mode);
     void updateFigureHeight (int delta_h);
     void updateContainer (void);
-    void toggleAxes (void);
-    void toggleGrid (void);
-    void autoAxes (void);
     void figureWindowShown ();
     void screenChanged (QScreen*);
 
@@ -134,7 +124,7 @@
     QStatusBar *m_statusBar;
     QRect m_innerRect;
     QRect m_outerRect;
-    MouseModeActionGroup *m_mouseModeGroup;
+    QImage m_pointer_cdata;
     int m_previousHeight;
     bool m_resizable;
   };
--- a/libgui/graphics/GLCanvas.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/GLCanvas.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -147,7 +147,6 @@
 
         try
           {
-#if defined (Q_OS_MAC)
             if (fig.get ("visible").string_value () == "on")
               octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
                                    term.toStdString ());
@@ -171,10 +170,6 @@
 
                 fbo.release ();
               }
-#else
-            octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
-                                 term.toStdString ());
-#endif
           }
         catch (octave::execution_exception& e)
           {
@@ -185,24 +180,6 @@
       }
   }
 
-  void
-  GLCanvas::toggleAxes (const graphics_handle& gh)
-  {
-    canvasToggleAxes (gh);
-  }
-
-  void
-  GLCanvas::toggleGrid (const graphics_handle& gh)
-  {
-    canvasToggleGrid (gh);
-  }
-
-  void
-  GLCanvas::autoAxes (const graphics_handle& gh)
-  {
-    canvasAutoAxes (gh);
-  }
-
   graphics_object
   GLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt)
   {
--- a/libgui/graphics/GLCanvas.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/GLCanvas.h	Fri Jul 12 12:14:43 2019 -0400
@@ -60,9 +60,6 @@
     uint8NDArray  do_getPixels (const graphics_handle& handle);
     void do_print (const QString& file_cmd, const QString& term,
                    const graphics_handle& handle);
-    void toggleAxes (const graphics_handle& handle);
-    void toggleGrid (const graphics_handle& handle);
-    void autoAxes (const graphics_handle& handle);
     void drawZoomBox (const QPoint& p1, const QPoint& p2);
     void resize (int /* x */, int /* y */,
                  int /* width */, int /* height */) { }
--- a/libgui/graphics/MouseModeActionGroup.cc	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
-
-Copyright (C) 2011-2019 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <QAction>
-#include <QIcon>
-
-#include "Figure.h"
-#include "MouseModeActionGroup.h"
-
-namespace QtHandles
-{
-
-  MouseModeActionGroup::MouseModeActionGroup (QObject *xparent)
-    : QObject (xparent), m_current (nullptr)
-  {
-    m_actions.append (new QAction (QIcon (":/images/rotate.png"),
-                                   tr ("Rotate"), this));
-    QAction *zoom_in = new QAction ("Z+", this);
-    zoom_in->setToolTip (tr ("Zoom In"));
-    m_actions.append (zoom_in);
-
-    QAction *zoom_out = new QAction ("Z-", this);
-    zoom_out->setToolTip (tr ("Zoom Out"));
-    m_actions.append (zoom_out);
-
-    m_actions.append (new QAction (QIcon (":/images/pan.png"),
-                                   tr ("Pan"), this));
-    m_actions.append (new QAction (QIcon::fromTheme ("insert-text"),
-                                   tr ("Insert Text"), this));
-    /*
-    // FIXME: Re-instate this button when the plotedit function
-    //        has been implemented.
-    m_actions.append (new QAction (QIcon (":/images/select.png"),
-                                   tr ("Select"), this));
-    */
-
-    foreach (QAction *a, m_actions)
-      {
-        a->setCheckable (true);
-        connect (a, SIGNAL (toggled (bool)), this, SLOT (actionToggled (bool)));
-      }
-  }
-
-  MouseModeActionGroup::~MouseModeActionGroup (void)
-  { }
-
-  void
-  MouseModeActionGroup::actionToggled (bool checked)
-  {
-    if (! checked)
-      {
-        if (sender () == m_current)
-          {
-            m_current = nullptr;
-            emit modeChanged (NoMode);
-          }
-      }
-    else
-      {
-        int i = m_actions.indexOf (qobject_cast<QAction *> (sender ()));
-
-        if (i >= 0)
-          {
-            m_current = m_actions[i];
-            for (int j = 0; j < m_actions.size (); j++)
-              {
-                if (j != i)
-                  m_actions[j]->setChecked (false);
-              }
-
-            emit modeChanged (static_cast<MouseMode> (i+1));
-          }
-      }
-  }
-
-  void
-  MouseModeActionGroup::setMode (MouseMode mode)
-  {
-    for (int i = 0; i < m_actions.size (); i++)
-      m_actions[i]->setChecked (i+1 == mode);
-  }
-
-};
--- a/libgui/graphics/MouseModeActionGroup.h	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
-
-Copyright (C) 2011-2019 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_MouseModeActionGroup_h)
-#define octave_MouseModeActionGroup_h 1
-
-#include <QList>
-#include <QObject>
-
-#include "Figure.h"
-
-class QAction;
-
-namespace QtHandles
-{
-
-  class MouseModeActionGroup : public QObject
-  {
-    Q_OBJECT
-
-  public:
-    MouseModeActionGroup (QObject *parent = nullptr);
-    ~MouseModeActionGroup (void);
-
-    QList<QAction*> actions (void) const { return m_actions; }
-
-    void setMode (MouseMode mode);
-
-  signals:
-    void modeChanged (MouseMode mode);
-
-  private slots:
-    void actionToggled (bool checked);
-
-  private:
-    QList<QAction*> m_actions;
-    QAction *m_current;
-  };
-
-};
-
-#endif
--- a/libgui/graphics/ObjectFactory.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/ObjectFactory.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -138,7 +138,7 @@
                 else if (go.isa ("uitoggletool"))
                   obj = ToggleTool::create (go);
                 else
-                  qWarning ("ObjectFactory::createObject: unsupported type `%s'",
+                  qWarning ("ObjectFactory::createObject: unsupported type '%s'",
                             go.type ().c_str ());
 
                 if (obj)
--- a/libgui/graphics/Panel.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Panel.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -138,6 +138,13 @@
 
     frame->installEventFilter (this);
     m_container->installEventFilter (this);
+    
+    graphics_object fig (go.get_ancestor ("figure"));
+    if (! fig.get ("keypressfcn").isempty ())
+      m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress);
+    
+    if (! fig.get ("keyreleasefcn").isempty ())
+      m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease);
 
     if (pp.is_visible ())
       QTimer::singleShot (0, frame, SLOT (show (void)));
@@ -337,6 +344,8 @@
   void
   Panel::redraw (void)
   {
+    update (uipanel::properties::ID_POSITION);
+
     Canvas *canvas = m_container->canvas (m_handle);
 
     if (canvas)
--- a/libgui/graphics/QtHandlesUtils.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/QtHandlesUtils.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -113,8 +113,6 @@
       if (! mapsInitialized)
         {
           weightMap["normal"] = QFont::Normal;
-          weightMap["light"] = QFont::Light;
-          weightMap["demi"] = QFont::DemiBold;
           weightMap["bold"] = QFont::Bold;
 
           angleMap["normal"] = QFont::StyleNormal;
@@ -186,13 +184,9 @@
                 return "normal";
               else if (buttons == Qt::RightButton)
                 return "alt";
-#if defined (Q_WS_WIN)
-              else if (buttons == (Qt::LeftButton | Qt::RightButton))
+              else if (buttons == Qt::MidButton
+                       || buttons == (Qt::LeftButton | Qt::RightButton))
                 return "extend";
-#elif defined (Q_WS_X11)
-              else if (buttons == Qt::MidButton)
-                return "extend";
-#endif
             }
           else if (buttons == Qt::LeftButton)
             {
@@ -390,6 +384,29 @@
       return retval;
     }
 
+    octave_scalar_map
+    makeScrollEventStruct (QWheelEvent *event)
+    {
+      octave_scalar_map retval;
+
+      // We assume a standard mouse with 15 degree steps and Qt returns
+      // 1/8 of a degree.
+#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
+      int ydelta = -(event->angleDelta().y ());
+#else
+      int ydelta = (event->orientation () == Qt::Vertical
+                    ? -(event->delta ()) : 0);
+#endif
+      retval.setfield ("VerticalScrollCount", octave_value (ydelta / 120));
+
+      // FIXME: Is there any way to access the number of lines a scroll step
+      // should correspond to?
+      retval.setfield ("VerticalScrollAmount", octave_value (3));
+      retval.setfield ("EventName", octave_value ("WindowScrollWheel"));
+
+      return retval;
+    }
+
   }
 
 }
--- a/libgui/graphics/QtHandlesUtils.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/QtHandlesUtils.h	Fri Jul 12 12:14:43 2019 -0400
@@ -35,6 +35,7 @@
 
 class QKeyEvent;
 class QMouseEvent;
+class QWheelEvent;
 
 namespace QtHandles
 {
@@ -78,6 +79,7 @@
                                int height = -1);
 
     octave_scalar_map makeKeyEventStruct (QKeyEvent *event);
+    octave_scalar_map makeScrollEventStruct (QWheelEvent *event);
   }
 
 }
--- a/libgui/graphics/Table.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Table.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -442,6 +442,7 @@
     : Object (go, tableWidget), m_tableWidget (tableWidget), m_curData (),
       m_blockUpdates (false)
   {
+    qObject ()->setObjectName ("UItable");
     uitable::properties& tp = properties<uitable> ();
 
     m_curData = octave_value (tp.get_data ());
@@ -863,6 +864,12 @@
   }
 
   void
+  Table::redraw (void)
+  {
+    update (uitable::properties::ID_POSITION);
+  }
+
+  void
   Table::update (int pId)
   {
     uitable::properties& tp = properties<uitable> ();
--- a/libgui/graphics/Table.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/Table.h	Fri Jul 12 12:14:43 2019 -0400
@@ -50,7 +50,7 @@
 
   protected:
     void update (int pId);
-    //void redraw (void);
+    void redraw (void);
     void updateColumnname (void);
     void updateColumnwidth (void);
     void updateData (void);
--- a/libgui/graphics/ToolBar.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/ToolBar.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -94,7 +94,8 @@
       dynamic_cast<Figure *> (Object::fromQObject (bar->parentWidget ()));
 
     if (m_figure)
-      m_figure->addCustomToolBar (bar, tp.is_visible ());
+      m_figure->addCustomToolBar (bar, tp.is_visible (),
+                                  tp.get_tag () == "__default_toolbar__");
 
     bar->installEventFilter (this);
   }
--- a/libgui/graphics/ToolBarButton.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/ToolBarButton.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,6 +29,7 @@
 
 #include "ToolBarButton.h"
 #include "QtHandlesUtils.h"
+#include "resource-manager.h"
 
 namespace QtHandles
 {
@@ -41,8 +42,22 @@
 
     action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));
     action->setVisible (tp.is_visible ());
-    QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
-    action->setIcon (QIcon (QPixmap::fromImage (img)));
+
+    // Get the icon data from cdata or as a named icon
+    QImage img = Utils::makeImageFromCData (tp.get_cdata (), 32, 32);
+
+    if (img.width () == 0)
+      {
+        QIcon ico;
+        std::string name = tp.get___named_icon__ ();
+        if (! name.empty ())
+          ico = octave::resource_manager::icon (QString::fromStdString (name));
+
+        action->setIcon (ico);
+      }
+    else
+      action->setIcon (QIcon (QPixmap::fromImage (img)));
+
     if (tp.is_separator ())
       {
         m_separator = new QAction (action);
@@ -83,9 +98,19 @@
 
       case T::properties::ID_CDATA:
         {
-          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
+          // Get the icon data from cdata or as a named icon
+          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 32, 32);
 
-          action->setIcon (QIcon (QPixmap::fromImage (img)));
+          if (img.width () == 0)
+            {
+              QIcon ico;
+              std::string name = tp.get___named_icon__ ();
+              if (! name.empty ())
+                ico = octave::resource_manager::icon (QString::fromStdString (name));
+              action->setIcon (ico);
+            }
+          else
+            action->setIcon (QIcon (QPixmap::fromImage (img)));
         }
         break;
 
--- a/libgui/graphics/images/README	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-This copyright and license notice covers the images in this directory.
-************************************************************************
-
-TITLE:	Crystal Project Icons
-AUTHOR:	Everaldo Coelho
-SITE:	http://www.everaldo.com
-CONTACT: everaldo@everaldo.com
-
-Copyright (c)  2006-2007  Everaldo Coelho.
-
-The following images are derivative work:
-
-zoom-in.png
-zoom-out.png
Binary file libgui/graphics/images/pan.png has changed
Binary file libgui/graphics/images/rotate.png has changed
Binary file libgui/graphics/images/select.png has changed
Binary file libgui/graphics/images/zoom-in.png has changed
Binary file libgui/graphics/images/zoom-out.png has changed
--- a/libgui/graphics/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/graphics/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -13,7 +13,6 @@
   %reldir%/moc-FigureWindow.cc \
   %reldir%/moc-ListBoxControl.cc \
   %reldir%/moc-Menu.cc \
-  %reldir%/moc-MouseModeActionGroup.cc \
   %reldir%/moc-Object.cc \
   %reldir%/moc-ObjectFactory.cc \
   %reldir%/moc-ObjectProxy.cc \
@@ -42,10 +41,6 @@
 
 BUILT_SOURCES += $(__init_qt___UI_H)
 
-__init_qt___RC = %reldir%/qrc-qthandles.cc
-
-$(__init_qt___RC): | %reldir%/$(octave_dirstamp)
-
 noinst_HEADERS += \
   %reldir%/__init_qt__.h \
   %reldir%/annotation-dialog.h \
@@ -67,7 +62,6 @@
   %reldir%/Logger.h \
   %reldir%/Menu.h \
   %reldir%/MenuContainer.h \
-  %reldir%/MouseModeActionGroup.h \
   %reldir%/Object.h \
   %reldir%/ObjectFactory.h \
   %reldir%/ObjectProxy.h \
@@ -108,7 +102,6 @@
   %reldir%/ListBoxControl.cc \
   %reldir%/Logger.cc \
   %reldir%/Menu.cc \
-  %reldir%/MouseModeActionGroup.cc \
   %reldir%/Object.cc \
   %reldir%/ObjectFactory.cc \
   %reldir%/ObjectProxy.cc \
@@ -130,7 +123,7 @@
 TEMPLATE_SRC = \
   %reldir%/ToolBarButton.cc
 
-nodist_%canon_reldir%___init_qt___la_SOURCES = $(__init_qt___MOC) $(__init_qt___RC)
+nodist_%canon_reldir%___init_qt___la_SOURCES = $(__init_qt___MOC)
 
 %canon_reldir%___init_qt___la_CPPFLAGS = \
   $(AM_CPPFLAGS) \
@@ -195,20 +188,12 @@
   $(GRAPHICS_PKG_ADD_FILE)
 
 libgui_EXTRA_DIST += \
-  %reldir%/qthandles.qrc \
-  %reldir%/images/README \
-  %reldir%/images/pan.png \
-  %reldir%/images/rotate.png \
-  %reldir%/images/select.png \
-  %reldir%/images/zoom-in.png \
-  %reldir%/images/zoom-out.png \
   $(__init_qt___UI)
 
 libgui_CLEANFILES += \
   $(GRAPHICS_OCT_FILES) \
   $(GRAPHICS_PKG_ADD_FILE) \
   $(__init_qt___MOC) \
-  $(__init_qt___RC) \
   $(__init_qt___UI_H)
 
 endif
--- a/libgui/graphics/qthandles.qrc	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
-  <file>images/pan.png</file>
-  <file>images/rotate.png</file>
-  <file>images/select.png</file>
-  <file>images/zoom-in.png</file>
-  <file>images/zoom-out.png</file>
-</qresource>
-</RCC>
--- a/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslator.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslator.h	Fri Jul 12 12:14:43 2019 -0400
@@ -9,10 +9,10 @@
 "key Return-Shift+NewLine : \"\\r\\n\"\n"
 "key Return+Shift         : \"\\EOM\"\n"
 "key Backspace      : \"\\x7f\"\n"
-"key Up   -Shift-Ansi : \"\\EA\"\n"
-"key Down -Shift-Ansi : \"\\EB\"\n"
-"key Right-Shift-Ansi : \"\\EC\"\n"
-"key Left -Shift-Ansi : \"\\ED\"\n"
+"key Up    -Shift-Ansi : \"\\EA\"\n"
+"key Down  -Shift-Ansi : \"\\EB\"\n"
+"key Right -Shift-Ansi : \"\\EC\"\n"
+"key Left  -Shift-Ansi : \"\\ED\"\n"
 "key Up    -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOA\"\n"
 "key Down  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOB\"\n"
 "key Right -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOC\"\n"
@@ -27,10 +27,10 @@
 "key Left  -Shift+AnyMod+Ansi                     : \"\\E[1;*D\"\n"
 "key Enter+NewLine : \"\\r\\n\"\n"
 "key Enter-NewLine : \"\\r\"\n"
-"key Home        -AnyMod     -AppCuKeys           : \"\\E[H\"  \n"
-"key End         -AnyMod     -AppCuKeys           : \"\\E[F\"  \n"
-"key Home        -AnyMod     +AppCuKeys           : \"\\EOH\"  \n"
-"key End         -AnyMod     +AppCuKeys           : \"\\EOF\"  \n"
+"key Home        -AnyMod     -AppCuKeys           : \"\\E[H\"\n"
+"key End         -AnyMod     -AppCuKeys           : \"\\E[F\"\n"
+"key Home        -AnyMod     +AppCuKeys           : \"\\EOH\"\n"
+"key End         -AnyMod     +AppCuKeys           : \"\\EOF\"\n"
 "key Home        +AnyMod                          : \"\\E[1;*H\"\n"
 "key End         +AnyMod                          : \"\\E[1;*F\"\n"
 "key Insert      -AnyMod                          : \"\\E[2~\"\n"
@@ -65,10 +65,10 @@
 "key F10         +AnyMod                          : \"\\E[21;*~\"\n"
 "key F11         +AnyMod                          : \"\\E[23;*~\"\n"
 "key F12         +AnyMod                          : \"\\E[24;*~\"\n"
-"key Space +Control : \"\\x00\"\n"
+"key Space +Control          : \"\\x00\"\n"
 "key Up    +Shift-AppScreen  : scrollLineUp\n"
 "key Prior +Shift-AppScreen  : scrollPageUp\n"
 "key Down  +Shift-AppScreen  : scrollLineDown\n"
 "key Next  +Shift-AppScreen  : scrollPageDown\n"
-"key ScrollLock     : scrollLock\n"
+"key ScrollLock              : scrollLock\n"
 "\0"
--- a/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslatorMac.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslatorMac.h	Fri Jul 12 12:14:43 2019 -0400
@@ -1,53 +1,53 @@
 "keyboard \"Default (XFree 4)\""
-"key Escape : \"\\x1b\""
-"key Tab -Shift : \"\\t\"\n"
-"key Tab +Shift+Ansi : \"\\E[Z\"\n"
-"key Tab +Shift-Ansi : \"\\t\"\n"
-"key Backtab +Ansi : \"\\E[Z\"\n"
-"key Backtab -Ansi : \"\\t\"\n"
+"key Escape             : \"\\x1b\""
+"key Tab   -Shift       : \"\\t\"\n"
+"key Tab   +Shift+Ansi  : \"\\E[Z\"\n"
+"key Tab   +Shift-Ansi  : \"\\t\"\n"
+"key Backtab     +Ansi  : \"\\E[Z\"\n"
+"key Backtab     -Ansi  : \"\\t\"\n"
 "key Return-Shift-NewLine : \"\\r\"\n"
 "key Return-Shift+NewLine : \"\\r\\n\"\n"
-"key Return+Shift : \"\\EOM\"\n"
-"key Backspace : \"\\x7f\"\n"
-"key Meta +C: \"\\x03\"\n"
-"key Up -Shift+Ansi-AppCuKeys : \"\\E[A\"\n"
-"key Down -Shift+Ansi-AppCuKeys : \"\\E[B\"\n"
-"key Right-Shift+Ansi-AppCuKeys : \"\\E[C\"\n"
-"key Left -Shift+Ansi-AppCuKeys : \"\\E[D\"\n"
-"key Up -Ansi : \"\\E[1;*A\"\n"
-"key Down -Ansi : \"\\E[1;*B\"\n"
-"key Right -Ansi : \"\\E[1;*C\"\n"
-"key Left -Ansi : \"\\E[1;*D\"\n"
+"key Return+Shift         : \"\\EOM\"\n"
+"key Backspace      : \"\\x7f\"\n"
+"key Meta +C        : \"\\x03\"\n"
+"key Up    -Shift+Ansi-AppCuKeys : \"\\E[A\"\n"
+"key Down  -Shift+Ansi-AppCuKeys : \"\\E[B\"\n"
+"key Right -Shift+Ansi-AppCuKeys : \"\\E[C\"\n"
+"key Left  -Shift+Ansi-AppCuKeys : \"\\E[D\"\n"
+"key Up          -Ansi                            : \"\\E[1;*A\"\n"
+"key Down        -Ansi                            : \"\\E[1;*B\"\n"
+"key Right       -Ansi                            : \"\\E[1;*C\"\n"
+"key Left        -Ansi                            : \"\\E[1;*D\"\n"
 "key Enter+NewLine : \"\\r\\n\"\n"
 "key Enter-NewLine : \"\\r\"\n"
-"key Home -AnyMod -AppCuKeys : \"\\E[H\"\n"
-"key End -AnyMod -AppCuKeys : \"\\E[F\"\n"
-"key Home -AnyMod +AppCuKeys : \"\\EOH\"\n"
-"key End -AnyMod +AppCuKeys : \"\\EOF\"\n"
-"key Home +AnyMod : \"\\E[1;*H\"\n"
-"key End +AnyMod : \"\\E[1;*F\"\n"
-"key Insert -AnyMod : \"\\E[2~\"\n"
-"key Delete -AnyMod : \"\\E[3~\"\n"
-"key Insert +AnyMod : \"\\E[2;*~\"\n"
-"key Delete +AnyMod : \"\\E[3;*~\"\n"
-"key Prior -Shift-AnyMod : \"\\E[5~\"\n"
-"key Next -Shift-AnyMod : \"\\E[6~\"\n"
-"key Prior -Shift+AnyMod : \"\\E[5;*~\"\n"
-"key Next -Shift+AnyMod : \"\\E[6;*~\"\n"
-"key F1 -AnyMod : \"\\EOP\"\n"
-"key F2 -AnyMod : \"\\EOQ\"\n"
-"key F3 -AnyMod : \"\\EOR\"\n"
-"key F4 -AnyMod : \"\\EOS\"\n"
-"key F5 -AnyMod : \"\\EOT\"\n"
-"key F6 -AnyMod : \"\\EOU\"\n"
-"key F7 -AnyMod : \"\\EOV\"\n"
-"key F8 -AnyMod : \"\\EOW\"\n"
-"key F9 -AnyMod : \"\\EOX\"\n"
-"key F10 -AnyMod : \"\\EOY\"\n"
-"key Space +Control : \"\\x00\"\n"
-"key Up +Shift-AppScreen : scrollLineUp\n"
-"key Prior +Shift-AppScreen : scrollPageUp\n"
-"key Down +Shift-AppScreen : scrollLineDown\n"
-"key Next +Shift-AppScreen : scrollPageDown\n"
-"key ScrollLock : scrollLock\n"
+"key Home        -AnyMod     -AppCuKeys           : \"\\E[H\"\n"
+"key End         -AnyMod     -AppCuKeys           : \"\\E[F\"\n"
+"key Home        -AnyMod     +AppCuKeys           : \"\\EOH\"\n"
+"key End         -AnyMod     +AppCuKeys           : \"\\EOF\"\n"
+"key Home        +AnyMod                          : \"\\E[1;*H\"\n"
+"key End         +AnyMod                          : \"\\E[1;*F\"\n"
+"key Insert      -AnyMod                          : \"\\E[2~\"\n"
+"key Delete      -AnyMod                          : \"\\E[3~\"\n"
+"key Insert      +AnyMod                          : \"\\E[2;*~\"\n"
+"key Delete      +AnyMod                          : \"\\E[3;*~\"\n"
+"key Prior -Shift-AnyMod                          : \"\\E[5~\"\n"
+"key Next  -Shift-AnyMod                          : \"\\E[6~\"\n"
+"key Prior -Shift+AnyMod                          : \"\\E[5;*~\"\n"
+"key Next  -Shift+AnyMod                          : \"\\E[6;*~\"\n"
+"key F1          -AnyMod                          : \"\\EOP\"\n"
+"key F2          -AnyMod                          : \"\\EOQ\"\n"
+"key F3          -AnyMod                          : \"\\EOR\"\n"
+"key F4          -AnyMod                          : \"\\EOS\"\n"
+"key F5          -AnyMod                          : \"\\EOT\"\n"
+"key F6          -AnyMod                          : \"\\EOU\"\n"
+"key F7          -AnyMod                          : \"\\EOV\"\n"
+"key F8          -AnyMod                          : \"\\EOW\"\n"
+"key F9          -AnyMod                          : \"\\EOX\"\n"
+"key F10         -AnyMod                          : \"\\EOY\"\n"
+"key Space +Control          : \"\\x00\"\n"
+"key Up    +Shift-AppScreen  : scrollLineUp\n"
+"key Prior +Shift-AppScreen  : scrollPageUp\n"
+"key Down  +Shift-AppScreen  : scrollLineDown\n"
+"key Next  +Shift-AppScreen  : scrollPageDown\n"
+"key ScrollLock              : scrollLock\n"
 "\0"
--- a/libgui/src/documentation.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/documentation.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -133,7 +133,7 @@
     QLabel *find_label = new QLabel (tr ("Find:"), find_footer);
     m_find_line_edit = new QLineEdit (find_footer);
     connect (m_find_line_edit, SIGNAL (returnPressed (void)),
-             this, SLOT(find_forward (void)));
+             this, SLOT(find (void)));
     connect (m_find_line_edit, SIGNAL (textEdited (const QString&)),
              this, SLOT(find_forward_from_anchor (const QString&)));
     QToolButton *forward_button = new QToolButton (find_footer);
@@ -141,7 +141,7 @@
     forward_button->setToolTip (tr ("Search forward"));
     forward_button->setIcon (resource_manager::icon ("go-down"));
     connect (forward_button, SIGNAL (pressed (void)),
-             this, SLOT(find_forward (void)));
+             this, SLOT(find (void)));
     QToolButton *backward_button = new QToolButton (find_footer);
     backward_button->setText (tr ("Search backward"));
     backward_button->setToolTip (tr ("Search backward"));
@@ -166,7 +166,7 @@
 
     m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
     connect (m_findnext_shortcut, SIGNAL (activated (void)),
-             this, SLOT(find_forward (void)));
+             this, SLOT(find (void)));
     m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
     connect (m_findprev_shortcut, SIGNAL (activated (void)),
              this, SLOT(find_backward (void)));
@@ -690,21 +690,32 @@
     m_filter->setCurrentIndex (0);
   }
 
-  void documentation::find_forward (void)
+  void documentation::find_backward (void)
+  {
+    find (true);
+  }
+
+  void documentation::find (bool backward)
   {
     if (! m_help_engine)
       return;
 
-    m_doc_browser->find (m_find_line_edit->text ());
-    record_anchor_position ();
-  }
+    QTextDocument::FindFlags find_flags = 0;
+    if (backward)
+      find_flags = QTextDocument::FindBackward;
 
-  void documentation::find_backward (void)
-  {
-    if (! m_help_engine)
-      return;
+    if (! m_doc_browser->find (m_find_line_edit->text (), find_flags))
+    {
+      // Nothing was found, restart search from the begin or end of text
+      QTextCursor textcur = m_doc_browser->textCursor ();
+      if (backward)
+        textcur.movePosition (QTextCursor::End);
+      else
+        textcur.movePosition (QTextCursor::Start);
+      m_doc_browser->setTextCursor (textcur);
+      m_doc_browser->find (m_find_line_edit->text (), find_flags);
+    }
 
-    m_doc_browser->find (m_find_line_edit->text (), QTextDocument::FindBackward);
     record_anchor_position ();
   }
 
@@ -713,10 +724,18 @@
     if (! m_help_engine)
       return;
 
+    // Search from the current position
     QTextCursor textcur = m_doc_browser->textCursor ();
     textcur.setPosition (m_search_anchor_position);
     m_doc_browser->setTextCursor (textcur);
-    m_doc_browser->find (text);
+
+    if (! m_doc_browser->find (text))
+      {
+        // Nothing was found, restart search from the beginning
+        textcur.movePosition (QTextCursor::Start);
+        m_doc_browser->setTextCursor (textcur);
+        m_doc_browser->find (text);
+      }
   }
 
   void documentation::record_anchor_position (void)
--- a/libgui/src/documentation.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/documentation.h	Fri Jul 12 12:14:43 2019 -0400
@@ -115,7 +115,7 @@
     void global_search_finished (int hits);
     void filter_update (const QString& expression);
     void filter_update_history (void);
-    void find_forward (void);
+    void find (bool backward = false);
     void find_backward (void);
     void find_forward_from_anchor (const QString& text);
     void record_anchor_position (void);
--- a/libgui/src/files-dock-widget.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/files-dock-widget.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -671,7 +671,8 @@
             // editor: close old
             emit file_remove_signal (old_name, new_name);
             // Do the renaming
-            bool st = path.rename (old_name, new_name);
+            QFile f (old_name);  // Must use QFile, not QDir (bug #56298)
+            bool st = f.rename (new_name);
             // editor: load new/old file depending on success
             emit file_renamed_signal (st);
             // Clear cache of file browser
--- a/libgui/src/gui-preferences.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/gui-preferences.h	Fri Jul 12 12:14:43 2019 -0400
@@ -28,8 +28,9 @@
 //#endif
 
 #include <QStringList>
+#include <QStyle>
+#include <QTabWidget>
 #include <QVariant>
-#include <QStyle>
 
 // Structure for the definition of pairs: key and default value
 
@@ -98,6 +99,14 @@
 const gui_pref ed_session_lines ("editor/saved_session_lines",
                                   QVariant (QStringList ()));
 
+// Tabs
+const QStringList ed_tab_position_names (
+     QStringList () << QT_TRANSLATE_NOOP ("file_editor::file_editor","Top")
+                    << QT_TRANSLATE_NOOP ("file_editor::file_editor","Bottom")
+                    << QT_TRANSLATE_NOOP ("file_editor::file_editor","Left")
+                    << QT_TRANSLATE_NOOP ("file_editor::file_editor","Right"));
+const gui_pref ed_tab_position ("editor/tab_position",
+                                QVariant (QTabWidget::North));
 
 // File handling
 const gui_pref ed_show_dbg_file ("editor/show_dbg_file", QVariant (true));
--- a/libgui/src/history-dock-widget.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/history-dock-widget.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -34,6 +34,7 @@
 
 #include "error.h"
 #include "resource-manager.h"
+#include "gui-preferences.h"
 
 #include "cmd-hist.h"
 
@@ -340,4 +341,18 @@
 
     m_history_list_view->setTextElideMode (Qt::ElideRight);
   }
+
+  void history_dock_widget::notice_settings (const QSettings *settings)
+  {
+    QFont font = QFont ();
+
+    font.setStyleHint (QFont::TypeWriter);
+    QString default_font = settings->value (global_mono_font.key, global_mono_font.def).toString ();
+
+    font.setFamily (settings->value (cs_font.key, default_font).toString ());
+    font.setPointSize (settings->value ("terminal/fontSize", 10).toInt ());
+
+    m_history_list_view->setFont (font);
+  }
+
 }
--- a/libgui/src/history-dock-widget.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/history-dock-widget.h	Fri Jul 12 12:14:43 2019 -0400
@@ -50,6 +50,7 @@
     void append_history (const QString& hist_entry);
     void clear_history (void);
     void save_settings (void);
+    void notice_settings (const QSettings *);
 
   signals:
 
Binary file libgui/src/icons/bottom_left_corner.png has changed
Binary file libgui/src/icons/bottom_right_corner.png has changed
Binary file libgui/src/icons/bottom_side.png has changed
Binary file libgui/src/icons/circle.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/circle.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 8.4666659 8.4666659"
+   version="1.1"
+   id="svg1917"
+   sodipodi:docname="circle.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   inkscape:export-filename="/home/pantxo/Dev/octaveclone/libgui/src/icons/circle.png"
+   inkscape:export-xdpi="96.000008"
+   inkscape:export-ydpi="96.000008">
+  <defs
+     id="defs1911">
+    <filter
+       inkscape:collect="always"
+       style="color-interpolation-filters:sRGB"
+       id="filter2851"
+       x="-0.063633107"
+       width="1.1272662"
+       y="-0.10485"
+       height="1.2097">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.50308888"
+         id="feGaussianBlur2853" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.839192"
+     inkscape:cx="32.278892"
+     inkscape:cy="22.118004"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1052"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     units="px" />
+  <metadata
+     id="metadata1914">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-288.53334)">
+    <path
+       inkscape:connector-curvature="0"
+       style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.33930296;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
+       d="M 4.213445,289.32696 A 3.4506385,3.4506385 0 0 0 0.76280612,292.7776 3.4506385,3.4506385 0 0 0 4.213445,296.22825 3.4506385,3.4506385 0 0 0 7.6640826,292.7776 3.4506385,3.4506385 0 0 0 4.213445,289.32696 Z m 0,0.93147 a 2.5191778,2.5191778 0 0 1 2.5191772,2.51917 2.5191778,2.5191778 0 0 1 -2.5191772,2.51918 2.5191778,2.5191778 0 0 1 -2.5191783,-2.51918 2.5191778,2.5191778 0 0 1 2.5191783,-2.51917 z"
+       id="path1844" />
+    <path
+       inkscape:connector-curvature="0"
+       style="display:inline;opacity:0.2;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter2851)"
+       d="m 1.3070234,9.3602459 a 10.1875,10.1875 0 0 0 -0.09961,1.3281251 10.1875,10.1875 0 0 0 10.1874996,10.1875 10.1875,10.1875 0 0 0 8.78711,-5.056641 l -2.66406,-0.912109 a 7.4375,7.4375 0 0 1 -6.12305,3.21875 7.4375,7.4375 0 0 1 -7.4374996,-7.4375 7.4375,7.4375 0 0 1 0.0215,-0.414062 z"
+       id="path2462"
+       transform="matrix(0.33871298,0,0,0.32344859,0.35384012,289.47597)" />
+  </g>
+</svg>
Binary file libgui/src/icons/cross.png has changed
Binary file libgui/src/icons/figure-axes.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-axes.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="axes.svg"
+   inkscape:export-filename="/media/pantxo/datadisk/dev/octavewrk/buguimenus/grid.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="EmptyTriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="EmptyTriangleInM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path11121"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="matrix(-0.4,0,0,-0.4,1.8,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path10973"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="matrix(0.4,0,0,0.4,4,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path10967"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path11112"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="scale(0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker4940"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="TriangleOutM">
+      <path
+         transform="scale(0.4)"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         id="path4942"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4834"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4836"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4282"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-3"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-6"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-7"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-5"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-5"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-62"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-9"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-1"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-7"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-0"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-93"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-6"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-6"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-2"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-6"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-18"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-9"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-20"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-2"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-3"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.839192"
+     inkscape:cx="-5.2134374"
+     inkscape:cy="9.4027107"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1052"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4136" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1020.3622)">
+    <rect
+       style="opacity:0.95;vector-effect:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;font-variant-east_asian:normal"
+       id="rect1030"
+       width="20.999962"
+       height="19.319965"
+       x="6.0000381"
+       y="1026.2021" />
+  </g>
+</svg>
Binary file libgui/src/icons/figure-grid.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-grid.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,357 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="grid.svg"
+   inkscape:export-filename="/media/pantxo/datadisk/dev/octavewrk/buguimenus/grid.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="EmptyTriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="EmptyTriangleInM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path11121"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="matrix(-0.4,0,0,-0.4,1.8,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path10973"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="matrix(0.4,0,0,0.4,4,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path10967"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path11112"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="scale(0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker4940"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="TriangleOutM">
+      <path
+         transform="scale(0.4)"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         id="path4942"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4834"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4836"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4282"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-3"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-6"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-7"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-5"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-5"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-62"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-9"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-1"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-7"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-0"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-93"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-6"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-6"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-2"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-6"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-18"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleInM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleInM-9"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4282-20"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(-0.4)" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutM-2"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4291-3"
+         d="M 5.77,0 -2.88,5 V -5 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
+         transform="scale(0.4)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.839192"
+     inkscape:cx="0.026728929"
+     inkscape:cy="9.4027107"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1052"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4136" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1020.3622)">
+    <circle
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.03419757;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate;opacity:0.95"
+       id="path10626"
+       cx="3.6666665"
+       cy="1024.9812"
+       r="0" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95"
+       d="m 10.333333,1045.6956 v -19.3334"
+       id="path12915"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path12921"
+       d="m 23.666667,1045.6956 v -19.3334"
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95"
+       d="M 7,1029.1242 H 27"
+       id="path12925"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95"
+       d="M 7,1042.9336 H 27"
+       id="path12927"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path13032"
+       d="M 7,1036.0156 H 27"
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.51709878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.95"
+       d="m 17,1045.6956 v -19.3334"
+       id="path13034"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
Binary file libgui/src/icons/figure-pan.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-pan.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,971 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="64"
+   inkscape:export-xdpi="64"
+   inkscape:export-filename="/home/pantxo/Dev/octavewrk/buguimenus/pan.png"
+   width="48px"
+   height="48px"
+   id="svg11300"
+   sodipodi:version="0.32"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="pan.svg"
+   version="1.1">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient2353">
+      <stop
+         id="stop2355"
+         offset="0"
+         style="stop-color:#86acd6;stop-opacity:1;" />
+      <stop
+         id="stop2357"
+         offset="1"
+         style="stop-color:#3970a9;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2343">
+      <stop
+         style="stop-color:#adc7e3;stop-opacity:1;"
+         offset="0"
+         id="stop2345" />
+      <stop
+         style="stop-color:#427fbf;stop-opacity:1;"
+         offset="1"
+         id="stop2347" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2333">
+      <stop
+         style="stop-color:#2b5388;stop-opacity:1;"
+         offset="0"
+         id="stop2335" />
+      <stop
+         id="stop2341"
+         offset="0"
+         style="stop-color:#2f5c96;stop-opacity:1;" />
+      <stop
+         style="stop-color:#97b6de;stop-opacity:1;"
+         offset="1"
+         id="stop2337" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2307">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2309" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2311" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2414">
+      <stop
+         id="stop2416"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0.5"
+         id="stop2315" />
+      <stop
+         id="stop2418"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2402">
+      <stop
+         style="stop-color:#d8d8d8;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2404" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2406" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2392">
+      <stop
+         id="stop2394"
+         offset="0.0000000"
+         style="stop-color:#a0a0a0;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2396"
+         offset="1.0000000"
+         style="stop-color:#e7e7e7;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2380"
+       inkscape:collect="always">
+      <stop
+         id="stop2382"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2384"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient10314">
+      <stop
+         id="stop10316"
+         offset="0.0000000"
+         style="stop-color:#f3f3f3;stop-opacity:1.0000000;" />
+      <stop
+         id="stop10318"
+         offset="1.0000000"
+         style="stop-color:#838383;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8938">
+      <stop
+         style="stop-color:#fdc674;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop8940" />
+      <stop
+         style="stop-color:#d88103;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop8942" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient7636">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop7638" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop7640" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7614">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7616" />
+      <stop
+         id="stop7649"
+         offset="0.21590909"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop7632"
+         offset="0.50000000"
+         style="stop-color:#838383;stop-opacity:1.0000000;" />
+      <stop
+         style="stop-color:#838383;stop-opacity:0;"
+         offset="1"
+         id="stop7618" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7608">
+      <stop
+         id="stop7610"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         style="stop-color:#e3e3e3;stop-opacity:1.0000000;"
+         offset="0.46022728"
+         id="stop7622" />
+      <stop
+         id="stop7624"
+         offset="0.61970556"
+         style="stop-color:#dadada;stop-opacity:0.67058824;" />
+      <stop
+         id="stop7612"
+         offset="1.0000000"
+         style="stop-color:#d1d1d1;stop-opacity:0.34285715;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7602">
+      <stop
+         style="stop-color:#f6f6f6;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7604" />
+      <stop
+         style="stop-color:#e0e0e0;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7606" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7586">
+      <stop
+         style="stop-color:#525252;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop7588" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop7590" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient12836"
+       inkscape:collect="always">
+      <stop
+         id="stop12838"
+         offset="0"
+         style="stop-color:#515152;stop-opacity:1;" />
+      <stop
+         id="stop12840"
+         offset="1"
+         style="stop-color:#515152;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient12828">
+      <stop
+         id="stop12830"
+         offset="0.0000000"
+         style="stop-color:#cccccd;stop-opacity:1.0000000;" />
+      <stop
+         style="stop-color:#adadae;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop12862" />
+      <stop
+         id="stop12832"
+         offset="1.0000000"
+         style="stop-color:#8f8f90;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient12810">
+      <stop
+         id="stop12812"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop12814"
+         offset="1.0000000"
+         style="stop-color:#e5e5e5;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11625"
+       inkscape:collect="always">
+      <stop
+         id="stop11627"
+         offset="0"
+         style="stop-color:#fce94f;stop-opacity:1;" />
+      <stop
+         id="stop11629"
+         offset="1"
+         style="stop-color:#fce94f;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11615">
+      <stop
+         id="stop11617"
+         offset="0.0000000"
+         style="stop-color:#636363;stop-opacity:1.0000000;" />
+      <stop
+         id="stop11619"
+         offset="1.0000000"
+         style="stop-color:#000000;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11602">
+      <stop
+         id="stop11604"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop11606"
+         offset="1.0000000"
+         style="stop-color:#c5c5c5;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11594">
+      <stop
+         id="stop11596"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop11598"
+         offset="1.0000000"
+         style="stop-color:#d1d1d1;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11520">
+      <stop
+         id="stop11522"
+         offset="0.0000000"
+         style="stop-color:#fbfbfb;stop-opacity:1.0000000;" />
+      <stop
+         id="stop11524"
+         offset="1.0000000"
+         style="stop-color:#dcdcdc;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11508"
+       inkscape:collect="always">
+      <stop
+         id="stop11510"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop11512"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11494"
+       inkscape:collect="always">
+      <stop
+         id="stop11496"
+         offset="0"
+         style="stop-color:#ef2929;stop-opacity:1;" />
+      <stop
+         id="stop11498"
+         offset="1"
+         style="stop-color:#ef2929;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11415">
+      <stop
+         id="stop11417"
+         offset="0.0000000"
+         style="stop-color:#204a87;stop-opacity:0.0000000;" />
+      <stop
+         style="stop-color:#204a87;stop-opacity:1.0000000;"
+         offset="0.50000000"
+         id="stop11423" />
+      <stop
+         id="stop11419"
+         offset="1"
+         style="stop-color:#204a87;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient11399"
+       inkscape:collect="always">
+      <stop
+         id="stop11401"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop11403"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-60.28571,-0.285714)"
+       y2="34.462429"
+       x2="43.615788"
+       y1="3.7744560"
+       x1="15.828360"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11425"
+       xlink:href="#linearGradient11415"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(-60.57143,0.000000)"
+       y2="39.033859"
+       x2="35.679932"
+       y1="9.3458843"
+       x1="9.6957054"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11427"
+       xlink:href="#linearGradient11415"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="33.462429"
+       x2="26.758644"
+       y1="19.774456"
+       x1="13.267134"
+       gradientTransform="translate(-60.85714,0.428571)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11439"
+       xlink:href="#linearGradient11415"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.5000000"
+       fy="39.142857"
+       fx="12.071428"
+       cy="39.142857"
+       cx="12.071428"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.487395,0.000000,20.06483)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient11441"
+       xlink:href="#linearGradient11399"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
+       gradientUnits="userSpaceOnUse"
+       r="3.8335034"
+       fy="15.048258"
+       fx="27.577173"
+       cy="15.048258"
+       cx="27.577173"
+       id="radialGradient11500"
+       xlink:href="#linearGradient11494"
+       inkscape:collect="always" />
+    <radialGradient
+       r="3.8335034"
+       fy="16.049133"
+       fx="27.577173"
+       cy="16.049133"
+       cx="27.577173"
+       gradientTransform="matrix(1.243453,2.106784e-16,-2.106784e-16,1.243453,-6.713754,-3.742847)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient11504"
+       xlink:href="#linearGradient11494"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,2.166583e-14,29.48178)"
+       r="6.5659914"
+       fy="44.565483"
+       fx="30.203562"
+       cy="44.565483"
+       cx="30.203562"
+       id="radialGradient11514"
+       xlink:href="#linearGradient11508"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(1.995058,-1.535926e-32,0.000000,1.855412,24.94925,-30.20430)"
+       gradientUnits="userSpaceOnUse"
+       r="20.530962"
+       fy="35.878170"
+       fx="24.445690"
+       cy="35.878170"
+       cx="24.445690"
+       id="radialGradient11526"
+       xlink:href="#linearGradient11520"
+       inkscape:collect="always" />
+    <radialGradient
+       r="6.5659914"
+       fy="44.565483"
+       fx="30.203562"
+       cy="44.565483"
+       cx="30.203562"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,-5.348412e-14,29.48178)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient11532"
+       xlink:href="#linearGradient11508"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.045319,0.000000,0.000000,0.957884,48.16627,1.415543)"
+       gradientUnits="userSpaceOnUse"
+       y2="38.947163"
+       x2="31.799011"
+       y1="8.9471626"
+       x1="20.092352"
+       id="linearGradient11600"
+       xlink:href="#linearGradient11594"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.984324,0.000000,0.000000,0.957884,49.65734,1.415543)"
+       gradientUnits="userSpaceOnUse"
+       y2="39.447163"
+       x2="24.445671"
+       y1="0.49847093"
+       x1="24.445671"
+       id="linearGradient11608"
+       xlink:href="#linearGradient11520"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.570338,3.171097e-15,-4.005596e-15,4.509900,-64.25843,-94.25499)"
+       r="4.7500000"
+       fy="27.749998"
+       fx="25.000000"
+       cy="27.749998"
+       cx="25.000000"
+       id="radialGradient11621"
+       xlink:href="#linearGradient11615"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       id="linearGradient11631"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(2.000000,0.000000)"
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11635"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(4.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11639"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(6.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11643"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(8.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11647"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11655"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(2.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11657"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(4.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11659"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(6.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient11661"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="21.459777"
+       x2="87.528968"
+       y1="21.459777"
+       x1="65.623963"
+       id="linearGradient12816"
+       xlink:href="#linearGradient12810"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="12.022278"
+       x2="62.591469"
+       y1="25.209778"
+       x1="84.998962"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12818"
+       xlink:href="#linearGradient12810"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.969219,0.227988,-0.194668,0.827570,9.443870,-15.99848)"
+       r="7.0056136"
+       fy="33.398670"
+       fx="88.593018"
+       cy="33.398670"
+       cx="88.593018"
+       id="radialGradient12834"
+       xlink:href="#linearGradient12828"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="36.656250"
+       x2="92.062500"
+       y1="31.656250"
+       x1="88.750000"
+       id="linearGradient12842"
+       xlink:href="#linearGradient12836"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="21.459777"
+       x2="87.528968"
+       y1="21.459777"
+       x1="65.623963"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12878"
+       xlink:href="#linearGradient12810"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.656250"
+       x2="92.062500"
+       y1="31.656250"
+       x1="88.750000"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12880"
+       xlink:href="#linearGradient12836"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.0056136"
+       fy="33.398670"
+       fx="88.593018"
+       cy="33.398670"
+       cx="88.593018"
+       gradientTransform="matrix(0.969219,0.227988,-0.194668,0.827570,9.443870,-15.99848)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient12882"
+       xlink:href="#linearGradient12828"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="12.022278"
+       x2="62.591469"
+       y1="25.209778"
+       x1="84.998962"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12884"
+       xlink:href="#linearGradient12810"
+       inkscape:collect="always" />
+    <radialGradient
+       r="4.7500000"
+       fy="27.749998"
+       fx="25.000000"
+       cy="27.749998"
+       cx="25.000000"
+       gradientTransform="matrix(3.570338,3.171097e-15,-4.005596e-15,4.509900,-64.25843,-94.25499)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient12894"
+       xlink:href="#linearGradient11615"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(7.267442e-2,-0.181686)"
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12896"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(2.072674,-0.181686)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12898"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(4.072674,-0.181686)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12900"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(6.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12902"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(7.267442e-2,-0.181686)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12911"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(2.072674,-0.181686)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12913"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.375000"
+       x2="21.500000"
+       y1="30.000000"
+       x1="21.500000"
+       gradientTransform="translate(4.072674,-0.181686)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient12915"
+       xlink:href="#linearGradient11625"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient11594"
+       id="linearGradient7584"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.476329,0.000000,0.000000,0.627721,62.07560,9.156933)"
+       x1="31.597168"
+       y1="33.447811"
+       x2="24.445690"
+       y2="21.067410" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7586"
+       id="radialGradient7592"
+       cx="24.399090"
+       cy="29.099535"
+       fx="24.399090"
+       fy="29.099535"
+       r="6.0270013"
+       gradientTransform="matrix(2.407878,2.776254e-16,-5.900875e-16,1.861050,14.96976,-20.55775)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7608"
+       id="linearGradient7596"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.059222,0.000000,0.000000,0.808101,48.08657,4.001391)"
+       x1="22.585604"
+       y1="34.149513"
+       x2="22.585604"
+       y2="11.042997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7636"
+       id="linearGradient7642"
+       x1="25.279068"
+       y1="28.554562"
+       x2="28.284273"
+       y2="38.454056"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(49.32070,0.000000)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7614"
+       id="radialGradient7647"
+       cx="24.483574"
+       cy="29.609560"
+       fx="24.483574"
+       fy="29.609560"
+       r="4.4774761"
+       gradientTransform="matrix(2.777122,-8.126449e-2,6.891211e-2,2.223012,4.035118,-33.24798)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2307"
+       id="linearGradient2313"
+       x1="21.985764"
+       y1="15.953948"
+       x2="21.776054"
+       y2="9.2115307"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-55.684662,3.005204)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient2349"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-66.114487,0.88388355)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2380"
+       id="radialGradient974"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.223129,0,0,0.33567164,-8.8071623,25.965578)"
+       cx="27.223612"
+       cy="39.072777"
+       fx="27.223612"
+       fy="39.072777"
+       r="18.384777" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient982"
+       gradientUnits="userSpaceOnUse"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206"
+       gradientTransform="matrix(0,0.48743869,-0.48743869,0,74.598989,8.6090155)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient982-1"
+       gradientUnits="userSpaceOnUse"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206"
+       gradientTransform="matrix(0,0.48743869,-0.48743869,0,11.94366,-1.802594)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient1015"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0,0.48743869,-0.48743869,0,127.96938,4.9886278)"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient1023-3"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0,0.48743869,-0.48743869,0,68.213099,2.2323471)"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2343"
+       id="linearGradient2349-5"
+       x1="17.329659"
+       y1="8.1524134"
+       x2="17.329659"
+       y2="22.389206"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-1.0110852,-7.0521685)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2307"
+       id="linearGradient2313-0"
+       x1="21.985764"
+       y1="15.953948"
+       x2="21.776054"
+       y2="9.2115307"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-4.6562264,-8.2714384)" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#204a87"
+     fill="#729fcf"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.25490196"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.656854"
+     inkscape:cx="31.383363"
+     inkscape:cy="40.213913"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1052"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:snap-global="false"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid988" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+        <dc:title></dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>view</rdf:li>
+            <rdf:li>refresh</rdf:li>
+            <rdf:li>reload</rdf:li>
+            <rdf:li>reboot</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.44919787;fill:url(#radialGradient974);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.08159184;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="ellipse960"
+       cx="24.490826"
+       cy="39.081177"
+       rx="22.486954"
+       ry="6.1712399" />
+    <path
+       style="opacity:1;vector-effect:none;fill:url(#linearGradient2349);fill-opacity:1;stroke:#204a87;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       d="m 24.113437,6.6437268 -6.168813,6.1688122 h 3.337803 v 7.498983 h -7.508102 v -3.328684 l -6.1688133,6.168813 6.1688133,6.168813 V 25.99178 h 7.508102 v 7.498983 h -3.337803 l 6.168813,6.168813 6.168813,-6.168813 H 26.963989 V 25.99178 h 7.48856 v 3.328684 l 6.168814,-6.168813 -6.168814,-6.168813 v 3.328684 h -7.48856 v -7.498983 h 3.318261 z"
+       id="rect990"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path1086"
+       d="m 24.113437,7.971912 -3.868492,3.887676 2.060265,-0.01563 -0.0625,9.455955 -9.477592,-0.03125 0.04687,-1.93147 -3.8216173,3.809551 3.8216173,3.840802 -0.01563,-1.993971 9.461967,0.04687 v 9.409081 h -1.95089 l 3.805992,3.528301 3.790367,-3.606426 -1.917714,0.0625 v -9.440331 h 9.413166 v 1.962721 l 3.915368,-3.731427 -3.977868,-4.043926 -0.0625,2.21272 -9.350666,-0.1875 0.1875,-9.44033 1.792714,0.0625 z"
+       style="opacity:0.46590911;vector-effect:none;fill:none;fill-opacity:1;stroke:url(#linearGradient2313);stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       sodipodi:nodetypes="ccccccccccccccccccccccccc" />
+  </g>
+</svg>
Binary file libgui/src/icons/figure-rotate.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-rotate.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="64"
+   inkscape:export-xdpi="64"
+   inkscape:export-filename="/home/pantxo/Dev/octaveclone/libgui/src/icons/figure-rotate.png"
+   width="48px"
+   height="48px"
+   id="svg11300"
+   sodipodi:version="0.32"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="figure-rotate.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective58" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2690">
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:1;"
+         offset="0"
+         id="stop2692" />
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:0;"
+         offset="1"
+         id="stop2694" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2682">
+      <stop
+         style="stop-color:#3977c3;stop-opacity:1;"
+         offset="0"
+         id="stop2684" />
+      <stop
+         style="stop-color:#89aedc;stop-opacity:0;"
+         offset="1"
+         id="stop2686" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2402">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1;"
+         offset="0"
+         id="stop2404" />
+      <stop
+         style="stop-color:#528ac5;stop-opacity:1;"
+         offset="1"
+         id="stop2406" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2380">
+      <stop
+         style="stop-color:#b9cfe7;stop-opacity:1"
+         offset="0"
+         id="stop2382" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1"
+         offset="1"
+         id="stop2384" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2871">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2873" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1"
+         offset="1"
+         id="stop2875" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2847">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2849" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:0;"
+         offset="1"
+         id="stop2851" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2831">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2833" />
+      <stop
+         id="stop2855"
+         offset="0.33333334"
+         style="stop-color:#5b86be;stop-opacity:1;" />
+      <stop
+         style="stop-color:#83a8d8;stop-opacity:0;"
+         offset="1"
+         id="stop2835" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2797">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2799" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2801" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2831"
+       id="linearGradient1486"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.92009777,0,0,0.92009777,2.3856234,1.4987352)"
+       x1="13.478554"
+       y1="10.612206"
+       x2="15.419417"
+       y2="19.115122" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2847"
+       id="linearGradient1488"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.92009777,0,0,-0.92009777,45.687722,43.938248)"
+       x1="37.128052"
+       y1="29.729605"
+       x2="37.065414"
+       y2="26.194071" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797"
+       id="linearGradient1491"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797"
+       id="linearGradient1493"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871"
+       id="linearGradient1501"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662"
+       id="radialGradient1503"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.536723,-9.680928e-14,16.87306)"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2380"
+       id="linearGradient2386"
+       x1="62.513836"
+       y1="36.061237"
+       x2="15.984863"
+       y2="20.60858"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2402"
+       id="linearGradient2408"
+       x1="18.935766"
+       y1="23.667896"
+       x2="53.588622"
+       y2="26.649362"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2682"
+       id="linearGradient2688"
+       x1="36.713837"
+       y1="31.455952"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.92009777,0,0,0.92009777,1.9573979,1.7541479)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2690"
+       id="linearGradient2696"
+       x1="32.647972"
+       y1="30.748846"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.92009777,0,0,0.92009777,1.9573979,1.7541479)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2380"
+       id="linearGradient872"
+       gradientUnits="userSpaceOnUse"
+       x1="62.513836"
+       y1="36.061237"
+       x2="15.984863"
+       y2="20.60858" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871"
+       id="linearGradient874"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2402"
+       id="linearGradient876"
+       gradientUnits="userSpaceOnUse"
+       x1="18.935766"
+       y1="23.667896"
+       x2="53.588622"
+       y2="26.649362" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871"
+       id="linearGradient878"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#3465a4"
+     fill="#729fcf"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.25490196"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.9999999"
+     inkscape:cx="-8.7701413"
+     inkscape:cy="19.722655"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1791"
+     inkscape:window-height="951"
+     inkscape:window-x="0"
+     inkscape:window-y="30"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:title>View Refresh</dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>reload</rdf:li>
+            <rdf:li>refresh</rdf:li>
+            <rdf:li>view</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <ellipse
+       transform="matrix(-1.489736,0,0,-1.001252,61.20865,75.2819)"
+       id="path8660"
+       style="opacity:0.38333333;color:#000000;fill:url(#radialGradient1503);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1  9.1923885,36.421127 A 15.644737 8.3968935 0 1 1  40.481863 36.421127 z"
+       sodipodi:type="arc"
+       sodipodi:ry="8.3968935"
+       sodipodi:rx="15.644737"
+       sodipodi:cy="36.421127"
+       sodipodi:cx="24.837126" />
+    <path
+       style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient1486);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1488);stroke-width:0.92009741;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       d="m 20.500048,11.332277 c 0,0 -8.223374,-0.575061 -5.693105,9.085966 H 7.7336919 c 0,0 0.4600488,-10.9261611 12.7663561,-9.085966 z"
+       id="path2865"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       sodipodi:nodetypes="cccc"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g1878"
+       transform="matrix(-0.53278354,-0.45013759,-0.45013759,0.53278354,54.325545,14.057116)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       style="fill:url(#linearGradient2386);fill-opacity:1;stroke:#3465a4;stroke-opacity:1">
+      <path
+         sodipodi:nodetypes="ccccccc"
+         id="path1880"
+         d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.113843,3.1515478 7.6245439,20.496754 22.714328,33.219189 c 0,0 -0.251917,-9.88122 -0.251917,-9.88122 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
+         style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient872);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient874);stroke-width:1.31916928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       sodipodi:nodetypes="cccc"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       id="path2839"
+       d="m 28.065172,32.519917 c 0,0 8.223374,0.575061 5.693105,-9.085965 h 7.154577 c 0,1.38254 -0.541374,10.926161 -12.847682,9.085965 z"
+       style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient2696);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2688);stroke-width:0.92009741;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       inkscape:connector-curvature="0" />
+    <g
+       style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2408);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1501);stroke-width:1.31916928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(0.53278354,0.45013759,0.45013759,-0.53278354,-5.3307177,29.850244)"
+       id="g2779">
+      <path
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient876);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient878);stroke-width:1.31916928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.399432,3.0690297 7.793943,20.424005 22.462411,33.006349 c 0,0 0,-9.66838 0,-9.66838 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
+         id="path2781"
+         sodipodi:nodetypes="ccccccc"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.27222224;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92009759;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       d="m 8.4555884,36.890382 0.057506,-13.686455 11.9037646,-0.345036 -4.038192,4.765018 3.558225,2.183575 c -2.760293,2.07022 -4.186029,2.228594 -5.106126,4.586345 l -2.591785,-1.941657 z"
+       id="path2791"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       sodipodi:nodetypes="cccccccc"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g2793"
+       transform="matrix(0.46790284,0.39532093,0.39532093,-0.46790284,-1.6983235,29.855029)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1">
+      <path
+         sodipodi:nodetypes="ccccccc"
+         id="path2795"
+         d="M 51.090265,45.943705 C 60.210465,30.723955 46.631614,12.20113 19.485058,11.948579 L 19.513464,3.7032834 6.5341979,19.296639 19.367661,30.26876 c 0,0 0.05562,-9.006878 0.05562,-9.006878 17.527815,-0.223909 35.195185,10.103372 31.666984,24.681823 z"
+         style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1493);stroke-width:1.50208926;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(-0.46790284,-0.39532093,-0.39532093,0.46790284,50.767665,14.051696)"
+       id="g2805">
+      <path
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         style="color:#000000;display:block;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1491);stroke-width:1.50208926;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         d="M 51.389927,46.505946 C 60.510127,31.286196 47.050763,12.432359 19.628482,12.069755 L 19.342824,4.0507204 6.3413093,19.379475 19.809059,30.764589 c 0,0 -0.181765,-9.453243 -0.181765,-9.453243 18.244937,0.381972 34.783881,10.925246 31.762633,25.1946 z"
+         id="path2807"
+         sodipodi:nodetypes="ccccccc"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.27222224;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92009759;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       d="m 8.225564,16.935761 c 3.306312,-9.6069914 15.129887,-5.653639 18.574474,-4.14044 3.84169,0.194578 5.221312,-2.608481 8.28088,-2.760293 C 22.153787,1.0272741 8.5706006,4.0543924 8.225564,16.935761 Z"
+       id="path2811"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       sodipodi:nodetypes="cccc"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
Binary file libgui/src/icons/figure-text.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-text.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,639 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   id="svg1306"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/mimetypes"
+   sodipodi:docname="font-x-generic.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs1308">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective73" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient6719"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5060">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient6717"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient6715"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4785">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop4787" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop4789" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4767">
+      <stop
+         style="stop-color:#729fcf"
+         offset="0"
+         id="stop4769" />
+      <stop
+         style="stop-color:#3465a4"
+         offset="1"
+         id="stop4771" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4755">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop4757" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000"
+         offset="1"
+         id="stop4759" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4755"
+       id="linearGradient4761"
+       x1="36.668537"
+       y1="36.383247"
+       x2="10.303555"
+       y2="7.4928832"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4767"
+       id="linearGradient4773"
+       x1="18.561554"
+       y1="12.998214"
+       x2="30.935921"
+       y2="33.681091"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-1.000000,-1.000000)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4785"
+       id="radialGradient4791"
+       cx="22.402998"
+       cy="43.071735"
+       fx="22.402998"
+       fy="43.071735"
+       r="22.318058"
+       gradientTransform="matrix(1.026073,-4.434013e-3,9.770098e-4,7.524542e-2,-0.626191,41.79022)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4767"
+       id="linearGradient4815"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(105.0249,14.77363)"
+       x1="18.561554"
+       y1="12.998214"
+       x2="30.935921"
+       y2="33.681091" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.11372549"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="56.344977"
+     inkscape:cy="12.600577"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     fill="#2e3436"
+     stroke="#888a85"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="872"
+     inkscape:window-height="746"
+     inkscape:window-x="357"
+     inkscape:window-y="41"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata1311">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Generic font</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Andreas Nilsson</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>the oxygen guys</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:source>http://tango-project.org</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>font</rdf:li>
+            <rdf:li>type</rdf:li>
+            <rdf:li>letter</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       style="display:inline"
+       transform="matrix(2.47484e-2,0,0,2.086758e-2,46.13711,41.50715)"
+       id="g6707">
+      <rect
+         style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         id="rect6709"
+         width="1339.6335"
+         height="478.35718"
+         x="-1559.2523"
+         y="-150.69685" />
+      <path
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+         id="path6711"
+         sodipodi:nodetypes="cccc" />
+      <path
+         sodipodi:nodetypes="cccc"
+         id="path6713"
+         d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+    </g>
+    <rect
+       style="opacity:1.0000000;fill:url(#linearGradient4761);fill-opacity:1.0;stroke:#888a85;stroke-width:1.0249254;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+       id="rect1314"
+       width="41.011471"
+       height="42.987240"
+       x="3.4883704"
+       y="2.5121932"
+       rx="0.99906075"
+       ry="0.99914879" />
+    <path
+       style="font-size:46.600502px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient4773);fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L"
+       d="M 39.000000,39.008527 C 36.343774,38.775525 36.064168,38.777717 35.458362,35.375884 L 31.077914,8.9999998 L 30.241301,8.9999998 L 16.352156,32.300251 C 12.670720,38.498111 11.798459,38.635723 9.9344410,39.008527 L 9.9344410,40.129135 L 19.054985,40.129135 L 19.054985,39.008527 C 16.678362,38.775525 16.305555,38.917521 16.305555,37.752510 C 16.305555,36.867101 16.445358,36.447694 17.237565,34.863278 L 19.893794,30.159922 L 30.145904,30.159922 L 31.077914,35.702087 C 31.124515,36.121492 31.171115,36.540897 31.171115,36.913700 C 31.171115,38.684518 30.924955,38.728924 27.942526,39.008527 L 27.942526,40.129135 L 39.000000,40.129135 L 39.000000,39.008527 M 20.872404,27.919804 L 27.862480,15.803673 L 29.912902,27.919804 L 20.872404,27.919804"
+       id="text2044"
+       sodipodi:nodetypes="cccccccccsccccscccccccc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4633"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520060,11.81453)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4635"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520061,13.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4639"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520065,17.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4641"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520061,19.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4643"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520056,21.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4645"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520057,23.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4647"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520061,25.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4649"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520061,27.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4651"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520057,29.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4653"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520065,31.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4655"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520066,33.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4657"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520070,35.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4659"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520070,37.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4661"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520066,39.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4663"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520061,15.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4665"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520065,41.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4667"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520066,43.81455)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4669"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(0.452550,0.000000,0.000000,-0.532412,-2.520070,45.81454)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4675"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,15.52001,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4679"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,21.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4681"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,23.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4683"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,25.52002,1.185486)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4685"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,27.52003,1.185486)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4687"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,29.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4689"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,31.52003,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4691"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,33.52003,1.185486)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4693"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,35.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4695"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,37.52003,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4697"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,39.52002,1.185506)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4699"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,41.52003,1.185506)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4701"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,43.52003,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4703"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,19.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4705"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,45.52002,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4707"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,47.52003,1.185496)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4709"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,49.52002,1.185506)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1.0000000;fill:#888a85;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;display:inline"
+       id="path4751"
+       sodipodi:cx="22.141281"
+       sodipodi:cy="9.9819622"
+       sodipodi:rx="1.1048543"
+       sodipodi:ry="0.93912619"
+       d="M 23.246135 9.9819622 A 1.1048543 0.93912619 0 1 1  21.036427,9.9819622 A 1.1048543 0.93912619 0 1 1  23.246135 9.9819622 z"
+       transform="matrix(-0.452550,0.000000,0.000000,0.532412,17.52000,-0.814489)" />
+    <rect
+       style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;stroke:#ffffff;stroke-width:1.0249996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+       id="rect4753"
+       width="39.013622"
+       height="41.033813"
+       x="4.4870877"
+       y="3.5124998"
+       rx="0.0000000"
+       ry="0.0000000" />
+  </g>
+</svg>
Binary file libgui/src/icons/figure-zoom-in.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-zoom-in.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,1183 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="figure-zoom-in.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:version="0.32"
+   id="svg11300"
+   height="48px"
+   width="48px"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1"
+   inkscape:export-filename="/home/pantxo/Dev/octaveclone/libgui/src/icons/figure-zoom-in.png"
+   inkscape:export-xdpi="64"
+   inkscape:export-ydpi="64">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient2846">
+      <stop
+         id="stop2848"
+         offset="0.0000000"
+         style="stop-color:#8a8a8a;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2850"
+         offset="1.0000000"
+         style="stop-color:#484848;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366">
+      <stop
+         id="stop2368"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.21904762;"
+         offset="0.50000000"
+         id="stop2374" />
+      <stop
+         id="stop2370"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4487">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4489" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4491" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4477">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4479" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4481" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4469" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.24761905;"
+         offset="1.0000000"
+         id="stop4471" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:0.20784314;"
+         offset="0.0000000"
+         id="stop4456" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:0.67619050;"
+         offset="1.0000000"
+         id="stop4458" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4440">
+      <stop
+         style="stop-color:#7d7d7d;stop-opacity:1;"
+         offset="0"
+         id="stop4442" />
+      <stop
+         id="stop4448"
+         offset="0.50000000"
+         style="stop-color:#b1b1b1;stop-opacity:1.0000000;" />
+      <stop
+         style="stop-color:#686868;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4444" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4440"
+       id="linearGradient4446"
+       x1="30.656250"
+       y1="34.000000"
+       x2="33.218750"
+       y2="31.062500"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0.000000,0.000000,1.291292,-6.973842,-7.460658)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4454"
+       id="radialGradient4460"
+       cx="18.240929"
+       cy="21.817987"
+       fx="18.240929"
+       fy="21.817987"
+       r="8.3085051"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient4473"
+       cx="15.414371"
+       cy="13.078408"
+       fx="15.414371"
+       fy="13.078408"
+       r="6.6562500"
+       gradientTransform="matrix(2.592963,-7.746900e-24,-5.714443e-24,2.252104,-25.05975,-18.94100)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4487"
+       id="radialGradient4493"
+       cx="24.130018"
+       cy="37.967922"
+       fx="24.130018"
+       fy="37.967922"
+       r="16.528622"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,3.152859e-15,28.93278)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="25.743469"
+       x2="17.500893"
+       y1="13.602121"
+       x1="18.292673"
+       id="linearGradient2372"
+       xlink:href="#linearGradient2366"
+       inkscape:collect="always" />
+    <radialGradient
+       r="16.528622"
+       fy="37.967922"
+       fx="24.130018"
+       cy="37.967922"
+       cx="24.130018"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,-2.471981e-16,28.93278)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2842"
+       xlink:href="#linearGradient4477"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="30.557772"
+       x2="31.335964"
+       y1="26.580296"
+       x1="27.366341"
+       id="linearGradient2852"
+       xlink:href="#linearGradient2846"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
+       r="10.319340"
+       fy="35.127438"
+       fx="23.070683"
+       cy="35.127438"
+       cx="23.070683"
+       id="radialGradient2097"
+       xlink:href="#linearGradient2091"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="50.939667"
+       x2="45.380436"
+       y1="45.264122"
+       x1="46.834816"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7186"
+       xlink:href="#linearGradient2871"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="26.649362"
+       x2="53.588622"
+       y1="23.667896"
+       x1="18.935766"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7184"
+       xlink:href="#linearGradient2402"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="50.939667"
+       x2="45.380436"
+       y1="45.264122"
+       x1="46.834816"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7182"
+       xlink:href="#linearGradient2871"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="20.60858"
+       x2="15.984863"
+       y1="36.061237"
+       x1="62.513836"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7180"
+       xlink:href="#linearGradient2380"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)"
+       y2="23.554308"
+       x2="22.374878"
+       y1="13.604306"
+       x1="13.435029"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7189"
+       xlink:href="#linearGradient7179"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="23.554308"
+       x2="22.374878"
+       y1="13.604306"
+       x1="13.435029"
+       id="linearGradient7185"
+       xlink:href="#linearGradient7179"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1322">
+      <stop
+         style="stop-color:#729fcf"
+         offset="0.0000000"
+         id="stop1324" />
+      <stop
+         style="stop-color:#5187d6;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop1326" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2316">
+      <stop
+         id="stop2318"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2320"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0.65979379;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7179"
+       inkscape:collect="always">
+      <stop
+         id="stop7181"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop7183"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.048164"
+       x2="52.854097"
+       y1="26.048164"
+       x1="5.9649176"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1491"
+       xlink:href="#linearGradient2797"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2797"
+       inkscape:collect="always">
+      <stop
+         id="stop2799"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2801"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.048164"
+       x2="52.854097"
+       y1="26.048164"
+       x1="5.9649176"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1493"
+       xlink:href="#linearGradient2797"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2402">
+      <stop
+         id="stop2404"
+         offset="0"
+         style="stop-color:#729fcf;stop-opacity:1;" />
+      <stop
+         id="stop2406"
+         offset="1"
+         style="stop-color:#528ac5;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2871"
+       inkscape:collect="always">
+      <stop
+         id="stop2873"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         id="stop2875"
+         offset="1"
+         style="stop-color:#3465a4;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-48.77039,-5.765705)"
+       gradientUnits="userSpaceOnUse"
+       y2="24.842253"
+       x2="37.124462"
+       y1="30.748846"
+       x1="32.647972"
+       id="linearGradient2696"
+       xlink:href="#linearGradient2690"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2690"
+       inkscape:collect="always">
+      <stop
+         id="stop2692"
+         offset="0"
+         style="stop-color:#c4d7eb;stop-opacity:1;" />
+      <stop
+         id="stop2694"
+         offset="1"
+         style="stop-color:#c4d7eb;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-48.77039,-5.765705)"
+       gradientUnits="userSpaceOnUse"
+       y2="24.842253"
+       x2="37.124462"
+       y1="31.455952"
+       x1="36.713837"
+       id="linearGradient2688"
+       xlink:href="#linearGradient2682"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2682">
+      <stop
+         id="stop2684"
+         offset="0"
+         style="stop-color:#3977c3;stop-opacity:1;" />
+      <stop
+         id="stop2686"
+         offset="1"
+         style="stop-color:#89aedc;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2380">
+      <stop
+         id="stop2382"
+         offset="0"
+         style="stop-color:#b9cfe7;stop-opacity:1" />
+      <stop
+         id="stop2384"
+         offset="1"
+         style="stop-color:#729fcf;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       y2="19.115122"
+       x2="15.419417"
+       y1="10.612206"
+       x1="13.478554"
+       gradientTransform="translate(-48.30498,-6.043298)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1486"
+       xlink:href="#linearGradient2831"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2831">
+      <stop
+         id="stop2833"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         style="stop-color:#5b86be;stop-opacity:1;"
+         offset="0.33333334"
+         id="stop2855" />
+      <stop
+         id="stop2835"
+         offset="1"
+         style="stop-color:#83a8d8;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.194071"
+       x2="37.065414"
+       y1="29.729605"
+       x1="37.128052"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1488"
+       xlink:href="#linearGradient2847"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2847"
+       inkscape:collect="always">
+      <stop
+         id="stop2849"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         id="stop2851"
+         offset="1"
+         style="stop-color:#3465a4;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="15.644737"
+       fy="36.421127"
+       fx="24.837126"
+       cy="36.421127"
+       cx="24.837126"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1503"
+       xlink:href="#linearGradient8662"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient8662"
+       inkscape:collect="always">
+      <stop
+         id="stop8664"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop8666"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7916">
+      <stop
+         id="stop7918"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop7920"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.34020618;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2091"
+       inkscape:collect="always">
+      <stop
+         id="stop2093"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2095"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2091-4">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop2093-5" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop2095-1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7916-4">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7918-2" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.34020618;"
+         offset="1.0000000"
+         id="stop7920-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662-1">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664-8" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666-3" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662-1"
+       id="radialGradient1503-3"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2847-9">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2849-2" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:0;"
+         offset="1"
+         id="stop2851-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2847-9"
+       id="linearGradient1488-8"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
+       x1="37.128052"
+       y1="29.729605"
+       x2="37.065414"
+       y2="26.194071" />
+    <linearGradient
+       id="linearGradient2831-3">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2833-8" />
+      <stop
+         id="stop2855-6"
+         offset="0.33333334"
+         style="stop-color:#5b86be;stop-opacity:1;" />
+      <stop
+         style="stop-color:#83a8d8;stop-opacity:0;"
+         offset="1"
+         id="stop2835-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2831-3"
+       id="linearGradient1486-4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.30498,-6.043298)"
+       x1="13.478554"
+       y1="10.612206"
+       x2="15.419417"
+       y2="19.115122" />
+    <linearGradient
+       id="linearGradient2380-5">
+      <stop
+         style="stop-color:#b9cfe7;stop-opacity:1"
+         offset="0"
+         id="stop2382-2" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1"
+         offset="1"
+         id="stop2384-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2682-7">
+      <stop
+         style="stop-color:#3977c3;stop-opacity:1;"
+         offset="0"
+         id="stop2684-4" />
+      <stop
+         style="stop-color:#89aedc;stop-opacity:0;"
+         offset="1"
+         id="stop2686-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2682-7"
+       id="linearGradient2688-2"
+       x1="36.713837"
+       y1="31.455952"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.77039,-5.765705)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2690-3">
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:1;"
+         offset="0"
+         id="stop2692-4" />
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:0;"
+         offset="1"
+         id="stop2694-9" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2690-3"
+       id="linearGradient2696-0"
+       x1="32.647972"
+       y1="30.748846"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.77039,-5.765705)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2871-3">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2873-7" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1"
+         offset="1"
+         id="stop2875-0" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2402-2">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1;"
+         offset="0"
+         id="stop2404-8" />
+      <stop
+         style="stop-color:#528ac5;stop-opacity:1;"
+         offset="1"
+         id="stop2406-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797-7"
+       id="linearGradient1493-3"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2797-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2799-4" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2801-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797-7"
+       id="linearGradient1491-2"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient7179-1">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7181-0" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop7183-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2316-2">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop2318-6" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.65979379;"
+         offset="1"
+         id="stop2320-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1322-8">
+      <stop
+         id="stop1324-1"
+         offset="0.0000000"
+         style="stop-color:#729fcf" />
+      <stop
+         id="stop1326-2"
+         offset="1.0000000"
+         style="stop-color:#5187d6;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1322-8"
+       id="linearGradient4975-0"
+       x1="34.892849"
+       y1="36.422989"
+       x2="45.918697"
+       y2="48.547989"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-18.01785,-13.57119)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7179-1"
+       id="linearGradient7185-5"
+       x1="13.435029"
+       y1="13.604306"
+       x2="22.374878"
+       y2="23.554308"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7179-1"
+       id="linearGradient7189-6"
+       gradientUnits="userSpaceOnUse"
+       x1="13.435029"
+       y1="13.604306"
+       x2="22.374878"
+       y2="23.554308"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2380-5"
+       id="linearGradient7180-0"
+       gradientUnits="userSpaceOnUse"
+       x1="62.513836"
+       y1="36.061237"
+       x2="15.984863"
+       y2="20.60858" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871-3"
+       id="linearGradient7182-5"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2402-2"
+       id="linearGradient7184-1"
+       gradientUnits="userSpaceOnUse"
+       x1="18.935766"
+       y1="23.667896"
+       x2="53.588622"
+       y2="26.649362" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871-3"
+       id="linearGradient7186-6"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7916-4"
+       id="linearGradient7922-7"
+       x1="16.874998"
+       y1="22.851799"
+       x2="27.900846"
+       y2="34.976799"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2091-4"
+       id="radialGradient2097-3"
+       cx="23.070683"
+       cy="35.127438"
+       fx="23.070683"
+       fy="35.127438"
+       r="10.319340"
+       gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2846-0"
+       id="linearGradient2852-6"
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4477-1"
+       id="radialGradient2842-7"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.237968,0,28.93278)"
+       cx="24.130018"
+       cy="37.967922"
+       fx="24.130018"
+       fy="37.967922"
+       r="16.528622" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2366-6"
+       id="linearGradient2372-0"
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.237968,0,28.93278)"
+       r="16.528622"
+       fy="37.967922"
+       fx="24.130018"
+       cy="37.967922"
+       cx="24.130018"
+       id="radialGradient4493-9"
+       xlink:href="#linearGradient4487-8"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,0,0,2.252104,-25.05975,-18.941)"
+       r="6.6562500"
+       fy="13.078408"
+       fx="15.414371"
+       cy="13.078408"
+       cx="15.414371"
+       id="radialGradient4473-9"
+       xlink:href="#linearGradient4467-5"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.3085051"
+       fy="21.817987"
+       fx="18.240929"
+       cy="21.817987"
+       cx="18.240929"
+       id="radialGradient4460-5"
+       xlink:href="#linearGradient4454-4"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.334593,0,0,1.291292,-6.973842,-7.460658)"
+       gradientUnits="userSpaceOnUse"
+       y2="31.062500"
+       x2="33.218750"
+       y1="34.000000"
+       x1="30.656250"
+       id="linearGradient4446-6"
+       xlink:href="#linearGradient4440-0"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient4440-0">
+      <stop
+         id="stop4442-8"
+         offset="0"
+         style="stop-color:#7d7d7d;stop-opacity:1;" />
+      <stop
+         style="stop-color:#b1b1b1;stop-opacity:1.0000000;"
+         offset="0.50000000"
+         id="stop4448-3" />
+      <stop
+         id="stop4444-5"
+         offset="1.0000000"
+         style="stop-color:#686868;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454-4">
+      <stop
+         id="stop4456-1"
+         offset="0.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.20784314;" />
+      <stop
+         id="stop4458-5"
+         offset="1.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.67619050;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467-5">
+      <stop
+         id="stop4469-9"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4471-3"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.24761905;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4477-1"
+       inkscape:collect="always">
+      <stop
+         id="stop4479-1"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop4481-3"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4487-8"
+       inkscape:collect="always">
+      <stop
+         id="stop4489-0"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4491-4"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366-6">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2368-3" />
+      <stop
+         id="stop2374-5"
+         offset="0.50000000"
+         style="stop-color:#ffffff;stop-opacity:0.21904762;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2370-0" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2846-0">
+      <stop
+         style="stop-color:#8a8a8a;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2848-8" />
+      <stop
+         style="stop-color:#484848;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2850-7" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2846"
+       id="linearGradient3882"
+       gradientUnits="userSpaceOnUse"
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4440"
+       id="linearGradient3884"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0,0,1.291292,-6.973842,-7.460658)"
+       x1="30.656250"
+       y1="34.000000"
+       x2="33.218750"
+       y2="31.062500" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2366"
+       id="linearGradient3886"
+       gradientUnits="userSpaceOnUse"
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4454"
+       id="radialGradient3888"
+       gradientUnits="userSpaceOnUse"
+       cx="18.240929"
+       cy="21.817987"
+       fx="18.240929"
+       fy="21.817987"
+       r="8.3085051" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient3890"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,0,0,2.252104,-25.05975,-18.941)"
+       cx="15.414371"
+       cy="13.078408"
+       fx="15.414371"
+       fy="13.078408"
+       r="6.6562500" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#3465a4"
+     inkscape:window-y="0"
+     inkscape:window-x="0"
+     inkscape:window-height="1052"
+     inkscape:window-width="1920"
+     inkscape:showpageshadow="false"
+     inkscape:document-units="px"
+     inkscape:grid-bbox="true"
+     showgrid="false"
+     inkscape:current-layer="g1037"
+     inkscape:cy="10.06332"
+     inkscape:cx="-10.858184"
+     inkscape:zoom="5.6568543"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="0.25490196"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     fill="#729fcf"
+     inkscape:object-paths="true"
+     inkscape:window-maximized="1"
+     inkscape:snap-global="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3085" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Martin Ruskov</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://commons.wikimedia.org/wiki/Tango_icon</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Shadow"
+     sodipodi:insensitive="true">
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.17112301;color:#000000;fill:url(#radialGradient2842);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+       id="path4475"
+       sodipodi:cx="24.130018"
+       sodipodi:cy="37.967922"
+       sodipodi:rx="16.528622"
+       sodipodi:ry="3.9332814"
+       d="m 40.65864,37.967922 a 16.528622,3.9332814 0 1 1 -33.0572434,0 16.528622,3.9332814 0 1 1 33.0572434,0 z"
+       transform="matrix(1.446431,0,0,1.51999,-10.97453,-17.75168)" />
+    <path
+       transform="matrix(0.497764,0,0,0.609621,8.973526,15.61929)"
+       d="m 40.65864,37.967922 a 16.528622,3.9332814 0 1 1 -33.0572434,0 16.528622,3.9332814 0 1 1 33.0572434,0 z"
+       sodipodi:ry="3.9332814"
+       sodipodi:rx="16.528622"
+       sodipodi:cy="37.967922"
+       sodipodi:cx="24.130018"
+       id="path4485"
+       style="color:#000000;fill:url(#radialGradient4493);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+       sodipodi:type="arc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Magnifying glass"
+     sodipodi:insensitive="true">
+    <g
+       id="g1772"
+       transform="translate(0.12372323,0.07535096)">
+      <path
+         sodipodi:nodetypes="csscccscccscczzzz"
+         id="path2844"
+         d="m 18.627569,3.1435548 c -8.13913,0 -14.7448008,6.6056711 -14.7448008,14.7448012 0,8.13913 6.6056708,14.744802 14.7448008,14.744802 3.479555,0 6.551001,-1.384393 9.073723,-3.402647 -0.205377,1.006881 -0.07803,2.035368 0.756144,2.759925 l 10.964084,9.52741 c 1.233416,1.071329 3.087462,0.93096 4.15879,-0.302457 1.071328,-1.233418 0.930959,-3.087462 -0.302457,-4.15879 L 32.313769,27.529188 c -0.671527,-0.583279 -1.492878,-0.755969 -2.306238,-0.642722 1.9867,-2.512422 3.364839,-5.548803 3.364839,-8.99811 0,-8.1391301 -6.605671,-14.7448012 -14.744801,-14.7448012 z m -0.07562,1.2261833 c 7.639459,0 13.291775,4.7889505 13.291775,13.2917749 0,8.675113 -5.81669,13.291775 -13.291775,13.291775 -7.302949,0 -13.2917734,-5.478092 -13.2917734,-13.291775 0,-7.9841069 5.8246384,-13.291775 13.2917734,-13.2917749 z"
+         style="color:#000000;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3882);stroke-width:2.00000095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         inkscape:connector-curvature="0" />
+      <path
+         style="color:#000000;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000036;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 18.602905,3.0803551 c -8.16544,0 -14.7924642,6.627024 -14.7924642,14.7924639 0,8.16544 6.6270242,14.792464 14.7924642,14.792464 3.490803,0 6.572177,-1.388867 9.103055,-3.413645 -0.206041,1.010136 -0.07829,2.041947 0.758587,2.768846 l 10.999526,9.558207 c 1.237403,1.074792 3.097442,0.93397 4.172233,-0.303435 1.074791,-1.237404 0.933968,-3.097442 -0.303435,-4.172233 L 32.333346,27.544815 c -0.673698,-0.585164 -1.497704,-0.758413 -2.313693,-0.644799 1.993122,-2.520544 3.375716,-5.56674 3.375716,-9.027197 0,-8.1654399 -6.627024,-14.7924639 -14.792464,-14.7924639 z m -0.07586,3.1860692 c 6.281108,2e-7 11.378818,5.0977107 11.378818,11.3788187 0,6.281108 -5.09771,11.378818 -11.378818,11.378818 -6.281108,0 -11.3788184,-5.09771 -11.3788184,-11.378818 2e-7,-6.281108 5.0977104,-11.3788187 11.3788184,-11.3788187 z"
+         id="path4430"
+         inkscape:connector-curvature="0" />
+      <path
+         style="color:#000000;fill:url(#linearGradient3884);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 39.507004,41.57769 c -0.478672,-2.273187 1.39733,-4.811422 3.584053,-4.788375 0,0 -10.760367,-9.258111 -10.760367,-9.258111 -2.944791,-0.05671 -4.269502,2.272616 -3.776814,4.599922 l 10.953128,9.446564 z"
+         id="path4438"
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:type="arc"
+         style="color:#000000;fill:none;stroke:url(#linearGradient3886);stroke-width:0.8027336;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         id="path4450"
+         sodipodi:cx="17.500893"
+         sodipodi:cy="18.920233"
+         sodipodi:rx="11.048544"
+         sodipodi:ry="11.048544"
+         d="M 28.549437,18.920233 A 11.048544,11.048544 0 0 1 17.500893,29.968777 11.048544,11.048544 0 0 1 6.4523487,18.920233 11.048544,11.048544 0 0 1 17.500893,7.8716888 11.048544,11.048544 0 0 1 28.549437,18.920233 Z"
+         transform="matrix(1.245743,0,0,1.245743,-3.425346,-6.177033)" />
+      <rect
+         style="opacity:0.43315507;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.00003111;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         id="rect4495"
+         width="19.048439"
+         height="4.4404783"
+         x="40.373337"
+         y="0.14086054"
+         rx="2.1366608"
+         ry="1.8879365"
+         transform="matrix(0.752986,0.658037,-0.648902,0.760872,0,0)" />
+      <path
+         sodipodi:type="arc"
+         style="color:#000000;fill:url(#radialGradient3888);fill-opacity:1;fill-rule:evenodd;stroke:#3063a3;stroke-width:0.71499395;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible"
+         id="path4452"
+         sodipodi:cx="17.589281"
+         sodipodi:cy="18.478292"
+         sodipodi:rx="8.3085051"
+         sodipodi:ry="8.3085051"
+         d="m 25.897786,18.478292 a 8.3085051,8.3085051 0 0 1 -8.308505,8.308506 8.3085051,8.3085051 0 0 1 -8.308505,-8.308506 8.3085051,8.3085051 0 0 1 8.308505,-8.308505 8.3085051,8.3085051 0 0 1 8.308505,8.308505 z"
+         transform="matrix(1.398614,0,0,1.398614,-6.224338,-8.298958)" />
+      <path
+         style="opacity:0.83422457;color:#000000;fill:url(#radialGradient3890);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 18.156915,7.3966938 c -5.20759,0 -9.4245469,4.2169572 -9.4245469,9.4245472 0,1.503975 0.4203072,2.887773 1.0471719,4.149903 1.25238,0.461613 2.582757,0.775683 3.994767,0.775683 6.170955,0 11.099282,-4.861637 11.480106,-10.937129 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 z"
+         id="path4462"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     inkscape:label="Symbol"
+     id="layer1"
+     style="display:inline">
+    <g
+       id="g1037"
+       transform="translate(0.4375,0.375)">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1031"
+         d="M 18.4375,8.3269029 V 25.799937"
+         style="fill:none;stroke:#3063a3;stroke-width:3.35902286;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-dashoffset:0" />
+      <path
+         style="fill:none;stroke:#3063a3;stroke-width:3.35902286;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-variant-east_asian:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-dashoffset:0"
+         d="M 27.174017,17.06342 H 9.7009829"
+         id="path1009"
+         inkscape:connector-curvature="0"
+         inkscape:export-xdpi="64"
+         inkscape:export-ydpi="64" />
+    </g>
+  </g>
+</svg>
Binary file libgui/src/icons/figure-zoom-original.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-zoom-original.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="48"
+   height="48"
+   id="svg11300"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="figure-zoom-original.svg"
+   inkscape:export-filename="/home/pantxo/Dev/octaveclone/libgui/src/icons/figure-zoom-original.png"
+   inkscape:export-xdpi="64"
+   inkscape:export-ydpi="64">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1052"
+     id="namedview5046"
+     showgrid="true"
+     inkscape:zoom="16"
+     inkscape:cx="1.03237"
+     inkscape:cy="32.234375"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg11300">
+    <inkscape:grid
+       type="xygrid"
+       id="grid5048" />
+  </sodipodi:namedview>
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient2846">
+      <stop
+         id="stop2848"
+         style="stop-color:#8a8a8a;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop2850"
+         style="stop-color:#484848;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366">
+      <stop
+         id="stop2368"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop2374"
+         style="stop-color:#ffffff;stop-opacity:0.21904762"
+         offset="0.5" />
+      <stop
+         id="stop2370"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4487">
+      <stop
+         id="stop4489"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4491"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4477">
+      <stop
+         id="stop4479"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4481"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467">
+      <stop
+         id="stop4469"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4471"
+         style="stop-color:#ffffff;stop-opacity:0.24761905"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454">
+      <stop
+         id="stop4456"
+         style="stop-color:#729fcf;stop-opacity:0.20784314"
+         offset="0" />
+      <stop
+         id="stop4458"
+         style="stop-color:#729fcf;stop-opacity:0.6761905"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4440">
+      <stop
+         id="stop4442"
+         style="stop-color:#7d7d7d;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4448"
+         style="stop-color:#b1b1b1;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop4444"
+         style="stop-color:#686868;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="30.65625"
+       y1="34"
+       x2="33.21875"
+       y2="31.0625"
+       id="linearGradient4446"
+       xlink:href="#linearGradient4440"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0,0,1.291292,-6.973842,-7.460658)" />
+    <radialGradient
+       cx="18.240929"
+       cy="21.817987"
+       r="8.3085051"
+       fx="18.240929"
+       fy="21.817987"
+       id="radialGradient4460"
+       xlink:href="#linearGradient4454"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.398614,0,0,1.398614,-6.224338,-8.298958)" />
+    <radialGradient
+       cx="15.414371"
+       cy="13.078408"
+       r="6.65625"
+       fx="15.414371"
+       fy="13.078408"
+       id="radialGradient4473"
+       xlink:href="#linearGradient4467"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,0,0,2.252104,-25.05975,-18.941)" />
+    <radialGradient
+       cx="24.130018"
+       cy="37.967922"
+       r="16.528622"
+       fx="24.130018"
+       fy="37.967922"
+       id="radialGradient4493"
+       xlink:href="#linearGradient4487"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.497764,0,0,0.14507029,8.973526,33.25732)" />
+    <linearGradient
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469"
+       id="linearGradient2372"
+       xlink:href="#linearGradient2366"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.245743,0,0,1.245743,-3.425346,-6.177033)" />
+    <radialGradient
+       cx="24.130018"
+       cy="37.967922"
+       r="16.528622"
+       fx="24.130018"
+       fy="37.967922"
+       id="radialGradient2842"
+       xlink:href="#linearGradient4477"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.446431,0,0,0.36170898,-10.97453,26.225856)" />
+    <linearGradient
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772"
+       id="linearGradient2852"
+       xlink:href="#linearGradient2846"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       cx="18.240929"
+       cy="21.817987"
+       r="8.3085051"
+       fx="18.240929"
+       fy="21.817987"
+       id="radialGradient4460-4"
+       xlink:href="#linearGradient4454"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.398614,0,0,1.398614,-12.480222,-13.719877)" />
+  </defs>
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="m 47.835387,39.959182 a 23.907511,5.9785484 0 1 1 -47.81502131,0 23.907511,5.9785484 0 1 1 47.81502131,0 z"
+     id="path4475"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.17112301;fill:url(#radialGradient2842);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.48275447;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 18.627569,3.1435548 c -8.13913,0 -14.7448008,6.6056711 -14.7448008,14.7448012 0,8.13913 6.6056708,14.744802 14.7448008,14.744802 3.479555,0 6.551001,-1.384393 9.073723,-3.402647 -0.205377,1.006881 -0.07803,2.035368 0.756144,2.759925 l 10.964084,9.52741 c 1.233416,1.071329 3.087462,0.93096 4.15879,-0.302457 1.071328,-1.233418 0.930959,-3.087462 -0.302457,-4.15879 L 32.313769,27.529188 c -0.671527,-0.583279 -1.492878,-0.755969 -2.306238,-0.642722 1.9867,-2.512422 3.364839,-5.548803 3.364839,-8.99811 0,-8.1391301 -6.605671,-14.7448012 -14.744801,-14.7448012 z m -0.07562,1.2261833 c 7.639459,0 13.291775,4.7889505 13.291775,13.2917749 0,8.675113 -5.81669,13.291775 -13.291775,13.291775 -7.302949,0 -13.2917734,-5.478092 -13.2917734,-13.291775 0,-7.9841069 5.8246384,-13.291775 13.2917734,-13.2917749 z"
+     id="path2844"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2852);stroke-width:2.00000095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 18.602905,3.0803551 c -8.16544,0 -14.7924642,6.627024 -14.7924642,14.7924639 0,8.16544 6.6270242,14.792464 14.7924642,14.792464 3.490803,0 6.572177,-1.388867 9.103055,-3.413645 -0.206041,1.010136 -0.07829,2.041947 0.758587,2.768846 l 10.999526,9.558207 c 1.237403,1.074792 3.097442,0.93397 4.172233,-0.303435 1.074791,-1.237404 0.933968,-3.097442 -0.303435,-4.172233 L 32.333346,27.544815 c -0.673698,-0.585164 -1.497704,-0.758413 -2.313693,-0.644799 1.993122,-2.520544 3.375716,-5.56674 3.375716,-9.027197 0,-8.1654399 -6.627024,-14.7924639 -14.792464,-14.7924639 z m -0.07586,3.1860692 c 6.281108,2e-7 11.378818,5.0977107 11.378818,11.3788187 0,6.281108 -5.09771,11.378818 -11.378818,11.378818 -6.281108,0 -11.3788184,-5.09771 -11.3788184,-11.378818 2e-7,-6.281108 5.0977104,-11.3788187 11.3788184,-11.3788187 z"
+     id="path4430"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000036;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 39.507004,41.57769 c -0.478672,-2.273187 1.39733,-4.811422 3.584053,-4.788375 0,0 -10.760367,-9.258111 -10.760367,-9.258111 -2.944791,-0.05671 -4.269502,2.272616 -3.776814,4.599922 z"
+     id="path4438"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient4446);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 32.139915,17.392715 a 13.763647,13.763647 0 1 1 -27.5272928,0 13.763647,13.763647 0 1 1 27.5272928,0 z"
+     id="path4450"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient2372);stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 29.211933,38.765333 a 8.227353,2.3978109 0 1 1 -16.454705,0 8.227353,2.3978109 0 1 1 16.454705,0 z"
+     id="path4485"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient4493);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.55086058;marker:none"
+     inkscape:connector-curvature="0" />
+  <rect
+     width="19.048445"
+     height="4.4404783"
+     rx="2.1366615"
+     ry="1.8879365"
+     x="40.373348"
+     y="0.14086054"
+     transform="matrix(0.75298577,0.6580368,-0.648902,0.760872,0,0)"
+     id="rect4495"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.43315507;fill:none;stroke:#ffffff;stroke-width:1.00003111;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" />
+  <path
+     d="m 29.996668,17.54504 a 11.620392,11.620392 0 1 1 -23.2407828,0 11.620392,11.620392 0 1 1 23.2407828,0 z"
+     id="path4452"
+     style="color:#000000;visibility:visible;fill:url(#radialGradient4460);fill-opacity:1;fill-rule:evenodd;stroke:#3063a3;stroke-width:1.0000006;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dashoffset:0;stroke-opacity:1;marker:none"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 18.156915,7.3966938 c -5.20759,0 -9.4245469,4.2169572 -9.4245469,9.4245472 0,1.503975 0.4203072,2.887773 1.0471719,4.149903 1.25238,0.461613 2.582757,0.775683 3.994767,0.775683 6.170955,0 11.099282,-4.861637 11.480106,-10.937129 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 Z"
+     id="path4462"
+     style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.83422457;fill:url(#radialGradient4473);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
+     inkscape:connector-curvature="0" />
+  <text
+     id="text2696"
+     y="25.497047"
+     x="11.396652"
+     style="font-style:normal;font-weight:normal;font-size:23.87401581px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#3063a3;fill-opacity:1;stroke:none;stroke-width:1.0000006;font-variant-east_asian:normal;opacity:1;vector-effect:none;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;"
+     xml:space="preserve"><tspan
+       style="stroke-width:1.0000006;fill:#3063a3;font-variant-east_asian:normal;vector-effect:none;fill-opacity:1;stroke:none;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;"
+       y="25.497047"
+       x="11.396652"
+       id="tspan2694"
+       sodipodi:role="line">1</tspan></text>
+</svg>
Binary file libgui/src/icons/figure-zoom-out.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-zoom-out.svg	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,1180 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="figure-zoom-out.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:version="0.32"
+   id="svg11300"
+   height="48px"
+   width="48px"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1"
+   inkscape:export-filename="/home/pantxo/Dev/octaveclone/libgui/src/icons/figure-zoom-out.png"
+   inkscape:export-xdpi="64"
+   inkscape:export-ydpi="64">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient2846">
+      <stop
+         id="stop2848"
+         offset="0.0000000"
+         style="stop-color:#8a8a8a;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2850"
+         offset="1.0000000"
+         style="stop-color:#484848;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366">
+      <stop
+         id="stop2368"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.21904762;"
+         offset="0.50000000"
+         id="stop2374" />
+      <stop
+         id="stop2370"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4487">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4489" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4491" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4477">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4479" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4481" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4469" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.24761905;"
+         offset="1.0000000"
+         id="stop4471" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:0.20784314;"
+         offset="0.0000000"
+         id="stop4456" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:0.67619050;"
+         offset="1.0000000"
+         id="stop4458" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4440">
+      <stop
+         style="stop-color:#7d7d7d;stop-opacity:1;"
+         offset="0"
+         id="stop4442" />
+      <stop
+         id="stop4448"
+         offset="0.50000000"
+         style="stop-color:#b1b1b1;stop-opacity:1.0000000;" />
+      <stop
+         style="stop-color:#686868;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop4444" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4440"
+       id="linearGradient4446"
+       x1="30.656250"
+       y1="34.000000"
+       x2="33.218750"
+       y2="31.062500"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0.000000,0.000000,1.291292,-6.973842,-7.460658)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4454"
+       id="radialGradient4460"
+       cx="18.240929"
+       cy="21.817987"
+       fx="18.240929"
+       fy="21.817987"
+       r="8.3085051"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient4473"
+       cx="15.414371"
+       cy="13.078408"
+       fx="15.414371"
+       fy="13.078408"
+       r="6.6562500"
+       gradientTransform="matrix(2.592963,-7.746900e-24,-5.714443e-24,2.252104,-25.05975,-18.94100)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4487"
+       id="radialGradient4493"
+       cx="24.130018"
+       cy="37.967922"
+       fx="24.130018"
+       fy="37.967922"
+       r="16.528622"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,3.152859e-15,28.93278)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="25.743469"
+       x2="17.500893"
+       y1="13.602121"
+       x1="18.292673"
+       id="linearGradient2372"
+       xlink:href="#linearGradient2366"
+       inkscape:collect="always" />
+    <radialGradient
+       r="16.528622"
+       fy="37.967922"
+       fx="24.130018"
+       cy="37.967922"
+       cx="24.130018"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,-2.471981e-16,28.93278)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2842"
+       xlink:href="#linearGradient4477"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="30.557772"
+       x2="31.335964"
+       y1="26.580296"
+       x1="27.366341"
+       id="linearGradient2852"
+       xlink:href="#linearGradient2846"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
+       r="10.319340"
+       fy="35.127438"
+       fx="23.070683"
+       cy="35.127438"
+       cx="23.070683"
+       id="radialGradient2097"
+       xlink:href="#linearGradient2091"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="50.939667"
+       x2="45.380436"
+       y1="45.264122"
+       x1="46.834816"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7186"
+       xlink:href="#linearGradient2871"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="26.649362"
+       x2="53.588622"
+       y1="23.667896"
+       x1="18.935766"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7184"
+       xlink:href="#linearGradient2402"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="50.939667"
+       x2="45.380436"
+       y1="45.264122"
+       x1="46.834816"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7182"
+       xlink:href="#linearGradient2871"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="20.60858"
+       x2="15.984863"
+       y1="36.061237"
+       x1="62.513836"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7180"
+       xlink:href="#linearGradient2380"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)"
+       y2="23.554308"
+       x2="22.374878"
+       y1="13.604306"
+       x1="13.435029"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient7189"
+       xlink:href="#linearGradient7179"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="23.554308"
+       x2="22.374878"
+       y1="13.604306"
+       x1="13.435029"
+       id="linearGradient7185"
+       xlink:href="#linearGradient7179"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1322">
+      <stop
+         style="stop-color:#729fcf"
+         offset="0.0000000"
+         id="stop1324" />
+      <stop
+         style="stop-color:#5187d6;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop1326" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2316">
+      <stop
+         id="stop2318"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2320"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0.65979379;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7179"
+       inkscape:collect="always">
+      <stop
+         id="stop7181"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop7183"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.048164"
+       x2="52.854097"
+       y1="26.048164"
+       x1="5.9649176"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1491"
+       xlink:href="#linearGradient2797"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2797"
+       inkscape:collect="always">
+      <stop
+         id="stop2799"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2801"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.048164"
+       x2="52.854097"
+       y1="26.048164"
+       x1="5.9649176"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1493"
+       xlink:href="#linearGradient2797"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2402">
+      <stop
+         id="stop2404"
+         offset="0"
+         style="stop-color:#729fcf;stop-opacity:1;" />
+      <stop
+         id="stop2406"
+         offset="1"
+         style="stop-color:#528ac5;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2871"
+       inkscape:collect="always">
+      <stop
+         id="stop2873"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         id="stop2875"
+         offset="1"
+         style="stop-color:#3465a4;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-48.77039,-5.765705)"
+       gradientUnits="userSpaceOnUse"
+       y2="24.842253"
+       x2="37.124462"
+       y1="30.748846"
+       x1="32.647972"
+       id="linearGradient2696"
+       xlink:href="#linearGradient2690"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2690"
+       inkscape:collect="always">
+      <stop
+         id="stop2692"
+         offset="0"
+         style="stop-color:#c4d7eb;stop-opacity:1;" />
+      <stop
+         id="stop2694"
+         offset="1"
+         style="stop-color:#c4d7eb;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-48.77039,-5.765705)"
+       gradientUnits="userSpaceOnUse"
+       y2="24.842253"
+       x2="37.124462"
+       y1="31.455952"
+       x1="36.713837"
+       id="linearGradient2688"
+       xlink:href="#linearGradient2682"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2682">
+      <stop
+         id="stop2684"
+         offset="0"
+         style="stop-color:#3977c3;stop-opacity:1;" />
+      <stop
+         id="stop2686"
+         offset="1"
+         style="stop-color:#89aedc;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2380">
+      <stop
+         id="stop2382"
+         offset="0"
+         style="stop-color:#b9cfe7;stop-opacity:1" />
+      <stop
+         id="stop2384"
+         offset="1"
+         style="stop-color:#729fcf;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       y2="19.115122"
+       x2="15.419417"
+       y1="10.612206"
+       x1="13.478554"
+       gradientTransform="translate(-48.30498,-6.043298)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1486"
+       xlink:href="#linearGradient2831"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2831">
+      <stop
+         id="stop2833"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         style="stop-color:#5b86be;stop-opacity:1;"
+         offset="0.33333334"
+         id="stop2855" />
+      <stop
+         id="stop2835"
+         offset="1"
+         style="stop-color:#83a8d8;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="26.194071"
+       x2="37.065414"
+       y1="29.729605"
+       x1="37.128052"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1488"
+       xlink:href="#linearGradient2847"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2847"
+       inkscape:collect="always">
+      <stop
+         id="stop2849"
+         offset="0"
+         style="stop-color:#3465a4;stop-opacity:1;" />
+      <stop
+         id="stop2851"
+         offset="1"
+         style="stop-color:#3465a4;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="15.644737"
+       fy="36.421127"
+       fx="24.837126"
+       cy="36.421127"
+       cx="24.837126"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1503"
+       xlink:href="#linearGradient8662"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient8662"
+       inkscape:collect="always">
+      <stop
+         id="stop8664"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop8666"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7916">
+      <stop
+         id="stop7918"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop7920"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.34020618;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2091"
+       inkscape:collect="always">
+      <stop
+         id="stop2093"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2095"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2091-4">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop2093-5" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop2095-1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7916-4">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7918-2" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.34020618;"
+         offset="1.0000000"
+         id="stop7920-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662-1">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664-8" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666-3" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662-1"
+       id="radialGradient1503-3"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.536723,-1.018989e-13,16.87306)"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2847-9">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2849-2" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:0;"
+         offset="1"
+         id="stop2851-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2847-9"
+       id="linearGradient1488-8"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,-1.242480,40.08170)"
+       x1="37.128052"
+       y1="29.729605"
+       x2="37.065414"
+       y2="26.194071" />
+    <linearGradient
+       id="linearGradient2831-3">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2833-8" />
+      <stop
+         id="stop2855-6"
+         offset="0.33333334"
+         style="stop-color:#5b86be;stop-opacity:1;" />
+      <stop
+         style="stop-color:#83a8d8;stop-opacity:0;"
+         offset="1"
+         id="stop2835-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2831-3"
+       id="linearGradient1486-4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.30498,-6.043298)"
+       x1="13.478554"
+       y1="10.612206"
+       x2="15.419417"
+       y2="19.115122" />
+    <linearGradient
+       id="linearGradient2380-5">
+      <stop
+         style="stop-color:#b9cfe7;stop-opacity:1"
+         offset="0"
+         id="stop2382-2" />
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1"
+         offset="1"
+         id="stop2384-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2682-7">
+      <stop
+         style="stop-color:#3977c3;stop-opacity:1;"
+         offset="0"
+         id="stop2684-4" />
+      <stop
+         style="stop-color:#89aedc;stop-opacity:0;"
+         offset="1"
+         id="stop2686-2" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2682-7"
+       id="linearGradient2688-2"
+       x1="36.713837"
+       y1="31.455952"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.77039,-5.765705)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2690-3">
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:1;"
+         offset="0"
+         id="stop2692-4" />
+      <stop
+         style="stop-color:#c4d7eb;stop-opacity:0;"
+         offset="1"
+         id="stop2694-9" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2690-3"
+       id="linearGradient2696-0"
+       x1="32.647972"
+       y1="30.748846"
+       x2="37.124462"
+       y2="24.842253"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-48.77039,-5.765705)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2871-3">
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1;"
+         offset="0"
+         id="stop2873-7" />
+      <stop
+         style="stop-color:#3465a4;stop-opacity:1"
+         offset="1"
+         id="stop2875-0" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2402-2">
+      <stop
+         style="stop-color:#729fcf;stop-opacity:1;"
+         offset="0"
+         id="stop2404-8" />
+      <stop
+         style="stop-color:#528ac5;stop-opacity:1;"
+         offset="1"
+         id="stop2406-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797-7"
+       id="linearGradient1493-3"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2797-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2799-4" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2801-0" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2797-7"
+       id="linearGradient1491-2"
+       gradientUnits="userSpaceOnUse"
+       x1="5.9649176"
+       y1="26.048164"
+       x2="52.854097"
+       y2="26.048164" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient7179-1">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7181-0" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop7183-4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2316-2">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop2318-6" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.65979379;"
+         offset="1"
+         id="stop2320-9" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1322-8">
+      <stop
+         id="stop1324-1"
+         offset="0.0000000"
+         style="stop-color:#729fcf" />
+      <stop
+         id="stop1326-2"
+         offset="1.0000000"
+         style="stop-color:#5187d6;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1322-8"
+       id="linearGradient4975-0"
+       x1="34.892849"
+       y1="36.422989"
+       x2="45.918697"
+       y2="48.547989"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-18.01785,-13.57119)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7179-1"
+       id="linearGradient7185-5"
+       x1="13.435029"
+       y1="13.604306"
+       x2="22.374878"
+       y2="23.554308"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7179-1"
+       id="linearGradient7189-6"
+       gradientUnits="userSpaceOnUse"
+       x1="13.435029"
+       y1="13.604306"
+       x2="22.374878"
+       y2="23.554308"
+       gradientTransform="matrix(-1.000000,0.000000,0.000000,-1.000000,47.93934,50.02474)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2380-5"
+       id="linearGradient7180-0"
+       gradientUnits="userSpaceOnUse"
+       x1="62.513836"
+       y1="36.061237"
+       x2="15.984863"
+       y2="20.60858" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871-3"
+       id="linearGradient7182-5"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2402-2"
+       id="linearGradient7184-1"
+       gradientUnits="userSpaceOnUse"
+       x1="18.935766"
+       y1="23.667896"
+       x2="53.588622"
+       y2="26.649362" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2871-3"
+       id="linearGradient7186-6"
+       gradientUnits="userSpaceOnUse"
+       x1="46.834816"
+       y1="45.264122"
+       x2="45.380436"
+       y2="50.939667" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7916-4"
+       id="linearGradient7922-7"
+       x1="16.874998"
+       y1="22.851799"
+       x2="27.900846"
+       y2="34.976799"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2091-4"
+       id="radialGradient2097-3"
+       cx="23.070683"
+       cy="35.127438"
+       fx="23.070683"
+       fy="35.127438"
+       r="10.319340"
+       gradientTransform="matrix(0.914812,1.265023e-2,-8.21502e-3,0.213562,2.253914,27.18889)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2846-0"
+       id="linearGradient2852-6"
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4477-1"
+       id="radialGradient2842-7"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.237968,0,28.93278)"
+       cx="24.130018"
+       cy="37.967922"
+       fx="24.130018"
+       fy="37.967922"
+       r="16.528622" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2366-6"
+       id="linearGradient2372-0"
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.237968,0,28.93278)"
+       r="16.528622"
+       fy="37.967922"
+       fx="24.130018"
+       cy="37.967922"
+       cx="24.130018"
+       id="radialGradient4493-9"
+       xlink:href="#linearGradient4487-8"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,0,0,2.252104,-25.05975,-18.941)"
+       r="6.6562500"
+       fy="13.078408"
+       fx="15.414371"
+       cy="13.078408"
+       cx="15.414371"
+       id="radialGradient4473-9"
+       xlink:href="#linearGradient4467-5"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.3085051"
+       fy="21.817987"
+       fx="18.240929"
+       cy="21.817987"
+       cx="18.240929"
+       id="radialGradient4460-5"
+       xlink:href="#linearGradient4454-4"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.334593,0,0,1.291292,-6.973842,-7.460658)"
+       gradientUnits="userSpaceOnUse"
+       y2="31.062500"
+       x2="33.218750"
+       y1="34.000000"
+       x1="30.656250"
+       id="linearGradient4446-6"
+       xlink:href="#linearGradient4440-0"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient4440-0">
+      <stop
+         id="stop4442-8"
+         offset="0"
+         style="stop-color:#7d7d7d;stop-opacity:1;" />
+      <stop
+         style="stop-color:#b1b1b1;stop-opacity:1.0000000;"
+         offset="0.50000000"
+         id="stop4448-3" />
+      <stop
+         id="stop4444-5"
+         offset="1.0000000"
+         style="stop-color:#686868;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454-4">
+      <stop
+         id="stop4456-1"
+         offset="0.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.20784314;" />
+      <stop
+         id="stop4458-5"
+         offset="1.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.67619050;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467-5">
+      <stop
+         id="stop4469-9"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4471-3"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.24761905;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4477-1"
+       inkscape:collect="always">
+      <stop
+         id="stop4479-1"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop4481-3"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4487-8"
+       inkscape:collect="always">
+      <stop
+         id="stop4489-0"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4491-4"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366-6">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2368-3" />
+      <stop
+         id="stop2374-5"
+         offset="0.50000000"
+         style="stop-color:#ffffff;stop-opacity:0.21904762;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2370-0" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2846-0">
+      <stop
+         style="stop-color:#8a8a8a;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2848-8" />
+      <stop
+         style="stop-color:#484848;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2850-7" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2846"
+       id="linearGradient3882"
+       gradientUnits="userSpaceOnUse"
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4440"
+       id="linearGradient3884"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0,0,1.291292,-6.973842,-7.460658)"
+       x1="30.656250"
+       y1="34.000000"
+       x2="33.218750"
+       y2="31.062500" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2366"
+       id="linearGradient3886"
+       gradientUnits="userSpaceOnUse"
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4454"
+       id="radialGradient3888"
+       gradientUnits="userSpaceOnUse"
+       cx="18.240929"
+       cy="21.817987"
+       fx="18.240929"
+       fy="21.817987"
+       r="8.3085051" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient3890"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,0,0,2.252104,-25.05975,-18.941)"
+       cx="15.414371"
+       cy="13.078408"
+       fx="15.414371"
+       fy="13.078408"
+       r="6.6562500" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#3465a4"
+     inkscape:window-y="0"
+     inkscape:window-x="0"
+     inkscape:window-height="1052"
+     inkscape:window-width="1920"
+     inkscape:showpageshadow="false"
+     inkscape:document-units="px"
+     inkscape:grid-bbox="true"
+     showgrid="false"
+     inkscape:current-layer="g4336"
+     inkscape:cy="16.836574"
+     inkscape:cx="7.5214099"
+     inkscape:zoom="16"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="0.25490196"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     fill="#729fcf"
+     inkscape:object-paths="true"
+     inkscape:window-maximized="1"
+     inkscape:snap-global="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3085" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Martin Ruskov</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://commons.wikimedia.org/wiki/Tango_icon</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Shadow"
+     sodipodi:insensitive="true">
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.17112301;color:#000000;fill:url(#radialGradient2842);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+       id="path4475"
+       sodipodi:cx="24.130018"
+       sodipodi:cy="37.967922"
+       sodipodi:rx="16.528622"
+       sodipodi:ry="3.9332814"
+       d="m 40.65864,37.967922 a 16.528622,3.9332814 0 1 1 -33.0572434,0 16.528622,3.9332814 0 1 1 33.0572434,0 z"
+       transform="matrix(1.446431,0,0,1.51999,-10.97453,-17.75168)" />
+    <path
+       transform="matrix(0.497764,0,0,0.609621,8.973526,15.61929)"
+       d="m 40.65864,37.967922 a 16.528622,3.9332814 0 1 1 -33.0572434,0 16.528622,3.9332814 0 1 1 33.0572434,0 z"
+       sodipodi:ry="3.9332814"
+       sodipodi:rx="16.528622"
+       sodipodi:cy="37.967922"
+       sodipodi:cx="24.130018"
+       id="path4485"
+       style="color:#000000;fill:url(#radialGradient4493);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+       sodipodi:type="arc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Magnifying glass"
+     sodipodi:insensitive="true">
+    <g
+       id="g1772"
+       transform="translate(0.12372323,0.07535096)">
+      <path
+         sodipodi:nodetypes="csscccscccscczzzz"
+         id="path2844"
+         d="m 18.627569,3.1435548 c -8.13913,0 -14.7448008,6.6056711 -14.7448008,14.7448012 0,8.13913 6.6056708,14.744802 14.7448008,14.744802 3.479555,0 6.551001,-1.384393 9.073723,-3.402647 -0.205377,1.006881 -0.07803,2.035368 0.756144,2.759925 l 10.964084,9.52741 c 1.233416,1.071329 3.087462,0.93096 4.15879,-0.302457 1.071328,-1.233418 0.930959,-3.087462 -0.302457,-4.15879 L 32.313769,27.529188 c -0.671527,-0.583279 -1.492878,-0.755969 -2.306238,-0.642722 1.9867,-2.512422 3.364839,-5.548803 3.364839,-8.99811 0,-8.1391301 -6.605671,-14.7448012 -14.744801,-14.7448012 z m -0.07562,1.2261833 c 7.639459,0 13.291775,4.7889505 13.291775,13.2917749 0,8.675113 -5.81669,13.291775 -13.291775,13.291775 -7.302949,0 -13.2917734,-5.478092 -13.2917734,-13.291775 0,-7.9841069 5.8246384,-13.291775 13.2917734,-13.2917749 z"
+         style="color:#000000;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3882);stroke-width:2.00000095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         inkscape:connector-curvature="0" />
+      <path
+         style="color:#000000;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000036;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 18.602905,3.0803551 c -8.16544,0 -14.7924642,6.627024 -14.7924642,14.7924639 0,8.16544 6.6270242,14.792464 14.7924642,14.792464 3.490803,0 6.572177,-1.388867 9.103055,-3.413645 -0.206041,1.010136 -0.07829,2.041947 0.758587,2.768846 l 10.999526,9.558207 c 1.237403,1.074792 3.097442,0.93397 4.172233,-0.303435 1.074791,-1.237404 0.933968,-3.097442 -0.303435,-4.172233 L 32.333346,27.544815 c -0.673698,-0.585164 -1.497704,-0.758413 -2.313693,-0.644799 1.993122,-2.520544 3.375716,-5.56674 3.375716,-9.027197 0,-8.1654399 -6.627024,-14.7924639 -14.792464,-14.7924639 z m -0.07586,3.1860692 c 6.281108,2e-7 11.378818,5.0977107 11.378818,11.3788187 0,6.281108 -5.09771,11.378818 -11.378818,11.378818 -6.281108,0 -11.3788184,-5.09771 -11.3788184,-11.378818 2e-7,-6.281108 5.0977104,-11.3788187 11.3788184,-11.3788187 z"
+         id="path4430"
+         inkscape:connector-curvature="0" />
+      <path
+         style="color:#000000;fill:url(#linearGradient3884);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 39.507004,41.57769 c -0.478672,-2.273187 1.39733,-4.811422 3.584053,-4.788375 0,0 -10.760367,-9.258111 -10.760367,-9.258111 -2.944791,-0.05671 -4.269502,2.272616 -3.776814,4.599922 l 10.953128,9.446564 z"
+         id="path4438"
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:type="arc"
+         style="color:#000000;fill:none;stroke:url(#linearGradient3886);stroke-width:0.8027336;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         id="path4450"
+         sodipodi:cx="17.500893"
+         sodipodi:cy="18.920233"
+         sodipodi:rx="11.048544"
+         sodipodi:ry="11.048544"
+         d="M 28.549437,18.920233 A 11.048544,11.048544 0 0 1 17.500893,29.968777 11.048544,11.048544 0 0 1 6.4523487,18.920233 11.048544,11.048544 0 0 1 17.500893,7.8716888 11.048544,11.048544 0 0 1 28.549437,18.920233 Z"
+         transform="matrix(1.245743,0,0,1.245743,-3.425346,-6.177033)" />
+      <rect
+         style="opacity:0.43315507;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.00003111;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+         id="rect4495"
+         width="19.048439"
+         height="4.4404783"
+         x="40.373337"
+         y="0.14086054"
+         rx="2.1366608"
+         ry="1.8879365"
+         transform="matrix(0.752986,0.658037,-0.648902,0.760872,0,0)" />
+      <path
+         sodipodi:type="arc"
+         style="color:#000000;fill:url(#radialGradient3888);fill-opacity:1;fill-rule:evenodd;stroke:#3063a3;stroke-width:0.71499395;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible"
+         id="path4452"
+         sodipodi:cx="17.589281"
+         sodipodi:cy="18.478292"
+         sodipodi:rx="8.3085051"
+         sodipodi:ry="8.3085051"
+         d="m 25.897786,18.478292 a 8.3085051,8.3085051 0 0 1 -8.308505,8.308506 8.3085051,8.3085051 0 0 1 -8.308505,-8.308506 8.3085051,8.3085051 0 0 1 8.308505,-8.308505 8.3085051,8.3085051 0 0 1 8.308505,8.308505 z"
+         transform="matrix(1.398614,0,0,1.398614,-6.224338,-8.298958)" />
+      <path
+         style="opacity:0.83422457;color:#000000;fill:url(#radialGradient3890);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         d="m 18.156915,7.3966938 c -5.20759,0 -9.4245469,4.2169572 -9.4245469,9.4245472 0,1.503975 0.4203072,2.887773 1.0471719,4.149903 1.25238,0.461613 2.582757,0.775683 3.994767,0.775683 6.170955,0 11.099282,-4.861637 11.480106,-10.937129 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 z"
+         id="path4462"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     inkscape:label="Symbol"
+     id="layer1"
+     style="display:inline">
+    <g
+       inkscape:label="Layer 1"
+       id="g4336"
+       transform="matrix(0.5028156,0,0,0.5028156,6.3171967,5.1658557)">
+      <path
+         style="display:inline;fill:#3063a3;stroke:#3063a3;stroke-width:6.96080233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+         d="M 41.726775,25.069487 H 6.9763933"
+         id="path1009"
+         inkscape:connector-curvature="0"
+         inkscape:export-xdpi="64"
+         inkscape:export-ydpi="64" />
+    </g>
+  </g>
+</svg>
Binary file libgui/src/icons/fleur.png has changed
Binary file libgui/src/icons/hand2.png has changed
--- a/libgui/src/icons/icons_license	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/icons/icons_license	Fri Jul 12 12:14:43 2019 -0400
@@ -33,6 +33,11 @@
 edit-paste.svg
 edit-redo.svg
 edit-undo.svg
+figure-rotate.svg           (original file view-refresh.svg)
+figure-text.svg             (original file font-x-generic.svg)
+figure-zoom-in.svg          (original file view-zoom-in.svg)
+figure-zoom-original.svg    (original file view-zoom-original.svg)
+figure-zoom-out.svg         (original file view-zoom-out.svg)
 folder.svg
 folder-new.svg
 go-down.svg
@@ -45,12 +50,15 @@
 preferences-system.svg
 user-home.svg
 view-refresh.svg
+view-refresh.svg
 
 ===========================================
 Icons created by the Octave developers
 with elements from the Tango theme
 ===========================================
 
+figure-axes.svg
+figure-grid.svg
 logo.png
 widget-close.svg
 widget-dock.svg
@@ -59,6 +67,7 @@
 Icons with elements from the Tango theme
 ===========================================
 
+figure-pan.svg
 graphic_logo_DocumentationDockWidget.svg
 graphic_logo_FileEditor.svg
 graphic_logo_FilesDockWidget.svg
@@ -87,3 +96,26 @@
 db-stop.svg
 plot-xy-curve.svg
 system-run.svg
+
+Cursors from the standard DMZ theme
+===================================
+
+https://github.com/GalliumOS/dmz-cursor-theme/tree/master/DMZ-White
+
+bottom_left_corner.png
+bottom_right_corner.png
+bottom_side.png
+cross.png
+fleur.png
+hand2.png
+left_side.png
+right_side.png
+top_left_corner.png
+top_right_corner.png
+top_side.png
+
+Cursor created by the Octave developers
+with elements from the DMZ theme:
+
+circle.png
+circle.svg
\ No newline at end of file
Binary file libgui/src/icons/left_side.png has changed
Binary file libgui/src/icons/right_side.png has changed
Binary file libgui/src/icons/top_left_corner.png has changed
Binary file libgui/src/icons/top_right_corner.png has changed
Binary file libgui/src/icons/top_side.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/interpreter-qobject.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,114 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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 "interpreter-qobject.h"
+#include "octave-qobject.h"
+#include "octave-qt-link.h"
+#include "qt-application.h"
+
+#include "input.h"
+#include "interpreter.h"
+
+namespace octave
+{
+  interpreter_qobject::interpreter_qobject (base_qobject *oct_qobj)
+    : QObject (), m_octave_qobject (oct_qobj),
+      m_qt_link (new octave_qt_link ())
+  {
+    octave_link::connect_link (m_qt_link);
+
+    connect (m_qt_link, SIGNAL (confirm_shutdown_signal (void)),
+             m_octave_qobject, SLOT (confirm_shutdown_octave (void)));
+
+    connect (m_qt_link,
+             SIGNAL (copy_image_to_clipboard_signal (const QString&, bool)),
+             m_octave_qobject,
+             SLOT (copy_image_to_clipboard (const QString&, bool)));
+  }
+
+  void interpreter_qobject::execute (void)
+  {
+    // The Octave application context owns the interpreter.
+
+    qt_application& app_context = m_octave_qobject->app_context ();
+
+    interpreter& interp = app_context.create_interpreter ();
+
+    int exit_status = 0;
+
+    try
+      {
+        // Final initialization.
+
+        interp.initialize ();
+
+        if (app_context.start_gui_p ())
+          {
+            input_system& input_sys = interp.get_input_system ();
+
+            input_sys.PS1 (">> ");
+            input_sys.PS2 ("");
+          }
+
+        if (interp.initialized ())
+          {
+            // The interpreter should be completely ready at this point so let
+            // the GUI know.
+
+            emit octave_ready_signal ();
+
+            // Start executing commands in the command window.
+
+            exit_status = interp.execute ();
+          }
+      }
+    catch (const exit_exception& ex)
+      {
+        exit_status = ex.exit_status ();
+      }
+
+    // Whether or not initialization succeeds we need to clean up the
+    // interpreter once we are done with it.
+
+    app_context.delete_interpreter ();
+
+    emit octave_finished_signal (exit_status);
+  }
+
+  void interpreter_qobject::confirm_shutdown (bool closenow)
+  {
+    // Wait for link thread to go to sleep state.
+    m_qt_link->lock ();
+
+    m_qt_link->shutdown_confirmation (closenow);
+
+    m_qt_link->unlock ();
+
+    // Awake the worker thread so that it continues shutting down (or not).
+    m_qt_link->wake_all ();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/interpreter-qobject.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,67 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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_interpreter_qobject_h)
+#define octave_interpreter_qobject_h 1
+
+#include <QObject>
+
+namespace octave
+{
+  class base_qobject;
+  class octave_qt_link;
+
+  class interpreter_qobject : public QObject
+  {
+    Q_OBJECT
+
+  public:
+
+    interpreter_qobject (base_qobject *oct_qobj);
+
+    ~interpreter_qobject (void) = default;
+
+    octave_qt_link * qt_link (void) { return m_qt_link; }
+
+    void confirm_shutdown (bool closenow);
+
+  signals:
+
+    void octave_ready_signal (void);
+    void octave_finished_signal (int);
+
+  public slots:
+
+    //! Initialize and execute the octave interpreter.
+
+    void execute (void);
+
+  private:
+
+    base_qobject *m_octave_qobject;
+
+    octave_qt_link *m_qt_link;
+  };
+}
+
+#endif
--- a/libgui/src/m-editor/file-editor-interface.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/file-editor-interface.h	Fri Jul 12 12:14:43 2019 -0400
@@ -73,6 +73,8 @@
 
   public slots:
 
+    virtual void toplevel_change (bool) = 0;
+
     virtual void handle_file_remove (const QString& o, const QString& n) = 0;
 
     virtual void request_new_file (const QString& command = QString ()) = 0;
--- a/libgui/src/m-editor/file-editor-tab.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/file-editor-tab.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -72,7 +72,6 @@
 #include "uniconv-wrappers.h"
 
 #include "bp-table.h"
-#include "call-stack.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "oct-map.h"
@@ -113,6 +112,9 @@
     _bp_conditions.clear ();
     m_bp_restore_count = 0;
 
+    m_breakpoint_info.remove_next = false;
+    m_breakpoint_info.remove_line = -1;
+
     // Initialize last modification date to now
     m_last_modified = QDateTime::currentDateTimeUtc();
 
@@ -163,7 +165,6 @@
 
     // Leave the find dialog box out of memory until requested.
     _find_dialog = nullptr;
-    _find_dialog_is_visible = false;
 
     // symbols
     _edit_area->setMarginType (1, QsciScintilla::SymbolMargin);
@@ -210,6 +211,7 @@
     edit_area_layout->addWidget (_edit_area);
     edit_area_layout->addWidget (_status_bar);
     edit_area_layout->setMargin (0);
+    edit_area_layout->setSpacing (0);
     setLayout (edit_area_layout);
 
     // connect modified signal
@@ -391,15 +393,23 @@
                                    &ok);
         if (ok)     // If cancel, don't change breakpoint condition.
           {
+            interpreter& interp
+              = __get_interpreter__ ("handle_context_menu_break_condition");
+
+            error_system& es = interp.get_error_system ();
+
             try
               {
                 // Suppress error messages on the console.
                 unwind_protect frame;
-                frame.protect_var (buffer_error_messages);
-                buffer_error_messages++;
-
-                bp_table& bptab
-                  = __get_bp_table__ ("handle_context_menu_break_condition");
+
+                int bem = es.buffer_error_messages ();
+                frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+                es.buffer_error_messages (bem + 1);
+
+                tree_evaluator& tw = interp.get_evaluator ();
+                bp_table& bptab = tw.get_bp_table ();
 
                 bptab.condition_valid (new_condition.toStdString ());
                 valid = true;
@@ -413,7 +423,7 @@
               }
 
             // In case we repeat, set new prompt.
-            prompt = "ERROR: " + last_error_message () + "\n\ndbstop if";
+            prompt = "ERROR: " + es.last_error_message () + "\n\ndbstop if";
             cond = new_condition;
           }
         else
@@ -618,9 +628,8 @@
     else
       {
         // Otherwise, delete the newly created lexer and
-        // use the old, exisiting one
-        if (lexer)
-          delete lexer;
+        // use the old, existing one.
+        delete lexer;
       }
   }
 
@@ -639,23 +648,33 @@
 
         bool update_apis = false;  // flag, whether update of apis files
 
-        // get path to prepared api info
+        // Get path to prepared api info (cache). Temporarily set the
+        // application name to 'octave' instead of 'GNU Octave' name for
+        // not having blanks in the path.
+        QString tmp_app_name = QCoreApplication::applicationName ();
+        QCoreApplication::setApplicationName ("octave");  // Set new name
+
 #if defined (HAVE_QSTANDARDPATHS)
-        QString prep_apis_path
-          = QStandardPaths::writableLocation (QStandardPaths::HomeLocation)
-            + "/.config/octave/" + QString (OCTAVE_VERSION) + "/qsci/";
+        QString local_data_path
+          = QStandardPaths::writableLocation (QStandardPaths::CacheLocation);
 #else
-        QString prep_apis_path
-          = QDesktopServices::storageLocation (QDesktopServices::HomeLocation)
-            + "/.config/octave/" + QString (OCTAVE_VERSION) + "/qsci/";
+        QString local_data_path
+          = QDesktopServices::storageLocation (QDesktopServices::CacheLocation);
 #endif
 
+        QCoreApplication::setApplicationName ("octave");  // Set temp. name
+
+        QString prep_apis_path = local_data_path + "/"
+                                  + QString (OCTAVE_VERSION) + "/qsci/";
+
         // get settings which infos are used for octave
         bool octave_builtins = settings->value (
                                  "editor/codeCompletion_octave_builtins", true).toBool ();
         bool octave_functions = settings->value (
                                   "editor/codeCompletion_octave_functions", true).toBool ();
 
+        QCoreApplication::setApplicationName (tmp_app_name);  // Restore name
+
         if (_is_octave_file)
           {
             // Keywords and Builtins do not change, these informations can be
@@ -843,6 +862,31 @@
     _lexer_apis->savePrepared (_prep_apis_file);
   }
 
+  // Slot for editors signal is its toplevel state has changed
+  void file_editor_tab::handle_toplevel_changed (bool)
+  {
+    // The find dialog has to be re-created since making the editor
+    // floating or docked obviously changes the parent/child relation
+    // of the find dialog
+    if (_find_dialog == nullptr)
+      return;
+    else
+      {
+        if (_find_dialog->isVisible ())
+          {
+            _find_dialog->save_data (&m_find_dlg_data);     // Save current data
+            delete _find_dialog;
+            _find_dialog = nullptr;
+
+            find_create ();                                 // Create new dialog
+
+            _find_dialog->restore_data (&m_find_dlg_data);  // Restore data
+
+            _edit_area->setFocus ();
+          }
+      }
+  }
+
   // slot for fetab_set_focus: sets the focus to the current edit area
   void file_editor_tab::set_focus (const QWidget *ID)
   {
@@ -916,7 +960,7 @@
     delete printer;
   }
 
-  void file_editor_tab::run_file (const QWidget *ID)
+  void file_editor_tab::run_file (const QWidget *ID, bool step_into)
   {
     if (ID != this)
       return;
@@ -928,6 +972,22 @@
           return;   // still invalid filename: "save as" was cancelled
       }
 
+    if (step_into)
+      {
+        // Get current first breakpoint and set breakpoint waiting for
+        // the returned line number. Store whether to remove this breakpoint
+        // afterwards.
+        int first_bp_line
+              = _edit_area->markerFindNext (0, (1 << marker::breakpoint)) + 1;
+
+        // Set flag for storing the line number of the breakpoint
+        m_breakpoint_info.remove_next = true;
+        m_breakpoint_info.do_not_remove_line = first_bp_line;
+
+        // Add breakpoint, storing its line number
+        handle_request_add_breakpoint (1, QString ());
+      }
+
     QFileInfo info (_file_name);
     emit run_file_signal (info);
   }
@@ -1014,7 +1074,16 @@
       {
         bp_table& bptab = __get_bp_table__ ("octave_qt_link::file_in_path");
 
-        bptab.add_breakpoint (info.function_name, line_info, info.condition);
+        bp_table::intmap bpmap
+          = bptab.add_breakpoint (info.function_name, "", line_info, info.condition);
+
+        // Store some info breakpoint
+        if (m_breakpoint_info.remove_next && (bpmap.size() > 0))
+          {
+            bp_table::intmap::iterator bp_it = bpmap.begin();
+            m_breakpoint_info.remove_line = bp_it->second;
+            m_breakpoint_info.remove_next = false;
+          }
       }
   }
 
@@ -1251,15 +1320,36 @@
   {
     // Find dialog is going to hide.  Save location of window for
     // when it is reshown.
-    _find_dialog_geometry = _find_dialog->geometry ();
-    _find_dialog_is_visible = false;
+    m_find_dlg_data.geometry = _find_dialog->geometry ();
+    m_find_dlg_data.is_visible = false;
   }
 
+  // Slot for initially creating and showing the find dialog
   void file_editor_tab::find (const QWidget *ID, QList<QAction *> fetab_actions)
   {
     if (ID != this)
       return;
 
+    m_find_dlg_data.actions = fetab_actions.mid (0,2);
+
+    // Create the dialog
+    find_create ();
+
+    // Since find_create shows the dialog without activating the widget
+    // (which is reuqired in other cases) do this manually here
+    _find_dialog->activateWindow ();
+
+    // Initiate search text from possible selection and save the initial
+    // data from the dialog on the defined structure
+    _find_dialog->init_search_text ();
+    _find_dialog->save_data (&m_find_dlg_data);
+  }
+
+  // This methos creates the find dialog in way that is at first suitable
+  // for re-creating it after the toplevel of the editor has changed.
+  // The find dialog is initially creatied, activated and shown with find ()
+  void file_editor_tab::find_create ()
+  {
     // The find_dialog feature doesn't need a slot for return info.
     // Rather than Qt::DeleteOnClose, let the find feature hang about
     // in case it contains useful information like previous searches
@@ -1270,8 +1360,8 @@
     if (! _find_dialog)
       {
         _find_dialog = new find_dialog (_edit_area,
-                                        fetab_actions.mid (0,2),
-                                        qobject_cast<QWidget *> (sender ()));
+                                        m_find_dlg_data.actions,
+                                        this);
         connect (_find_dialog, SIGNAL (finished (int)),
                  this, SLOT (handle_find_dialog_finished (int)));
 
@@ -1282,20 +1372,16 @@
                  _find_dialog, SLOT (find_prev ()));
 
         _find_dialog->setWindowModality (Qt::NonModal);
-        _find_dialog_geometry = _find_dialog->geometry ();
       }
     else if (! _find_dialog->isVisible ())
       {
-        _find_dialog->setGeometry (_find_dialog_geometry);
+        _find_dialog->setGeometry (m_find_dlg_data.geometry);
         QPoint p = _find_dialog->pos ();
         _find_dialog->move (p.x ()+10, p.y ()+10);
       }
 
+    _find_dialog->setAttribute(Qt::WA_ShowWithoutActivating);
     _find_dialog->show ();
-    _find_dialog_is_visible = true;
-    _find_dialog->activateWindow ();
-    _find_dialog->init_search_text ();
-
   }
 
   void file_editor_tab::find_next (const QWidget *ID)
@@ -1604,10 +1690,7 @@
           }
       }
 
-    if (modified)
-      emit file_name_changed (title.prepend ("* "), tooltip);
-    else
-      emit file_name_changed (title, tooltip);
+    emit file_name_changed (title, tooltip, modified);
   }
 
   void file_editor_tab::handle_copy_available (bool enableCopy)
@@ -2026,13 +2109,7 @@
     octave_value sym;
     try
       {
-        // FIXME: maybe we should be looking up functions directly
-        // instead of using a function that can also find variables?
-
-        symbol_scope curr_scope
-          = __get_current_scope__ ("file_editor_tab::exit_debug_and_clear");
-
-        sym = curr_scope.find (base_name);
+        sym = symtab.find_user_function (base_name);
       }
     catch (const execution_exception& e)
       {
@@ -2053,11 +2130,12 @@
 
     // If this file is loaded, check that we aren't currently running it
     bool retval = true;
+
     octave_idx_type curr_frame = -1;
-    size_t nskip = 0;
-    call_stack& cs
-      = __get_call_stack__ ("file_editor_tab::exit_debug_and_clear");
-    octave_map stk = cs.backtrace (nskip, curr_frame, false);
+    tree_evaluator& tw
+      = __get_evaluator__ ("file_editor_tab::exit_debug_and_clear");
+    octave_map stk = tw.backtrace (curr_frame, false);
+
     Cell names = stk.contents ("name");
     for (octave_idx_type i = names.numel () - 1; i >= 0; i--)
       {
@@ -2077,8 +2155,8 @@
                 // Wait until dbquit has actually occurred
                 while (names.numel () > i)
                   {
-                    octave::sleep (0.01);
-                    stk = cs.backtrace (nskip, curr_frame, false);
+                    sleep (0.01);
+                    stk = tw.backtrace (curr_frame, false);
                     names = stk.contents ("name");
                   }
               }
@@ -2614,6 +2692,10 @@
     _edit_area->setTabWidth
       (settings->value ("editor/tab_width",2).toInt ());
 
+    m_ind_char_width = 1;
+    if (_edit_area->indentationsUseTabs ())
+      m_ind_char_width = _edit_area->tabWidth ();
+
     _edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR,
                                settings->value ("editor/show_hscroll_bar",true).toBool ());
     _edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1);
@@ -2711,16 +2793,16 @@
           {
             if (_find_dialog->isVisible ())
               {
-                _find_dialog_geometry = _find_dialog->geometry ();
+                m_find_dlg_data.geometry = _find_dialog->geometry ();
                 _find_dialog->hide ();
               }
           }
         return;
       }
 
-    if (_find_dialog && _find_dialog_is_visible)
+    if (_find_dialog && m_find_dlg_data.is_visible)
       {
-        _find_dialog->setGeometry (_find_dialog_geometry);
+        _find_dialog->setGeometry (m_find_dlg_data.geometry);
         QPoint p = _find_dialog->pos ();
         _find_dialog->move (p.x ()+10, p.y ()+10);
         _find_dialog->show ();
@@ -2824,7 +2906,18 @@
               }
           }
         else
-          dp = new marker (_edit_area, line, marker::debugger_position);
+          {
+            dp = new marker (_edit_area, line, marker::debugger_position);
+
+            // In case of a not modified file we might have to remove
+            // a breakpoint here if we have stepped into the file
+            if (line == m_breakpoint_info.remove_line)
+              {
+                m_breakpoint_info.remove_line = -1;
+                if (line != m_breakpoint_info.do_not_remove_line)
+                  handle_request_remove_breakpoint (line);
+              }
+          }
 
         connect (this, SIGNAL (remove_position_via_debugger_linenr (int)),
                  dp,   SLOT (handle_remove_via_original_linenr (int)));
@@ -2952,7 +3045,8 @@
           {
             // Obviously, we have a newline here
             if (_smart_indent || _auto_endif)
-              _edit_area->smart_indent (_smart_indent, _auto_endif, _line);
+              _edit_area->smart_indent (_smart_indent, _auto_endif,
+                                        _line, m_ind_char_width);
           }
       }
 
@@ -3086,7 +3180,7 @@
                     // get cursor position after having found an occurrence
                     _edit_area->getCursorPosition (&oline, &ocol);
                     // mark the selection
-                    _edit_area->show_selection_markers (oline, ocol, wlen);
+                    _edit_area->show_selection_markers (oline, ocol-wlen, oline, ocol);
 
                     // find next occurrence
                     find_result_available = _edit_area->findNext ();
@@ -3109,6 +3203,7 @@
     QRegExp rxfun2 ("^[\t ]*function[\t ]+([^\\(]+)\\([^\\)]*\\)[\t ]*$");
     QRegExp rxfun3 ("^[\t ]*function[^=]+=[\t ]*([^\\s]+)[\t ]*$");
     QRegExp rxfun4 ("^[\t ]*function[\t ]+([^\\s]+)[\t ]*$");
+    QRegExp rxfun5 ("^[\t ]*classdef[\t ]+([^\\s]+)[\t ]*$");
 
     QStringList lines = _edit_area->text ().split ("\n");
 
@@ -3122,6 +3217,8 @@
           return rxfun3.cap (1).remove (QRegExp ("[ \t]*"));
         else if (rxfun4.indexIn (lines.at (i)) != -1)
           return rxfun4.cap (1).remove (QRegExp ("[ \t]*"));
+        else if (rxfun5.indexIn (lines.at (i)) != -1)
+          return rxfun5.cap (1).remove (QRegExp ("[ \t]*"));
       }
 
     return QString ();
--- a/libgui/src/m-editor/file-editor-tab.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/file-editor-tab.h	Fri Jul 12 12:14:43 2019 -0400
@@ -84,6 +84,7 @@
     // Simply transmit filename.
     void file_name_query (const QWidget *ID);
 
+    void handle_toplevel_changed (bool);
     void set_focus (const QWidget *ID);
     void set_current_directory (const QString& dir);
     void context_help (const QWidget *ID, bool);
@@ -94,7 +95,7 @@
                     bool remove_on_success);
     void save_file_as (const QWidget *ID);
     void print_file (const QWidget *ID);
-    void run_file (const QWidget *ID);
+    void run_file (const QWidget *ID, bool step_into = false);
     void context_run (const QWidget *ID);
     void toggle_bookmark (const QWidget *ID);
     void next_bookmark (const QWidget *ID);
@@ -154,7 +155,9 @@
 
   signals:
 
-    void file_name_changed (const QString& fileName, const QString& toolTip);
+    void file_name_changed (const QString& fileName,
+                            const QString& toolTip,
+                            bool modified);
     void editor_state_changed (bool copy_available, bool is_octave_file);
     void set_focus_editor_signal (QWidget *);
     void tab_remove_request (void);
@@ -244,6 +247,8 @@
       std::string condition;
     };
 
+    void find_create (void);
+
     bool valid_file_name (const QString& file = QString ());
     bool exit_debug_and_clear (const QString& full_name,
                                const QString& base_name);
@@ -299,16 +304,13 @@
     bool _always_reload_changed_files;
     bool _smart_indent;
     int _auto_endif;
+    int m_ind_char_width;
 
     QFileSystemWatcher _file_system_watcher;
 
     QIntList _bp_lines;
     QStringList _bp_conditions;
 
-    find_dialog *_find_dialog;
-    bool _find_dialog_is_visible;
-    QRect _find_dialog_geometry;
-
     QsciAPIs *_lexer_apis;
     QString _prep_apis_file;
 
@@ -321,6 +323,17 @@
     bool _lines_changed;
     bool _highlight_all_occurrences;
     int m_bp_restore_count;
+
+    struct
+      {
+        bool        remove_next;
+        int         remove_line;
+        int         do_not_remove_line;
+      } m_breakpoint_info;
+
+    find_dialog *_find_dialog;
+    find_dialog::find_dialog_data m_find_dlg_data;
+
   };
 }
 
--- a/libgui/src/m-editor/file-editor.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/file-editor.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -66,6 +66,7 @@
     this->setTabBar (bar);
 
     setTabsClosable (true);
+    setUsesScrollButtons (true);
 #if defined (HAVE_QTABWIDGET_SETMOVABLE)
     setMovable (true);
 #endif
@@ -95,6 +96,9 @@
     m_closed = false;
     m_no_focus = false;
 
+    m_copy_action_enabled = false;
+    m_undo_action_enabled = false;
+
     construct ();
 
     // actions that should also be available in the find dialog
@@ -129,10 +133,6 @@
     m_undo_action = shared_actions.at (UNDO_ACTION);
     m_tool_bar->insertAction (m_redo_action,m_undo_action);
     m_edit_menu->insertAction (m_redo_action,m_undo_action);
-    // copy
-    m_copy_action = shared_actions.at (COPY_ACTION);
-    m_tool_bar->insertAction (m_cut_action,m_copy_action);
-    m_edit_menu->insertAction (m_cut_action,m_copy_action);
     // select all
     m_selectall_action = shared_actions.at (SELECTALL_ACTION);
     m_edit_menu->insertAction (m_find_action,m_selectall_action);
@@ -142,6 +142,10 @@
     m_tool_bar->insertAction (m_find_action,m_paste_action);
     m_edit_menu->insertAction (m_selectall_action,m_paste_action);
     m_edit_menu->insertSeparator (m_selectall_action);
+    // copy
+    m_copy_action = shared_actions.at (COPY_ACTION);
+    m_tool_bar->insertAction (m_paste_action,m_copy_action);
+    m_edit_menu->insertAction (m_paste_action,m_copy_action);
     // find files
     m_find_files_action = shared_actions.at (FIND_FILES_ACTION);
     m_edit_menu->insertAction (m_find_action, m_find_files_action);
@@ -149,14 +153,20 @@
 
   void file_editor::handle_enter_debug_mode (void)
   {
-    m_run_action->setEnabled (false);
-    m_run_action->setShortcut (QKeySequence ());
+    QSettings *settings = resource_manager::get_settings ();
+    QString sc_run = settings->value ("shortcuts/editor_run:run_file").toString ();
+    QString sc_cont = settings->value ("shortcuts/main_debug:continue").toString ();
+
+    if (sc_run == sc_cont)
+      m_run_action->setShortcut (QKeySequence ());  // prevent ambigous shortcuts
+
+    m_run_action->setToolTip (tr ("Continue"));   // update tool tip
   }
 
   void file_editor::handle_exit_debug_mode (void)
   {
-    m_run_action->setEnabled (true);
     shortcut_manager::set_shortcut (m_run_action, "editor_run:run_file");
+    m_run_action->setToolTip (tr ("Save File and Run"));  // update tool tip
   }
 
   void file_editor::check_actions (void)
@@ -194,6 +204,8 @@
     m_close_action->setEnabled (have_tabs);
     m_close_all_action->setEnabled (have_tabs);
     m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1);
+
+    emit editor_tabs_changed_signal (have_tabs);
   }
 
   // empty_script determines whether we have to create an empty script
@@ -340,10 +352,20 @@
 
     // when editor loses focus, enable the actions, which are always active
     // in the main window due to missing info on selected text and undo actions
-    if (! enable && m_copy_action && m_undo_action)
+    if (m_copy_action && m_undo_action)
       {
-        m_copy_action->setEnabled (true);
-        m_undo_action->setEnabled (true);
+        if (enable)
+          {
+            m_copy_action->setEnabled (m_copy_action_enabled);
+            m_undo_action->setEnabled (m_undo_action_enabled);
+          }
+        else
+          {
+            m_copy_action_enabled = m_copy_action->isEnabled ();
+            m_undo_action_enabled = m_undo_action->isEnabled ();
+            m_copy_action->setEnabled (true);
+            m_undo_action->setEnabled (true);
+          }
       }
   }
 
@@ -444,12 +466,9 @@
     // pass a signal to.  Hence, functionality is here.
 
     file_editor_tab *fileEditorTab = new file_editor_tab (m_ced);
-    if (fileEditorTab)
-      {
-        add_file_editor_tab (fileEditorTab, "");  // new tab with empty title
-        fileEditorTab->new_file (commands);       // title is updated here
-        focus ();                                 // focus editor and new tab
-      }
+    add_file_editor_tab (fileEditorTab, "");  // new tab with empty title
+    fileEditorTab->new_file (commands);       // title is updated here
+    focus ();                                 // focus editor and new tab
   }
 
   void file_editor::request_close_file (bool)
@@ -542,7 +561,15 @@
 
   void file_editor::request_run_file (bool)
   {
-    emit fetab_run_file (m_tab_widget->currentWidget ());
+    if ((Fisdebugmode ())(0).is_true ())
+      emit request_dbcont_signal ();
+    else
+      emit fetab_run_file (m_tab_widget->currentWidget ());
+  }
+
+  void file_editor::request_step_into_file ()
+  {
+    emit fetab_run_file (m_tab_widget->currentWidget (), true);
   }
 
   void file_editor::request_context_run (bool)
@@ -743,7 +770,8 @@
   }
 
   void file_editor::handle_file_name_changed (const QString& fname,
-                                              const QString& tip)
+                                              const QString& tip,
+                                              bool modified)
   {
     QObject *fileEditorTab = sender ();
     if (fileEditorTab)
@@ -754,6 +782,11 @@
               {
                 m_tab_widget->setTabText (i, fname);
                 m_tab_widget->setTabToolTip (i, tip);
+                if (modified)
+                  m_tab_widget->setTabIcon (i,
+                                  resource_manager::icon ("document-save"));
+                else
+                  m_tab_widget->setTabIcon (i, QIcon ());
               }
           }
       }
@@ -820,6 +853,9 @@
 
         setFocusProxy (m_tab_widget->currentWidget ());
       }
+
+    m_copy_action_enabled = m_copy_action->isEnabled ();
+    m_undo_action_enabled = m_undo_action->isEnabled ();
   }
 
   void file_editor::handle_mru_add_file (const QString& file_name,
@@ -1008,7 +1044,7 @@
                     std::string ndir = new_name.toStdString ();
                     std::string ofile = old.fileName ().toStdString ();
                     f_data.new_file_name = QString::fromStdString (
-                      octave::sys::env::make_absolute (ofile, ndir));
+                      sys::env::make_absolute (ofile, ndir));
                   }
                 else
                   f_data.new_file_name = new_name;
@@ -1066,23 +1102,64 @@
     int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
     m_tool_bar->setIconSize (QSize (icon_size, icon_size));
 
+    // Tab position
+    QTabWidget::TabPosition pos = static_cast<QTabWidget::TabPosition>(
+          settings->value (ed_tab_position.key, ed_tab_position.def).toInt ());
+    m_tab_widget->setTabPosition (pos);
+
+    // Update style sheet properties depending on position
+    QString width_str ("width");
+    QString height_str ("height");
+    if (pos == QTabWidget::West || pos == QTabWidget::East)
+      {
+        width_str = QString ("height");
+        height_str = QString ("width");
+      }
+
+    // Min and max width for full path titles
     int tab_width_min = settings->value ("editor/notebook_tab_width_min", 160)
                         .toInt ();
     int tab_width_max = settings->value ("editor/notebook_tab_width_max", 300)
                         .toInt ();
 
+    // Get suitable height of a tab related to font and icon size
+    int height = 1.5*QFontMetrics (m_tab_widget->font ()).height ();
+    int is = 1.5*m_tab_widget->iconSize ().height ();
+    if (is > height)
+      height = is;
+
+    // Style sheet for tab height
+    QString style_sheet = QString ("QTabBar::tab {max-" + height_str + ": %1px;}")
+                                   .arg (height);
+
+    // Style sheet for tab height together with width
     if (settings->value ("editor/longWindowTitle", false).toBool ())
       {
-        QString style_sheet = QString ("QTabBar::tab "
-                                       "{min-width: %1px; max-width: %2px;}")
-                              .arg (tab_width_min).arg (tab_width_max);
+        style_sheet = QString ("QTabBar::tab "
+                               " {max-" + height_str + ": %1px;"
+                               "  min-" + width_str + ": %2px;"
+                               "  max-" + width_str + ": %3px;}")
+                              .arg (height).arg (tab_width_min).arg (tab_width_max);
         m_tab_widget->setElideMode (Qt::ElideLeft);
-        m_tab_widget->setStyleSheet (style_sheet);
       }
     else
-      m_tab_widget->setElideMode (Qt::ElideNone);
-
-    m_tab_widget->setUsesScrollButtons (true);
+      {
+        m_tab_widget->setElideMode (Qt::ElideNone);
+      }
+
+#if defined (Q_OS_MAC)
+    // FIXME: This is a workaround for missing tab close buttons on MacOS
+    // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092)
+    QString close_button_css (
+      "QTabBar::close-button"
+      "  { width: 6px; image: url(:/actions/icons/widget-close.png);}\n"
+      "QTabBar::close-button:hover"
+      "  { background-color: #cccccc; }"
+      );
+    style_sheet = style_sheet + close_button_css;
+#endif
+
+    m_tab_widget->setStyleSheet (style_sheet);
 
     bool show_it;
     show_it = settings->value ("editor/showLineNumbers",true).toBool ();
@@ -1218,6 +1295,12 @@
 
   }
 
+  void file_editor::toplevel_change (bool toplevel)
+  {
+    emit fetab_toplevel_changed (toplevel);
+    octave_dock_widget::toplevel_change (toplevel);
+  }
+
   void file_editor::update_octave_directory (const QString& dir)
   {
     m_ced = dir;
@@ -1325,103 +1408,100 @@
             if (! fileEditorTab)
               fileEditorTab = new file_editor_tab ();
 
-            if (fileEditorTab)
+            fileEditorTab->set_encoding (encoding);
+            QString result = fileEditorTab->load_file (openFileName);
+            if (result == "")
               {
-                fileEditorTab->set_encoding (encoding);
-                QString result = fileEditorTab->load_file (openFileName);
-                if (result == "")
+                // Supply empty title then have the file_editor_tab update
+                // with full or short name.
+                if (! reusing)
+                  add_file_editor_tab (fileEditorTab, "", index);
+                fileEditorTab->update_window_title (false);
+                // file already loaded, add file to mru list here
+                QFileInfo file_info = QFileInfo (openFileName);
+                handle_mru_add_file (file_info.canonicalFilePath (),
+                                     encoding);
+
+                if (line > 0)
                   {
-                    // Supply empty title then have the file_editor_tab update
-                    // with full or short name.
-                    if (! reusing)
-                      add_file_editor_tab (fileEditorTab, "", index);
-                    fileEditorTab->update_window_title (false);
-                    // file already loaded, add file to mru list here
-                    QFileInfo file_info = QFileInfo (openFileName);
-                    handle_mru_add_file (file_info.canonicalFilePath (),
-                                         encoding);
-
-                    if (line > 0)
-                      {
-                        if (insert)
-                          emit fetab_goto_line (fileEditorTab, line);
-
-                        if (debug_pointer)
-                          emit fetab_insert_debugger_pointer (fileEditorTab,
-                                                              line);
-                        if (breakpoint_marker)
-                          emit fetab_do_breakpoint_marker (insert, fileEditorTab,
-                                                           line, cond);
-                      }
+                    if (insert)
+                      emit fetab_goto_line (fileEditorTab, line);
+
+                    if (debug_pointer)
+                      emit fetab_insert_debugger_pointer (fileEditorTab,
+                                                          line);
+                    if (breakpoint_marker)
+                      emit fetab_do_breakpoint_marker (insert, fileEditorTab,
+                                                       line, cond);
+                  }
+              }
+            else
+              {
+                delete fileEditorTab;
+                fileEditorTab = nullptr;
+
+                if (QFile::exists (openFileName))
+                  {
+                    // File not readable:
+                    // create a NonModal message about error.
+                    QMessageBox *msgBox
+                      = new QMessageBox (QMessageBox::Critical,
+                                         tr ("Octave Editor"),
+                                         tr ("Could not open file\n%1\nfor read: %2.").
+                                         arg (openFileName).arg (result),
+                                         QMessageBox::Ok, this);
+
+                    msgBox->setWindowModality (Qt::NonModal);
+                    msgBox->setAttribute (Qt::WA_DeleteOnClose);
+                    msgBox->show ();
                   }
                 else
                   {
-                    delete fileEditorTab;
-                    fileEditorTab = nullptr;
-
-                    if (QFile::exists (openFileName))
+                    // File does not exist, should it be created?
+                    bool create_file = true;
+                    QMessageBox *msgBox;
+
+                    if (! settings->value ("editor/create_new_file", false).toBool ())
                       {
-                        // File not readable:
-                        // create a NonModal message about error.
-                        QMessageBox *msgBox
-                          = new QMessageBox (QMessageBox::Critical,
-                                             tr ("Octave Editor"),
-                                             tr ("Could not open file\n%1\nfor read: %2.").
-                                             arg (openFileName).arg (result),
-                                             QMessageBox::Ok, this);
-
-                        msgBox->setWindowModality (Qt::NonModal);
-                        msgBox->setAttribute (Qt::WA_DeleteOnClose);
-                        msgBox->show ();
+                        msgBox = new QMessageBox (QMessageBox::Question,
+                                                  tr ("Octave Editor"),
+                                                  tr ("File\n%1\ndoes not exist. "
+                                                      "Do you want to create it?").arg (openFileName),
+                                                  QMessageBox::NoButton,nullptr);
+                        QPushButton *create_button =
+                          msgBox->addButton (tr ("Create"), QMessageBox::YesRole);
+                        msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole);
+                        msgBox->setDefaultButton (create_button);
+                        msgBox->exec ();
+
+                        QAbstractButton *clicked_button = msgBox->clickedButton ();
+                        if (clicked_button != create_button)
+                          create_file = false;
+
+                        delete msgBox;
                       }
-                    else
+
+                    if (create_file)
                       {
-                        // File does not exist, should it be created?
-                        bool create_file = true;
-                        QMessageBox *msgBox;
-
-                        if (! settings->value ("editor/create_new_file", false).toBool ())
+                        // create the file and call the editor again
+                        QFile file (openFileName);
+                        if (! file.open (QIODevice::WriteOnly))
                           {
-                            msgBox = new QMessageBox (QMessageBox::Question,
+                            // error opening the file
+                            msgBox = new QMessageBox (QMessageBox::Critical,
                                                       tr ("Octave Editor"),
-                                                      tr ("File\n%1\ndoes not exist. "
-                                                          "Do you want to create it?").arg (openFileName),
-                                                      QMessageBox::NoButton,nullptr);
-                            QPushButton *create_button =
-                              msgBox->addButton (tr ("Create"), QMessageBox::YesRole);
-                            msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole);
-                            msgBox->setDefaultButton (create_button);
-                            msgBox->exec ();
-
-                            QAbstractButton *clicked_button = msgBox->clickedButton ();
-                            if (clicked_button != create_button)
-                              create_file = false;
-
-                            delete msgBox;
+                                                      tr ("Could not open file\n%1\nfor write: %2.").
+                                                      arg (openFileName).arg (file.errorString ()),
+                                                      QMessageBox::Ok, this);
+
+                            msgBox->setWindowModality (Qt::NonModal);
+                            msgBox->setAttribute (Qt::WA_DeleteOnClose);
+                            msgBox->show ();
                           }
-
-                        if (create_file)
+                        else
                           {
-                            // create the file and call the editor again
-                            QFile file (openFileName);
-                            if (! file.open (QIODevice::WriteOnly))
-                              {
-                                // error opening the file
-                                msgBox = new QMessageBox (QMessageBox::Critical,
-                                                          tr ("Octave Editor"),
-                                                          tr ("Could not open file\n%1\nfor write: %2.").
-                                                          arg (openFileName).arg (file.errorString ()),
-                                                          QMessageBox::Ok, this);
-
-                                msgBox->setWindowModality (Qt::NonModal);
-                                msgBox->setAttribute (Qt::WA_DeleteOnClose);
-                                msgBox->show ();
-                              }
-                            else
-                              {
-                                file.close ();
-                                request_open_file (openFileName);
-                              }
+                            file.close ();
+                            request_open_file (openFileName);
                           }
                       }
                   }
@@ -2024,7 +2104,7 @@
     m_run_action
       = add_action (_run_menu,
                     resource_manager::icon ("system-run"),
-                    tr ("Save File and Run"),
+                    tr ("Save File and Run / Continue"),
                     SLOT (request_run_file (bool)));
 
     m_run_selection_action
@@ -2084,8 +2164,8 @@
     // m_undo_action: later via main window
     m_tool_bar->addAction (m_redo_action);
     m_tool_bar->addSeparator ();
+    m_tool_bar->addAction (m_cut_action);
     // m_copy_action: later via the main window
-    m_tool_bar->addAction (m_cut_action);
     // m_paste_action: later via the main window
     m_tool_bar->addAction (m_find_action);
     //m_tool_bar->addAction (m_find_next_action);
@@ -2104,6 +2184,7 @@
     vbox_layout->addWidget (m_tool_bar);
     vbox_layout->addWidget (m_tab_widget);
     vbox_layout->setMargin (0);
+    vbox_layout->setSpacing (0);
     editor_widget->setLayout (vbox_layout);
     setWidget (editor_widget);
 
@@ -2119,6 +2200,9 @@
              main_win (),
              SLOT (process_settings_dialog_request (const QString&)));
 
+    connect (this, SIGNAL (request_dbcont_signal (void)),
+             main_win (), SLOT (debug_continue (void)));
+
     connect (m_mru_file_menu, SIGNAL (triggered (QAction *)),
              this, SLOT (request_mru_open_file (QAction *)));
 
@@ -2160,9 +2244,9 @@
              main_win (), SLOT (execute_command_in_terminal (const QString&)));
 
     // Signals from the file editor_tab
-    connect (f, SIGNAL (file_name_changed (const QString&, const QString&)),
+    connect (f, SIGNAL (file_name_changed (const QString&, const QString&, bool)),
              this, SLOT (handle_file_name_changed (const QString&,
-                                                   const QString&)));
+                                                   const QString&, bool)));
 
     connect (f, SIGNAL (editor_state_changed (bool, bool)),
              this, SLOT (handle_editor_state_changed (bool, bool)));
@@ -2246,8 +2330,8 @@
     connect (this, SIGNAL (fetab_print_file (const QWidget*)),
              f, SLOT (print_file (const QWidget*)));
 
-    connect (this, SIGNAL (fetab_run_file (const QWidget*)),
-             f, SLOT (run_file (const QWidget*)));
+    connect (this, SIGNAL (fetab_run_file (const QWidget*, bool)),
+             f, SLOT (run_file (const QWidget*, bool)));
 
     connect (this, SIGNAL (fetab_context_run (const QWidget*)),
              f, SLOT (context_run (const QWidget*)));
@@ -2320,6 +2404,9 @@
     connect (this, SIGNAL (fetab_set_focus (const QWidget*)),
              f, SLOT (set_focus (const QWidget*)));
 
+    connect (this, SIGNAL (fetab_toplevel_changed (bool)),
+             f, SLOT (handle_toplevel_changed (bool)));
+
     connect (this, SIGNAL (fetab_insert_debugger_pointer (const QWidget*, int)),
              f, SLOT (insert_debugger_pointer (const QWidget*, int)));
 
--- a/libgui/src/m-editor/file-editor.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/file-editor.h	Fri Jul 12 12:14:43 2019 -0400
@@ -122,6 +122,7 @@
 
   signals:
 
+    void fetab_toplevel_changed (bool);
     void fetab_settings_changed (const QSettings *settings);
     void fetab_change_request (const QWidget *ID);
     void fetab_file_name_query (const QWidget *ID);
@@ -136,7 +137,7 @@
     void fetab_save_file (const QWidget *ID);
     void fetab_save_file_as (const QWidget *ID);
     void fetab_print_file (const QWidget *ID);
-    void fetab_run_file (const QWidget *ID);
+    void fetab_run_file (const QWidget *ID, bool step_into = false);
     void fetab_context_run (const QWidget *ID);
     void fetab_toggle_bookmark (const QWidget *ID);
     void fetab_next_bookmark (const QWidget *ID);
@@ -176,8 +177,13 @@
     void request_open_file_external (const QString& file_name, int line);
     void file_loaded_signal (void);
 
+    void editor_tabs_changed_signal (bool);
+    void request_dbcont_signal (void);
+
   public slots:
 
+    void toplevel_change (bool);
+
     void focus (void);
     void set_focus (QWidget *fet);
     void enable_menu_shortcuts (bool);
@@ -198,6 +204,7 @@
     void request_save_file (bool);
     void request_save_file_as (bool);
     void request_run_file (bool);
+    void request_step_into_file ();
     void request_context_run (bool);
     void request_toggle_bookmark (bool);
     void request_next_bookmark (bool);
@@ -242,7 +249,8 @@
     void request_completion (bool);
 
     void handle_file_name_changed (const QString& fileName,
-                                   const QString& toolTip);
+                                   const QString& toolTip,
+                                   bool modified);
     void handle_tab_close_request (int index);
     void handle_tab_remove_request (void);
     void handle_add_filename_to_list (const QString& fileName,
@@ -429,6 +437,9 @@
     QAction *m_previous_breakpoint_action;
     QAction *m_remove_all_breakpoints_action;
 
+    bool m_copy_action_enabled;
+    bool m_undo_action_enabled;
+
     QMenu *m_edit_menu;
     QMenu *m_edit_cmd_menu;
     QMenu *m_edit_fmt_menu;
--- a/libgui/src/m-editor/find-dialog.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/find-dialog.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -80,9 +80,9 @@
 
 namespace octave
 {
-  find_dialog::find_dialog (QsciScintilla *edit_area,
+  find_dialog::find_dialog (octave_qscintilla *edit_area,
                             QList<QAction *> find_actions, QWidget *p)
-    : QDialog (p)
+    : QDialog (p), m_in_sel (false), m_sel_beg (-1), m_sel_end (-1)
   {
     setWindowTitle (tr ("Find and Replace"));
     setWindowIcon (QIcon (":/actions/icons/find.png"));
@@ -120,14 +120,9 @@
     _regex_check_box = new QCheckBox (tr ("Regular E&xpressions"));
     _backward_check_box = new QCheckBox (tr ("Search &backward"));
     _search_selection_check_box = new QCheckBox (tr ("Search se&lection"));
-#if defined (HAVE_QSCI_FINDSELECTION)
     _search_selection_check_box->setCheckable (true);
     if (edit_area)
       _search_selection_check_box->setEnabled (edit_area->hasSelectedText ());
-#else
-    _search_selection_check_box->setCheckable (false);
-    _search_selection_check_box->setEnabled (false);
-#endif
 
     _edit_area = edit_area;
     connect (_find_next_button,   SIGNAL (clicked ()),
@@ -147,12 +142,10 @@
     connect (_search_line_edit,   SIGNAL (textChanged (QString)),
              this,                SLOT (handle_search_text_changed (QString)));
 
-#if defined (HAVE_QSCI_FINDSELECTION)
     connect (_edit_area, SIGNAL (copyAvailable (bool)),
              this,       SLOT (handle_selection_changed (bool)));
     connect (_search_selection_check_box, SIGNAL (stateChanged (int)),
              this,                        SLOT (handle_sel_search_changed (int)));
-#endif
 
     QVBoxLayout *extension_layout = new QVBoxLayout ();
     extension_layout->setMargin (0);
@@ -202,6 +195,39 @@
 
   }
 
+  void find_dialog::save_data (find_dialog_data *fdlg_data)
+  {
+    fdlg_data->text = _search_line_edit->text ();
+    fdlg_data->replace_text = _replace_line_edit->text ();
+    fdlg_data->geometry = geometry ();
+    fdlg_data->is_visible = isVisible ();
+    fdlg_data->options = 0
+          + _extension->isVisible () * FIND_DLG_MORE
+          + _case_check_box->isChecked () * FIND_DLG_CASE
+          + _from_start_check_box->isChecked () * FIND_DLG_START
+          + _wrap_check_box->isChecked () * FIND_DLG_WRAP
+          + _regex_check_box->isChecked () * FIND_DLG_REGX
+          + _whole_words_check_box->isChecked () * FIND_DLG_WORDS
+          + _backward_check_box->isChecked () * FIND_DLG_BACK
+          + _search_selection_check_box->isChecked () * FIND_DLG_SEL;
+  }
+
+  void find_dialog::restore_data (const find_dialog_data* fdlg_data)
+  {
+    setGeometry (fdlg_data->geometry);
+    setVisible (fdlg_data->is_visible);
+    _search_line_edit->setText (fdlg_data->text);
+    _replace_line_edit->setText (fdlg_data->replace_text);
+    _extension->setVisible (FIND_DLG_MORE & fdlg_data->options);
+    _case_check_box->setChecked (FIND_DLG_CASE & fdlg_data->options);
+    _from_start_check_box->setChecked (FIND_DLG_START & fdlg_data->options);
+    _wrap_check_box->setChecked (FIND_DLG_WRAP & fdlg_data->options);
+    _regex_check_box->setChecked (FIND_DLG_REGX & fdlg_data->options);
+    _whole_words_check_box->setChecked (FIND_DLG_WORDS & fdlg_data->options);
+    _backward_check_box->setChecked (FIND_DLG_BACK & fdlg_data->options);
+    _search_selection_check_box->setChecked (FIND_DLG_SEL & fdlg_data->options);
+  }
+
   // set text of "search from start" depending on backward search
   void find_dialog::handle_backward_search_changed (int backward)
   {
@@ -218,17 +244,12 @@
       _find_result_available = false;
   }
 
-#if defined (HAVE_QSCI_FINDSELECTION)
   void find_dialog::handle_sel_search_changed (int selected)
   {
     _from_start_check_box->setEnabled (! selected);
     _find_result_available = false;
   }
-#else
-  void find_dialog::handle_sel_search_changed (int /* selected */) { }
-#endif
 
-#if defined (HAVE_QSCI_FINDSELECTION)
   void find_dialog::handle_selection_changed (bool has_selected)
   {
     if (_rep_active)
@@ -236,12 +257,7 @@
 
     _search_selection_check_box->setEnabled (has_selected);
     _find_result_available = false;
-    if (! has_selected)
-      _search_selection_check_box->setChecked (false);
   }
-#else
-  void find_dialog::handle_selection_changed (bool /* has_selected */) { }
-#endif
 
   // initialize search text with selected text if this is in one single line
   void find_dialog::init_search_text (void)
@@ -278,46 +294,84 @@
     if (! _edit_area)
       return;
 
-    int line, col;
-    line = col = -1;
+    // line adn col: -1 means search starts at current position
+    int line = -1, col = -1;
+
     bool do_wrap = _wrap_check_box->isChecked ();
     bool do_forward = forward;
 
+    // Initialize the selection begin and end if it is the first search
+    if (! _find_result_available)
+      {
+        if (_search_selection_check_box->isChecked ()
+            && _edit_area->hasSelectedText ())
+          {
+            int l1, c1, l2, c2;
+            _edit_area->getSelection (&l1, &c1, &l2, &c2);
+
+            // Store the position of the selection
+            m_sel_beg = _edit_area->positionFromLineIndex (l1, c1);
+            m_sel_end = _edit_area->positionFromLineIndex (l2, c2);
+            m_in_sel = true;
+          }
+        else
+          m_in_sel = false;
+      }
+
+    // Get the correct line/col for beginning the search
     if (_rep_all)
       {
+        // Replace All
         if (_rep_all == 1)
           {
-            line = 0;
-            col = 0;
-          }
-        do_wrap = false;
-        // The following line is a workaround for the issue that when replacing
-        // a text with a new one with different size within the selection,
-        // the selection is not updated leading to missing or extra replacements.
-        // This does not happen, when the selection is search backwards
-        do_forward = ! _search_selection_check_box->isChecked ();
-      }
-    else
-      {
-        if (_from_start_check_box->isChecked ())
-          {
-            if (do_forward)
+            // Start at the beginning of file/sel if it is the first try
+            if (m_in_sel)
+              _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);
+            else
               {
                 line = 0;
                 col = 0;
               }
+          }
+        do_wrap = false;  // Never wrap when replacing all
+      }
+    else
+      {
+        // Normal search (not replace all): calculate start position of
+        // search (in file or selection)
+        if (_from_start_check_box->isChecked ()
+            || (m_in_sel && (! _find_result_available)))
+          {
+            // From the beginning or the end of file/sel
+            if (do_forward)
+              {
+                // From the beginning
+                if (m_in_sel)
+                  _edit_area->lineIndexFromPosition (m_sel_beg, &line, &col);
+                else
+                  {
+                    line = 0;
+                    col = 0;
+                  }
+              }
             else
               {
-                line = _edit_area->lines () - 1;
-                col  = _edit_area->text (line).length () - 1;
-                if (col == -1)
-                  col = 0;
+                // From the end
+                if (m_in_sel)
+                  _edit_area->lineIndexFromPosition (m_sel_end, &line, &col);
+                else
+                  {
+                    line = _edit_area->lines () - 1;
+                    col  = _edit_area->text (line).length () - 1;
+                    if (col == -1)
+                      col = 0;
+                  }
               }
           }
         else if (! do_forward)
           {
-            // search from position before search characters text length
-            // if search backward on existing results,
+            // Start from where the cursor is. Fix QScintilla's cursor
+            // positioning
             _edit_area->getCursorPosition (&line,&col);
             if (_find_result_available && _edit_area->hasSelectedText ())
               {
@@ -325,54 +379,65 @@
                 currpos -= (_search_line_edit->text ().length ());
                 if (currpos < 0)
                   currpos = 0;
-                _edit_area->lineIndexFromPosition (currpos, &line,&col);
+                _edit_area->lineIndexFromPosition (currpos, &line, &col);
               }
           }
       }
 
-    if (_edit_area->hasSelectedText ()
-        && _search_selection_check_box->isChecked ())
-      {
-#if defined (HAVE_QSCI_FINDSELECTION)
-        if (_find_result_available)
-          _find_result_available = _edit_area->findNext ();
-        else
-          _find_result_available
-            = _edit_area->findFirstInSelection (
-                                                _search_line_edit->text (),
-                                                _regex_check_box->isChecked (),
-                                                _case_check_box->isChecked (),
-                                                _whole_words_check_box->isChecked (),
-                                                do_forward,
-                                                true
+    // Do the search
+    _find_result_available = _edit_area->findFirst (
+                                  _search_line_edit->text (),
+                                  _regex_check_box->isChecked (),
+                                  _case_check_box->isChecked (),
+                                  _whole_words_check_box->isChecked (),
+                                  do_wrap,
+                                  do_forward,
+                                  line,col,
+                                  true
 #if defined (HAVE_QSCI_VERSION_2_6_0)
-                                                , true
+                                , true
 #endif
-                                               );
-#endif
-      }
-    else
+                              );
+
+    if (_find_result_available)
       {
-        _find_result_available
-          = _edit_area->findFirst (_search_line_edit->text (),
-                                   _regex_check_box->isChecked (),
-                                   _case_check_box->isChecked (),
-                                   _whole_words_check_box->isChecked (),
-                                   do_wrap,
-                                   do_forward,
-                                   line,col,
-                                   true
-#if defined (HAVE_QSCI_VERSION_2_6_0)
-                                    , true
-#endif
-                                  );
+        // Search successful: reset search-from-start box and check for
+        // the current selection
+        _from_start_check_box->setChecked (0);
+
+        if (m_in_sel)
+          {
+            _edit_area->getCursorPosition (&line,&col);
+            int pos = _edit_area->positionFromLineIndex (line, col);
+
+            int l1, c1, l2, c2;
+            _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);
+            _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);
+            _edit_area->show_selection_markers (l1, c1, l2, c2);
+
+            // Check if new start position is still wihtin the selection
+            _find_result_available =  pos >= m_sel_beg && pos <= m_sel_end;
+          }
       }
 
+    // No more search hits
+    if (! _find_result_available)
+      {
+        if (m_in_sel)
+          {
+            // Restore real selection and remove marker for selection
+            int l1, c1, l2, c2;
+            _edit_area->lineIndexFromPosition (m_sel_beg, &l1, &c1);
+            _edit_area->lineIndexFromPosition (m_sel_end, &l2, &c2);
+            _edit_area->setSelection (l1, c1, l2, c2);
+            _edit_area->clear_selection_markers ();
+          }
 
-    if (_find_result_available)
-      _from_start_check_box->setChecked (0);
-    else if (! _rep_all)
-      no_matches_message ();
+        // Display message if not replace all
+        if (! _rep_all)
+          no_matches_message ();
+      }
+
   }
 
   void find_dialog::do_replace (void)
@@ -380,7 +445,16 @@
     if (_edit_area)
       {
         _rep_active = true;  // changes in selection not made by the user
+
         _edit_area->replace (_replace_line_edit->text ());
+        if (m_in_sel)
+          {
+            // Update the length of the selection
+            m_sel_end = m_sel_end
+                        - _search_line_edit->text ().toUtf8 ().size ()
+                        + _replace_line_edit->text ().toUtf8 ().size ();
+          }
+
         _rep_active = false;
       }
   }
@@ -389,14 +463,7 @@
   {
     if (_edit_area)
       {
-        // The following line is a workaround for the issue that when replacing
-        // a text with a new one with different size within the selection,
-        // the selection is not updated leading to missing or extra replacements.
-        // This does not happen, when the selection is search backwards
-        if (_search_selection_check_box->isChecked ())
-          _backward_check_box->setChecked (true);
-
-        // do the replace if we have selected text
+        // Do the replace if we have selected text
         if (_find_result_available && _edit_area->hasSelectedText ())
           do_replace ();
 
--- a/libgui/src/m-editor/find-dialog.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/find-dialog.h	Fri Jul 12 12:14:43 2019 -0400
@@ -63,7 +63,8 @@
 #define octave_find_dialog_h 1
 
 #include <QDialog>
-#include <Qsci/qsciscintilla.h>
+
+#include "octave-qscintilla.h"
 
 class QCheckBox;
 class QDialogButtonBox;
@@ -77,10 +78,36 @@
   class find_dialog : public QDialog
   {
     Q_OBJECT
+
   public:
-    find_dialog (QsciScintilla *edit_area, QList<QAction *> find_actions,
+
+    typedef struct
+      {
+        QList<QAction *>  actions;
+        QString           text;
+        QString           replace_text;
+        QRect             geometry;
+        bool              is_visible;
+        int               options;
+      } find_dialog_data;
+
+    enum find_dialog_options
+      {
+        FIND_DLG_MORE  = 1,
+        FIND_DLG_CASE  = 2,
+        FIND_DLG_START = 4,
+        FIND_DLG_WRAP  = 8,
+        FIND_DLG_REGX  = 16,
+        FIND_DLG_WORDS = 32,
+        FIND_DLG_BACK  = 64,
+        FIND_DLG_SEL   = 128
+      };
+
+    find_dialog (octave_qscintilla *edit_area, QList<QAction *> find_actions,
                  QWidget *parent = nullptr);
     void init_search_text (void);
+    void save_data (find_dialog_data *fdlg_data);
+    void restore_data (const find_dialog_data *fdlg_data);
 
   private slots:
     void handle_sel_search_changed (int);
@@ -118,10 +145,14 @@
     QPushButton       *_replace_all_button;
     QPushButton       *_more_button;
     QWidget           *_extension;
-    QsciScintilla     *_edit_area;
+    octave_qscintilla  *_edit_area;
     bool               _find_result_available;
     int                _rep_all;
     bool               _rep_active;
+
+    bool               m_in_sel;
+    int                m_sel_beg;
+    int                m_sel_end;
   };
 }
 
--- a/libgui/src/m-editor/octave-qscintilla.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -65,45 +65,45 @@
 // Used for testing the last word of an "if" etc. line,
 // or the first word of the following line.
 
-static bool
-is_end (const QString& candidate, const QString& opening)
-{
-  bool retval = false;
-
-  if (opening == "do")          // The only one that can't be ended by "end"
-    {
-      if (candidate == "until")
-        retval = true;
-    }
-  else
-    {
-      if (candidate == "end")
-        retval =  true;
-      else
-        {
-          if (opening == "try")
-            {
-              if (candidate == "catch" || candidate == "end_try_catch")
-                retval = true;
-            }
-          else if (opening == "unwind_protect")
-            {
-              if (candidate == "unwind_protect_cleanup"
-                  || candidate == "end_unwind_protect")
-                retval = true;
-            }
-          else if (candidate == "end" + opening)
-            retval = true;
-          else if (opening == "if" && candidate == "else")
-            retval = true;
-        }
-    }
-
-  return retval;
-}
-
 namespace octave
 {
+  static bool
+  is_end (const QString& candidate, const QString& opening)
+  {
+    bool retval = false;
+
+    if (opening == "do")          // The only one that can't be ended by "end"
+      {
+        if (candidate == "until")
+          retval = true;
+      }
+    else
+      {
+        if (candidate == "end")
+          retval =  true;
+        else
+          {
+            if (opening == "try")
+              {
+                if (candidate == "catch" || candidate == "end_try_catch")
+                  retval = true;
+              }
+            else if (opening == "unwind_protect")
+              {
+                if (candidate == "unwind_protect_cleanup"
+                    || candidate == "end_unwind_protect")
+                  retval = true;
+              }
+            else if (candidate == "end" + opening)
+              retval = true;
+            else if (opening == "if" && candidate == "else")
+              retval = true;
+          }
+      }
+
+    return retval;
+  }
+
   octave_qscintilla::octave_qscintilla (QWidget *p)
     : QsciScintilla (p), m_word_at_cursor (), m_selection (),
       m_selection_replacement (), m_selection_line (-1),
@@ -499,8 +499,8 @@
   }
 
   // Do smart indendation after if, for, ...
-  void octave_qscintilla::smart_indent (bool do_smart_indent,
-                                        int do_auto_close, int line)
+  void octave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close,
+                                        int line, int ind_char_width)
   {
     QString prevline = text (line);
 
@@ -534,7 +534,7 @@
           {
             // Do smart indent in the current line (line+1)
             indent (line+1);
-            setCursorPosition (line+1, indentation (line) + indentationWidth ());
+            setCursorPosition (line+1, indentation (line+1) / ind_char_width);
           }
 
         if (do_auto_close
@@ -726,11 +726,12 @@
       }
   }
 
-  void octave_qscintilla::show_selection_markers (int line, int col, int len)
+  void octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2)
   {
-    fillIndicatorRange (line, col - len, line, col, m_indicator_id);
+    fillIndicatorRange (l1, c1, l2, c2, m_indicator_id);
 
-    markerAdd (line, marker::selection);
+    if (l1 == l2)
+      markerAdd (l1, marker::selection);
   }
 
   void octave_qscintilla::contextmenu_help (bool)
@@ -965,9 +966,11 @@
     //       end* (until) (catch)
     if (linenr < lines () - 1)
       {
-        int offset = 1;
+        int offset = 2;     // linenr is the old line, thus, linnr+1 is the
+                            // new one and can not be taken into account
         size_t next_start;
         QString next_line;
+
         do                            // find next non-blank line
           {
             next_line = text (linenr + offset++);
@@ -975,8 +978,11 @@
           }
         while (linenr + offset < lines ()
                && next_start == std::string::npos);
+
         if (next_start == std::string::npos)
           next_start = 0;
+        if (start == 0 && next_start == 0)
+          return;                     // bug #56160, don't add at 0
         if (next_start > start)       // more indented => don't add "end"
           return;
         if (next_start == start)      // same => check if already is "end"
@@ -1022,7 +1028,9 @@
         next_line = "end" + first_word + "\n";
       }
 
-    insertAt (QString (start, ' ') + next_line, linenr + 2, 0);
+    //insertAt (QString (start, ' ') + next_line, linenr + 2, 0);
+    insertAt (next_line, linenr + 2, 0);
+    setIndentation (linenr + 2, indentation (linenr));
   }
 
   void octave_qscintilla::dragEnterEvent (QDragEnterEvent *e)
--- a/libgui/src/m-editor/octave-qscintilla.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/m-editor/octave-qscintilla.h	Fri Jul 12 12:14:43 2019 -0400
@@ -63,13 +63,14 @@
     QStringList comment_string (bool comment = true);
     int get_style (int pos = -1);
     int is_style_comment (int pos = -1);
-    void smart_indent (bool do_smart_indent, int do_auto_close, int line);
+    void smart_indent (bool do_smart_indent, int do_auto_close,
+                       int line, int ind_char_width);
 
     void smart_indent_line_or_selected_text (int lineFrom, int lineTo);
 
     void set_word_selection (const QString& word = QString ());
 
-    void show_selection_markers (int line, int col, int len);
+    void show_selection_markers (int l1, int c1, int l2, int c2);
 
     void set_selection_marker_color (const QColor& c);
 
--- a/libgui/src/main-window.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/main-window.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -55,7 +55,10 @@
 #if defined (HAVE_QSCINTILLA)
 #  include "file-editor.h"
 #endif
+#include "interpreter-qobject.h"
 #include "main-window.h"
+#include "news-reader.h"
+#include "octave-qobject.h"
 #include "settings-dialog.h"
 #include "shortcut-manager.h"
 #include "welcome-wizard.h"
@@ -67,7 +70,6 @@
 #include "url-transfer.h"
 
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defaults.h"
 #include "defun.h"
 #include "interpreter-private.h"
@@ -80,90 +82,22 @@
 #include "utils.h"
 #include "version.h"
 
-static octave::file_editor_interface *
-create_default_editor (QWidget *p)
-{
-#if defined (HAVE_QSCINTILLA)
-  return new octave::file_editor (p);
-#else
-  octave_unused_parameter (p);
-
-  return 0;
-#endif
-}
-
-// Disable all Qt messages by default.
-
-static void
-#if defined (QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT)
-message_handler (QtMsgType, const QMessageLogContext &, const QString &)
-#else
-message_handler (QtMsgType, const char *)
-#endif
-{ }
-
 namespace octave
 {
-  octave_interpreter::octave_interpreter (gui_application& app_context)
-    : QObject (), m_app_context (app_context)
-  { }
-
-  void octave_interpreter::execute (void)
+  static file_editor_interface *
+  create_default_editor (QWidget *p)
   {
-    // The application context owns the interpreter.
-
-    interpreter& interp = m_app_context.create_interpreter ();
-
-    int exit_status = 0;
-
-    try
-      {
-        // Final initialization.
-
-        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
-            // the GUI know.
-
-            emit octave_ready_signal ();
-
-            // Start executing commands in the command window.
-
-            exit_status = interp.execute ();
-          }
-      }
-    catch (const exit_exception& ex)
-      {
-        exit_status = ex.exit_status ();
-      }
-
-    // Whether or not initialization succeeds we need to clean up the
-    // interpreter once we are done with it.
-
-    m_app_context.delete_interpreter ();
-
-    emit octave_finished_signal (exit_status);
+#if defined (HAVE_QSCINTILLA)
+    return new file_editor (p);
+#else
+    octave_unused_parameter (p);
+
+    return 0;
+#endif
   }
 
-  main_window::main_window (octave_qt_app& oct_qt_app,
-                            octave_qt_link *oct_qt_lnk)
-    : QMainWindow (),
-      m_qt_app (oct_qt_app.qt_app ()), m_octave_qt_link (oct_qt_lnk),
-      m_workspace_model (nullptr),
+  main_window::main_window (base_qobject& qobj)
+    : QMainWindow (), m_octave_qobj (qobj), m_workspace_model (nullptr),
       m_status_bar (nullptr), m_command_window (nullptr),
       m_history_window (nullptr), m_file_browser_window (nullptr),
       m_doc_browser_window (nullptr), m_editor_window (nullptr),
@@ -179,7 +113,7 @@
     if (resource_manager::is_first_run ())
       {
         // Before wizard.
-        oct_qt_app.config_translators ();
+        qobj.config_translators ();
 
         welcome_wizard welcomeWizard;
 
@@ -195,7 +129,7 @@
         resource_manager::reload_settings ();
 
         // After settings.
-        oct_qt_app.config_translators ();
+        qobj.config_translators ();
       }
 
     resource_manager::update_network_settings ();
@@ -229,7 +163,9 @@
     QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop");
 #endif
 
-    m_default_style = m_qt_app->style ()->objectName ();
+    QApplication *qapp = m_octave_qobj.qapplication ();
+
+    m_default_style = qapp->style ()->objectName ();
 
     QSettings *settings = resource_manager::get_settings ();
 
@@ -279,10 +215,6 @@
 
   main_window::~main_window (void)
   {
-    // Note that we don't delete m_main_thread here.  That is handled by
-    // deleteLater slot that is called when the m_main_thread issues a
-    // finished signal.
-
     // Destroy the terminal first so that STDERR stream is redirected back
     // to its original pipe to capture error messages at exit.
 
@@ -495,8 +427,12 @@
 
   void main_window::file_remove_proxy (const QString& o, const QString& n)
   {
+    interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
+
+    octave_qt_link *qt_link = interp_qobj->qt_link ();
+
     // Wait for worker to suspend
-    m_octave_qt_link->lock ();
+    qt_link->lock ();
 
     // Close the file if opened
 #if defined (HAVE_QSCINTILLA)
@@ -507,8 +443,8 @@
 #endif
 
     // We are done: Unlock and wake the worker thread
-    m_octave_qt_link->unlock ();
-    m_octave_qt_link->wake_all ();
+    qt_link->unlock ();
+    qt_link->wake_all ();
   }
 
   void main_window::open_online_documentation_page (void)
@@ -738,7 +674,11 @@
 
     QStyle *new_style = QStyleFactory::create (preferred_style);
     if (new_style)
-      m_qt_app->setStyle (new_style);
+      {
+        QApplication *qapp = m_octave_qobj.qapplication ();
+
+        qapp->setStyle (new_style);
+      }
 
     // the widget's icons (when floating)
     QString icon_set
@@ -1016,7 +956,7 @@
 
     m_debug_continue->setEnabled (false);
     m_debug_step_into->setEnabled (false);
-    m_debug_step_over->setEnabled (false);
+    m_debug_step_over->setEnabled (m_editor_has_tabs);
     m_debug_step_out->setEnabled (false);
     m_debug_quit->setEnabled (false);
 
@@ -1040,9 +980,18 @@
 
   void main_window::debug_step_over (void)
   {
-    octave_cmd_debug *cmd
-      = new octave_cmd_debug ("step", m_suppress_dbg_location);
-    queue_cmd (cmd);
+    if (m_debug_quit->isEnabled ())
+      {
+        // We are in debug mode, just call dbstep
+        octave_cmd_debug *cmd
+          = new octave_cmd_debug ("step", m_suppress_dbg_location);
+        queue_cmd (cmd);
+      }
+    else
+      {
+        // Not in debug mode: "step into" the current editor file
+        emit step_into_file_signal ();
+      }
   }
 
   void main_window::debug_step_out (void)
@@ -1707,17 +1656,21 @@
     connect (m_workspace_model, SIGNAL (model_changed (void)),
              m_workspace_window, SLOT (handle_model_changed (void)));
 
-    connect (m_octave_qt_link,
+    interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
+
+    octave_qt_link *qt_link = interp_qobj->qt_link ();
+
+    connect (qt_link,
              SIGNAL (edit_variable_signal (const QString&,
                                            const octave_value&)),
              this,
              SLOT (edit_variable (const QString&, const octave_value&)));
 
-    connect (m_octave_qt_link, SIGNAL (refresh_variable_editor_signal (void)),
+    connect (qt_link, SIGNAL (refresh_variable_editor_signal (void)),
              this, SLOT (refresh_variable_editor (void)));
 
-    connect (m_workspace_model,
-             SIGNAL (rename_variable (const QString&, const QString&)),
+    connect (m_workspace_window,
+             SIGNAL (rename_variable_signal (const QString&, const QString&)),
              this,
              SLOT (handle_rename_variable_request (const QString&,
                                                    const QString&)));
@@ -1773,6 +1726,12 @@
     connect (this, SIGNAL (editor_focus_changed (bool)),
              m_editor_window, SLOT (enable_menu_shortcuts (bool)));
 
+    connect (this, SIGNAL (step_into_file_signal (void)),
+             m_editor_window, SLOT (request_step_into_file (void)));
+
+    connect (m_editor_window, SIGNAL (editor_tabs_changed_signal (bool)),
+             this, SLOT (editor_tabs_changed (bool)));
+
     connect (m_editor_window,
              SIGNAL (request_open_file_external (const QString&, int)),
              m_external_editor,
@@ -1862,12 +1821,12 @@
              m_editor_window, SLOT (handle_file_renamed (bool)));
 
     // Signals for removing/renaming files/dirs in the temrinal window
-    connect (m_octave_qt_link, SIGNAL (file_renamed_signal (bool)),
+    connect (qt_link, SIGNAL (file_renamed_signal (bool)),
              m_editor_window, SLOT (handle_file_renamed (bool)));
 #endif
 
     // Signals for removing/renaming files/dirs in the temrinal window
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (file_remove_signal (const QString&, const QString&)),
              this, SLOT (file_remove_proxy (const QString&, const QString&)));
 
@@ -1879,88 +1838,92 @@
 
   void main_window::construct_octave_qt_link (void)
   {
-    connect (m_octave_qt_link,
+    interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
+
+    octave_qt_link *qt_link = interp_qobj->qt_link ();
+
+    connect (qt_link,
              SIGNAL (set_workspace_signal (bool, bool, const symbol_info_list&)),
              m_workspace_model,
              SLOT (set_workspace (bool, bool, const symbol_info_list&)));
 
-    connect (m_octave_qt_link, SIGNAL (clear_workspace_signal (void)),
+    connect (qt_link, SIGNAL (clear_workspace_signal (void)),
              m_workspace_model, SLOT (clear_workspace (void)));
 
-    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+    connect (qt_link, SIGNAL (change_directory_signal (QString)),
              this, SLOT (change_directory (QString)));
 
-    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+    connect (qt_link, SIGNAL (change_directory_signal (QString)),
              m_file_browser_window, SLOT (update_octave_directory (QString)));
 
-    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+    connect (qt_link, SIGNAL (change_directory_signal (QString)),
              m_editor_window, SLOT (update_octave_directory (QString)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (execute_command_in_terminal_signal (QString)),
              this, SLOT (execute_command_in_terminal (QString)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (set_history_signal (const QStringList&)),
              m_history_window, SLOT (set_history (const QStringList&)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (append_history_signal (const QString&)),
              m_history_window, SLOT (append_history (const QString&)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (clear_history_signal (void)),
              m_history_window, SLOT (clear_history (void)));
 
-    connect (m_octave_qt_link, SIGNAL (enter_debugger_signal (void)),
+    connect (qt_link, SIGNAL (enter_debugger_signal (void)),
              this, SLOT (handle_enter_debugger (void)));
 
-    connect (m_octave_qt_link, SIGNAL (exit_debugger_signal (void)),
+    connect (qt_link, SIGNAL (exit_debugger_signal (void)),
              this, SLOT (handle_exit_debugger (void)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (show_preferences_signal (void)),
              this, SLOT (process_settings_dialog_request (void)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (gui_preference_signal (const QString&, const QString&,
                                             QString*)),
              this, SLOT (gui_preference (const QString&, const QString&,
                                          QString*)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (edit_file_signal (const QString&)),
              m_active_editor,
              SLOT (handle_edit_file_request (const QString&)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
              this,
              SLOT (handle_insert_debugger_pointer_request (const QString&,
                                                            int)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
              this,
              SLOT (handle_delete_debugger_pointer_request (const QString&,
                                                            int)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (update_breakpoint_marker_signal (bool, const QString&,
                                                       int, const QString&)),
              this,
              SLOT (handle_update_breakpoint_marker_request (bool, const QString&,
                                                             int, const QString&)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (show_doc_signal (const QString &)),
              this, SLOT (handle_show_doc (const QString &)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (register_doc_signal (const QString &)),
              this, SLOT (handle_register_doc (const QString &)));
 
-    connect (m_octave_qt_link,
+    connect (qt_link,
              SIGNAL (unregister_doc_signal (const QString &)),
              this, SLOT (handle_unregister_doc (const QString &)));
   }
@@ -2058,6 +2021,7 @@
     file_menu->addSeparator ();
 
     m_exit_action = file_menu->addAction (tr ("Exit"));
+    m_exit_action->setMenuRole (QAction::QuitRole);
     m_exit_action->setShortcutContext (Qt::ApplicationShortcut);
 
     connect (m_open_action, SIGNAL (triggered (void)),
@@ -2238,6 +2202,13 @@
                                               SLOT (debug_quit (void)));
   }
 
+  void main_window::editor_tabs_changed (bool have_tabs)
+  {
+    // Set state of action which depend on the existance of editor tabs
+    m_editor_has_tabs = have_tabs;
+    m_debug_step_over->setEnabled (have_tabs);
+  }
+
   QAction * main_window::construct_window_menu_item (QMenu *p,
                                                      const QString& item,
                                                      bool checkable,
@@ -2468,8 +2439,12 @@
     QSettings *settings = resource_manager::get_settings ();
     *read_value = settings->value (key).toString ();
 
+    interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
+
+    octave_qt_link *qt_link = interp_qobj->qt_link ();
+
     // Wait for worker to suspend
-    m_octave_qt_link->lock ();
+    qt_link->lock ();
 
     // Some preferences need extra handling
     QString adjusted_value = gui_preference_adjust (key, value);
@@ -2482,8 +2457,8 @@
       }
 
     // We are done: Unlock and wake the worker thread
-    m_octave_qt_link->unlock ();
-    m_octave_qt_link->wake_all ();
+    qt_link->unlock ();
+    qt_link->wake_all ();
   }
 
   void main_window::rename_variable_callback (const main_window::name_pair& names)
@@ -2497,10 +2472,10 @@
       {
         scope.rename (names.first, names.second);
 
-        call_stack& cs
-          = __get_call_stack__ ("main_window::rename_variable_callback");
-
-        octave_link::set_workspace (true, cs.get_symbol_info ());
+        tree_evaluator& tw
+          = __get_evaluator__ ("main_window::rename_variable_callback");
+
+        octave_link::set_workspace (true, tw.get_symbol_info ());
       }
 
     // FIXME: if this action fails, do we need a way to display that info
@@ -2541,13 +2516,13 @@
   {
     // INTERPRETER THREAD
 
-    octave::feval ("open", ovl (file));
+    feval ("open", ovl (file));
 
     // Update the workspace since open.m may have loaded new variables.
-    call_stack& cs
-      = __get_call_stack__ ("main_window::open_any_callback");
-
-    octave_link::set_workspace (true, cs.get_symbol_info ());
+    tree_evaluator& tw
+      = __get_evaluator__ ("main_window::open_any_callback");
+
+    octave_link::set_workspace (true, tw.get_symbol_info ());
   }
 
   void main_window::clear_history_callback (void)
@@ -2564,10 +2539,10 @@
   {
     // INTERPRETER THREAD
 
-    call_stack& cs
-      = __get_call_stack__ ("main_window::force_refresh_workspace");
-
-    octave_link::set_workspace (true, cs.get_symbol_info (), false);
+    tree_evaluator& tw
+      = __get_evaluator__ ("main_window::force_refresh_workspace");
+
+    octave_link::set_workspace (true, tw.get_symbol_info (), false);
   }
 
   bool main_window::focus_console_after_command (void)
@@ -2680,420 +2655,4 @@
     list.append (static_cast<octave_dock_widget *> (m_variable_editor_window));
     return list;
   }
-
-  void news_reader::process (void)
-  {
-    QString html_text;
-
-    if (m_connect_to_web)
-      {
-        // Run this part in a separate thread so Octave can continue to
-        // run while we wait for the page to load.  Then emit the signal
-        // to display it when we have the page contents.
-
-        QString url = m_base_url + '/' + m_page;
-        std::ostringstream buf;
-        url_transfer octave_dot_org (url.toStdString (), buf);
-
-        if (octave_dot_org.is_valid ())
-          {
-            Array<std::string> param;
-            octave_dot_org.http_get (param);
-
-            if (octave_dot_org.good ())
-              html_text = QString::fromStdString (buf.str ());
-          }
-
-        if (html_text.contains ("this-is-the-gnu-octave-community-news-page"))
-          {
-            if (m_serial >= 0)
-              {
-                QSettings *settings = resource_manager::get_settings ();
-
-                if (settings)
-                  {
-                    settings->setValue ("news/last_time_checked",
-                                        QDateTime::currentDateTime ());
-
-                    settings->sync ();
-                  }
-
-                QString tag ("community-news-page-serial=");
-
-                int b = html_text.indexOf (tag);
-
-                if (b)
-                  {
-                    b += tag.length ();
-
-                    int e = html_text.indexOf ("\n", b);
-
-                    QString tmp = html_text.mid (b, e-b);
-
-                    int curr_page_serial = tmp.toInt ();
-
-                    if (curr_page_serial > m_serial)
-                      {
-                        if (settings)
-                          {
-                            settings->setValue ("news/last_news_item",
-                                                curr_page_serial);
-
-                            settings->sync ();
-                          }
-                      }
-                    else
-                      return;
-                  }
-                else
-                  return;
-              }
-          }
-        else
-          html_text = QString
-            (tr ("<html>\n"
-                 "<body>\n"
-                 "<p>\n"
-                 "Octave's community news source seems to be unavailable.\n"
-                 "</p>\n"
-                 "<p>\n"
-                 "For the latest news, please check\n"
-                 "<a href=\"https://octave.org/community-news.html\">https://octave.org/community-news.html</a>\n"
-                 "when you have a connection to the web (link opens in an external browser).\n"
-                 "</p>\n"
-                 "<p>\n"
-                 "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
-             "</p>\n"
-             "</body>\n"
-             "</html>\n");
-      }
-    else
-      html_text = QString
-        (tr ("<html>\n"
-             "<body>\n"
-             "<p>\n"
-             "Connecting to the web to display the latest Octave Community news has been disabled.\n"
-             "</p>\n"
-             "<p>\n"
-             "For the latest news, please check\n"
-             "<a href=\"https://octave.org/community-news.html\">https://octave.org/community-news.html</a>\n"
-             "when you have a connection to the web (link opens in an external browser)\n"
-             "or enable web connections for news in Octave's network settings dialog.\n"
-             "</p>\n"
-             "<p>\n"
-             "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
-         "</p>\n"
-         "</body>\n"
-         "</html>\n");
-
-    emit display_news_signal (html_text);
-
-    emit finished ();
-  }
-
-  //! Reimplements QApplication::notify.
-  /*! Octave's own exceptions are caugh and rethrown in the interpreter
-      thread.*/
-  bool
-  octave_qapplication::notify (QObject *receiver, QEvent *ev)
-  {
-    try
-      {
-        return QApplication::notify (receiver, ev);
-      }
-    catch (octave::execution_exception&)
-      {
-        octave_link::post_exception (std::current_exception ());
-      }
-
-   return false;
-  }
-
-  octave_qt_app::octave_qt_app (gui_application& app_context)
-    : QObject (), m_app_context (app_context),
-      m_argc (m_app_context.sys_argc ()),
-      m_argv (m_app_context.sys_argv ()), m_qt_app (nullptr),
-      m_qt_tr (new QTranslator ()), m_gui_tr (new QTranslator ()),
-      m_qsci_tr (new QTranslator ()), m_translators_installed (false),
-      m_octave_qt_link (new octave_qt_link ()),
-      m_interpreter (new octave_interpreter (m_app_context)),
-      m_main_thread (new QThread ()),
-      m_main_window (nullptr)
-  {
-    std::string show_gui_msgs =
-      sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
-
-    // Installing our handler suppresses the messages.
-
-    if (show_gui_msgs.empty ())
-      {
-#if defined (HAVE_QINSTALLMESSAGEHANDLER)
-        qInstallMessageHandler (message_handler);
-#else
-        qInstallMsgHandler (message_handler);
-#endif
-      }
-
-    // Set the codec for all strings (before wizard or any GUI object)
-#if ! defined (Q_OS_WIN32)
-    QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
-#endif
-
-#if defined (HAVE_QT4)
-    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
-#endif
-
-    // Initialize global Qt application metadata.
-
-    QCoreApplication::setApplicationName ("GNU Octave");
-    QCoreApplication::setApplicationVersion (OCTAVE_VERSION);
-
-    // Register octave_value_list for connecting thread crossing signals.
-
-    qRegisterMetaType<octave_value_list> ("octave_value_list");
-
-    // Even if START_GUI is false, we still set up the QApplication so
-    // that we can use Qt widgets for plot windows.
-
-    m_qt_app = new octave_qapplication (m_argc, m_argv);
-
-    // Force left-to-right alignment (see bug #46204)
-    m_qt_app->setLayoutDirection (Qt::LeftToRight);
-
-    octave_link::connect_link (m_octave_qt_link);
-
-    connect (m_octave_qt_link, SIGNAL (confirm_shutdown_signal (void)),
-             this, SLOT (confirm_shutdown_octave (void)));
-
-    connect (m_octave_qt_link,
-             SIGNAL (copy_image_to_clipboard_signal (const QString&, bool)),
-             this, SLOT (copy_image_to_clipboard (const QString&, bool)));
-
-    connect_uiwidget_links ();
-
-    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
-             this, SLOT (handle_octave_finished (int)));
-
-    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
-             m_main_thread, SLOT (quit (void)));
-
-    connect (m_main_thread, SIGNAL (finished (void)),
-             m_main_thread, SLOT (deleteLater (void)));
-
-    if (m_app_context.start_gui_p ())
-      create_main_window ();
-    else
-      {
-        // Get settings file.
-        resource_manager::reload_settings ();
-
-        // After settings.
-        config_translators ();
-
-        m_qt_app->setQuitOnLastWindowClosed (false);
-      }
-
-    // Defer initializing and executing the interpreter until after the main
-    // window and QApplication are running to prevent race conditions
-    QTimer::singleShot (0, m_interpreter, SLOT (execute (void)));
-
-    m_interpreter->moveToThread (m_main_thread);
-
-    m_main_thread->start ();
-  }
-
-  octave_qt_app::~octave_qt_app (void)
-  {
-    delete m_main_window;
-    delete m_interpreter;
-    delete m_qt_app;
-
-    string_vector::delete_c_str_vec (m_argv);
-  }
-
-  void octave_qt_app::config_translators (void)
-  {
-    if (m_translators_installed)
-      return;
-
-    resource_manager::config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);
-
-    m_qt_app->installTranslator (m_qt_tr);
-    m_qt_app->installTranslator (m_gui_tr);
-    m_qt_app->installTranslator (m_qsci_tr);
-
-    m_translators_installed = true;
-  }
-
-  void octave_qt_app::create_main_window (void)
-  {
-    m_main_window = new main_window (*this, m_octave_qt_link);
-
-    connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
-             m_main_window, SLOT (handle_octave_ready (void)));
-
-    m_app_context.gui_running (true);
-  }
-
-  int octave_qt_app::exec (void)
-  {
-    return m_qt_app->exec ();
-  }
-
-  void octave_qt_app::handle_octave_finished (int exit_status)
-  {
-    qApp->exit (exit_status);
-  }
-
-  void octave_qt_app::confirm_shutdown_octave (void)
-  {
-    bool closenow = true;
-
-    if (m_main_window)
-      closenow = m_main_window->confirm_shutdown_octave ();
-
-    // Wait for link thread to go to sleep state.
-    m_octave_qt_link->lock ();
-
-    m_octave_qt_link->shutdown_confirmation (closenow);
-
-    m_octave_qt_link->unlock ();
-
-    // Awake the worker thread so that it continues shutting down (or not).
-    m_octave_qt_link->wake_all ();
-  }
-
-  void octave_qt_app::copy_image_to_clipboard (const QString& file,
-                                                bool remove_file)
-  {
-    QClipboard *clipboard = QApplication::clipboard ();
-
-    QImage img (file);
-
-    if (img.isNull ())
-      {
-        // Report error?
-        return;
-      }
-
-    clipboard->setImage (img);
-
-    if (remove_file)
-      QFile::remove (file);
-  }
-
-  // Create a message dialog with specified string, buttons and decorative
-  // text.
-
-  void octave_qt_app::handle_create_dialog (const QString& message,
-                                            const QString& title,
-                                            const QString& icon,
-                                            const QStringList& button,
-                                            const QString& defbutton,
-                                            const QStringList& role)
-  {
-    MessageDialog *message_dialog = new MessageDialog (message, title, icon,
-                                                       button, defbutton, role);
-    message_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    message_dialog->show ();
-  }
-
-  // Create a list dialog with specified list, initially selected, mode,
-  // view size and decorative text.
-
-  void octave_qt_app::handle_create_listview (const QStringList& list,
-                                              const QString& mode,
-                                              int wd, int ht,
-                                              const QIntList& initial,
-                                              const QString& name,
-                                              const QStringList& prompt,
-                                              const QString& ok_string,
-                                              const QString& cancel_string)
-  {
-    ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
-                                              initial, name, prompt,
-                                              ok_string, cancel_string);
-
-    list_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    list_dialog->show ();
-  }
-
-  // Create an input dialog with specified prompts and defaults, title and
-  // row/column size specifications.
-  void octave_qt_app::handle_create_inputlayout (const QStringList& prompt,
-                                                 const QString& title,
-                                                 const QFloatList& nr,
-                                                 const QFloatList& nc,
-                                                 const QStringList& defaults)
-  {
-    InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
-                                                 defaults);
-
-    input_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    input_dialog->show ();
-  }
-
-  void octave_qt_app::handle_create_filedialog (const QStringList& filters,
-                                                const QString& title,
-                                                const QString& filename,
-                                                const QString& dirname,
-                                                const QString& multimode)
-  {
-    FileDialog *file_dialog = new FileDialog (filters, title, filename,
-                                              dirname, multimode);
-
-    file_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    file_dialog->show ();
-  }
-
-  // Connect the signals emitted when the Octave thread wants to create
-  // a dialog box of some sort.  Perhaps a better place for this would be
-  // as part of the QUIWidgetCreator class.  However, mainWindow currently
-  // is not a global variable and not accessible for connecting.
-
-  void octave_qt_app::connect_uiwidget_links (void)
-  {
-    connect (&uiwidget_creator,
-             SIGNAL (create_dialog (const QString&, const QString&,
-                                    const QString&, const QStringList&,
-                                    const QString&, const QStringList&)),
-             this,
-             SLOT (handle_create_dialog (const QString&, const QString&,
-                                         const QString&, const QStringList&,
-                                         const QString&, const QStringList&)));
-
-    // Register QIntList so that list of ints may be part of a signal.
-    qRegisterMetaType<QIntList> ("QIntList");
-    connect (&uiwidget_creator,
-             SIGNAL (create_listview (const QStringList&, const QString&,
-                                      int, int, const QIntList&,
-                                      const QString&, const QStringList&,
-                                      const QString&, const QString&)),
-             this,
-             SLOT (handle_create_listview (const QStringList&, const QString&,
-                                           int, int, const QIntList&,
-                                           const QString&, const QStringList&,
-                                           const QString&, const QString&)));
-
-    // Register QFloatList so that list of floats may be part of a signal.
-    qRegisterMetaType<QFloatList> ("QFloatList");
-    connect (&uiwidget_creator,
-             SIGNAL (create_inputlayout (const QStringList&, const QString&,
-                                         const QFloatList&, const QFloatList&,
-                                         const QStringList&)),
-             this,
-             SLOT (handle_create_inputlayout (const QStringList&, const QString&,
-                                              const QFloatList&,
-                                              const QFloatList&,
-                                              const QStringList&)));
-
-    connect (&uiwidget_creator,
-             SIGNAL (create_filedialog (const QStringList &,const QString&,
-                                        const QString&, const QString&,
-                                        const QString&)),
-             this,
-             SLOT (handle_create_filedialog (const QStringList &, const QString&,
-                                             const QString&, const QString&,
-                                             const QString&)));
-  }
 }
--- a/libgui/src/main-window.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/main-window.h	Fri Jul 12 12:14:43 2019 -0400
@@ -52,7 +52,6 @@
 #include "history-dock-widget.h"
 #include "octave-cmd.h"
 #include "octave-dock-widget.h"
-#include "octave-gui.h"
 #include "octave-qt-link.h"
 #include "resource-manager.h"
 #include "terminal-dock-widget.h"
@@ -64,36 +63,9 @@
 
 namespace octave
 {
+  class base_qobject;
   class settings_dialog;
 
-  class octave_interpreter : public QObject
-  {
-    Q_OBJECT
-
-  public:
-
-    octave_interpreter (gui_application& app_context);
-
-    ~octave_interpreter (void) = default;
-
-  signals:
-
-    void octave_ready_signal (void);
-    void octave_finished_signal (int);
-
-  public slots:
-
-    //! Initialize and execute the octave interpreter.
-
-    void execute (void);
-
-  private:
-
-    gui_application& m_app_context;
-  };
-
-  class octave_qt_app;
-
   //! Represents the main window.
 
   class main_window : public QMainWindow
@@ -105,7 +77,7 @@
     typedef std::pair <std::string, std::string> name_pair;
     typedef std::pair <int, int> int_pair;
 
-    main_window (octave_qt_app& oct_qt_app, octave_qt_link *oct_qt_lnk);
+    main_window (base_qobject& qapp);
 
     ~main_window (void);
 
@@ -123,6 +95,7 @@
     void new_file_signal (const QString&);
     void open_file_signal (const QString&);
     void open_file_signal (const QString& file, const QString& enc, int line);
+    void step_into_file_signal (void);
 
     void show_doc_signal (const QString&);
     void register_doc_signal (const QString&);
@@ -194,6 +167,7 @@
     void debug_step_over (void);
     void debug_step_out (void);
     void debug_quit (void);
+    void editor_tabs_changed (bool);
 
     void request_open_file (void);
     void request_new_script (const QString& commands = QString ());
@@ -332,9 +306,7 @@
 
     QList<octave_dock_widget *> dock_widget_list (void);
 
-    QApplication *m_qt_app;
-
-    octave_qt_link *m_octave_qt_link;
+    base_qobject& m_octave_qobj;
 
     workspace_model *m_workspace_model;
 
@@ -455,6 +427,7 @@
     //!@{
     bool m_prevent_readline_conflicts;
     bool m_suppress_dbg_location;
+    bool m_editor_has_tabs;
 
     //! Flag for closing the whole application.
 
@@ -463,127 +436,6 @@
 
     QString m_file_encoding;
   };
-
-  class news_reader : public QObject
-  {
-    Q_OBJECT
-
-  public:
-
-    news_reader (const QString& base_url, const QString& page,
-                 int serial = -1, bool connect_to_web = false)
-      : QObject (), m_base_url (base_url), m_page (page), m_serial (serial),
-        m_connect_to_web (connect_to_web)
-    { }
-
-  public slots:
-
-    void process (void);
-
-  signals:
-
-    void display_news_signal (const QString& news);
-
-    void finished (void);
-
-  private:
-
-    QString m_base_url;
-    QString m_page;
-    int m_serial;
-    bool m_connect_to_web;
-  };
-
-  class octave_qapplication : public QApplication
-  {
-  public:
-
-    octave_qapplication (int& argc, char **argv)
-    : QApplication (argc, argv)
-    { }
-
-    virtual bool notify (QObject *receiver, QEvent *e) override;
-
-    ~octave_qapplication (void) { };
-  };
-
-  class octave_qt_app : public QObject
-  {
-    Q_OBJECT
-
-  public:
-
-    octave_qt_app (gui_application& app_context);
-
-    ~octave_qt_app (void);
-
-    void config_translators (void);
-
-    void create_main_window (void);
-
-    int exec (void);
-
-    QApplication *qt_app (void) { return m_qt_app; };
-
-  public slots:
-
-    void handle_octave_finished (int);
-
-    void confirm_shutdown_octave (void);
-
-    void copy_image_to_clipboard (const QString& file, bool remove_file);
-
-    void handle_create_dialog (const QString& message, const QString& title,
-                               const QString& icon, const QStringList& button,
-                               const QString& defbutton,
-                               const QStringList& role);
-
-    void handle_create_listview (const QStringList& list, const QString& mode,
-                                 int width, int height,
-                                 const QIntList& initial,
-                                 const QString& name,
-                                 const QStringList& prompt,
-                                 const QString& ok_string,
-                                 const QString& cancel_string);
-
-    void handle_create_inputlayout (const QStringList&, const QString&,
-                                    const QFloatList&, const QFloatList&,
-                                    const QStringList&);
-
-    void handle_create_filedialog (const QStringList& filters,
-                                   const QString& title,
-                                   const QString& filename,
-                                   const QString& dirname,
-                                   const QString& multimode);
-
-  private:
-
-    gui_application& m_app_context;
-
-    // Use these to ensure that argc and argv exist for as long as the
-    // QApplication object.
-
-    int m_argc;
-    char **m_argv;
-
-    octave_qapplication *m_qt_app;
-
-    QTranslator *m_qt_tr;
-    QTranslator *m_gui_tr;
-    QTranslator *m_qsci_tr;
-
-    bool m_translators_installed;
-
-    octave_qt_link *m_octave_qt_link;
-
-    octave_interpreter *m_interpreter;
-
-    QThread *m_main_thread;
-
-    main_window *m_main_window;
-
-    void connect_uiwidget_links (void);
-  };
 }
 
 #endif
--- a/libgui/src/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -1,9 +1,14 @@
 octave_gui_ICONS = \
   %reldir%/icons/applications-system.png \
+  %reldir%/icons/bottom_left_corner.png \
+  %reldir%/icons/bottom_right_corner.png \
+  %reldir%/icons/bottom_side.png \
   %reldir%/icons/bp-next.png \
   %reldir%/icons/bp-prev.png \
   %reldir%/icons/bp-rm-all.png \
   %reldir%/icons/bp-toggle.png \
+  %reldir%/icons/circle.png \
+  %reldir%/icons/cross.png \
   %reldir%/icons/db-cont.png \
   %reldir%/icons/db-step-in.png \
   %reldir%/icons/db-step-out.png \
@@ -25,6 +30,15 @@
   %reldir%/icons/edit-paste.png \
   %reldir%/icons/edit-redo.png \
   %reldir%/icons/edit-undo.png \
+  %reldir%/icons/figure-axes.png \
+  %reldir%/icons/figure-grid.png \
+  %reldir%/icons/figure-pan.png \
+  %reldir%/icons/figure-rotate.png \
+  %reldir%/icons/figure-text.png \
+  %reldir%/icons/figure-zoom-in.png \
+  %reldir%/icons/figure-zoom-original.png \
+  %reldir%/icons/figure-zoom-out.png \
+  %reldir%/icons/fleur.png \
   %reldir%/icons/folder.png \
   %reldir%/icons/folder-new.png \
   %reldir%/icons/go-down.png \
@@ -52,7 +66,9 @@
   %reldir%/icons/graphic_logo_WorkspaceView.svg \
   %reldir%/icons/graphic_logo_ReleaseWidget.svg \
   %reldir%/icons/graphic_logo_VariableEditor.svg \
+  %reldir%/icons/hand2.png \
   %reldir%/icons/icons_license \
+  %reldir%/icons/left_side.png \
   %reldir%/icons/letter_logo_DocumentationDockWidget.png \
   %reldir%/icons/letter_logo_FileEditor.png \
   %reldir%/icons/letter_logo_FilesDockWidget.png \
@@ -74,7 +90,11 @@
   %reldir%/icons/logo.png \
   %reldir%/icons/plot-xy-curve.png \
   %reldir%/icons/preferences-system.png \
+  %reldir%/icons/right_side.png \
   %reldir%/icons/system-run.png \
+  %reldir%/icons/top_left_corner.png \
+  %reldir%/icons/top_right_corner.png \
+  %reldir%/icons/top_side.png \
   %reldir%/icons/user-home.png \
   %reldir%/icons/view-refresh.png \
   %reldir%/icons/widget-close.png \
@@ -118,8 +138,11 @@
   %reldir%/moc-dw-main-window.cc \
   %reldir%/moc-files-dock-widget.cc \
   %reldir%/moc-history-dock-widget.cc \
+  %reldir%/moc-interpreter-qobject.cc \
   %reldir%/moc-main-window.cc \
+  %reldir%/moc-news-reader.cc \
   %reldir%/moc-octave-cmd.cc \
+  %reldir%/moc-octave-qobject.cc \
   %reldir%/moc-octave-qt-link.cc \
   %reldir%/moc-settings-dialog.cc \
   %reldir%/moc-terminal-dock-widget.cc \
@@ -167,6 +190,7 @@
   %reldir%/external-editor-interface.h \
   %reldir%/files-dock-widget.h \
   %reldir%/history-dock-widget.h \
+  %reldir%/interpreter-qobject.h \
   %reldir%/m-editor/file-editor-interface.h \
   %reldir%/m-editor/file-editor-tab.h \
   %reldir%/m-editor/file-editor.h \
@@ -175,9 +199,11 @@
   %reldir%/m-editor/octave-txt-lexer.h \
   %reldir%/m-editor/marker.h \
   %reldir%/main-window.h \
-  %reldir%/octave-gui.h \
+  %reldir%/news-reader.h \
   %reldir%/octave-cmd.h \
+  %reldir%/octave-qobject.h \
   %reldir%/octave-qt-link.h \
+  %reldir%/qt-application.h \
   %reldir%/resource-manager.h \
   %reldir%/settings-dialog.h \
   %reldir%/shortcut-manager.h \
@@ -200,6 +226,7 @@
   %reldir%/external-editor-interface.cc \
   %reldir%/files-dock-widget.cc \
   %reldir%/history-dock-widget.cc \
+  %reldir%/interpreter-qobject.cc \
   %reldir%/m-editor/file-editor-tab.cc \
   %reldir%/m-editor/file-editor.cc \
   %reldir%/m-editor/find-dialog.cc \
@@ -207,10 +234,12 @@
   %reldir%/m-editor/octave-txt-lexer.cc \
   %reldir%/m-editor/marker.cc \
   %reldir%/main-window.cc \
+  %reldir%/news-reader.cc \
   %reldir%/octave-cmd.cc \
   %reldir%/octave-dock-widget.cc \
-  %reldir%/octave-gui.cc \
+  %reldir%/octave-qobject.cc \
   %reldir%/octave-qt-link.cc \
+  %reldir%/qt-application.cc \
   %reldir%/resource-manager.cc \
   %reldir%/settings-dialog.cc \
   %reldir%/shortcut-manager.cc \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/news-reader.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,150 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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 <QDateTime>
+#include <QString>
+
+#include "news-reader.h"
+#include "resource-manager.h"
+
+#include "url-transfer.h"
+#include "version.h"
+
+namespace octave
+{
+  void news_reader::process (void)
+  {
+    QString html_text;
+
+    if (m_connect_to_web)
+      {
+        // Run this part in a separate thread so Octave can continue to
+        // run while we wait for the page to load.  Then emit the signal
+        // to display it when we have the page contents.
+
+        QString url = m_base_url + '/' + m_page;
+        std::ostringstream buf;
+        url_transfer octave_dot_org (url.toStdString (), buf);
+
+        if (octave_dot_org.is_valid ())
+          {
+            Array<std::string> param;
+            octave_dot_org.http_get (param);
+
+            if (octave_dot_org.good ())
+              html_text = QString::fromStdString (buf.str ());
+          }
+
+        if (html_text.contains ("this-is-the-gnu-octave-community-news-page"))
+          {
+            if (m_serial >= 0)
+              {
+                QSettings *settings = resource_manager::get_settings ();
+
+                if (settings)
+                  {
+                    settings->setValue ("news/last_time_checked",
+                                        QDateTime::currentDateTime ());
+
+                    settings->sync ();
+                  }
+
+                QString tag ("community-news-page-serial=");
+
+                int b = html_text.indexOf (tag);
+
+                if (b)
+                  {
+                    b += tag.length ();
+
+                    int e = html_text.indexOf ("\n", b);
+
+                    QString tmp = html_text.mid (b, e-b);
+
+                    int curr_page_serial = tmp.toInt ();
+
+                    if (curr_page_serial > m_serial)
+                      {
+                        if (settings)
+                          {
+                            settings->setValue ("news/last_news_item",
+                                                curr_page_serial);
+
+                            settings->sync ();
+                          }
+                      }
+                    else
+                      return;
+                  }
+                else
+                  return;
+              }
+          }
+        else
+          html_text = QString
+            (tr ("<html>\n"
+                 "<body>\n"
+                 "<p>\n"
+                 "Octave's community news source seems to be unavailable.\n"
+                 "</p>\n"
+                 "<p>\n"
+                 "For the latest news, please check\n"
+                 "<a href=\"https://octave.org/community-news.html\">https://octave.org/community-news.html</a>\n"
+                 "when you have a connection to the web (link opens in an external browser).\n"
+                 "</p>\n"
+                 "<p>\n"
+                 "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
+             "</p>\n"
+             "</body>\n"
+             "</html>\n");
+      }
+    else
+      html_text = QString
+        (tr ("<html>\n"
+             "<body>\n"
+             "<p>\n"
+             "Connecting to the web to display the latest Octave Community news has been disabled.\n"
+             "</p>\n"
+             "<p>\n"
+             "For the latest news, please check\n"
+             "<a href=\"https://octave.org/community-news.html\">https://octave.org/community-news.html</a>\n"
+             "when you have a connection to the web (link opens in an external browser)\n"
+             "or enable web connections for news in Octave's network settings dialog.\n"
+             "</p>\n"
+             "<p>\n"
+             "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
+         "</p>\n"
+         "</body>\n"
+         "</html>\n");
+
+    emit display_news_signal (html_text);
+
+    emit finished ();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/news-reader.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,63 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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_news_reader_h)
+#define octave_news_reader_h 1
+
+#include <QObject>
+#include <QString>
+
+namespace octave
+{
+  class news_reader : public QObject
+  {
+    Q_OBJECT
+
+  public:
+
+    news_reader (const QString& base_url, const QString& page,
+                 int serial = -1, bool connect_to_web = false)
+      : QObject (), m_base_url (base_url), m_page (page), m_serial (serial),
+        m_connect_to_web (connect_to_web)
+    { }
+
+  public slots:
+
+    void process (void);
+
+  signals:
+
+    void display_news_signal (const QString& news);
+
+    void finished (void);
+
+  private:
+
+    QString m_base_url;
+    QString m_page;
+    int m_serial;
+    bool m_connect_to_web;
+  };
+}
+
+#endif
--- a/libgui/src/octave-cmd.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-cmd.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -65,8 +65,9 @@
       }
     else
       {
-        // no valid identifier: use Fsource (), no debug possible
-        Fsource (ovl (file_path));
+        interpreter& interp = __get_interpreter__ ("octave_cmd_eval::execute");
+        // no valid identifier: use equivalent of Fsource (), no debug possible
+        interp.source_file (file_path);
         command_editor::replace_line ("");
       }
 
@@ -88,10 +89,10 @@
       {
         case CMD_UPD_WORKSPACE:
           {
-            call_stack& cs
-              = __get_call_stack__ ("octave_cmd_builtin::execute");
+            tree_evaluator& tw
+              = __get_evaluator__ ("octave_cmd_builtin::execute");
 
-            octave_link::set_workspace (true, cs.get_symbol_info ());
+            octave_link::set_workspace (true, tw.get_symbol_info ());
           }
           break;
 
--- a/libgui/src/octave-cmd.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-cmd.h	Fri Jul 12 12:14:43 2019 -0400
@@ -98,7 +98,7 @@
      *               the executing Ff
      */
     octave_cmd_builtin (
-          octave_value_list (*Ff) (octave::interpreter&, const octave_value_list&, int),
+          octave_value_list (*Ff) (interpreter&, const octave_value_list&, int),
           octave_value_list argin = ovl (), cmd_upd update = CMD_UPD_NO)
       : octave_cmd (), m_callback_fi (Ff), m_callback_f (nullptr),
         m_argin (argin), m_nargout (0), m_argout_receiver (nullptr),
@@ -129,7 +129,7 @@
      * worker thread is busy and can not execute the desired command immediately.
      */
     octave_cmd_builtin (
-          octave_value_list (*Ff) (octave::interpreter&, const octave_value_list&, int),
+          octave_value_list (*Ff) (interpreter&, const octave_value_list&, int),
           octave_value_list argin, int nargout, QObject *argout_receiver,
           const char *argout_handler = nullptr, cmd_upd update = CMD_UPD_NO)
       : octave_cmd (), m_callback_fi (Ff), m_callback_f (nullptr),
@@ -160,7 +160,7 @@
 
   protected:
 
-    octave_value_list (*m_callback_fi) (octave::interpreter&,
+    octave_value_list (*m_callback_fi) (interpreter&,
                                         const octave_value_list&, int);
     octave_value_list (*m_callback_f) (const octave_value_list&, int);
 
--- a/libgui/src/octave-dock-widget.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-dock-widget.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -305,6 +305,8 @@
       focus ();
       set_style (true);
     }
+
+    emit topLevelChanged (true);  // Be sure signal is emitted
   }
 
   // dock the widget
--- a/libgui/src/octave-dock-widget.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-dock-widget.h	Fri Jul 12 12:14:43 2019 -0400
@@ -150,6 +150,8 @@
 
   protected slots:
 
+    virtual void toplevel_change (bool);
+
     //! Slot to steer changing visibility from outside.
 
     virtual void handle_visibility_changed (bool visible)
@@ -165,7 +167,6 @@
   private slots:
 
     void change_visibility (bool);
-    void toplevel_change (bool);
 
   private:
 
--- a/libgui/src/octave-gui.cc	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
-
-Copyright (C) 2011-2019 Jacob Dawid
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for 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 "lo-utils.h"
-#include "oct-env.h"
-#include "oct-syscalls.h"
-#include "signal-wrappers.h"
-
-#include "builtin-defun-decls.h"
-#include "display.h"
-#include "octave.h"
-#include "sysdep.h"
-
-#include "main-window.h"
-#include "octave-gui.h"
-
-namespace octave
-{
-  gui_application::gui_application (int argc, char **argv)
-    : application (argc, argv)
-  {
-    // This should probably happen early.
-    sysdep_init ();
-  }
-
-  bool gui_application::start_gui_p (void) const
-  {
-    return m_options.gui ();
-  }
-
-  int gui_application::execute (void)
-  {
-    octave_block_interrupt_signal ();
-
-    set_application_id ();
-
-    // Create and show main window.
-
-    octave_qt_app oct_qt_app (*this);
-
-    return oct_qt_app.exec ();
-  }
-}
--- a/libgui/src/octave-gui.h	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
-
-Copyright (C) 2012-2019 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_octave_gui_h)
-#define octave_octave_gui_h 1
-
-#include "octave.h"
-
-namespace octave
-{
-  class OCTGUI_API gui_application : public application
-  {
-  public:
-
-    gui_application (int argc, char **argv);
-
-    // No copying, at least not yet.
-
-    gui_application (const gui_application&) = delete;
-
-    gui_application& operator = (const gui_application&) = delete;
-
-    ~gui_application (void) = default;
-
-    // Should we start the GUI or fall back to the CLI?
-    bool start_gui_p (void) const;
-
-    int execute (void);
-
-    bool gui_running (void) const { return m_gui_running; }
-    void gui_running (bool arg) { m_gui_running = arg; }
-
-  private:
-
-    int m_argc;
-    char **m_argv;
-
-    // If TRUE, the GUI should be started.
-    bool m_gui_running = false;
-  };
-}
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-qobject.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,371 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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 <QApplication>
+#include <QFile>
+#include <QTextCodec>
+#include <QThread>
+#include <QTranslator>
+#include <QTimer>
+
+#include <utility>
+
+#include "dialog.h"
+#include "interpreter-qobject.h"
+#include "main-window.h"
+#include "octave-qobject.h"
+#include "octave-qt-link.h"
+#include "qt-application.h"
+#include "resource-manager.h"
+
+#include "oct-env.h"
+#include "version.h"
+
+namespace octave
+{
+  // Disable all Qt messages by default.
+
+  static void
+#if defined (QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT)
+  message_handler (QtMsgType, const QMessageLogContext &, const QString &)
+#else
+  message_handler (QtMsgType, const char *)
+#endif
+  { }
+
+  //! Reimplement QApplication::notify.  Octave's own exceptions are
+  //! caught and rethrown in the interpreter thread.
+
+  bool octave_qapplication::notify (QObject *receiver, QEvent *ev)
+  {
+    try
+      {
+        return QApplication::notify (receiver, ev);
+      }
+    catch (execution_exception&)
+      {
+        octave_link::post_exception (std::current_exception ());
+      }
+
+   return false;
+  }
+
+  // We will create a QApplication object, even if START_GUI is false,
+  // so that we can use Qt widgets for plot windows when running in
+  // command-line mode.  Note that we are creating an
+  // octave_qapplication object but handling it as a QApplication object
+  // because the octave_qapplication should behave identically to a
+  // QApplication object except that it overrides the notify method so
+  // we can handle forward Octave interpreter exceptions from the GUI
+  // thread to the interpreter thread.
+
+  base_qobject::base_qobject (qt_application& app_context)
+    : QObject (), m_app_context (app_context),
+      m_argc (m_app_context.sys_argc ()),
+      m_argv (m_app_context.sys_argv ()),
+      m_qapplication (new octave_qapplication (m_argc, m_argv)),
+      m_qt_tr (new QTranslator ()), m_gui_tr (new QTranslator ()),
+      m_qsci_tr (new QTranslator ()), m_translators_installed (false),
+      m_interpreter_qobj (new interpreter_qobject (this)),
+      m_main_thread (new QThread ())
+  {
+    std::string show_gui_msgs =
+      sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+
+    // Installing our handler suppresses the messages.
+
+    if (show_gui_msgs.empty ())
+      {
+#if defined (HAVE_QINSTALLMESSAGEHANDLER)
+        qInstallMessageHandler (message_handler);
+#else
+        qInstallMsgHandler (message_handler);
+#endif
+      }
+
+    // Set the codec for all strings (before wizard or any GUI object)
+#if ! defined (Q_OS_WIN32)
+    QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
+#endif
+
+#if defined (HAVE_QT4)
+    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
+#endif
+
+    // Initialize global Qt application metadata.
+
+    QCoreApplication::setApplicationName ("GNU Octave");
+    QCoreApplication::setApplicationVersion (OCTAVE_VERSION);
+
+    // Register octave_value_list for connecting thread crossing signals.
+
+    qRegisterMetaType<octave_value_list> ("octave_value_list");
+
+    // Force left-to-right alignment (see bug #46204)
+    m_qapplication->setLayoutDirection (Qt::LeftToRight);
+
+    connect_uiwidget_links ();
+
+    connect (m_interpreter_qobj, SIGNAL (octave_finished_signal (int)),
+             this, SLOT (handle_octave_finished (int)));
+
+    connect (m_interpreter_qobj, SIGNAL (octave_finished_signal (int)),
+             m_main_thread, SLOT (quit (void)));
+
+    connect (m_main_thread, SIGNAL (finished (void)),
+             m_main_thread, SLOT (deleteLater (void)));
+  }
+
+  base_qobject::~base_qobject (void)
+  {
+    // Note that we don't delete m_main_thread here.  That is handled by
+    // deleteLater slot that is called when the m_main_thread issues a
+    // finished signal.
+
+    delete m_interpreter_qobj;
+    delete m_qsci_tr;
+    delete m_gui_tr;
+    delete m_qt_tr;
+    delete m_qapplication;
+
+    string_vector::delete_c_str_vec (m_argv);
+  }
+
+  void base_qobject::config_translators (void)
+  {
+    if (m_translators_installed)
+      return;
+
+    resource_manager::config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);
+
+    m_qapplication->installTranslator (m_qt_tr);
+    m_qapplication->installTranslator (m_gui_tr);
+    m_qapplication->installTranslator (m_qsci_tr);
+
+    m_translators_installed = true;
+  }
+
+  void base_qobject::start_main_thread (void)
+  {
+    // Defer initializing and executing the interpreter until after the main
+    // window and QApplication are running to prevent race conditions
+    QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute (void)));
+
+    m_interpreter_qobj->moveToThread (m_main_thread);
+
+    m_main_thread->start ();
+  }
+
+  int base_qobject::exec (void)
+  {
+    return m_qapplication->exec ();
+  }
+
+  void base_qobject::handle_octave_finished (int exit_status)
+  {
+    qApp->exit (exit_status);
+  }
+
+  void base_qobject::confirm_shutdown_octave (void)
+  {
+    m_interpreter_qobj->confirm_shutdown (true);
+  }
+
+  void base_qobject::copy_image_to_clipboard (const QString& file,
+                                              bool remove_file)
+  {
+    QClipboard *clipboard = QApplication::clipboard ();
+
+    QImage img (file);
+
+    if (img.isNull ())
+      {
+        // Report error?
+        return;
+      }
+
+    clipboard->setImage (img);
+
+    if (remove_file)
+      QFile::remove (file);
+  }
+
+  // Create a message dialog with specified string, buttons and decorative
+  // text.
+
+  void base_qobject::handle_create_dialog (const QString& message,
+                                           const QString& title,
+                                           const QString& icon,
+                                           const QStringList& button,
+                                           const QString& defbutton,
+                                           const QStringList& role)
+  {
+    MessageDialog *message_dialog = new MessageDialog (message, title, icon,
+                                                       button, defbutton, role);
+    message_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    message_dialog->show ();
+  }
+
+  // Create a list dialog with specified list, initially selected, mode,
+  // view size and decorative text.
+
+  void base_qobject::handle_create_listview (const QStringList& list,
+                                             const QString& mode,
+                                             int wd, int ht,
+                                             const QIntList& initial,
+                                             const QString& name,
+                                             const QStringList& prompt,
+                                             const QString& ok_string,
+                                             const QString& cancel_string)
+  {
+    ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
+                                              initial, name, prompt,
+                                              ok_string, cancel_string);
+
+    list_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    list_dialog->show ();
+  }
+
+  // Create an input dialog with specified prompts and defaults, title and
+  // row/column size specifications.
+  void base_qobject::handle_create_inputlayout (const QStringList& prompt,
+                                                const QString& title,
+                                                const QFloatList& nr,
+                                                const QFloatList& nc,
+                                                const QStringList& defaults)
+  {
+    InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
+                                                 defaults);
+
+    input_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    input_dialog->show ();
+  }
+
+  void base_qobject::handle_create_filedialog (const QStringList& filters,
+                                               const QString& title,
+                                               const QString& filename,
+                                               const QString& dirname,
+                                               const QString& multimode)
+  {
+    FileDialog *file_dialog = new FileDialog (filters, title, filename,
+                                              dirname, multimode);
+
+    file_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    file_dialog->show ();
+  }
+
+  // Connect the signals emitted when the Octave thread wants to create
+  // a dialog box of some sort.  Perhaps a better place for this would be
+  // as part of the QUIWidgetCreator class.  However, mainWindow currently
+  // is not a global variable and not accessible for connecting.
+
+  void base_qobject::connect_uiwidget_links (void)
+  {
+    connect (&uiwidget_creator,
+             SIGNAL (create_dialog (const QString&, const QString&,
+                                    const QString&, const QStringList&,
+                                    const QString&, const QStringList&)),
+             this,
+             SLOT (handle_create_dialog (const QString&, const QString&,
+                                         const QString&, const QStringList&,
+                                         const QString&, const QStringList&)));
+
+    // Register QIntList so that list of ints may be part of a signal.
+    qRegisterMetaType<QIntList> ("QIntList");
+    connect (&uiwidget_creator,
+             SIGNAL (create_listview (const QStringList&, const QString&,
+                                      int, int, const QIntList&,
+                                      const QString&, const QStringList&,
+                                      const QString&, const QString&)),
+             this,
+             SLOT (handle_create_listview (const QStringList&, const QString&,
+                                           int, int, const QIntList&,
+                                           const QString&, const QStringList&,
+                                           const QString&, const QString&)));
+
+    // Register QFloatList so that list of floats may be part of a signal.
+    qRegisterMetaType<QFloatList> ("QFloatList");
+    connect (&uiwidget_creator,
+             SIGNAL (create_inputlayout (const QStringList&, const QString&,
+                                         const QFloatList&, const QFloatList&,
+                                         const QStringList&)),
+             this,
+             SLOT (handle_create_inputlayout (const QStringList&, const QString&,
+                                              const QFloatList&,
+                                              const QFloatList&,
+                                              const QStringList&)));
+
+    connect (&uiwidget_creator,
+             SIGNAL (create_filedialog (const QStringList &,const QString&,
+                                        const QString&, const QString&,
+                                        const QString&)),
+             this,
+             SLOT (handle_create_filedialog (const QStringList &, const QString&,
+                                             const QString&, const QString&,
+                                             const QString&)));
+  }
+
+  cli_qobject::cli_qobject (qt_application& app_context)
+    : base_qobject (app_context)
+  {
+    // Get settings file.
+    resource_manager::reload_settings ();
+
+    // After settings.
+    config_translators ();
+
+    m_qapplication->setQuitOnLastWindowClosed (false);
+
+    start_main_thread ();
+  }
+
+  gui_qobject::gui_qobject (qt_application& app_context)
+    : base_qobject (app_context), m_main_window (new main_window (*this))
+  {
+    connect (m_interpreter_qobj, SIGNAL (octave_ready_signal (void)),
+             m_main_window, SLOT (handle_octave_ready (void)));
+
+    m_app_context.gui_running (true);
+
+    start_main_thread ();
+  }
+
+  gui_qobject::~gui_qobject (void)
+  {
+    delete m_main_window;
+  }
+
+  void gui_qobject::confirm_shutdown_octave (void)
+  {
+    bool closenow = true;
+
+    if (m_main_window)
+      closenow = m_main_window->confirm_shutdown_octave ();
+
+    m_interpreter_qobj->confirm_shutdown (closenow);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-qobject.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,193 @@
+/*
+
+Copyright (C) 2013-2019 John W. Eaton
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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_octave_qobject_h)
+#define octave_octave_qobject_h 1
+
+#include <QApplication>
+#include <QList>
+#include <QObject>
+#include <QString>
+#include <QStringList>
+
+// Defined for purposes of sending QList<int> as part of signal.
+typedef QList<int> QIntList;
+
+// Defined for purposes of sending QList<float> as part of signal.
+typedef QList<float> QFloatList;
+
+namespace octave
+{
+  class interpreter_qobject;
+  class main_window;
+  class qt_application;
+
+  //! This class is a simple wrapper around QApplication so that we can
+  //! reimplement QApplication::notify.  The octave_qapplication object
+  //! should behave identically to a QApplication object except that it
+  //! overrides the notify method so we can handle forward Octave
+  //! octave::execution_exception exceptions from the GUI thread to the
+  //! interpreter thread.
+
+  class octave_qapplication : public QApplication
+  {
+  public:
+
+    octave_qapplication (int& argc, char **argv)
+      : QApplication (argc, argv)
+    { }
+
+    virtual bool notify (QObject *receiver, QEvent *e) override;
+
+    ~octave_qapplication (void) { };
+  };
+
+  //! Base class for Octave interfaces that use Qt.  There are two
+  //! classes derived from this one.  One provides a command-line
+  //! interface that may use Qt graphics and another provides the
+  //! full GUI experience.
+
+  class base_qobject : public QObject
+  {
+    Q_OBJECT
+
+  public:
+
+    base_qobject (qt_application& app_context);
+
+    ~base_qobject (void);
+
+    void config_translators (void);
+
+    void start_main_thread (void);
+
+    int exec (void);
+
+    // The Octave application context.
+    qt_application& app_context (void) { return m_app_context; }
+
+    // The Qt QApplication.
+    QApplication * qapplication (void) { return m_qapplication; };
+
+    interpreter_qobject * interpreter_qobj (void)
+    {
+      return m_interpreter_qobj;
+    }
+
+    QThread *main_thread (void) { return m_main_thread; }
+
+  public slots:
+
+    void handle_octave_finished (int);
+
+    virtual void confirm_shutdown_octave (void);
+
+    void copy_image_to_clipboard (const QString& file, bool remove_file);
+
+    void handle_create_dialog (const QString& message, const QString& title,
+                               const QString& icon, const QStringList& button,
+                               const QString& defbutton,
+                               const QStringList& role);
+
+    void handle_create_listview (const QStringList& list, const QString& mode,
+                                 int width, int height,
+                                 const QIntList& initial,
+                                 const QString& name,
+                                 const QStringList& prompt,
+                                 const QString& ok_string,
+                                 const QString& cancel_string);
+
+    void handle_create_inputlayout (const QStringList&, const QString&,
+                                    const QFloatList&, const QFloatList&,
+                                    const QStringList&);
+
+    void handle_create_filedialog (const QStringList& filters,
+                                   const QString& title,
+                                   const QString& filename,
+                                   const QString& dirname,
+                                   const QString& multimode);
+
+  protected:
+
+    qt_application& m_app_context;
+
+    // Use these to ensure that argc and argv exist for as long as the
+    // QApplication object.
+
+    int m_argc;
+    char **m_argv;
+
+    QApplication *m_qapplication;
+
+    QTranslator *m_qt_tr;
+    QTranslator *m_gui_tr;
+    QTranslator *m_qsci_tr;
+
+    bool m_translators_installed;
+
+    interpreter_qobject *m_interpreter_qobj;
+
+    QThread *m_main_thread;
+
+    void connect_uiwidget_links (void);
+  };
+
+  //! This object provides a command-line interface to Octave that may
+  //! use Qt graphics.
+
+  class cli_qobject : public base_qobject
+  {
+    Q_OBJECT
+
+  public:
+
+    cli_qobject (qt_application& app_context);
+
+    ~cli_qobject (void) = default;
+  };
+
+  //! This object provides a full GUI interface to Octave that is
+  //! implemented Qt.
+
+  class gui_qobject : public base_qobject
+  {
+    Q_OBJECT
+
+  public:
+
+    gui_qobject (qt_application& app_context);
+
+    ~gui_qobject (void);
+
+  public slots:
+
+    void confirm_shutdown_octave (void);
+
+  private:
+
+    main_window *m_main_window;
+  };
+}
+
+#endif
+
--- a/libgui/src/octave-qt-link.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-qt-link.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -46,7 +46,6 @@
 #include "syminfo.h"
 #include "utils.h"
 
-#include "octave-gui.h"
 #include "octave-qt-link.h"
 #include "resource-manager.h"
 
@@ -100,7 +99,7 @@
     if (! settings || settings->value ("editor/create_new_file",false).toBool ())
       return true;
 
-    std::string abs_fname = octave::sys::env::make_absolute (file);
+    std::string abs_fname = sys::env::make_absolute (file);
 
     QStringList btn;
     QStringList role;
--- a/libgui/src/octave-qt-link.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/octave-qt-link.h	Fri Jul 12 12:14:43 2019 -0400
@@ -34,7 +34,6 @@
 #include <QMutex>
 #include <QWaitCondition>
 
-#include "octave-gui.h"
 #include "octave-link.h"
 
 // Defined for purposes of sending QList<int> as part of signal.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/qt-application.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,74 @@
+/*
+
+Copyright (C) 2011-2019 Jacob Dawid
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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 "lo-utils.h"
+#include "oct-env.h"
+#include "oct-syscalls.h"
+#include "signal-wrappers.h"
+
+#include "builtin-defun-decls.h"
+#include "display.h"
+#include "octave.h"
+#include "sysdep.h"
+
+#include "main-window.h"
+#include "octave-qobject.h"
+#include "qt-application.h"
+
+namespace octave
+{
+  qt_application::qt_application (int argc, char **argv)
+    : application (argc, argv)
+  {
+    // This should probably happen early.
+    sysdep_init ();
+  }
+
+  bool qt_application::start_gui_p (void) const
+  {
+    return m_options.gui ();
+  }
+
+  int qt_application::execute (void)
+  {
+    octave_block_interrupt_signal ();
+
+    set_application_id ();
+
+    // Create and show main window.
+
+    if (start_gui_p ())
+      {
+        gui_qobject gui_interface (*this);
+        return gui_interface.exec ();
+      }
+    else
+      {
+        cli_qobject cli_interface (*this);
+        return cli_interface.exec ();
+      }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/qt-application.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,70 @@
+/*
+
+Copyright (C) 2012-2019 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_octave_gui_h)
+#define octave_octave_gui_h 1
+
+#include "octave.h"
+
+namespace octave
+{
+  // Programming Note: This file must not include any Qt headers.  Any
+  // Qt header files required by the qt_application::execute function
+  // must be included only in the corresponding .cc file.
+
+  //! This class inherits from the pure-virtual base class
+  //! octave::application and provides an implementation of the
+  //! application::execute method that starts an interface to Octave
+  //! that is based on Qt.  It may start a command-line interface that
+  //! allows Qt graphics to be used or it may start an interface that
+  //! provides the full GUI experience.
+
+  class OCTGUI_API qt_application  : public application
+  {
+  public:
+
+    qt_application (int argc, char **argv);
+
+    // No copying, at least not yet.
+
+    qt_application (const qt_application&) = delete;
+
+    qt_application& operator = (const qt_application&) = delete;
+
+    ~qt_application (void) = default;
+
+    // Should we start the GUI or fall back to the CLI?
+    bool start_gui_p (void) const;
+
+    int execute (void);
+
+    bool gui_running (void) const { return m_gui_running; }
+    void gui_running (bool arg) { m_gui_running = arg; }
+
+  private:
+
+    // If TRUE, the GUI should be started.
+    bool m_gui_running = false;
+  };
+}
+
+#endif
--- a/libgui/src/resource-manager.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/resource-manager.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -70,20 +70,54 @@
     : m_settings_directory (), m_settings_file (), m_settings (nullptr),
       m_default_settings (nullptr)
   {
+    // Let QSettings decide where to put the ini file with gui preferences
+    m_default_settings
+              = new QSettings(QSettings::IniFormat, QSettings::UserScope,
+                              "octave", "octave-gui");
+
+    m_settings_file = m_default_settings->fileName ();
+
+    QFileInfo sfile (m_settings_file);
+    m_settings_directory = sfile.absolutePath ();
+
+    QString xdg_config_home
+        = QString::fromLocal8Bit (qgetenv ("XDG_CONFIG_HOME"));
+
+    if ((! sfile.exists ()) && xdg_config_home.isEmpty ())
+      {
+        // File does not exist yet: Look for a settings file at the old
+        // location ($HOME/.config/octave/qt-settings) for impoting all
+        // available keys into the new settings file.
+        // Do not look for an old settings file if XDG_CONFIG_HOME is set,
+        // since then a non-existin new settings file does not necessarily
+        // indicate a first run of octave with new config file locations.
 #if defined (HAVE_QSTANDARDPATHS)
-    QString home_path
-      = QStandardPaths::writableLocation (QStandardPaths::HomeLocation);
+        QString home_path
+            = QStandardPaths::writableLocation (QStandardPaths::HomeLocation);
 #else
-    QString home_path
-      = QDesktopServices::storageLocation (QDesktopServices::HomeLocation);
+        QString home_path
+            = QDesktopServices::storageLocation (QDesktopServices::HomeLocation);
 #endif
 
-    m_settings_directory = home_path + "/.config/octave";
+        QString old_settings_directory = home_path + "/.config/octave";
+        QString old_settings_file = old_settings_directory + "/qt-settings";
+
+        QFile ofile (old_settings_file);
 
-    m_settings_file = m_settings_directory + "/qt-settings";
+        if (ofile.exists ())
+          {
+            // Old settings file exists, create a QSettings object related
+            // to it and copy all available keys to the new settings
+            QSettings old_settings (old_settings_file, QSettings::IniFormat);
 
-    m_default_settings = new QSettings (default_qt_settings_file (),
-                                        QSettings::IniFormat);
+            QStringList keys = old_settings.allKeys ();
+            for (int i = 0; i < keys.count(); i++)
+              m_default_settings->setValue (keys.at(i),
+                                            old_settings.value(keys.at(i)));
+
+            m_default_settings->sync ();  // Done, make sure keys are written
+          }
+      }
   }
 
   resource_manager::~resource_manager (void)
@@ -120,23 +154,31 @@
         language = settings->value ("language", "SYSTEM").toString ();
       }
 
+    // load the translations depending on the settings
     if (language == "SYSTEM")
-      language = QLocale::system ().name ();    // get system wide locale
-
-    // load the translator file for qt strings
-    loaded = qt_tr->load ("qt_" + language, qt_trans_dir);
-
-    if (! loaded) // try lower case
-      qt_tr->load ("qt_" + language.toLower (), qt_trans_dir);
+      {
+        // get the system locale and pass it to the translators for loading
+        // the suitable translation files
+        QLocale sys_locale = QLocale::system ();
 
-    // load the translator file for qscintilla settings
-    loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir);
+        qt_tr->load (sys_locale, "qt", "_", qt_trans_dir);
+        qsci_tr->load (sys_locale, "qscintilla", "_", qt_trans_dir);
+        gui_tr->load (sys_locale, "", "", get_gui_translation_dir ());
+      }
+    else
+      {
+        // load the translation files depending on the given locale name
+        loaded = qt_tr->load ("qt_" + language, qt_trans_dir);
+        if (! loaded) // try lower case
+          qt_tr->load ("qt_" + language.toLower (), qt_trans_dir);
 
-    if (! loaded) // try lower case
-      qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir);
+        loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir);
+        if (! loaded) // try lower case
+          qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir);
 
-    // load the translator file for gui strings
-    gui_tr->load (language, get_gui_translation_dir ());
+        gui_tr->load (language, get_gui_translation_dir ());
+      }
+
   }
 
   QStringList resource_manager::storage_class_names (void)
@@ -176,13 +218,6 @@
     if (! instance)
       instance = new resource_manager ();
 
-    if (! instance)
-      {
-        error ("unable to create resource_manager object!");
-
-        retval = false;
-      }
-
     return retval;
   }
 
@@ -294,8 +329,7 @@
     delete m_settings;
     m_settings = new QSettings (file, QSettings::IniFormat);
 
-    if (! (m_settings
-           && QFile::exists (m_settings->fileName ())
+    if (! (QFile::exists (m_settings->fileName ())
            && m_settings->isWritable ()
            && m_settings->status () == QSettings::NoError))
       {
--- a/libgui/src/resource-manager.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/resource-manager.h	Fri Jul 12 12:14:43 2019 -0400
@@ -120,7 +120,7 @@
       return instance_ok () ? instance->do_is_first_run () : true;
     }
 
-    static QString storage_class_chars (void) { return "afghip"; }
+    static QString storage_class_chars (void) { return "agp"; }
     static QStringList storage_class_names (void);
     static QList<QColor> storage_class_default_colors (void);
 
--- a/libgui/src/resource.qrc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/resource.qrc	Fri Jul 12 12:14:43 2019 -0400
@@ -5,6 +5,11 @@
         <file>icons/bp-rm-all.png</file>
         <file>icons/bp-prev.png</file>
         <file>icons/bp-next.png</file>
+        <file>icons/bottom_left_corner.png</file>
+        <file>icons/bottom_right_corner.png</file>
+        <file>icons/bottom_side.png</file>
+        <file>icons/circle.png</file>
+        <file>icons/cross.png</file>
         <file>icons/db-cont.png</file>
         <file>icons/db-step.png</file>
         <file>icons/db-step-in.png</file>
@@ -26,6 +31,14 @@
         <file>icons/edit-paste.png</file>
         <file>icons/edit-redo.png</file>
         <file>icons/edit-undo.png</file>
+        <file>icons/figure-axes.png</file>
+        <file>icons/figure-grid.png</file>
+        <file>icons/figure-pan.png</file>
+        <file>icons/figure-rotate.png</file>
+        <file>icons/figure-text.png</file>
+        <file>icons/figure-zoom-in.png</file>
+        <file>icons/figure-zoom-original.png</file>
+        <file>icons/figure-zoom-out.png</file>
         <file>icons/folder.png</file>
         <file>icons/folder-new.png</file>
         <file>icons/go-down.png</file>
@@ -44,6 +57,9 @@
         <file>icons/graphic_logo_DocumentationDockWidget.png</file>
         <file>icons/graphic_logo_ReleaseWidget.png</file>
         <file>icons/graphic_logo_VariableEditor.png</file>
+        <file>icons/fleur.png</file>
+        <file>icons/hand2.png</file>
+        <file>icons/left_side.png</file>
         <file>icons/letter_logo_FilesDockWidget.png</file>
         <file>icons/letter_logo_FileEditor.png</file>
         <file>icons/letter_logo_NewsDockWidget.png</file>
@@ -56,7 +72,11 @@
         <file>icons/logo.png</file>
         <file>icons/plot-xy-curve.png</file>
         <file>icons/preferences-system.png</file>
+        <file>icons/right_side.png</file>
         <file>icons/system-run.png</file>
+        <file>icons/top_left_corner.png</file>
+        <file>icons/top_right_corner.png</file>
+        <file>icons/top_side.png</file>
         <file>icons/user-home.png</file>
         <file>icons/view-refresh.png</file>
         <file>icons/widget-close.png</file>
--- a/libgui/src/settings-dialog.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/settings-dialog.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -293,6 +293,10 @@
     cb_show_eol->setChecked (settings->value ("editor/show_eol_chars", false).toBool ());
     cb_show_hscrollbar->setChecked (settings->value ("editor/show_hscroll_bar", true).toBool ());
 
+    editor_combox_tab_pos->insertItems (0, ed_tab_position_names);
+    editor_combox_tab_pos->setCurrentIndex (
+          settings->value (ed_tab_position.key, ed_tab_position.def).toInt ());
+
     int selected_comment_string, selected_uncomment_string;
 
     if (settings->contains (ed_comment_str.key))   // new version (radio buttons)
@@ -492,7 +496,7 @@
     read_lexer_settings (lexer, settings);
     delete lexer;
 
-    lexer = new octave::octave_txt_lexer ();
+    lexer = new octave_txt_lexer ();
     read_lexer_settings (lexer, settings);
     delete lexer;
 
@@ -887,6 +891,8 @@
     settings->setValue ("editor/show_hscroll_bar", cb_show_hscrollbar->isChecked ());
     settings->setValue ("editor/default_eol_mode", combo_eol_mode->currentIndex ());
 
+    settings->setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ());
+
     // Comment strings
     int rb_uncomment = 0;
     for (int i = 0; i < ed_comment_strings_count; i++)
@@ -990,7 +996,7 @@
     write_lexer_settings (lexer, settings);
     delete lexer;
 
-    lexer = new octave::octave_txt_lexer ();
+    lexer = new octave_txt_lexer ();
     write_lexer_settings (lexer, settings);
     delete lexer;
 
@@ -1157,8 +1163,8 @@
 
   void settings_dialog::read_varedit_colors (QSettings *settings)
   {
-    QList<QColor> default_colors = octave::variable_editor::default_colors ();
-    QStringList class_names = octave::variable_editor::color_names ();
+    QList<QColor> default_colors = variable_editor::default_colors ();
+    QStringList class_names = variable_editor::color_names ();
     QString class_chars = resource_manager::varedit_color_chars ();
     int nr_of_classes = class_chars.length ();
 
--- a/libgui/src/settings-dialog.ui	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/settings-dialog.ui	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,7 @@
       </size>
      </property>
      <property name="currentIndex">
-      <number>0</number>
+      <number>2</number>
      </property>
      <widget class="QWidget" name="tab_general">
       <property name="enabled">
@@ -53,7 +53,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_17">
@@ -69,6 +69,12 @@
                  <layout class="QHBoxLayout" name="horizontalLayout_8">
                   <item>
                    <widget class="QComboBox" name="comboBox_language">
+                    <property name="minimumSize">
+                     <size>
+                      <width>135</width>
+                      <height>0</height>
+                     </size>
+                    </property>
                     <property name="insertPolicy">
                      <enum>QComboBox::InsertAtBottom</enum>
                     </property>
@@ -425,7 +431,14 @@
                 <item row="2" column="1">
                  <layout class="QHBoxLayout" name="horizontalLayout_17">
                   <item>
-                   <widget class="QComboBox" name="combo_styles"/>
+                   <widget class="QComboBox" name="combo_styles">
+                    <property name="minimumSize">
+                     <size>
+                      <width>135</width>
+                      <height>0</height>
+                     </size>
+                    </property>
+                   </widget>
                   </item>
                   <item>
                    <spacer name="horizontalSpacer">
@@ -549,7 +562,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_7">
@@ -829,8 +842,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>645</width>
-            <height>1213</height>
+            <width>644</width>
+            <height>1322</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -845,120 +858,7 @@
                 <property name="topMargin">
                  <number>0</number>
                 </property>
-                <item row="1" column="2">
-                 <layout class="QGridLayout" name="gridLayout_6">
-                  <item row="0" column="0">
-                   <widget class="QLabel" name="editor_lbl_min_tab_width">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="text">
-                     <string>Tab width min.</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="3">
-                   <widget class="QSpinBox" name="editor_notebook_tab_width_min">
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="minimum">
-                     <number>80</number>
-                    </property>
-                    <property name="maximum">
-                     <number>600</number>
-                    </property>
-                    <property name="singleStep">
-                     <number>20</number>
-                    </property>
-                    <property name="value">
-                     <number>160</number>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="6">
-                   <spacer name="horizontalSpacer_25">
-                    <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="0" column="5">
-                   <widget class="QSpinBox" name="editor_notebook_tab_width_max">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="minimum">
-                     <number>180</number>
-                    </property>
-                    <property name="maximum">
-                     <number>600</number>
-                    </property>
-                    <property name="singleStep">
-                     <number>20</number>
-                    </property>
-                    <property name="value">
-                     <number>300</number>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="4">
-                   <widget class="QLabel" name="editor_lbl_max_tab_width">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="text">
-                     <string>max.</string>
-                    </property>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-                <item row="1" column="0">
-                 <widget class="QCheckBox" name="editor_longWindowTitle">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="text">
-                   <string>Show complete path in title</string>
-                  </property>
-                 </widget>
-                </item>
-                <item row="1" column="1">
-                 <spacer name="horizontalSpacer_24">
-                  <property name="orientation">
-                   <enum>Qt::Horizontal</enum>
-                  </property>
-                  <property name="sizeType">
-                   <enum>QSizePolicy::Fixed</enum>
-                  </property>
-                  <property name="sizeHint" stdset="0">
-                   <size>
-                    <width>10</width>
-                    <height>0</height>
-                   </size>
-                  </property>
-                 </spacer>
-                </item>
-                <item row="3" column="2">
+                <item row="2" column="2">
                  <widget class="QCheckBox" name="editor_ws_indent_checkbox">
                   <property name="enabled">
                    <bool>false</bool>
@@ -968,7 +868,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="10" column="0">
+                <item row="9" column="0">
                  <widget class="QCheckBox" name="cb_edit_status_bar">
                   <property name="sizePolicy">
                    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -984,7 +884,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="2" column="0">
+                <item row="1" column="0">
                  <widget class="QCheckBox" name="editor_showLineNumbers">
                   <property name="enabled">
                    <bool>true</bool>
@@ -1000,7 +900,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="3" column="0">
+                <item row="2" column="0">
                  <widget class="QCheckBox" name="editor_ws_checkbox">
                   <property name="sizePolicy">
                    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -1013,7 +913,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="9" column="0">
+                <item row="8" column="0">
                  <widget class="QCheckBox" name="cb_code_folding">
                   <property name="sizePolicy">
                    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -1029,7 +929,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="10" column="2">
+                <item row="9" column="2">
                  <widget class="QCheckBox" name="cb_edit_tool_bar">
                   <property name="sizePolicy">
                    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -1045,7 +945,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="9" column="2">
+                <item row="8" column="2">
                  <widget class="QCheckBox" name="cb_show_hscrollbar">
                   <property name="enabled">
                    <bool>true</bool>
@@ -1064,7 +964,7 @@
                   </property>
                  </widget>
                 </item>
-                <item row="2" column="2">
+                <item row="1" column="2">
                  <layout class="QGridLayout" name="gridLayout_17">
                   <item row="0" column="0">
                    <widget class="QLabel" name="editor_linenr_size_label">
@@ -1107,7 +1007,7 @@
                   </item>
                  </layout>
                 </item>
-                <item row="4" column="2">
+                <item row="3" column="2">
                  <layout class="QGridLayout" name="gridLayout_16">
                   <item row="0" column="1">
                    <spacer name="horizontalSpacer_11">
@@ -1170,7 +1070,7 @@
                   </item>
                  </layout>
                 </item>
-                <item row="4" column="0">
+                <item row="3" column="0">
                  <widget class="QCheckBox" name="cb_show_eol">
                   <property name="sizePolicy">
                    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -1183,6 +1083,22 @@
                   </property>
                  </widget>
                 </item>
+                <item row="1" column="1">
+                 <spacer name="horizontalSpacer_36">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Fixed</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>10</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
                </layout>
               </item>
               <item>
@@ -1256,6 +1172,162 @@
             </widget>
            </item>
            <item>
+            <widget class="QGroupBox" name="groupBox_11">
+             <property name="title">
+              <string>Tabs</string>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_32">
+              <item>
+               <layout class="QGridLayout" name="gridLayout_23">
+                <item row="1" column="1">
+                 <spacer name="horizontalSpacer_24">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Fixed</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>10</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item row="0" column="2">
+                 <layout class="QHBoxLayout" name="horizontalLayout_21">
+                  <item>
+                   <widget class="QComboBox" name="editor_combox_tab_pos"/>
+                  </item>
+                  <item>
+                   <spacer name="horizontalSpacer_25">
+                    <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="0" column="0">
+                 <widget class="QLabel" name="label_30">
+                  <property name="text">
+                   <string>Tab position</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="2">
+                 <layout class="QHBoxLayout" name="horizontalLayout_20">
+                  <property name="rightMargin">
+                   <number>0</number>
+                  </property>
+                  <item>
+                   <widget class="QLabel" name="editor_lbl_min_tab_width">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Tab width min.</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QSpinBox" name="editor_notebook_tab_width_min">
+                    <property name="sizePolicy">
+                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                      <horstretch>0</horstretch>
+                      <verstretch>0</verstretch>
+                     </sizepolicy>
+                    </property>
+                    <property name="minimum">
+                     <number>80</number>
+                    </property>
+                    <property name="maximum">
+                     <number>600</number>
+                    </property>
+                    <property name="singleStep">
+                     <number>20</number>
+                    </property>
+                    <property name="value">
+                     <number>160</number>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QLabel" name="editor_lbl_max_tab_width">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>max.</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QSpinBox" name="editor_notebook_tab_width_max">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="sizePolicy">
+                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                      <horstretch>0</horstretch>
+                      <verstretch>0</verstretch>
+                     </sizepolicy>
+                    </property>
+                    <property name="minimum">
+                     <number>180</number>
+                    </property>
+                    <property name="maximum">
+                     <number>600</number>
+                    </property>
+                    <property name="singleStep">
+                     <number>20</number>
+                    </property>
+                    <property name="value">
+                     <number>300</number>
+                    </property>
+                   </widget>
+                  </item>
+                 </layout>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QCheckBox" name="editor_longWindowTitle">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="text">
+                   <string>Show complete path in title</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="3">
+                 <spacer name="horizontalSpacer_5">
+                  <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>
+             </layout>
+            </widget>
+           </item>
+           <item>
             <widget class="QGroupBox" name="groupBox_9">
              <property name="title">
               <string>Comments (Octave)</string>
@@ -2156,7 +2228,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QGridLayout" name="gridLayout_8">
@@ -2306,7 +2378,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_19">
@@ -2367,8 +2439,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>669</width>
-            <height>558</height>
+            <width>658</width>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_vesc_manual">
@@ -2570,7 +2642,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_25">
@@ -2769,7 +2841,7 @@
             <x>0</x>
             <y>0</y>
             <width>658</width>
-            <height>571</height>
+            <height>576</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_20">
--- a/libgui/src/shortcut-manager.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/shortcut-manager.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -28,6 +28,7 @@
 #include <QMessageBox>
 #include <QDebug>
 #include <QGridLayout>
+#include <QApplication>
 #include <QVBoxLayout>
 #include <QDialogButtonBox>
 #include <QKeySequence>
@@ -50,6 +51,7 @@
   enter_shortcut::enter_shortcut (QWidget *p) : QLineEdit (p)
   {
     m_direct_shortcut = true;      // the shortcut is directly entered
+    m_shift_modifier = false;      // the shift modifier is not added
   }
 
   // new keyPressEvent
@@ -68,9 +70,13 @@
         if (key == Qt::Key_unknown || key == 0)
           return;
 
-        Qt::KeyboardModifiers modifiers = e->modifiers ();
+#if defined (HAVE_QGUIAPPLICATION)
+        Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();
+#else
+        Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers (); //e->modifiers ();
+#endif
 
-        if (modifiers & Qt::ShiftModifier)
+        if (m_shift_modifier || (modifiers & Qt::ShiftModifier))
           key += Qt::SHIFT;
         if (modifiers & Qt::ControlModifier)
           key += Qt::CTRL;
@@ -92,6 +98,16 @@
       m_direct_shortcut = false; // the shortcut has to be written as text
   }
 
+  // slot for checkbox whether the shift modifier should be added
+  void enter_shortcut::handle_shift_modifier (int state)
+  {
+    if (state)
+      m_shift_modifier = true;  // the shortcut is directly entered
+    else
+      m_shift_modifier = false; // the shortcut has to be written as text
+  }
+
+
   shortcut_manager *shortcut_manager::instance = nullptr;
 
   shortcut_manager::shortcut_manager (void)
@@ -172,13 +188,6 @@
     if (! instance)
       instance = new shortcut_manager ();
 
-    if (! instance)
-      {
-        error ("unable to create shortcut_manager object!");
-
-        retval = false;
-      }
-
     return retval;
   }
 
@@ -726,6 +735,8 @@
         m_dialog->setWindowTitle (tr ("Enter new Shortcut"));
 
         QVBoxLayout *box = new QVBoxLayout (m_dialog);
+        box->setSpacing (2);
+        box->setContentsMargins (12, 12, 12, 12);
 
         QLabel *help = new QLabel (tr ("Apply the desired shortcut or click "
                                        "on the right button to reset the "
@@ -735,8 +746,20 @@
 
         QCheckBox *direct = new QCheckBox (
                                            tr ("Enter shortcut directly by performing it"));
+        QCheckBox *shift = new QCheckBox (
+                                 tr ("Add Shift modifier\n"
+                                     "(allows to enter number keys)"));
+        shift->setStyleSheet ("QCheckBox::indicator { subcontrol-position: left top; }");
+
+        connect (direct, SIGNAL (clicked (bool)),
+                 shift, SLOT (setEnabled (bool)));
+
         direct->setCheckState (Qt::Checked);
+
         box->addWidget (direct);
+        box->addWidget (shift);
+
+        box->addSpacing (15);
 
         QGridLayout *grid = new QGridLayout ();
 
@@ -759,6 +782,8 @@
 
         box->addLayout (grid);
 
+        box->addSpacing (18);
+
         QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok
                                                              | QDialogButtonBox::Cancel);
         QList<QAbstractButton *> buttons = button_box->buttons ();
@@ -772,6 +797,8 @@
 
         connect (direct, SIGNAL (stateChanged (int)),
                  m_edit_actual, SLOT (handle_direct_shortcut (int)));
+        connect (shift, SIGNAL (stateChanged (int)),
+                 m_edit_actual, SLOT (handle_shift_modifier (int)));
         connect (m_dialog, SIGNAL (finished (int)),
                  this, SLOT (shortcut_dialog_finished (int)));
 
--- a/libgui/src/shortcut-manager.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/shortcut-manager.h	Fri Jul 12 12:14:43 2019 -0400
@@ -48,10 +48,12 @@
   public slots:
 
     void handle_direct_shortcut (int);
+    void handle_shift_modifier (int);
 
   private:
 
     bool m_direct_shortcut;
+    bool m_shift_modifier;
 
   };
 
--- a/libgui/src/variable-editor-model.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/variable-editor-model.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -46,48 +46,48 @@
 #include "utils.h"
 #include "variables.h"
 
-static bool
-cell_is_editable (const octave_value& val)
-{
-  if ((val.isnumeric () || val.islogical ()) && val.numel () == 1)
-    return true;
-
-  if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))
-    return true;
-
-  return false;
-}
-
-static char
-get_quote_char (const octave_value& val)
-{
-  if (val.is_sq_string ())
-    return '\'';
-
-  if (val.is_dq_string ())
-    return '"';
-
-  return 0;
-}
-
-static float_display_format
-get_edit_display_format (const octave_value& val)
-{
-  // FIXME: make this limit configurable.
-
-  return (val.numel () > 250000
-          ? float_display_format () : val.get_edit_display_format ());
-}
-
-static bool
-do_requires_sub_editor_sub (const octave_value& elt)
-{
-  return (! ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ()))
-             || (elt.is_string () && (elt.rows () == 1 || elt.isempty ()))));
-}
-
 namespace octave
 {
+  static bool
+  cell_is_editable (const octave_value& val)
+  {
+    if ((val.isnumeric () || val.islogical ()) && val.numel () == 1)
+      return true;
+
+    if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))
+      return true;
+
+    return false;
+  }
+
+  static char
+  get_quote_char (const octave_value& val)
+  {
+    if (val.is_sq_string ())
+      return '\'';
+
+    if (val.is_dq_string ())
+      return '"';
+
+    return 0;
+  }
+
+  static float_display_format
+  get_edit_display_format (const octave_value& val)
+  {
+    // FIXME: make this limit configurable.
+
+    return (val.numel () > 250000
+            ? float_display_format () : val.get_edit_display_format ());
+  }
+
+  static bool
+  do_requires_sub_editor_sub (const octave_value& elt)
+  {
+    return (! ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ()))
+               || (elt.is_string () && (elt.rows () == 1 || elt.isempty ()))));
+  }
+
   base_ve_model::base_ve_model (const QString& expr, const octave_value& val)
     : m_name (expr.toStdString ()),
       m_value (val),
@@ -129,8 +129,8 @@
     float_format r_fmt = m_display_fmt.real_format ();
     float_format i_fmt = m_display_fmt.imag_format ();
 
-    int rw = r_fmt.fw;
-    int iw = i_fmt.fw;
+    int rw = r_fmt.width ();
+    int iw = i_fmt.width ();
 
     if (rw > 0)
       {
--- a/libgui/src/variable-editor.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/variable-editor.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -54,36 +54,36 @@
 #include "variable-editor-model.h"
 #include "gui-preferences.h"
 
-// Code reuse functions
-
-static QString
-idx_to_expr (int32_t from, int32_t to)
-{
-  return (from == to
-          ? QString ("%1").arg (from)
-          : QString ("%1:%2").arg (from).arg (to));
-}
-
-static QSignalMapper *
-make_plot_mapper (QMenu *menu)
-{
-  QList<QString> list;
-  list << "plot" << "bar" << "stem" << "stairs" << "area" << "pie" << "hist";
-
-  QSignalMapper *plot_mapper = new QSignalMapper (menu);
-
-  for (int i = 0; i < list.size(); ++i)
-    {
-      plot_mapper->setMapping
-        (menu->addAction (list.at (i), plot_mapper, SLOT (map ())),
-         "figure (); " + list.at (i) + " (%1); title (\"%1\");");
-    }
-
-  return plot_mapper;
-}
-
 namespace octave
 {
+  // Code reuse functions
+
+  static QString
+  idx_to_expr (int32_t from, int32_t to)
+  {
+    return (from == to
+            ? QString ("%1").arg (from)
+            : QString ("%1:%2").arg (from).arg (to));
+  }
+
+  static QSignalMapper *
+  make_plot_mapper (QMenu *menu)
+  {
+    QList<QString> list;
+    list << "plot" << "bar" << "stem" << "stairs" << "area" << "pie" << "hist";
+
+    QSignalMapper *plot_mapper = new QSignalMapper (menu);
+
+    for (int i = 0; i < list.size(); ++i)
+      {
+        plot_mapper->setMapping
+          (menu->addAction (list.at (i), plot_mapper, SLOT (map ())),
+           "figure (); " + list.at (i) + " (%1); title (\"%1\");");
+      }
+
+    return plot_mapper;
+  }
+
   // Variable dock widget
 
   variable_dock_widget::variable_dock_widget (QWidget *p)
--- a/libgui/src/welcome-wizard.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/welcome-wizard.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -39,21 +39,22 @@
 #include "welcome-wizard.h"
 #include "resource-manager.h"
 
-static QLabel *
-make_octave_logo (QWidget *p = nullptr, int height = 100)
-{
-  QLabel *logo = new QLabel (p);
-  QPixmap logo_pixmap (":/actions/icons/logo.png");
-  logo->setPixmap (logo_pixmap.scaledToHeight (height));
-  return logo;
-};
-
 namespace octave
 {
+  static QLabel *
+  make_octave_logo (QWidget *p = nullptr, int height = 100)
+  {
+    QLabel *logo = new QLabel (p);
+    QPixmap logo_pixmap (":/actions/icons/logo.png");
+    logo->setPixmap (logo_pixmap.scaledToHeight (height));
+    return logo;
+  };
+
   welcome_wizard::welcome_wizard (QWidget *p)
     : QDialog (p), m_page_ctor_list (), m_page_list_iterator (),
       m_current_page (initial_page::create (this)),
-      m_allow_web_connect_state (false)
+      m_allow_web_connect_state (false),
+      m_max_height (0), m_max_width (0)
   {
     m_page_ctor_list.push_back (initial_page::create);
     m_page_ctor_list.push_back (setup_community_news::create);
@@ -65,19 +66,21 @@
 
     setEnabled (true);
 
-    QDesktopWidget *m_desktop = QApplication::desktop ();
-    int screen = m_desktop->screenNumber (this);  // screen of the main window
-    QRect screen_geo = m_desktop->availableGeometry (screen);
+    setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
 
-    int win_x = screen_geo.width ();        // width of the screen
-    int win_y = screen_geo.height ();       // height of the screen
-    int ww_x = std::max (win_x/2, 600);    // desired width
-    int ww_y = std::max (win_y*2/3, 480);  // desired height
+    // Create all pages for pre-setting the minimal required size for all pages
+    show_page ();
+    adjust_size ();
+    next_page ();
+    adjust_size ();
+    next_page ();
+    adjust_size ();
+    // now go back to the first page
+    previous_page ();
+    previous_page ();
 
-    resize (ww_x, ww_y);
-    setMinimumSize (QSize (ww_x, ww_y));
-
-    show_page ();
+    // Set the size determined above
+    resize (m_max_width, m_max_height);
 
 #if defined (OCTAVE_USE_WINDOWS_API)
     // HACK to forceshow of dialog if started minimized
@@ -85,6 +88,21 @@
 #endif
   }
 
+  void welcome_wizard::adjust_size (void)
+  {
+    // Get adjusted size for the current page
+    adjustSize ();
+    QSize sz = size ();
+
+    // Update the max. size of the three pages if required
+
+    if (sz.height () > m_max_height)
+      m_max_height = sz.height ();
+
+    if (sz.width () > m_max_width)
+      m_max_width = sz.width ();
+  }
+
   void welcome_wizard::handle_web_connect_option (int state)
   {
     m_allow_web_connect_state = state == Qt::Checked;
@@ -180,8 +198,11 @@
 
     page_layout->addLayout (message_and_logo);
     page_layout->addStretch (10);
+    page_layout->addSpacing (20);
     page_layout->addLayout (button_bar);
 
+    setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
     m_next->setDefault (true);
     m_next->setFocus ();
 
@@ -267,8 +288,11 @@
 
     page_layout->addLayout (message_logo_and_checkbox);
     page_layout->addStretch (10);
+    page_layout->addSpacing (20);
     page_layout->addLayout (button_bar);
 
+    setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
     m_next->setDefault (true);
     m_next->setFocus ();
 
@@ -345,8 +369,11 @@
     page_layout->addSpacing (20);
     page_layout->addWidget (m_links);
     page_layout->addStretch (10);
+    page_layout->addSpacing (20);
     page_layout->addLayout (button_bar);
 
+    setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
     m_finish->setDefault (true);
     m_finish->setFocus ();
 
--- a/libgui/src/welcome-wizard.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/welcome-wizard.h	Fri Jul 12 12:14:43 2019 -0400
@@ -42,12 +42,16 @@
 
     ~welcome_wizard (void) = default;
 
+    void adjust_size (void);
+
   private:
 
     QList<page_creator_fptr> m_page_ctor_list;
     QList<page_creator_fptr>::iterator m_page_list_iterator;
     QWidget *m_current_page;
     bool m_allow_web_connect_state;
+    int m_max_height;
+    int m_max_width;
 
   private slots:
 
--- a/libgui/src/workspace-model.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/workspace-model.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -48,7 +48,12 @@
     m_columnNames.append (tr ("Value"));
     m_columnNames.append (tr ("Attribute"));
 
-    for (int i = 0; i < resource_manager::storage_class_chars ().length (); i++)
+    // Initialize the bachground and foreground colors of special
+    // classes in the workspace view. The structure is
+    // m_storage_class_colors(1,2,...,colors):        background colors
+    // m_storage_class_colors(colors+1,...,2*colors): foreground colors
+    int colors = resource_manager::storage_class_chars ().length ();
+    for (int i = 0; i < 2*colors; i++)
       m_storage_class_colors.append (QColor (Qt::white));
 
   }
@@ -61,10 +66,7 @@
     if (colors.isEmpty ())
       {
         colors << QColor (190, 255, 255)
-               << QColor (220, 255, 220)
-               << QColor (220, 220, 255)
                << QColor (255, 255, 190)
-               << QColor (255, 220, 220)
                << QColor (255, 190, 255);
       }
 
@@ -78,11 +80,8 @@
 
     if (names.isEmpty ())
       {
-        names << QObject::tr ("automatic")
-              << QObject::tr ("function")
+        names << QObject::tr ("argument")
               << QObject::tr ("global")
-              << QObject::tr ("hidden")
-              << QObject::tr ("inherited")
               << QObject::tr ("persistent");
       }
 
@@ -134,13 +133,21 @@
 
     if (idx.isValid ())
       {
-        if (role == Qt::BackgroundColorRole && m_enable_colors)
+        if ((role == Qt::BackgroundColorRole || role == Qt::ForegroundRole)
+            && m_enable_colors)
           {
             QString class_chars = resource_manager::storage_class_chars ();
             int actual_class
               = class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ());
             if (actual_class >= 0)
-              return QVariant (m_storage_class_colors.at (actual_class));
+              {
+                // Valid class: Get backgorund (normal indexes) or foreground
+                // color (indexes with offset)
+                if (role == Qt::ForegroundRole)
+                  actual_class += class_chars.length ();
+
+                return QVariant (m_storage_class_colors.at (actual_class));
+              }
             else
               return retval;
           }
@@ -206,31 +213,6 @@
     return retval;
   }
 
-  bool
-  workspace_model::setData (const QModelIndex& idx, const QVariant& value,
-                            int role)
-  {
-    bool retval = false;
-
-    if (idx.column () == 0 && role == Qt::EditRole)
-      {
-        QString qold_name = m_symbols[idx.row ()];
-
-        QString qnew_name = value.toString ();
-
-        std::string new_name = qnew_name.toStdString ();
-
-        if (valid_identifier (new_name))
-          {
-            emit rename_variable (qold_name, qnew_name);
-
-            retval = true;
-          }
-      }
-
-    return retval;
-  }
-
   void
   workspace_model::set_workspace (bool top_level, bool /* debug */,
                                   const symbol_info_list& syminfo)
@@ -266,7 +248,13 @@
         QColor setting_color = settings->value ("workspaceview/color_"
                                                 + class_chars.mid (i,1),
                                                 default_var).value<QColor> ();
+
+        QPalette p (setting_color);
         m_storage_class_colors.replace (i,setting_color);
+
+        QColor fg_color = p.color (QPalette::WindowText);
+        m_storage_class_colors.replace (i + class_chars.length (), fg_color);
+
       }
   }
 
@@ -301,14 +289,12 @@
           dv(i) = sz(i);
 
         char storage = ' ';
-        if (syminfo.is_global ())
+        if (syminfo.is_formal ())
+          storage = 'a';
+        else if (syminfo.is_global ())
           storage = 'g';
         else if (syminfo.is_persistent ())
           storage = 'p';
-        else if (syminfo.is_automatic ())
-          storage = 'a';
-        else if (syminfo.is_formal ())
-          storage = 'f';
 
         std::ostringstream buf;
         val.short_disp (buf);
--- a/libgui/src/workspace-model.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/workspace-model.h	Fri Jul 12 12:14:43 2019 -0400
@@ -66,9 +66,6 @@
 
     QVariant data (const QModelIndex& index, int role) const;
 
-    bool setData (const QModelIndex& index, const QVariant& value,
-                  int role = Qt::EditRole);
-
     bool is_top_level (void) const { return m_top_level; }
 
     QColor storage_class_color (int s_class)
@@ -92,8 +89,6 @@
     void model_changed (void);
     void prompt_variable_editor(void);
 
-    void rename_variable (const QString& old_name, const QString& new_name);
-
   private:
 
     void clear_data (void);
--- a/libgui/src/workspace-view.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/workspace-view.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -44,6 +44,7 @@
 #include "resource-manager.h"
 
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "syminfo.h"
 
 namespace octave
@@ -198,11 +199,13 @@
       {
         tool_tip  = QString (tr ("View the variables in the active workspace.<br>"));
         tool_tip += QString (tr ("Colors for variable attributes:"));
-        for (i = 0; i < resource_manager::storage_class_chars ().length (); i++)
+        int colors = resource_manager::storage_class_chars ().length ();
+        for (i = 0; i < colors; i++)
           {
             tool_tip +=
-              QString (R"(<div style="background-color:%1;color:#000000">%2</div>)")
+              QString (R"(<div style="background-color:%1;color:%2">%3</div>)")
               .arg (m_model->storage_class_color (i).name ())
+              .arg (m_model->storage_class_color (i + colors).name ())
               .arg (resource_manager::storage_class_names ().at (i));
           }
       }
@@ -354,10 +357,9 @@
         QAction *rename = menu.addAction (tr ("Rename"), this,
                                           SLOT (handle_contextmenu_rename ()));
 
-        QAbstractItemModel *m = m_view->model ();
-        const workspace_model *wm = static_cast<const workspace_model *> (m);
-
-        if (! wm->is_top_level ())
+        // Use m_model here instead of using "m_view->model ()" because
+        // that points to the proxy model.
+        if (! m_model->is_top_level ())
           {
             rename->setDisabled (true);
             rename->setToolTip (tr ("Only top-level symbols may be renamed"));
@@ -415,10 +417,13 @@
       {
         QString var_name = get_var_name (index);
 
-        symbol_scope scope
-          = __get_current_scope__ ("workspace_view::handle_contextmenu_copy_value");
+        // FIXME: this looks suspciously unsafe.
+        interpreter& interp
+          = __get_interpreter__ ("workspace_view::handle_contextmenu_copy_value");
 
-        octave_value val = scope ? scope.varval (var_name.toStdString ()) : 0;
+        octave_value val = interp.varval (var_name.toStdString ());
+        if (val.is_undefined ())
+          val = 0;
         std::ostringstream buf;
         val.print_raw (buf, true);
 
@@ -447,10 +452,7 @@
                                   QLineEdit::Normal, var_name, &ok);
 
         if (ok && ! new_name.isEmpty ())
-          {
-            QAbstractItemModel *m = m_view->model ();
-            m->setData (index, new_name, Qt::EditRole);
-          }
+          emit rename_variable_signal (var_name, new_name);
       }
   }
 
@@ -464,7 +466,6 @@
         QString var_name = get_var_name (index);
 
         symbol_info_list syminfo = m_model->get_symbol_info ();
-
         octave_value val = syminfo.varval (var_name.toStdString ());
 
         emit edit_variable_signal (var_name, val);
--- a/libgui/src/workspace-view.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libgui/src/workspace-view.h	Fri Jul 12 12:14:43 2019 -0400
@@ -63,6 +63,10 @@
 
     void command_requested (const QString& cmd);
 
+    //! Signal that user wants to rename a variable.
+
+    void rename_variable_signal (const QString&, const QString&);
+
     //! Signal that user wants to edit a variable.
 
     void edit_variable_signal (const QString&, const octave_value&);
--- a/libinterp/build-env.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/build-env.h	Fri Jul 12 12:14:43 2019 -0400
@@ -161,6 +161,9 @@
     extern const char *SUNDIALS_NVECSERIAL_CPPFLAGS;
     extern const char *SUNDIALS_NVECSERIAL_LDFLAGS;
     extern const char *SUNDIALS_NVECSERIAL_LIBS;
+    extern const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS;
+    extern const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS;
+    extern const char *SUNDIALS_SUNLINSOLKLU_LIBS;
     extern const char *TERM_LIBS;
     extern const char *UMFPACK_CPPFLAGS;
     extern const char *UMFPACK_LDFLAGS;
--- a/libinterp/build-env.in.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/build-env.in.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -289,6 +289,12 @@
 
     const char *SUNDIALS_NVECSERIAL_LIBS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%;
 
+    const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%;
+
+    const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%;
+
+    const char *SUNDIALS_SUNLINSOLKLU_LIBS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%;
+
     const char *TERM_LIBS = %OCTAVE_CONF_TERM_LIBS%;
 
     const char *UMFPACK_CPPFLAGS = %OCTAVE_CONF_UMFPACK_CPPFLAGS%;
--- a/libinterp/corefcn/Cell.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/Cell.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -166,6 +166,7 @@
       switch (n)
         {
         case 0:
+          warn_empty_index ("cell array");
           retval = *this;
           break;
 
@@ -211,9 +212,11 @@
 }
 
 /*
-%!test
+%% This behavior is required for Matlab compatibility.
+%!shared a
 %! a = {"foo", "bar"};
-%! assert (a(), a);
+%!assert (a(), a);
+%!error <invalid empty index expression> a{}
 */
 
 void
--- a/libinterp/corefcn/Cell.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/Cell.h	Fri Jul 12 12:14:43 2019 -0400
@@ -40,8 +40,13 @@
 {
 public:
 
-  Cell (void)
-    : Array<octave_value> (dim_vector (0, 0)) { }
+  Cell (void) = default;
+
+  Cell (const Cell& c) = default;
+
+  Cell& operator = (const Cell& c) = default;
+
+  ~Cell (void) = default;
 
   Cell (const octave_value& val)
     : Array<octave_value> (dim_vector (1, 1), val) { }
@@ -87,9 +92,6 @@
 
   Cell (const dim_vector& dv, const string_vector& sv, bool trim = false);
 
-  Cell (const Cell& c)
-    : Array<octave_value> (c) { }
-
   bool iscellstr (void) const;
 
   Array<std::string> cellstr_value (void) const;
--- a/libinterp/corefcn/__ichol__.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/__ichol__.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -453,7 +453,7 @@
 }
 
 /*
-%!test <51736>
+%!test <*51736>
 %! k = 4;
 %! n = 2^k;
 %! Afull = diag (ones (n,1)) / ...
--- a/libinterp/corefcn/__qp__.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/__qp__.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -101,15 +101,13 @@
 qp (const Matrix& H, const ColumnVector& q,
     const Matrix& Aeq, const ColumnVector& beq,
     const Matrix& Ain, const ColumnVector& bin,
-    int maxit,
+    int maxit, double rtol,
     ColumnVector& x, ColumnVector& lambda, int& iter)
 {
   int info = 0;
 
   iter = 0;
 
-  double rtol = sqrt (std::numeric_limits<double>::epsilon ());
-
   // Problem dimension.
   octave_idx_type n = x.numel ();
 
@@ -489,7 +487,7 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  if (args.length () != 8)
+  if (args.length () != 9)
     print_usage ();
 
   const ColumnVector x0  (args(0).vector_value ());
@@ -500,6 +498,7 @@
   const Matrix Ain       (args(5).matrix_value ());
   const ColumnVector bin (args(6).vector_value ());
   const int maxit        (args(7).int_value ());
+  const double rtol      (args(8).double_value());
 
   int iter = 0;
 
@@ -509,7 +508,7 @@
   // Reordering the Lagrange multipliers
   ColumnVector lambda;
 
-  int info = qp (H, q, Aeq, beq, Ain, bin, maxit, x, lambda, iter);
+  int info = qp (H, q, Aeq, beq, Ain, bin, maxit, rtol, x, lambda, iter);
 
   return ovl (x, lambda, info, iter);
 }
--- a/libinterp/corefcn/base-text-renderer.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/base-text-renderer.h	Fri Jul 12 12:14:43 2019 -0400
@@ -52,6 +52,9 @@
 
     virtual ~base_text_renderer (void) = default;
 
+    virtual void
+    set_anti_aliasing (bool val) = 0;
+
     virtual Matrix
     get_extent (text_element *elt, double rotation) = 0;
 
--- a/libinterp/corefcn/call-stack.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/call-stack.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,12 +24,15 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include "lo-regexp.h"
 #include "str-vec.h"
 
 #include "call-stack.h"
 #include "defun.h"
 #include "interpreter.h"
+#include "interpreter-private.h"
 #include "oct-map.h"
 #include "ov.h"
 #include "ov-fcn.h"
@@ -37,291 +40,157 @@
 #include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
+#include "stack-frame.h"
+#include "stack-frame-walker.h"
 #include "syminfo.h"
+#include "syminfo-accumulator.h"
 #include "symrec.h"
 #include "symscope.h"
 #include "variables.h"
 
-// Use static fields for the best efficiency.
-// NOTE: C++0x will allow these two to be merged into one.
-static const char *bt_fieldnames[] =
-  { "file", "name", "line", "column", "scope", "context", nullptr };
-static const octave_fields bt_fields (bt_fieldnames);
-
 namespace octave
 {
-  std::string
-  call_stack::stack_frame::fcn_file_name (void) const
-  {
-    return m_fcn ? m_fcn->fcn_file_name () : "";
-  }
-
-  std::string
-  call_stack::stack_frame::fcn_name (bool print_subfn) const
-  {
-    std::string retval;
+  // Use static fields for the best efficiency.
+  // NOTE: C++0x will allow these two to be merged into one.
+  static const char *bt_fieldnames[] =
+    { "file", "name", "line", "column", "scope", nullptr };
 
-    if (m_fcn)
-      {
-        std::string parent_fcn_name = m_fcn->parent_fcn_name ();
-
-        if (print_subfn && ! parent_fcn_name.empty ())
-          retval = parent_fcn_name + '>';
+  static const octave_fields bt_fields (bt_fieldnames);
 
-        if (m_fcn->is_anonymous_function ())
-          retval += octave_fcn_handle::anonymous;
-        else
-          retval += m_fcn->name ();
-      }
-    else
-      retval = "<unknown>";
-
-    return retval;
+  call_stack::call_stack (tree_evaluator& evaluator)
+    : m_evaluator (evaluator), m_cs (), m_curr_frame (0),
+      m_max_stack_depth (1024), m_global_values ()
+  {
+    push (symbol_scope ("top scope"));
   }
 
-  bool
-  call_stack::stack_frame::operator == (const call_stack::stack_frame& rhs) const
-  {
-    if (this->line () != rhs.line ())
-      return false;
-    else if (this->column () != rhs.column ())
-      return false;
-    else if (this->fcn_file_name () != rhs.fcn_file_name ())
-      return false;
-    else if (this->fcn_name () != rhs.fcn_name ())
-      return false;
-    else
-      return true;
-  }
-
-  symbol_info_list
-  call_stack::stack_frame::make_symbol_info_list
-    (const std::list<symbol_record>& symrec_list) const
-  {
-    symbol_info_list symbol_stats;
-
-    for (const auto& sr : symrec_list)
-      {
-        octave_value value = sr.varval (m_context);
-
-        if (value.is_defined ())
-          {
-            symbol_info syminf (sr.name (), value, sr.is_automatic (),
-                                value.iscomplex (), sr.is_formal (),
-                                sr.is_global (), sr.is_persistent ());
-
-            symbol_stats.append (syminf);
-          }
-      }
-
-    return symbol_stats;
-  }
-
-  symbol_info_list
-  call_stack::stack_frame::glob_symbol_info (const std::string& pat) const
-  {
-    return make_symbol_info_list (m_scope.glob (pat, true));
-  }
-
-  symbol_info_list
-  call_stack::stack_frame::regexp_symbol_info (const std::string& pat) const
-  {
-    return make_symbol_info_list (m_scope.regexp (pat, true));
-  }
-
-  symbol_info_list call_stack::stack_frame::get_symbol_info (void) const
-  {
-    return make_symbol_info_list (m_scope.all_variables ());
-  }
-
-  call_stack::call_stack (interpreter& interp)
-    : cs (), curr_frame (0), m_max_stack_depth (1024), m_interpreter (interp)
-  {
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-    push (nullptr, nullptr, symtab.top_scope (), 0);
-  }
-
-  int
-  call_stack::current_line (void) const
+  int call_stack::current_line (void) const
   {
     int retval = -1;
 
-    if (! cs.empty ())
+    if (! m_cs.empty ())
       {
-        const stack_frame& elt = cs[curr_frame];
-        retval = elt.m_line;
+        const stack_frame *elt = m_cs[m_curr_frame];
+        retval = elt->line ();
       }
 
     return retval;
   }
 
-  int
-  call_stack::current_column (void) const
+  int call_stack::current_column (void) const
   {
     int retval = -1;
 
-    if (! cs.empty ())
+    if (! m_cs.empty ())
       {
-        const stack_frame& elt = cs[curr_frame];
-        retval = elt.m_column;
+        const stack_frame *elt = m_cs[m_curr_frame];
+        retval = elt->column ();
       }
 
     return retval;
   }
 
-  size_t
-  call_stack::num_user_code_frames (octave_idx_type& curr_user_frame) const
+  octave_user_code * call_stack::current_user_code (void) const
   {
-    size_t retval = 0;
-
-    curr_user_frame = 0;
-
-    // Look for the caller of dbstack.
-    size_t xframe = cs[curr_frame].m_prev;
+    // Start at current frame.
 
-    bool found = false;
-
-    size_t k = cs.size ();
-
-    for (auto p = cs.crbegin (); p != cs.crend (); p++)
-      {
-        octave_function *f = (*p).m_fcn;
-
-        if (--k == xframe)
-          found = true;
+    size_t xframe = find_current_user_frame ();
 
-        if (f && f->is_user_code ())
-          {
-            if (! found)
-              curr_user_frame++;
-
-            retval++;
-          }
-      }
-
-    // We counted how many user frames were not the one, in reverse.
-    // Now set curr_user_frame to be the index in the other direction.
-    curr_user_frame = retval - curr_user_frame - 1;
+    if (xframe > 0)
+      {
+        const stack_frame *elt = m_cs[xframe];
 
-    return retval;
-  }
-
-  octave_user_code *
-  call_stack::caller_user_code (size_t nskip) const
-  {
-    octave_user_code *retval = nullptr;
-
-    auto p = cs.cend ();
-
-    while (p != cs.cbegin ())
-      {
-        const stack_frame& elt = *(--p);
-
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && f->is_user_code ())
-          {
-            if (nskip > 0)
-              nskip--;
-            else
-              {
-                retval = dynamic_cast<octave_user_code *> (f);
-                break;
-              }
-          }
-      }
-
-    return retval;
-  }
-
-  int
-  call_stack::caller_user_code_line (void) const
-  {
-    int retval = -1;
-
-    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 ())
-          {
-            if (elt.m_line > 0)
-              {
-                retval = elt.m_line;
-                break;
-              }
-          }
-      }
-
-    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 dynamic_cast<octave_user_code *> (f);
       }
 
     return nullptr;
   }
 
-  int
-  call_stack::caller_user_code_column (void) const
+  int call_stack::current_user_code_line (void) const
   {
-    int retval = -1;
+    // Start at current frame.
+
+    size_t xframe = find_current_user_frame ();
 
-    auto p = cs.cend ();
-
-    while (p != cs.cbegin ())
+    if (xframe > 0)
       {
-        const stack_frame& elt = *(--p);
+        const stack_frame *elt = m_cs[xframe];
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && f->is_user_code ())
           {
-            if (elt.m_column)
-              {
-                retval = elt.m_column;
-                break;
-              }
+            int line = elt->line ();
+
+            if (line > 0)
+              return line;
           }
       }
 
-    return retval;
+    return -1;
   }
 
-  octave_user_code *
-  call_stack::debug_user_code (void) const
+  int call_stack::current_user_code_column (void) const
+  {
+    // Start at current frame.
+
+    size_t xframe = find_current_user_frame ();
+
+    if (xframe > 0)
+      {
+        const stack_frame *elt = m_cs[xframe];
+
+        octave_function *f = elt->function ();
+
+        if (f && f->is_user_code ())
+          {
+            int column = elt->column ();
+
+            if (column > 0)
+              return column;
+          }
+      }
+
+    return -1;
+  }
+
+  unwind_protect * call_stack::curr_fcn_unwind_protect_frame (void) const
+  {
+    // Start at current frame.
+
+    size_t xframe = find_current_user_frame ();
+
+    if (xframe > 0)
+      {
+        const stack_frame *elt = m_cs[xframe];
+
+        octave_function *f = elt->function ();
+
+        if (f && f->is_user_code ())
+          return elt->unwind_protect_frame ();
+      }
+
+    return nullptr;
+  }
+
+  octave_user_code * call_stack::debug_user_code (void) const
   {
     octave_user_code *retval = nullptr;
 
     // This should never happen...
-    if (curr_frame == 0)
+    if (m_curr_frame == 0)
       return retval;
 
-    // Start looking with the caller of the calling debug function.
-    size_t i = cs[curr_frame].m_prev;
+    size_t i = m_curr_frame;
 
     while (i != 0)
       {
-        const stack_frame& elt = cs[i--];
+        const stack_frame *elt = m_cs[i--];
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && f->is_user_code ())
           {
@@ -333,29 +202,27 @@
     return retval;
   }
 
-  int
-  call_stack::debug_user_code_line (void) const
+  int call_stack::debug_user_code_line (void) const
   {
     int retval = -1;
 
     // This should never happen...
-    if (curr_frame == 0)
+    if (m_curr_frame == 0)
       return retval;
 
-    // Start looking with the caller of the calling debug function.
-    size_t i = cs[curr_frame].m_prev;
+    size_t i = m_curr_frame;
 
     while (i != 0)
       {
-        const stack_frame& elt = cs[i--];
+        const stack_frame *elt = m_cs[i--];
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && f->is_user_code ())
           {
-            if (elt.m_line)
+            if (elt->line ())
               {
-                retval = elt.m_line;
+                retval = elt->line ();
                 break;
               }
           }
@@ -364,29 +231,28 @@
     return retval;
   }
 
-  int
-  call_stack::debug_user_code_column (void) const
+  int call_stack::debug_user_code_column (void) const
   {
     int retval = -1;
 
     // This should never happen...
-    if (curr_frame == 0)
+    if (m_curr_frame == 0)
       return retval;
 
     // Start looking with the caller of the calling debug function.
-    size_t i = cs[curr_frame].m_prev;
+    size_t i = m_curr_frame;
 
     while (i != 0)
       {
-        const stack_frame& elt = cs[i--];
+        const stack_frame *elt = m_cs[i--];
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && f->is_user_code ())
           {
-            if (elt.m_column)
+            if (elt->column ())
               {
-                retval = elt.m_column;
+                retval = elt->column ();
                 break;
               }
           }
@@ -395,18 +261,55 @@
     return retval;
   }
 
-  bool
-  call_stack::all_scripts (void) const
+  std::string call_stack::get_dispatch_class (void) const
+  {
+    return m_cs[m_curr_frame]->get_dispatch_class ();
+  }
+
+  void call_stack::set_dispatch_class (const std::string& class_name)
+  {
+    m_cs[m_curr_frame]->set_dispatch_class (class_name);
+  }
+
+  bool call_stack::is_class_method_executing (std::string& dispatch_class) const
+  {
+    dispatch_class = "";
+
+    octave_function *f = current ();
+
+    bool retval = (f && f->is_class_method ());
+
+    if (retval)
+      dispatch_class = f->dispatch_class ();
+
+    return retval;
+  }
+
+  bool call_stack::is_class_constructor_executing (std::string& dispatch_class) const
+  {
+    dispatch_class = "";
+
+    octave_function *f = current ();
+
+    bool retval = (f && f->is_class_constructor ());
+
+    if (retval)
+      dispatch_class = f->dispatch_class ();
+
+    return retval;
+  }
+
+  bool call_stack::all_scripts (void) const
   {
     bool retval = true;
 
-    auto p = cs.cend ();
+    auto p = m_cs.cend ();
 
-    while (p != cs.cbegin ())
+    while (p != m_cs.cbegin ())
       {
-        const stack_frame& elt = *(--p);
+        const stack_frame *elt = *(--p);
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (f && ! f->is_user_script ())
           {
@@ -418,229 +321,310 @@
     return retval;
   }
 
-  void
-  call_stack::push (octave_function *fcn, unwind_protect *up_frame)
+  stack_frame * call_stack::get_static_link (size_t prev_frame) const
   {
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
+    // FIXME: is there a better way?
+
+    stack_frame *slink = nullptr;
+
+    if (m_curr_frame > 0)
+      {
+        octave_function *t_fcn = m_cs[prev_frame]->function ();
 
-    push (fcn, up_frame, symtab.current_scope (), symtab.current_context ());
+        slink = (t_fcn
+                 ? (t_fcn->is_user_code ()
+                    ? m_cs[prev_frame] : m_cs[prev_frame]->static_link ())
+                 : m_cs[prev_frame]);
+      }
+
+    return slink;
   }
 
-  void
-  call_stack::push (octave_function *fcn, unwind_protect *up_frame,
-                    const symbol_scope& scope,
-                    symbol_record::context_id context)
+  void call_stack::push (const symbol_scope& scope)
   {
-    size_t prev_frame = curr_frame;
-    curr_frame = cs.size ();
+    size_t prev_frame = m_curr_frame;
+    m_curr_frame = m_cs.size ();
 
     // m_max_stack_depth should never be less than zero.
-    if (curr_frame > static_cast<size_t> (m_max_stack_depth))
+    if (m_curr_frame > static_cast<size_t> (m_max_stack_depth))
       error ("max_stack_depth exceeded");
 
-    cs.push_back (stack_frame (fcn, up_frame, scope, context, prev_frame));
+    stack_frame *slink = get_static_link (prev_frame);
 
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
+    stack_frame *new_frame
+      = new scope_stack_frame (m_evaluator, scope, m_curr_frame, slink);
 
-    symtab.set_scope_and_context (scope, context);
+    m_cs.push_back (new_frame);
   }
 
-  bool
-  call_stack::goto_frame (size_t n, bool verbose)
+  void call_stack::push (octave_user_function *fcn, unwind_protect *up_frame,
+                         stack_frame *closure_frames)
   {
-    bool retval = false;
-
-    if (n < cs.size ())
-      {
-        retval = true;
-
-        curr_frame = n;
-
-        const stack_frame& elt = cs[n];
+    size_t prev_frame = m_curr_frame;
+    m_curr_frame = m_cs.size ();
 
-        symbol_table& symtab = m_interpreter.get_symbol_table ();
+    // m_max_stack_depth should never be less than zero.
+    if (m_curr_frame > static_cast<size_t> (m_max_stack_depth))
+      error ("max_stack_depth exceeded");
 
-        symtab.set_scope_and_context (elt.m_scope, elt.m_context);
+    stack_frame *slink = get_static_link (prev_frame);
 
-        if (verbose)
-          octave_stdout << "stopped in " << elt.fcn_name ()
-                        << " at line " << elt.m_line
-                        << " column " << elt.m_column
-                        << " [" << elt.fcn_file_name () << "] "
-                        << "[context = " << elt.m_context << "])"
-                        << std::endl;
-      }
+    stack_frame *new_frame
+      = new user_fcn_stack_frame (m_evaluator, fcn, up_frame, m_curr_frame,
+                                  slink, closure_frames);
 
-    return retval;
+    m_cs.push_back (new_frame);
   }
 
-  bool
-  call_stack::goto_frame_relative (int nskip, bool verbose)
+  void call_stack::push (octave_user_script *script, unwind_protect *up_frame)
+  {
+    size_t prev_frame = m_curr_frame;
+    m_curr_frame = m_cs.size ();
+
+    // m_max_stack_depth should never be less than zero.
+    if (m_curr_frame > static_cast<size_t> (m_max_stack_depth))
+      error ("max_stack_depth exceeded");
+
+    stack_frame *slink = get_static_link (prev_frame);
+
+    stack_frame *new_frame
+      = new script_stack_frame (m_evaluator, script, up_frame, m_curr_frame,
+                                slink);
+
+    m_cs.push_back (new_frame);
+  }
+
+  void call_stack::push (octave_function *fcn)
+  {
+    size_t prev_frame = m_curr_frame;
+    m_curr_frame = m_cs.size ();
+
+    // m_max_stack_depth should never be less than zero.
+    if (m_curr_frame > static_cast<size_t> (m_max_stack_depth))
+      error ("max_stack_depth exceeded");
+
+    stack_frame *slink = get_static_link (prev_frame);
+
+    stack_frame *new_frame
+      = new compiled_fcn_stack_frame (m_evaluator, fcn, m_curr_frame, slink);
+
+    m_cs.push_back (new_frame);
+  }
+
+  bool call_stack::goto_frame (size_t n, bool verbose)
   {
     bool retval = false;
 
-    int incr = 0;
-
-    if (nskip < 0)
-      incr = -1;
-    else if (nskip > 0)
-      incr = 1;
-
-    // Start looking with the caller of dbup/dbdown/keyboard.
-    size_t xframe = cs[curr_frame].m_prev;
-
-    while (true)
+    if (n < m_cs.size ())
       {
-        if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1))
-          break;
-
-        xframe += incr;
-
-        const stack_frame& elt = cs[xframe];
-
-        octave_function *f = elt.m_fcn;
-
-        if (xframe == 0 || (f && f->is_user_code ()))
-          {
-            if (nskip > 0)
-              nskip--;
-            else if (nskip < 0)
-              nskip++;
-
-            if (nskip == 0)
-              {
-                curr_frame = xframe;
-                cs[cs.size () - 1].m_prev = curr_frame;
-
-                symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-                symtab.set_scope_and_context (elt.m_scope, elt.m_context);
+        retval = true;
 
-                if (verbose)
-                  {
-                    std::ostringstream buf;
-
-                    if (f)
-                      buf << "stopped in " << elt.fcn_name ()
-                          << " at line " << elt.m_line
-                          << " [" << elt.fcn_file_name () << "] "
-                          << std::endl;
-                    else
-                      buf << "at top level" << std::endl;
-
-                    octave_stdout << buf.str ();
-                  }
-
-                retval = true;
-                break;
-              }
-          }
-        else if (incr == 0)  // Break out of infinite loop by choosing an incr.
-          incr = -1;
-
-        // There is no need to set scope and context here.  That will
-        // happen when the dbup/dbdown/keyboard frame is popped and we
-        // jump to the new "prev" frame set above.
-      }
-
-    return retval;
-  }
-
-  void
-  call_stack::goto_caller_frame (void)
-  {
-    size_t xframe = curr_frame;
-
-    bool skipped = false;
+        m_curr_frame = n;
 
-    while (xframe != 0)
-      {
-        xframe = cs[xframe].m_prev;
-
-        const stack_frame& elt = cs[xframe];
-
-        octave_function *f = elt.m_fcn;
-
-        if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ()))
+        if (verbose)
           {
-            if (! skipped)
-              // We found the current user code frame, so skip it.
-              skipped = true;
-            else
-              {
-                // We found the caller user code frame.
-                stack_frame tmp (elt);
-                tmp.m_prev = curr_frame;
-
-                curr_frame = cs.size ();
-
-                cs.push_back (tmp);
-
-                symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-                symtab.set_scope_and_context (tmp.m_scope, tmp.m_context);
-
-                break;
-              }
-          }
-      }
-  }
+            const stack_frame *elt = m_cs[n];
 
-  void
-  call_stack::goto_base_frame (void)
-  {
-    stack_frame tmp (cs[0]);
-    tmp.m_prev = curr_frame;
-
-    curr_frame = cs.size ();
-
-    cs.push_back (tmp);
-
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-    symtab.set_scope_and_context (tmp.m_scope, tmp.m_context);
-  }
-
-  std::list<call_stack::stack_frame>
-  call_stack::backtrace_frames (size_t nskip,
-                                octave_idx_type& curr_user_frame) const
-  {
-    std::list<call_stack::stack_frame> retval;
-
-    size_t user_code_frames = num_user_code_frames (curr_user_frame);
-
-    size_t nframes = (nskip <= user_code_frames ? user_code_frames - nskip : 0);
-
-    // Our list is reversed.
-    curr_user_frame = nframes - curr_user_frame - 1;
-
-    if (nframes > 0)
-      {
-        for (auto p = cs.crbegin (); p != cs.crend (); p++)
-          {
-            const stack_frame& elt = *p;
-
-            octave_function *f = elt.m_fcn;
-
-            if (f && f->is_user_code ())
-              {
-                if (nskip > 0)
-                  nskip--;
-                else
-                  retval.push_back (elt);
-              }
+            elt->display_stopped_in_message (octave_stdout);
           }
       }
 
     return retval;
   }
 
-  octave_map
-  call_stack::backtrace (size_t nskip, octave_idx_type& curr_user_frame,
-                         bool print_subfn) const
+  size_t call_stack::find_current_user_frame (void) const
+  {
+    size_t user_frame = m_curr_frame;
+
+    stack_frame *frm = m_cs[user_frame];
+
+    if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
+           || frm->is_scope_frame ()))
+      {
+        frm = frm->static_link ();
+
+        user_frame = frm->index ();
+      }
+
+    return user_frame;
+  }
+
+  stack_frame *call_stack::current_user_frame (void) const
+  {
+    size_t frame = find_current_user_frame ();
+
+    return m_cs[frame];
+  }
+
+  // Go to the Nth frame (up if N is negative or down if positive) in
+  // the call stack that corresponds to a script, function, or scope
+  // beginning with the frame indexed by START.
+
+  size_t call_stack::dbupdown (size_t start, int n, bool verbose)
   {
-    std::list<call_stack::stack_frame> frames
-      = backtrace_frames (nskip, curr_user_frame);
+    if (start >= m_cs.size ())
+      error ("invalid stack frame");
+
+    // Can't go up from here.
+
+    if (start == 0 && n < 0)
+      {
+        if (verbose)
+          m_cs[start]->display_stopped_in_message (octave_stdout);
+
+        return start;
+      }
+
+    stack_frame *frm = m_cs[start];
+
+    if (! (frm && (frm->is_user_fcn_frame ()
+                   || frm->is_user_script_frame ()
+                   || frm->is_scope_frame ())))
+      error ("call_stack::dbupdown: invalid initial frame in call stack!");
+
+    // Use index into the call stack to begin the search.  At this point
+    // we iterate up or down using indexing instead of static links
+    // because ... FIXME: it's a bit complicated, but deserves
+    // explanation.  May be easiest with some pictures of the call stack
+    // for an example or two.
+
+    size_t xframe = frm->index ();
+
+    if (n == 0)
+      {
+        if (verbose)
+          frm->display_stopped_in_message (octave_stdout);
+
+        return xframe;
+      }
+
+    int incr = 0;
+
+    if (n < 0)
+      {
+        incr = -1;
+        n = -n;
+      }
+    else if (n > 0)
+      incr = 1;
+
+    size_t last_good_frame = 0;
+
+    while (true)
+      {
+        frm = m_cs[xframe];
+
+        if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
+            || frm->is_scope_frame ())
+          {
+            last_good_frame = xframe;
+
+            if (n == 0)
+              break;
+
+            n--;
+          }
+
+        xframe += incr;
+
+        if (xframe == 0)
+          {
+            last_good_frame = 0;
+            break;
+          }
+
+        if (xframe == m_cs.size ())
+          break;
+      }
+
+    if (verbose)
+      m_cs[last_good_frame]->display_stopped_in_message (octave_stdout);
+
+    return last_good_frame;
+  }
+
+  // Like dbupdown above but find the starting frame automatically from
+  // the current frame.  If the current frame is already a user
+  // function, script, or scope frame, use that.  Otherwise, follow
+  // the static link for the current frame.  If that is not a user
+  // function, script or scope frame then there is an error in the
+  // implementation.
+
+  size_t call_stack::dbupdown (int n, bool verbose)
+  {
+    size_t start = find_current_user_frame ();
+
+    return dbupdown (start, n, verbose);
+  }
+
+  // May be used to temporarily change the value ov m_curr_frame inside
+  // a function like evalin.  If used in a function like dbup, the new
+  // value of m_curr_frame would be wiped out when dbup returns and the
+  // stack frame for dbup is popped.
+
+  void call_stack::goto_caller_frame (void)
+  {
+    size_t start = find_current_user_frame ();
+
+    // FIXME: is this supposed to be an error?
+    if (start == 0)
+      error ("already at top level");
+
+    m_curr_frame = dbupdown (start, -1, false);
+  }
+
+  void call_stack::goto_base_frame (void)
+  {
+    if (m_curr_frame > 0)
+      m_curr_frame = 0;
+  }
+
+  std::list<stack_frame *>
+  call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const
+  {
+    std::list<stack_frame *> frames;
+
+    // curr_frame is the index to the current frame in the overall call
+    // stack, which includes any compiled function frames and scope
+    // frames.  The curr_user_frame value we set is the index into the
+    // subset of frames returned in the octave_map object.
+
+    size_t curr_frame = find_current_user_frame ();
+
+    // Don't include top-level stack frame in the list.
+
+    for (size_t n = m_cs.size () - 1; n > 0; n--)
+      {
+        stack_frame *frm = m_cs[n];
+
+        if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
+            || frm->is_scope_frame ())
+          {
+            if (frm->index () == curr_frame)
+              curr_user_frame = frames.size ();
+
+            frames.push_back (frm);
+          }
+
+        if (n == 0)
+          break;
+      }
+
+    return frames;
+  }
+
+  std::list<stack_frame *>
+  call_stack::backtrace_frames (void) const
+  {
+    octave_idx_type curr_user_frame = -1;
+
+    return backtrace_frames (curr_user_frame);
+  }
+
+  octave_map call_stack::backtrace (octave_idx_type& curr_user_frame,
+                                    bool print_subfn) const
+  {
+    std::list<stack_frame *> frames = backtrace_frames (curr_user_frame);
 
     size_t nframes = frames.size ();
 
@@ -650,82 +634,460 @@
     Cell& name = retval.contents (1);
     Cell& line = retval.contents (2);
     Cell& column = retval.contents (3);
-    Cell& context = retval.contents (5);
 
     octave_idx_type k = 0;
 
-    for (const auto& frm : frames)
+    for (const auto *frm : frames)
       {
-        context(k) = frm.m_context;
-        file(k)    = frm.fcn_file_name ();
-        name(k)    = frm.fcn_name (print_subfn);
-        line(k)    = frm.m_line;
-        column(k)  = frm.m_column;
+        if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
+            || frm->is_scope_frame ())
+          {
+            file(k) = frm->fcn_file_name ();
+            name(k) = frm->fcn_name (print_subfn);
+            line(k) = frm->line ();
+            column(k) = frm->column ();
 
-        k++;
+            k++;
+          }
       }
 
     return retval;
   }
 
-  octave_map
-  call_stack::backtrace (size_t nskip)
+  octave_map call_stack::backtrace (void) const
   {
     octave_idx_type curr_user_frame = -1;
 
-    return backtrace (nskip, curr_user_frame, true);
+    return backtrace (curr_user_frame, true);
   }
 
-  octave_map
-  call_stack::empty_backtrace (void) const
+  octave_map call_stack::empty_backtrace (void) const
   {
     return octave_map (dim_vector (0, 1), bt_fields);
   }
 
-  void
-  call_stack::pop (void)
+  void call_stack::pop (void)
   {
-    if (cs.size () > 1)
+    // Never pop top scope.
+    // FIXME: is it possible for this case to happen?
+
+    if (m_cs.size () > 1)
       {
-        const stack_frame& elt = cs.back ();
-        curr_frame = elt.m_prev;
-        cs.pop_back ();
-        const stack_frame& new_elt = cs[curr_frame];
+        stack_frame *elt = m_cs.back ();
+
+        stack_frame *caller = elt->static_link ();
 
-        symbol_table& symtab = m_interpreter.get_symbol_table ();
+        m_curr_frame = caller->index ();
 
-        symtab.set_scope_and_context (new_elt.m_scope, new_elt.m_context);
+        m_cs.pop_back ();
+
+        delete elt;
       }
   }
 
-  symbol_info_list
-  call_stack::glob_symbol_info (const std::string& pat) const
+  void call_stack::clear (void)
+  {
+    while (! m_cs.empty ())
+      pop ();
+  }
+
+  symbol_info_list call_stack::all_variables (void)
+  {
+    return m_cs[m_curr_frame]->all_variables ();
+  }
+
+  std::list<symbol_record> call_stack::glob (const std::string& pattern) const
+  {
+    return m_cs[m_curr_frame]->glob (pattern);
+  }
+
+  std::list<symbol_record> call_stack::regexp (const std::string& pattern) const
+  {
+    return m_cs[m_curr_frame]->regexp (pattern);
+  }
+
+  std::list<std::string> call_stack::variable_names (void) const
+  {
+    return m_cs[m_curr_frame]->variable_names ();
+  }
+
+  std::list<std::string> call_stack::global_variable_names (void) const
   {
-    return cs[curr_frame].glob_symbol_info (pat);
+    std::list<std::string> retval;
+
+    for (const auto& nm_ov : m_global_values)
+      {
+        if (nm_ov.second.is_defined ())
+          retval.push_back (nm_ov.first);
+      }
+
+    retval.sort ();
+
+    return retval;
+  }
+
+  void call_stack::clear_global_variable (const std::string& name)
+  {
+    auto p = m_global_values.find (name);
+
+    if (p != m_global_values.end ())
+      p->second = octave_value ();
+  }
+
+  void call_stack::clear_global_variable_pattern (const std::string& pattern)
+  {
+    glob_match pat (pattern);
+
+    for (auto& nm_ov : m_global_values)
+      {
+        if (pat.match (nm_ov.first))
+          nm_ov.second = octave_value ();
+      }
+  }
+
+  void call_stack::clear_global_variable_regexp (const std::string& pattern)
+  {
+    octave::regexp pat (pattern);
+
+    for (auto& nm_ov : m_global_values)
+      {
+        if (pat.is_match (nm_ov.first))
+          nm_ov.second = octave_value ();
+      }
+  }
+
+  void call_stack::clear_global_variables (void)
+  {
+    for (auto& nm_ov : m_global_values)
+      nm_ov.second = octave_value ();
   }
 
   symbol_info_list
-  call_stack::regexp_symbol_info (const std::string& pat) const
+  call_stack::glob_symbol_info (const std::string& pattern) const
   {
-    return cs[curr_frame].glob_symbol_info (pat);
+    return m_cs[m_curr_frame]->glob_symbol_info (pattern);
   }
 
-  symbol_info_list call_stack::get_symbol_info (void) const
+  symbol_info_list
+  call_stack::regexp_symbol_info (const std::string& pattern) const
   {
-    return cs[curr_frame].get_symbol_info ();
+    return m_cs[m_curr_frame]->glob_symbol_info (pattern);
+  }
+
+  symbol_info_list call_stack::get_symbol_info (void)
+  {
+    return m_cs[m_curr_frame]->get_symbol_info ();
   }
 
   symbol_info_list call_stack::top_scope_symbol_info (void) const
   {
-    return cs[0].get_symbol_info ();
+    return m_cs[0]->get_symbol_info ();
   }
 
-  octave_value
-  call_stack::max_stack_depth (const octave_value_list& args, int nargout)
+  octave_value call_stack::max_stack_depth (const octave_value_list& args,
+                                            int nargout)
   {
     return set_internal_variable (m_max_stack_depth, args, nargout,
                                   "max_stack_depth", 0);
   }
+
+  void call_stack::make_persistent (const symbol_record& sym)
+  {
+    m_cs[m_curr_frame]->make_persistent (sym);
+  }
+
+  void call_stack::make_global (const symbol_record& sym)
+  {
+    m_cs[m_curr_frame]->make_global (sym);
+  }
+
+  octave_value call_stack::global_varval (const std::string& name) const
+  {
+    auto p = m_global_values.find (name);
+
+    return p == m_global_values.end () ? octave_value () : p->second;
+  }
+
+  octave_value& call_stack::global_varref (const std::string& name)
+  {
+    return m_global_values[name];
+  }
+
+  octave_value call_stack::get_top_level_value (const std::string& name) const
+  {
+    return m_cs[0]->varval (name);
+  }
+
+  void call_stack::set_top_level_value (const std::string& name,
+                                        const octave_value& value)
+  {
+    m_cs[0]->assign (name, value);
+  }
+
+  octave_value call_stack::do_who (int argc, const string_vector& argv,
+                                   bool return_list, bool verbose)
+  {
+    octave_value retval;
+
+    std::string my_name = argv[0];
+
+    std::string file_name;
+
+    bool from_file = false;
+    bool global_only = false;
+    bool have_regexp = false;
+
+    int i = 1;
+    while (i < argc)
+      {
+        if (argv[i] == "-file")
+          {
+            if (from_file)
+              error ("%s: -file option may only be specified once",
+                     my_name.c_str ());
+
+            from_file = true;
+
+            if (i == argc - 1)
+              error ("%s: -file argument must be followed by a filename",
+                     my_name.c_str ());
+
+            file_name = argv[++i];
+          }
+        else if (argv[i] == "-regexp")
+          {
+            have_regexp = true;
+          }
+        else if (argv[i] == "global")
+          global_only = true;
+        else if (argv[i][0] == '-')
+          warning ("%s: unrecognized option '%s'", my_name.c_str (),
+                   argv[i].c_str ());
+        else
+          break;
+
+        i++;
+      }
+
+    int npatterns = argc - i;
+    string_vector patterns;
+    if (npatterns > 0)
+      {
+        patterns.resize (npatterns);
+        for (int j = 0; j < npatterns; j++)
+          patterns[j] = argv[i+j];
+      }
+    else
+      {
+        patterns.resize (1);
+        patterns[0] = "*";
+      }
+
+    if (from_file)
+      {
+        // FIXME: This is an inefficient manner to implement this as the
+        // variables are loaded in to a temporary context and then treated.
+        // It would be better to refactor symbol_info_list to not store the
+        // symbol records and then use it in load-save.cc (do_load) to
+        // implement this option there so that the variables are never
+        // stored at all.
+
+        unwind_protect frame;
+
+        // Set up temporary scope.
+
+        symbol_scope tmp_scope ("$dummy_scope$");
+
+        push (tmp_scope);
+        frame.add_method (*this, &call_stack::pop);
+
+        feval ("load", octave_value (file_name), 0);
+
+        std::string newmsg = "Variables in the file " + file_name + ":\n\n";
+
+        if (global_only)
+          return do_global_who_two (patterns, have_regexp, return_list,
+                                    verbose, newmsg);
+        else
+          return do_who_two (patterns, have_regexp, return_list, verbose,
+                             newmsg);
+      }
+    else
+      {
+        if (global_only)
+          return do_global_who_two (patterns, have_regexp, return_list,
+                                    verbose);
+        else
+          return do_who_two (patterns, have_regexp, return_list, verbose);
+      }
+  }
+
+  octave_value call_stack::do_who_two (const string_vector& patterns,
+                                       bool have_regexp, bool return_list,
+                                       bool verbose, const std::string& msg)
+  {
+    symbol_info_accumulator sym_inf_accum (patterns, have_regexp);
+
+    m_cs[m_curr_frame]->accept (sym_inf_accum);
+
+    if (return_list)
+      {
+        if (verbose)
+          return sym_inf_accum.map_value ();
+        else
+          return Cell (string_vector (sym_inf_accum.names ()));
+      }
+    else if (! sym_inf_accum.is_empty ())
+      {
+
+        if (msg.empty ())
+          octave_stdout << "Variables visible from the current scope:\n";
+        else
+          octave_stdout << msg;
+
+        if (verbose)
+          sym_inf_accum.display (octave_stdout,
+                                 m_evaluator.whos_line_format ());
+        else
+          {
+            octave_stdout << "\n";
+            string_vector names (sym_inf_accum.names ());
+            names.list_in_columns (octave_stdout);
+          }
+
+        octave_stdout << "\n";
+      }
+
+    return octave_value ();
+  }
+
+  octave_value call_stack::do_global_who_two (const string_vector& patterns,
+                                              bool have_regexp,
+                                              bool return_list, bool verbose,
+                                              const std::string& msg)
+  {
+    symbol_info_list symbol_stats;
+    std::list<std::string> symbol_names;
+
+    octave_idx_type npatterns = patterns.numel ();
+
+    for (octave_idx_type j = 0; j < npatterns; j++)
+      {
+        std::string pattern = patterns[j];
+
+        std::list<std::string> tmp;
+
+        if (have_regexp)
+          {
+            octave::regexp pat (pattern);
+
+            for (auto& nm_ov : m_global_values)
+              {
+                if (pat.is_match (nm_ov.first))
+                  tmp.push_back (nm_ov.first);
+              }
+          }
+        else
+          {
+            glob_match pat (pattern);
+
+            for (auto& nm_ov : m_global_values)
+              {
+                if (pat.match (nm_ov.first))
+                  tmp.push_back (nm_ov.first);
+              }
+          }
+
+        for (const auto& nm : tmp)
+          {
+            octave_value value = m_global_values[nm];
+
+            if (value.is_defined ())
+              {
+                if (verbose)
+                  {
+                    bool is_formal = false;
+                    bool is_global = true;
+                    bool is_persistent = false;
+
+                    symbol_info
+                      syminf (nm, value, is_formal,
+                              is_global, is_persistent);
+
+                    symbol_stats.append (syminf);
+                  }
+                else
+                  symbol_names.push_back (nm);
+              }
+          }
+      }
+
+    if (return_list)
+      {
+        if (verbose)
+          {
+            std::string caller_function_name;
+            octave_function *caller_function = caller ();
+            if (caller_function)
+              caller_function_name = caller_function->name ();
+
+            return symbol_stats.map_value (caller_function_name, 1);
+          }
+        else
+          return Cell (string_vector (symbol_names));
+      }
+    else if (! (symbol_stats.empty () && symbol_names.empty ()))
+      {
+        if (msg.empty ())
+          octave_stdout << "Global variables:\n\n";
+        else
+          octave_stdout << msg;
+
+        if (verbose)
+          symbol_stats.display (octave_stdout,
+                                m_evaluator.whos_line_format ());
+        else
+          {
+            string_vector names (symbol_names);
+
+            names.list_in_columns (octave_stdout);
+          }
+
+        octave_stdout << "\n";
+      }
+
+    return octave_value ();
+  }
+
+  void call_stack::clear_current_frame_values (void)
+  {
+    m_cs[m_curr_frame]->clear_values ();
+  }
+
+  void call_stack::display (void) const
+  {
+    std::ostream& os = octave_stdout;
+
+    size_t nframes = size ();
+
+    for (size_t i = 0; i < nframes; i++)
+      {
+        m_cs[i]->display (false);
+        if (i < nframes - 1)
+          os << std::endl;
+      }
+  }
+
+  void call_stack::set_auto_fcn_var (stack_frame::auto_var_type avt,
+                                     const octave_value& val)
+  {
+    m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);
+  }
+
+  octave_value call_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const
+  {
+    return m_cs[m_curr_frame]->get_auto_fcn_var (avt);
+  }
 }
 
 DEFMETHOD (max_stack_depth, interp, args, nargout,
@@ -746,9 +1108,9 @@
 @seealso{max_recursion_depth}
 @end deftypefn */)
 {
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  return cs.max_stack_depth (args, nargout);
+  return tw.max_stack_depth (args, nargout);
 }
 
 /*
@@ -763,193 +1125,6 @@
 %!error (max_stack_depth (1, 2))
 */
 
-static octave_value
-do_who_two (octave::interpreter& interp, const string_vector& pats,
-            bool global_only, bool have_regexp, bool return_list,
-            bool verbose = false, std::string msg = "")
-{
-  octave::symbol_info_list symbol_stats;
-  std::list<std::string> symbol_names;
-
-  octave::tree_evaluator& tw = interp.get_evaluator ();
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  octave::symbol_record::context_id context = scope.current_context ();
-
-  octave_idx_type npats = pats.numel ();
-
-  for (octave_idx_type j = 0; j < npats; j++)
-    {
-      std::string pat = pats[j];
-
-      std::list<octave::symbol_record> tmp
-        = (have_regexp
-           ? (global_only
-              ? symtab.regexp_global_variables (pat)
-              : symtab.regexp_variables (pat))
-           : (global_only
-              ? symtab.glob_global_variables (pat)
-              : symtab.glob_variables (pat)));
-
-      for (const auto& sr : tmp)
-        {
-          octave_value value = sr.varval (context);
-
-          if (value.is_defined ())
-            {
-              if (verbose)
-                {
-                  octave::symbol_info
-                    syminf (sr.name (), value, sr.is_automatic (),
-                            value.iscomplex (), sr.is_formal (),
-                            sr.is_global (), sr.is_persistent ());
-
-                  symbol_stats.append (syminf);
-                }
-              else
-                symbol_names.push_back (sr.name ());
-            }
-        }
-    }
-
-  if (return_list)
-    {
-      if (verbose)
-        {
-          octave::call_stack& cs = interp.get_call_stack ();
-
-          std::string caller_function_name;
-          octave_function *caller = cs.caller ();
-          if (caller)
-            caller_function_name = caller->name ();
-
-          return symbol_stats.map_value (caller_function_name, 1);
-        }
-      else
-        return Cell (string_vector (symbol_names));
-    }
-  else if (! (symbol_stats.empty () && symbol_names.empty ()))
-    {
-      if (msg.empty ())
-        if (global_only)
-          octave_stdout << "Global variables:\n\n";
-        else
-          octave_stdout << "Variables in the current scope:\n\n";
-      else
-        octave_stdout << msg;
-
-      if (verbose)
-        symbol_stats.display (octave_stdout, tw.whos_line_format ());
-      else
-        {
-          string_vector names (symbol_names);
-
-          names.list_in_columns (octave_stdout);
-        }
-
-      octave_stdout << "\n";
-    }
-
-  return octave_value ();
-}
-
-static octave_value
-do_who (octave::interpreter& interp, int argc, const string_vector& argv,
-        bool return_list, bool verbose = false)
-{
-  octave_value retval;
-
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  std::string my_name = argv[0];
-
-  std::string file_name;
-
-  bool from_file = false;
-  bool global_only = false;
-  bool have_regexp = false;
-
-  int i = 1;
-  while (i < argc)
-    {
-      if (argv[i] == "-file")
-        {
-          if (from_file)
-            error ("%s: -file option may only be specified once",
-                   my_name.c_str ());
-
-          from_file = true;
-
-          if (i == argc - 1)
-            error ("%s: -file argument must be followed by a filename",
-                   my_name.c_str ());
-
-          file_name = argv[++i];
-        }
-      else if (argv[i] == "-regexp")
-        {
-          have_regexp = true;
-        }
-      else if (argv[i] == "global")
-        global_only = true;
-      else if (argv[i][0] == '-')
-        warning ("%s: unrecognized option '%s'", my_name.c_str (),
-                 argv[i].c_str ());
-      else
-        break;
-
-      i++;
-    }
-
-  int npats = argc - i;
-  string_vector pats;
-  if (npats > 0)
-    {
-      pats.resize (npats);
-      for (int j = 0; j < npats; j++)
-        pats[j] = argv[i+j];
-    }
-  else
-    {
-      pats.resize (1);
-      pats[0] = "*";
-    }
-
-  if (from_file)
-    {
-      // FIXME: This is an inefficient manner to implement this as the
-      // variables are loaded in to a temporary context and then treated.
-      // It would be better to refactor symbol_info_list to not store the
-      // symbol records and then use it in load-save.cc (do_load) to
-      // implement this option there so that the variables are never
-      // stored at all.
-
-      octave::unwind_protect frame;
-
-      // Set up temporary scope.
-
-      octave::symbol_scope tmp_scope ("$dummy_scope$");
-
-      symtab.set_scope (tmp_scope);
-
-      cs.push (tmp_scope, 0);
-      frame.add_method (cs, &octave::call_stack::pop);
-
-      octave::feval ("load", octave_value (file_name), 0);
-
-      std::string newmsg = "Variables in the file " + file_name + ":\n\n";
-
-      return do_who_two (interp, pats, global_only, have_regexp,
-                         return_list, verbose, newmsg);
-    }
-  else
-    return do_who_two (interp, pats, global_only, have_regexp,
-                       return_list, verbose);
-}
-
 DEFMETHOD (who, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} who
@@ -989,13 +1164,16 @@
 
   string_vector argv = args.make_argv ("who");
 
-  return do_who (interp, argc, argv, nargout == 1);
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  return tw.do_who (argc, argv, nargout == 1);
 }
 
 /*
 %!test
 %! avar = magic (4);
 %! ftmp = [tempname() ".mat"];
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   save (ftmp, "avar");
 %!   vars = whos ("-file", ftmp);
@@ -1032,10 +1210,6 @@
 @item blank
 Variable in local scope
 
-@item @code{a}
-Automatic variable.  An automatic variable is one created by the
-interpreter, for example @code{argn}.
-
 @item @code{c}
 Variable of complex type.
 
@@ -1078,5 +1252,7 @@
 
   string_vector argv = args.make_argv ("whos");
 
-  return do_who (interp, argc, argv, nargout == 1, true);
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  return tw.do_who (argc, argv, nargout == 1, true);
 }
--- a/libinterp/corefcn/call-stack.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/call-stack.h	Fri Jul 12 12:14:43 2019 -0400
@@ -35,11 +35,12 @@
 class octave_value;
 class octave_value_list;
 
+#include "stack-frame.h"
 #include "symscope.h"
 
 namespace octave
 {
-  class interpreter;
+  class tree_evaluator;
   class symbol_info_list;
   class unwind_protect;
 
@@ -49,76 +50,25 @@
   {
   public:
 
-    class stack_frame
-    {
-    public:
-
-      friend class call_stack;
+    typedef std::deque<stack_frame *> stack_frames;
 
-      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_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_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; }
-
-      int column (void) const { return m_column; }
-
-      std::string fcn_file_name (void) const;
+    typedef stack_frames::iterator iterator;
+    typedef stack_frames::const_iterator const_iterator;
 
-      std::string fcn_name (bool print_subfn = true) const;
-
-      bool operator == (const stack_frame& rhs) const;
-
-      symbol_info_list
-      make_symbol_info_list (const std::list<symbol_record>& srl) const;
-
-      symbol_info_list glob_symbol_info (const std::string& pat) const;
-
-      symbol_info_list regexp_symbol_info (const std::string& pat) const;
-
-      symbol_info_list get_symbol_info (void) const;
-
-    private:
+    typedef stack_frames::reverse_iterator reverse_iterator;
+    typedef stack_frames::const_reverse_iterator const_reverse_iterator;
 
-      octave_function *m_fcn;
-      unwind_protect *m_unwind_protect_frame;
-      int m_line;
-      int m_column;
-      symbol_scope m_scope;
-      symbol_record::context_id m_context;
-      size_t m_prev;
-    };
-
-    typedef std::deque<stack_frame>::iterator iterator;
-    typedef std::deque<stack_frame>::const_iterator const_iterator;
-
-    typedef std::deque<stack_frame>::reverse_iterator reverse_iterator;
-    typedef std::deque<stack_frame>::const_reverse_iterator const_reverse_iterator;
-
-    call_stack (interpreter& interp);
+    call_stack (tree_evaluator& evaluator);
 
     // Current function (top of stack).
     octave_function * current (void) const
     {
       octave_function *retval = nullptr;
 
-      if (! cs.empty ())
+      if (! m_cs.empty ())
         {
-          const stack_frame& elt = cs[curr_frame];
-          retval = elt.m_fcn;
+          const stack_frame *elt = m_cs[m_curr_frame];
+          retval = elt->function ();
         }
 
       return retval;
@@ -134,25 +84,39 @@
 
     octave_function * caller (void) const
     {
-      return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn;
+      return (m_curr_frame > 1
+              ? m_cs[m_curr_frame-1]->function () : m_cs[0]->function ());
     }
 
-    size_t current_frame (void) const { return curr_frame; }
+    size_t current_frame (void) const { return m_curr_frame; }
+
+    size_t size (void) const { return m_cs.size (); }
+
+    const stack_frame& get_current_stack_frame (void) const
+    {
+      return *(m_cs[m_curr_frame]);
+    }
 
-    size_t size (void) const { return cs.size (); }
+    stack_frame& get_current_stack_frame (void)
+    {
+      return *(m_cs[m_curr_frame]);
+    }
 
-    size_t num_user_code_frames (octave_idx_type& curr_user_frame) const;
+    symbol_scope top_scope (void) const
+    {
+      return m_cs[0]->get_scope ();
+    }
 
     symbol_scope current_scope (void) const
     {
-      return (curr_frame > 0 && curr_frame < cs.size ()
-              ? cs[curr_frame].m_scope : symbol_scope ());
+      // FIXME: Can m_curr_frame ever be invalid?
+      return (m_curr_frame < m_cs.size ()
+              ? m_cs[m_curr_frame]->get_scope () : symbol_scope ());
     }
 
-    symbol_record::context_id current_context (void) const
+    bool at_top_level (void) const
     {
-      return (curr_frame > 0 && curr_frame < cs.size ()
-              ? cs[curr_frame].m_context : 0);
+      return current_scope () == top_scope ();
     }
 
     // Function at location N on the call stack (N == 0 is current), may
@@ -161,25 +125,25 @@
     {
       octave_function *retval = nullptr;
 
-      if (cs.size () > n)
+      if (m_cs.size () > n)
         {
-          stack_frame& elt = cs[n];
-          retval = elt.m_fcn;
+          stack_frame *elt = m_cs[n];
+          retval = elt->function ();
         }
 
       return retval;
     }
 
     // User code caller.
-    octave_user_code * caller_user_code (size_t nskip = 0) const;
+    octave_user_code * current_user_code (void) const;
 
-    unwind_protect *curr_fcn_unwind_protect_frame (void) const;
+    unwind_protect * curr_fcn_unwind_protect_frame (void) const;
 
     // Line in user code caller.
-    int caller_user_code_line (void) const;
+    int current_user_code_line (void) const;
 
     // Column in user code caller.
-    int caller_user_code_column (void) const;
+    int current_user_code_column (void) const;
 
     // Current function that we are debugging.
     octave_user_code * debug_user_code (void) const;
@@ -190,48 +154,56 @@
     // Column number in current function that we are debugging.
     int debug_user_code_column (void) const;
 
+    std::string get_dispatch_class (void) const;
+
+    void set_dispatch_class (const std::string& class_name);
+
+    bool is_class_method_executing (std::string& dispatch_class) const;
+
+    bool is_class_constructor_executing (std::string& dispatch_class) const;
+
     // Return TRUE if all elements on the call stack are scripts.
     bool all_scripts (void) const;
 
-    void push (octave_function *fcn = nullptr,
-               unwind_protect *up_frame = nullptr);
+    stack_frame * get_static_link (size_t prev_frame) const;
+
+    void push (const symbol_scope& scope);
 
-    void push (octave_function *fcn, unwind_protect *up_frame,
-               const symbol_scope& scope, symbol_record::context_id context);
+    void push (octave_user_function *fcn, unwind_protect *up_frame,
+               stack_frame *closure_frames = nullptr);
 
-    void push (const symbol_scope& scope, symbol_record::context_id context)
-    {
-      push (nullptr, nullptr, scope, context);
-    }
+    void push (octave_user_script *script, unwind_protect *up_frame);
+
+    void push (octave_function *fcn);
 
     void set_location (int l, int c)
     {
-      if (! cs.empty ())
+      if (! m_cs.empty ())
         {
-          stack_frame& elt = cs.back ();
+          stack_frame *elt = m_cs.back ();
 
-          elt.m_line = l;
-          elt.m_column = c;
+          elt->line (l);
+          elt->column (c);
         }
     }
 
     void set_line (int l)
     {
-      if (! cs.empty ())
+      if (! m_cs.empty ())
         {
-          stack_frame& elt = cs.back ();
+          stack_frame *elt = m_cs.back ();
 
-          elt.m_line = l;
+          elt->line (l);
         }
     }
 
     void set_column (int c)
     {
-      if (! cs.empty ())
+      if (! m_cs.empty ())
         {
-          stack_frame& elt = cs.back ();
+          stack_frame *elt = m_cs.back ();
 
-          elt.m_column = c;
+          elt->column (c);
         }
     }
 
@@ -242,62 +214,113 @@
       goto_frame (n);
     }
 
-    bool goto_frame_relative (int n, bool verbose = false);
+    size_t find_current_user_frame (void) const;
+    stack_frame *current_user_frame (void) const;
+
+    size_t dbupdown (size_t start, int n, bool verbose);
+    size_t dbupdown (int n = -1, bool verbose = false);
 
     void goto_caller_frame (void);
 
     void goto_base_frame (void);
 
-    std::list<call_stack::stack_frame>
-    backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
+    std::list<stack_frame *>
+    backtrace_frames (octave_idx_type& curr_user_frame) const;
 
-    std::list<call_stack::stack_frame>
-    backtrace_frames (size_t nskip = 0) const
-    {
-      octave_idx_type curr_user_frame = -1;
+    std::list<stack_frame *> backtrace_frames (void) const;
 
-      return backtrace_frames (nskip, curr_user_frame);
-    }
-
-    octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
+    octave_map backtrace (octave_idx_type& curr_user_frame,
                           bool print_subfn = true) const;
 
-    octave_map backtrace (size_t nskip = 0);
+    octave_map backtrace (void) const;
 
     octave_map empty_backtrace (void) const;
 
     void pop (void);
 
-    void clear (void) { cs.clear (); }
+    void clear (void);
+
+    symbol_info_list all_variables (void);
+
+    std::list<symbol_record> glob (const std::string& pattern) const;
 
-    symbol_info_list glob_symbol_info (const std::string& pat) const;
+    std::list<symbol_record> regexp (const std::string& pattern) const;
+
+    std::list<std::string> variable_names (void) const;
+
+    std::list<std::string> global_variable_names (void) const;
 
-    symbol_info_list regexp_symbol_info (const std::string& pat) const;
+    void clear_global_variable (const std::string& name);
+
+    void clear_global_variable_pattern (const std::string& pattern);
+
+    void clear_global_variable_regexp(const std::string& pattern);
 
-    symbol_info_list get_symbol_info (void) const;
+    void clear_global_variables (void);
+
+    symbol_info_list glob_symbol_info (const std::string& pattern) const;
+
+    symbol_info_list regexp_symbol_info (const std::string& pattern) const;
+
+    symbol_info_list get_symbol_info (void);
 
     symbol_info_list top_scope_symbol_info (void) const;
 
     octave_value max_stack_depth (const octave_value_list& args, int nargout);
 
+    void make_persistent (const symbol_record& sym);
+
+    void make_global (const symbol_record& sym);
+
+    octave_value global_varval (const std::string& name) const;
+
+    octave_value& global_varref (const std::string& name);
+
+    octave_value get_top_level_value (const std::string& name) const;
+
+    void set_top_level_value (const std::string& name,
+                              const octave_value& value);
+
+    octave_value do_who (int argc, const string_vector& argv,
+                         bool return_list, bool verbose = false);
+
+    octave_value do_who_two (const string_vector& patterns, bool have_regexp,
+                             bool return_list, bool verbose,
+                             const std::string& msg = "");
+
+    octave_value do_global_who_two (const string_vector& patterns,
+                                    bool have_regexp, bool return_list,
+                                    bool verbose, const std::string& msg = "");
+
+    void clear_current_frame_values (void);
+
+    void display (void) const;
+
+    void set_auto_fcn_var (stack_frame::auto_var_type avt,
+                           const octave_value& val);
+
+    octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;
+
   private:
 
+    tree_evaluator& m_evaluator;
+
     // The current call stack.
-    std::deque<stack_frame> cs;
+    // FIXME: maybe we should be using a std::shared_ptr to manage the
+    // individual stack frames?
+    stack_frames m_cs;
 
-    size_t curr_frame;
+    // FIXME: Could we eliminate this varaible and manage the current
+    // frame in the evaluator class instead?  The current frame might
+    // always be the top of the stack.  Restoring the previous/current
+    // frame would be managed by other means, such as an
+    // unwind_protect frame.
+    size_t m_curr_frame;
 
     int m_max_stack_depth;
 
-    interpreter& m_interpreter;
+    std::map<std::string, octave_value> m_global_values;
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::call_stack' instead")
-typedef octave::call_stack octave_call_stack;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/cdisplay.c	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/cdisplay.c	Fri Jul 12 12:14:43 2019 -0400
@@ -55,6 +55,9 @@
 
   *dpy_avail = 0;
 
+  double ht_mm = 0.0;
+  double wd_mm = 0.0;
+
 #if defined (OCTAVE_USE_WINDOWS_API)
 
   octave_unused_parameter (dpy_name);
@@ -68,11 +71,8 @@
       *ht = GetDeviceCaps (hdc, VERTRES);
       *wd = GetDeviceCaps (hdc, HORZRES);
 
-      double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
-      double wd_mm = GetDeviceCaps (hdc, HORZSIZE);
-
-      *rx = *wd * 25.4 / wd_mm;
-      *ry = *ht * 25.4 / ht_mm;
+      ht_mm = GetDeviceCaps (hdc, VERTSIZE);
+      wd_mm = GetDeviceCaps (hdc, HORZSIZE);
 
       *dpy_avail = 1;
     }
@@ -118,11 +118,8 @@
          values, but the CGFloat typedef is not present on older
          systems, so use double instead.  */
 
-      double ht_mm = sz_mm.height;
-      double wd_mm = sz_mm.width;
-
-      *rx = *wd * 25.4 / wd_mm;
-      *ry = *ht * 25.4 / ht_mm;
+      ht_mm = sz_mm.height;
+      wd_mm = sz_mm.width;
 
       *dpy_avail = 1;
     }
@@ -149,11 +146,8 @@
 
           int screen_number = XScreenNumberOfScreen (screen);
 
-          double ht_mm = DisplayHeightMM (display, screen_number);
-          double wd_mm = DisplayWidthMM (display, screen_number);
-
-          *rx = *wd * 25.4 / wd_mm;
-          *ry = *ht * 25.4 / ht_mm;
+          ht_mm = DisplayHeightMM (display, screen_number);
+          wd_mm = DisplayWidthMM (display, screen_number);
         }
       else
         msg = "X11 display has no default screen";
@@ -178,5 +172,26 @@
 
 #endif
 
+  if (*dpy_avail)
+    {
+      if (wd_mm == 0 || ht_mm == 0)
+        {
+          msg = "screen width or height reported to be zero";
+
+          // Sizes reported as zero have been found on some systems.
+          // For example, X/Wayland running inside virtualbox.
+
+          // Guess a DPI.
+
+          *rx = 96.0;
+          *ry = 96.0;
+        }
+      else
+        {
+          *rx = *wd * 25.4 / wd_mm;
+          *ry = *ht * 25.4 / ht_mm;
+        }
+    }
+
   return msg;
 }
--- a/libinterp/corefcn/cellfun.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/cellfun.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -39,6 +39,7 @@
 #include "Cell.h"
 #include "oct-map.h"
 #include "defun.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "parse.h"
 #include "variables.h"
@@ -65,7 +66,8 @@
 #include "ov-fcn-handle.h"
 
 static octave_value_list
-get_output_list (octave_idx_type count, octave_idx_type nargout,
+get_output_list (octave::error_system& es,
+                 octave_idx_type count, octave_idx_type nargout,
                  const octave_value_list& inputlist,
                  octave_value& func,
                  octave_value& error_handler)
@@ -95,8 +97,8 @@
       if (error_handler.is_defined ())
         {
           octave_scalar_map msg;
-          msg.assign ("identifier", last_error_id ());
-          msg.assign ("message", last_error_message ());
+          msg.assign ("identifier", es.last_error_id ());
+          msg.assign ("message", es.last_error_message ());
           msg.assign ("index",
                       static_cast<double> (count
                                            + static_cast<octave_idx_type> (1)));
@@ -104,7 +106,7 @@
           octave_value_list errlist = inputlist;
           errlist.prepend (msg);
 
-          buffer_error_messages--;
+          es.buffer_error_messages (es.buffer_error_messages () - 1);
 
           tmp = octave::feval (error_handler, errlist, nargout);
         }
@@ -426,17 +428,7 @@
       std::string name = args(0).string_value ();
 
       if (! octave::valid_identifier (name))
-        {
-          std::string fcn_name = unique_symbol_name ("__cellfun_fcn__");
-          std::string fname = "function y = " + fcn_name + "(x) y = ";
-
-          octave_function *ptr_func
-            = extract_function (args(0), "cellfun", fcn_name,
-                                fname, "; endfunction");
-
-          if (ptr_func)
-            func = octave_value (ptr_func, true);
-        }
+        func = octave::get_function_handle (interp, args(0), "x");
       else
         {
           func = symtab.find_function (name);
@@ -461,6 +453,11 @@
   {
     if (func.is_function_handle ())
       {
+        // We can't check for overloads now.  Is there something else we
+        // should be doing instead?
+        goto nevermind;
+
+#if 0
         octave_fcn_handle *f = func.fcn_handle_value ();
 
         // Overloaded function handles need to check the type of the
@@ -468,6 +465,7 @@
         // optimized this way.
         if (f -> is_overloaded ())
           goto nevermind;
+#endif
       }
 
     std::string name = func.function_value () -> name ();
@@ -544,11 +542,15 @@
         }
     }
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave::unwind_protect frame;
-  frame.protect_var (buffer_error_messages);
+
+  int bem = es.buffer_error_messages ();
+  frame.add_method (es, &octave::error_system::set_buffer_error_messages, bem);
 
   if (error_handler.is_defined ())
-    buffer_error_messages++;
+    es.buffer_error_messages (bem + 1);
 
   // Apply functions.
 
@@ -569,7 +571,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (count, nargout, inputlist, func,
+            = get_output_list (es, count, nargout, inputlist, func,
                                error_handler);
 
           if (nargout > 0 && tmp.length () < nargout)
@@ -650,7 +652,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (count, nargout, inputlist, func,
+            = get_output_list (es, count, nargout, inputlist, func,
                                error_handler);
 
           if (nargout > 0 && tmp.length () < nargout)
@@ -1141,17 +1143,7 @@
       std::string name = args(0).string_value ();
 
       if (! octave::valid_identifier (name))
-        {
-          std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__");
-          std::string fname = "function y = " + fcn_name + "(x) y = ";
-
-          octave_function *ptr_func
-            = extract_function (args(0), "arrayfun", fcn_name,
-                                fname, "; endfunction");
-
-          if (ptr_func)
-            func = octave_value (ptr_func, true);
-        }
+        func = octave::get_function_handle (interp, args(0), "x");
       else
         {
           func = symtab.find_function (name);
@@ -1176,6 +1168,11 @@
         {
           if (func.is_function_handle ())
             {
+              // We can't check for overloads now.  Is there something
+              // else we should be doing instead?
+              goto nevermind;
+
+#if 0
               octave_fcn_handle *f = func.fcn_handle_value ();
 
               // Overloaded function handles need to check the type of the
@@ -1183,7 +1180,9 @@
               // optimized this way.
               if (f -> is_overloaded ())
                 goto nevermind;
+#endif
             }
+
           octave_value f
             = symtab.find_function (func.function_value () -> name ());
 
@@ -1236,11 +1235,16 @@
             }
         }
 
+      octave::error_system& es = interp.get_error_system ();
+
       octave::unwind_protect frame;
-      frame.protect_var (buffer_error_messages);
+
+      int bem = es.buffer_error_messages ();
+      frame.add_method (es, &octave::error_system::set_buffer_error_messages,
+                        bem);
 
       if (error_handler.is_defined ())
-        buffer_error_messages++;
+        es.buffer_error_messages (bem + 1);
 
       // Apply functions.
 
@@ -1263,7 +1267,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (count, nargout, inputlist, func,
+                = get_output_list (es, count, nargout, inputlist, func,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
@@ -1355,7 +1359,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (count, nargout, inputlist, func,
+                = get_output_list (es, count, nargout, inputlist, func,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
--- a/libinterp/corefcn/daspk.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/daspk.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 
+#include <list>
 #include <string>
 
 #include "DASPK.h"
@@ -31,6 +32,7 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
@@ -43,10 +45,10 @@
 #include "DASPK-opts.cc"
 
 // Global pointer for user defined function required by daspk.
-static octave_function *daspk_fcn;
+static octave_value daspk_fcn;
 
 // Global pointer for optional user defined jacobian function.
-static octave_function *daspk_jac;
+static octave_value daspk_jac;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_fcn_imaginary = false;
@@ -69,7 +71,7 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (daspk_fcn)
+  if (daspk_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -119,7 +121,7 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (daspk_jac)
+  if (daspk_jac.is_defined ())
     {
       octave_value_list tmp;
 
@@ -269,17 +271,19 @@
   frame.protect_var (call_depth);
   call_depth++;
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
   if (call_depth > 1)
     error ("daspk: invalid recursive call");
 
   std::string fcn_name, fname, jac_name, jname;
-  daspk_fcn = nullptr;
-  daspk_jac = nullptr;
+
+  daspk_fcn = octave_value ();
+  daspk_jac = octave_value ();
 
   octave_value f_arg = args(0);
 
+  std::list<std::string> fcn_param_names ({"x", "xdot", "t"});
+  std::list<std::string> jac_param_names ({"x", "xdot", "t", "cj"});
+
   if (f_arg.iscell ())
     {
       Cell c = f_arg.cell_value ();
@@ -287,99 +291,61 @@
         f_arg = c(0);
       else if (c.numel () == 2)
         {
-          if (c(0).is_function_handle () || c(0).is_inline_function ())
-            daspk_fcn = c(0).function_value ();
-          else
-            {
-              fcn_name = unique_symbol_name ("__daspk_fcn__");
-              fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append (" (x, xdot, t) y = ");
-              daspk_fcn = extract_function (c(0), "daspk", fcn_name,
-                                            fname, "; endfunction");
-            }
+          daspk_fcn = octave::get_function_handle (interp, c(0),
+                                                   fcn_param_names);
 
-          if (daspk_fcn)
+          if (daspk_fcn.is_defined ())
             {
-              if (c(1).is_function_handle () || c(1).is_inline_function ())
-                daspk_jac = c(1).function_value ();
-              else
-                {
-                  jac_name = unique_symbol_name ("__daspk_jac__");
-                  jname = "function jac = ";
-                  jname.append (jac_name);
-                  jname.append (" (x, xdot, t, cj) jac = ");
-                  daspk_jac = extract_function (c(1), "daspk", jac_name,
-                                                jname, "; endfunction");
+              daspk_jac = octave::get_function_handle (interp, c(1),
+                                                       jac_param_names);
 
-                  if (! daspk_jac)
-                    {
-                      if (fcn_name.length ())
-                        symtab.clear_function (fcn_name);
-                      daspk_fcn = nullptr;
-                    }
-                }
+              if (daspk_jac.is_undefined ())
+                daspk_fcn = octave_value ();
             }
         }
       else
         error ("daspk: incorrect number of elements in cell array");
     }
 
-  if (! daspk_fcn && ! f_arg.iscell ())
+  if (daspk_fcn.is_undefined () && ! f_arg.iscell ())
     {
       if (f_arg.is_function_handle () || f_arg.is_inline_function ())
-        daspk_fcn = f_arg.function_value ();
+        daspk_fcn = f_arg;
       else
         {
           switch (f_arg.rows ())
             {
             case 1:
-              do
-                {
-                  fcn_name = unique_symbol_name ("__daspk_fcn__");
-                  fname = "function y = ";
-                  fname.append (fcn_name);
-                  fname.append (" (x, xdot, t) y = ");
-                  daspk_fcn = extract_function (f_arg, "daspk", fcn_name,
-                                                fname, "; endfunction");
-                }
-              while (0);
+              daspk_fcn = octave::get_function_handle (interp, f_arg,
+                                                       fcn_param_names);
               break;
 
             case 2:
               {
                 string_vector tmp = f_arg.string_vector_value ();
 
-                fcn_name = unique_symbol_name ("__daspk_fcn__");
-                fname = "function y = ";
-                fname.append (fcn_name);
-                fname.append (" (x, xdot, t) y = ");
-                daspk_fcn = extract_function (tmp(0), "daspk", fcn_name,
-                                              fname, "; endfunction");
+                daspk_fcn = octave::get_function_handle (interp, tmp(0),
+                                                         fcn_param_names);
 
-                if (daspk_fcn)
+                if (daspk_fcn.is_defined ())
                   {
-                    jac_name = unique_symbol_name ("__daspk_jac__");
-                    jname = "function jac = ";
-                    jname.append (jac_name);
-                    jname.append (" (x, xdot, t, cj) jac = ");
-                    daspk_jac = extract_function (tmp(1), "daspk", jac_name,
-                                                  jname, "; endfunction");
+                    daspk_jac = octave::get_function_handle (interp, tmp(1),
+                                                             jac_param_names);
 
-                    if (! daspk_jac)
-                      {
-                        if (fcn_name.length ())
-                          symtab.clear_function (fcn_name);
-                        daspk_fcn = nullptr;
-                      }
+                    if (daspk_jac.is_undefined ())
+                      daspk_fcn = octave_value ();
                   }
               }
+              break;
+
+            default:
+              error ("daspk: first arg should be a string or 2-element string array");
             }
         }
     }
 
-  if (! daspk_fcn)
-    return retval;
+  if (daspk_fcn.is_undefined ())
+    error ("daspk: FCN argument is not a valid function name or handle");
 
   ColumnVector state = args(1).xvector_value ("daspk: initial state X_0 must be a vector");
 
@@ -402,7 +368,7 @@
   double tzero = out_times (0);
 
   DAEFunc func (daspk_user_function);
-  if (daspk_jac)
+  if (daspk_jac.is_defined ())
     func.set_jacobian_function (daspk_user_jacobian);
 
   DASPK dae (state, deriv, tzero, func);
@@ -416,11 +382,6 @@
   else
     output = dae.integrate (out_times, deriv_output);
 
-  if (fcn_name.length ())
-    symtab.clear_function (fcn_name);
-  if (jac_name.length ())
-    symtab.clear_function (jac_name);
-
   std::string msg = dae.error_message ();
 
   if (dae.integration_ok ())
--- a/libinterp/corefcn/dasrt.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/dasrt.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 
+#include <list>
 #include <string>
 
 #include "DASRT.h"
@@ -32,6 +33,7 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
@@ -44,9 +46,9 @@
 #include "DASRT-opts.cc"
 
 // Global pointers for user defined function required by dasrt.
-static octave_function *dasrt_f;
-static octave_function *dasrt_j;
-static octave_function *dasrt_cf;
+static octave_value dasrt_fcn;
+static octave_value dasrt_jac;
+static octave_value dasrt_cf;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_fcn_imaginary = false;
@@ -70,13 +72,13 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (dasrt_f)
+  if (dasrt_fcn.is_defined ())
     {
       octave_value_list tmp;
 
       try
         {
-          tmp = octave::feval (dasrt_f, args, 1);
+          tmp = octave::feval (dasrt_fcn, args, 1);
         }
       catch (octave::execution_exception& e)
         {
@@ -111,7 +113,7 @@
   args(1) = t;
   args(0) = x;
 
-  if (dasrt_cf)
+  if (dasrt_cf.is_defined ())
     {
       octave_value_list tmp;
 
@@ -157,13 +159,13 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (dasrt_j)
+  if (dasrt_jac.is_defined ())
     {
       octave_value_list tmp;
 
       try
         {
-          tmp = octave::feval (dasrt_j, args, 1);
+          tmp = octave::feval (dasrt_jac, args, 1);
         }
       catch (octave::execution_exception& e)
         {
@@ -353,11 +355,10 @@
 
   int argp = 0;
   std::string fcn_name, fname, jac_name, jname;
-  dasrt_f = nullptr;
-  dasrt_j = nullptr;
-  dasrt_cf = nullptr;
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
+  dasrt_fcn = octave_value ();
+  dasrt_jac = octave_value ();
+  dasrt_cf = octave_value ();
 
   // Check all the arguments.  Are they the right animals?
 
@@ -365,6 +366,9 @@
 
   octave_value f_arg = args(0);
 
+  std::list<std::string> fcn_param_names ({"x", "xdot", "t"});
+  std::list<std::string> jac_param_names ({"x", "xdot", "t", "cj"});
+
   if (f_arg.iscell ())
     {
       Cell c = f_arg.cell_value ();
@@ -372,83 +376,49 @@
         f_arg = c(0);
       else if (c.numel () == 2)
         {
-          if (c(0).is_function_handle () || c(0).is_inline_function ())
-            dasrt_f = c(0).function_value ();
-          else
-            {
-              fcn_name = unique_symbol_name ("__dasrt_fcn__");
-              fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append (" (x, xdot, t) y = ");
-              dasrt_f = extract_function (c(0), "dasrt", fcn_name, fname,
-                                          "; endfunction");
-            }
+          dasrt_fcn = octave::get_function_handle (interp, c(0),
+                                                   fcn_param_names);
 
-          if (dasrt_f)
+          if (dasrt_fcn.is_defined ())
             {
-              if (c(1).is_function_handle () || c(1).is_inline_function ())
-                dasrt_j = c(1).function_value ();
-              else
-                {
-                  jac_name = unique_symbol_name ("__dasrt_jac__");
-                  jname = "function jac = ";
-                  jname.append (jac_name);
-                  jname.append (" (x, xdot, t, cj) jac = ");
-                  dasrt_j = extract_function (c(1), "dasrt", jac_name, jname,
-                                              "; endfunction");
+              dasrt_jac = octave::get_function_handle (interp, c(1),
+                                                       jac_param_names);
 
-                  if (! dasrt_j)
-                    {
-                      if (fcn_name.length ())
-                        symtab.clear_function (fcn_name);
-                      dasrt_f = nullptr;
-                    }
-                }
+              if (dasrt_jac.is_undefined ())
+                dasrt_fcn = octave_value ();
             }
         }
       else
         error ("dasrt: incorrect number of elements in cell array");
     }
 
-  if (! dasrt_f && ! f_arg.iscell ())
+  if (dasrt_fcn.is_undefined () && ! f_arg.iscell ())
     {
       if (f_arg.is_function_handle () || f_arg.is_inline_function ())
-        dasrt_f = f_arg.function_value ();
+        dasrt_fcn = f_arg;
       else
         {
           switch (f_arg.rows ())
             {
             case 1:
-              fcn_name = unique_symbol_name ("__dasrt_fcn__");
-              fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append (" (x, xdot, t) y = ");
-              dasrt_f = extract_function (f_arg, "dasrt", fcn_name, fname,
-                                          "; endfunction");
+              dasrt_fcn = octave::get_function_handle (interp, f_arg,
+                                                       fcn_param_names);
               break;
 
             case 2:
               {
-                string_vector tmp = args(0).string_vector_value ();
+                string_vector tmp = f_arg.string_vector_value ();
 
-                fcn_name = unique_symbol_name ("__dasrt_fcn__");
-                fname = "function y = ";
-                fname.append (fcn_name);
-                fname.append (" (x, xdot, t) y = ");
-                dasrt_f = extract_function (tmp(0), "dasrt", fcn_name,
-                                            fname, "; endfunction");
+                dasrt_fcn = octave::get_function_handle (interp, tmp(0),
+                                                         fcn_param_names);
 
-                if (dasrt_f)
+                if (dasrt_fcn.is_defined ())
                   {
-                    jac_name = unique_symbol_name ("__dasrt_jac__");
-                    jname = "function jac = ";
-                    jname.append (jac_name);
-                    jname.append (" (x, xdot, t, cj) jac = ");
-                    dasrt_j = extract_function (tmp(1), "dasrt", jac_name,
-                                                jname, "; endfunction");
+                    dasrt_jac = octave::get_function_handle (interp, tmp(1),
+                                                             jac_param_names);
 
-                    if (! dasrt_j)
-                      dasrt_f = nullptr;
+                    if (dasrt_jac.is_undefined ())
+                      dasrt_fcn = octave_value ();
                   }
               }
               break;
@@ -459,8 +429,8 @@
         }
     }
 
-  if (! dasrt_f)
-    return retval;
+  if (dasrt_fcn.is_undefined ())
+    error ("dasrt: FCN argument is not a valid function name or handle");
 
   DAERTFunc func (dasrt_user_f);
 
@@ -475,19 +445,15 @@
     }
   else
     {
-      if (args(1).is_function_handle () || args(1).is_inline_function ())
-        dasrt_cf = args(1).function_value ();
-      else if (args(1).is_string ())
+      if (args(1).is_function_handle () || args(1).is_inline_function ()
+          || args(1).is_string ())
         {
-          fcn_name = unique_symbol_name ("__dasrt_constraint_fcn__");
-          fname = "function g_out = ";
-          fname.append (fcn_name);
-          fname.append (" (x, t) g_out = ");
-          dasrt_cf = extract_function (args(1), "dasrt", fcn_name, fname,
-                                       "; endfunction");
+          std::list<std::string> cf_param_names ({"x", "t"});
+
+          dasrt_cf = octave::get_function_handle (interp, args(1), cf_param_names);
         }
 
-      if (dasrt_cf)
+      if (dasrt_cf.is_defined ())
         {
           argp++;
 
@@ -518,7 +484,7 @@
       crit_times_set = true;
     }
 
-  if (dasrt_j)
+  if (dasrt_jac.is_defined ())
     func.set_jacobian_function (dasrt_user_j);
 
   DASRT_result output;
@@ -532,11 +498,6 @@
   else
     output = dae.integrate (out_times);
 
-  if (fcn_name.length ())
-    symtab.clear_function (fcn_name);
-  if (jac_name.length ())
-    symtab.clear_function (jac_name);
-
   std::string msg = dae.error_message ();
 
   if (dae.integration_ok ())
--- a/libinterp/corefcn/dassl.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/dassl.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -31,6 +31,7 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
@@ -43,10 +44,10 @@
 #include "DASSL-opts.cc"
 
 // Global pointer for user defined function required by dassl.
-static octave_function *dassl_fcn;
+static octave_value dassl_fcn;
 
 // Global pointer for optional user defined jacobian function.
-static octave_function *dassl_jac;
+static octave_value dassl_jac;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_fcn_imaginary = false;
@@ -69,7 +70,7 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (dassl_fcn)
+  if (dassl_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -119,7 +120,7 @@
   args(1) = xdot;
   args(0) = x;
 
-  if (dassl_jac)
+  if (dassl_jac.is_defined ())
     {
       octave_value_list tmp;
 
@@ -273,14 +274,16 @@
   if (call_depth > 1)
     error ("dassl: invalid recursive call");
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
+  std::string fcn_name, fname, jac_name, jname;
 
-  std::string fcn_name, fname, jac_name, jname;
-  dassl_fcn = nullptr;
-  dassl_jac = nullptr;
+  dassl_fcn = octave_value ();
+  dassl_jac = octave_value ();
 
   octave_value f_arg = args(0);
 
+  std::list<std::string> fcn_param_names ({"x", "xdot", "t"});
+  std::list<std::string> jac_param_names ({"x", "xdot", "t", "cj"});
+
   if (f_arg.iscell ())
     {
       Cell c = f_arg.cell_value ();
@@ -288,100 +291,61 @@
         f_arg = c(0);
       else if (c.numel () == 2)
         {
-          if (c(0).is_function_handle () || c(0).is_inline_function ())
-            dassl_fcn = c(0).function_value ();
-          else
-            {
-              fcn_name = unique_symbol_name ("__dassl_fcn__");
-              fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append (" (x, xdot, t) y = ");
-              dassl_fcn = extract_function (c(0), "dassl", fcn_name, fname,
-                                            "; endfunction");
-            }
+          dassl_fcn = octave::get_function_handle (interp, c(0),
+                                                   fcn_param_names);
 
-          if (dassl_fcn)
+          if (dassl_fcn.is_defined ())
             {
-              if (c(1).is_function_handle () || c(1).is_inline_function ())
-                dassl_jac = c(1).function_value ();
-              else
-                {
-                  jac_name = unique_symbol_name ("__dassl_jac__");
-                  jname = "function jac = ";
-                  jname.append (jac_name);
-                  jname.append (" (x, xdot, t, cj) jac = ");
-                  dassl_jac = extract_function (c(1), "dassl", jac_name,
-                                                jname, "; endfunction");
+              dassl_jac = octave::get_function_handle (interp, c(1),
+                                                       jac_param_names);
 
-                  if (! dassl_jac)
-                    {
-                      if (fcn_name.length ())
-                        symtab.clear_function (fcn_name);
-                      dassl_fcn = nullptr;
-                    }
-                }
+              if (dassl_jac.is_undefined ())
+                dassl_fcn = octave_value ();
             }
         }
       else
         error ("dassl: incorrect number of elements in cell array");
     }
 
-  if (! dassl_fcn && ! f_arg.iscell ())
+  if (dassl_fcn.is_undefined () && ! f_arg.iscell ())
     {
       if (f_arg.is_function_handle () || f_arg.is_inline_function ())
-        dassl_fcn = f_arg.function_value ();
+        dassl_fcn = f_arg;
       else
         {
           switch (f_arg.rows ())
             {
             case 1:
-              do
-                {
-                  fcn_name = unique_symbol_name ("__dassl_fcn__");
-                  fname = "function y = ";
-                  fname.append (fcn_name);
-                  fname.append (" (x, xdot, t) y = ");
-                  dassl_fcn = extract_function (f_arg, "dassl", fcn_name,
-                                                fname, "; endfunction");
-                }
-              while (0);
+              dassl_fcn = octave::get_function_handle (interp, f_arg,
+                                                       fcn_param_names);
               break;
 
             case 2:
               {
                 string_vector tmp = f_arg.string_vector_value ();
 
-                fcn_name = unique_symbol_name ("__dassl_fcn__");
-                fname = "function y = ";
-                fname.append (fcn_name);
-                fname.append (" (x, xdot, t) y = ");
-                dassl_fcn = extract_function (tmp(0), "dassl", fcn_name,
-                                              fname, "; endfunction");
+                dassl_fcn = octave::get_function_handle (interp, tmp(0),
+                                                         fcn_param_names);
 
-                if (dassl_fcn)
+                if (dassl_fcn.is_defined ())
                   {
-                    jac_name = unique_symbol_name ("__dassl_jac__");
-                    jname = "function jac = ";
-                    jname.append (jac_name);
-                    jname.append (" (x, xdot, t, cj) jac = ");
-                    dassl_jac = extract_function (tmp(1), "dassl",
-                                                  jac_name, jname,
-                                                  "; endfunction");
+                    dassl_jac = octave::get_function_handle (interp, tmp(1),
+                                                             jac_param_names);
 
-                    if (! dassl_jac)
-                      {
-                        if (fcn_name.length ())
-                          symtab.clear_function (fcn_name);
-                        dassl_fcn = nullptr;
-                      }
+                    if (dassl_jac.is_undefined ())
+                      dassl_fcn = octave_value ();
                   }
               }
+              break;
+
+            default:
+              error ("dassl: first arg should be a string or 2-element string array");
             }
         }
     }
 
-  if (! dassl_fcn)
-    return retval;
+  if (dassl_fcn.is_undefined ())
+    error ("dassl: FCN argument is not a valid function name or handle");
 
   ColumnVector state = args(1).xvector_value ("dassl: initial state X_0 must be a vector");
 
@@ -404,7 +368,7 @@
   double tzero = out_times (0);
 
   DAEFunc func (dassl_user_function);
-  if (dassl_jac)
+  if (dassl_jac.is_defined ())
     func.set_jacobian_function (dassl_user_jacobian);
 
   DASSL dae (state, deriv, tzero, func);
@@ -419,11 +383,6 @@
   else
     output = dae.integrate (out_times, deriv_output);
 
-  if (fcn_name.length ())
-    symtab.clear_function (fcn_name);
-  if (jac_name.length ())
-    symtab.clear_function (jac_name);
-
   std::string msg = dae.error_message ();
 
   if (dae.integration_ok ())
--- a/libinterp/corefcn/debug.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/debug.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -36,7 +36,6 @@
 #include "dNDArray.h"
 
 #include "bp-table.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
@@ -90,10 +89,13 @@
 @deftypefnx {} {} dbstop in @var{func}
 @deftypefnx {} {} dbstop in @var{func} at @var{line}
 @deftypefnx {} {} dbstop in @var{func} at @var{line} if "@var{condition}"
+@deftypefnx {} {} dbstop in @var{class} at @var{method}
 @deftypefnx {} {} dbstop if @var{event}
 @deftypefnx {} {} dbstop if @var{event} @var{ID}
 @deftypefnx {} {} dbstop (@var{bp_struct})
 @deftypefnx {} {@var{rline} =} dbstop @dots{}
+dbstop in waveClass at waveClass.plotEta
+dbstop waveClass at waveClass.plotEta
 
 Set breakpoints for the built-in debugger.
 
@@ -173,6 +175,7 @@
 {
   octave::bp_table::intmap retmap;
   std::string symbol_name = "";  // stays empty for "dbstop if error" etc
+  std::string class_name = "";
   octave::bp_table::intmap lines;
   std::string condition = "";
   octave_value retval;
@@ -185,14 +188,15 @@
     {
       // explicit function / line / condition
       bptab.parse_dbfunction_params ("dbstop", args, symbol_name,
-                                     lines, condition);
+                                     class_name, lines, condition);
 
       if (lines.size () == 0)
         lines[0] = 1;
 
       if (symbol_name != "")
         {
-          retmap = bptab.add_breakpoint (symbol_name, lines, condition);
+          retmap = bptab.add_breakpoint (symbol_name, class_name,
+                                         lines, condition);
           retval = intmap_to_ov (retmap);
         }
     }
@@ -243,7 +247,7 @@
           for (octave_idx_type i = 0; i < line.numel (); i++)
             {
               lines [0] = line(i).double_value ();
-              bptab.add_breakpoint (name(i).string_value (), lines,
+              bptab.add_breakpoint (name(i).string_value (), "", lines,
                                     (use_cond
                                      ? cond(i).string_value ()
                                      : unconditional));
@@ -252,6 +256,9 @@
         }
     }
 
+  // If we add a breakpoint, we also need to reset debug_mode.
+  tw.reset_debug_state ();
+
   return retval;
 }
 
@@ -300,6 +307,7 @@
 @end deftypefn */)
 {
   std::string symbol_name = "";  // stays empty for "dbclear if error" etc
+  std::string class_name = "";
   octave::bp_table::intmap lines;
   std::string dummy;             // "if" condition -- only used for dbstop
 
@@ -309,7 +317,7 @@
 
   octave::bp_table& bptab = tw.get_bp_table ();
 
-  bptab.parse_dbfunction_params ("dbclear", args, symbol_name, lines, dummy);
+  bptab.parse_dbfunction_params ("dbclear", args, symbol_name, class_name, lines, dummy);
 
   if (nargin == 1 && symbol_name == "all")
     {
@@ -322,6 +330,9 @@
         bptab.remove_breakpoint (symbol_name, lines);
     }
 
+  // If we remove a breakpoint, we also need to reset debug_mode.
+  tw.reset_debug_state ();
+
   return ovl ();
 }
 
@@ -395,7 +406,7 @@
   else
     {
 /*
-      if (Vdebugging)
+      if (tw.in_debug_repl ())
         {
           octave_user_code *dbg_fcn = tw.get_user_code ();
           if (dbg_fcn)
@@ -557,40 +568,7 @@
 {
   octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave_user_code *dbg_fcn = tw.get_user_code ();
-
-  if (! dbg_fcn)
-    {
-      octave_stdout << "stopped at top level" << std::endl;
-      return ovl ();
-    }
-
-  octave_stdout << "stopped in " << dbg_fcn->name () << " at ";
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  int l = cs.debug_user_code_line ();
-
-  if (l > 0)
-    {
-      octave_stdout << "line " << l;
-
-      std::string file_name = dbg_fcn->fcn_file_name ();
-
-      if (! file_name.empty ())
-        {
-          octave_stdout << " [" << file_name << ']' << std::endl;
-
-          std::string line = dbg_fcn->get_code_line (l);
-
-          if (! line.empty ())
-            octave_stdout << l << ": " << line << std::endl;
-        }
-      else
-        octave_stdout << std::endl;
-    }
-  else
-    octave_stdout << "<unknown line>" << std::endl;
+  tw.debug_where (octave_stdout);
 
   return ovl ();
 }
@@ -824,9 +802,7 @@
       name = dbg_fcn->name ();
     }
 
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  int l = cs.debug_user_code_line ();
+  int l = tw.debug_user_code_line ();
 
   if (l > 0)
     {
@@ -899,14 +875,14 @@
         nskip = n;
     }
 
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
   if (nargout == 0)
     {
-      octave_map stk = cs.backtrace (nskip, curr_frame);
-      octave_idx_type nframes_to_display = stk.numel ();
+      octave_map stk = tw.backtrace (curr_frame);
+      octave_idx_type nframes = stk.numel ();
 
-      if (nframes_to_display > 0)
+      if (nframes > 0)
         {
           octave::preserve_stream_state stream_state (os);
 
@@ -920,14 +896,14 @@
 
           size_t max_name_len = 0;
 
-          for (octave_idx_type i = 0; i < nframes_to_display; i++)
+          for (octave_idx_type i = nskip; i < nframes; i++)
             {
               std::string name = names(i).string_value ();
 
               max_name_len = std::max (name.length (), max_name_len);
             }
 
-          for (octave_idx_type i = 0; i < nframes_to_display; i++)
+          for (octave_idx_type i = nskip; i < nframes; i++)
             {
               std::string name = names(i).string_value ();
               std::string file = files(i).string_value ();
@@ -943,15 +919,20 @@
                  << std::endl;
             }
 
-          if (show_top_level)
+          if (tw.at_top_level () && show_top_level)
             os << "  --> top level" << std::endl;
         }
     }
   else
     {
-      octave_map stk = cs.backtrace (nskip, curr_frame, false);
+      octave_map stk = tw.backtrace (curr_frame, false);
 
-      retval = ovl (stk, curr_frame < 0 ? 1 : curr_frame + 1);
+      // If current stack frame is not in the list curr_frame will be
+      // -1 and either nskip caused us to skip it or we are at the top
+      // level, which is not included in the list of frames.  So in the
+      // interpreter, 0 will be our invalid frame index value.
+
+      retval = ovl (stk, curr_frame + 1);
     }
 
   return retval;
@@ -1039,10 +1020,9 @@
   if (who == "dbup")
     n = -n;
 
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  if (! cs.goto_frame_relative (n, true))
-    error ("%s: invalid stack frame", who.c_str ());
+  tw.dbupdown (n, true);
 }
 
 DEFMETHOD (dbup, interp, args, ,
@@ -1098,7 +1078,9 @@
 @seealso{dbcont, dbquit}
 @end deftypefn */)
 {
-  if (! Vdebugging)
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  if (! tw.in_debug_repl ())
     error ("dbstep: can only be called in debug mode");
 
   int nargin = args.length ();
@@ -1106,45 +1088,37 @@
   if (nargin > 1)
     print_usage ();
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
+  int n = 0;
 
   if (nargin == 1)
     {
-      std::string arg = args(0).xstring_value ("dbstep: input argument must be a string");
+      std::string arg
+        = args(0).xstring_value ("dbstep: input argument must be a string");
 
       if (arg == "in")
-        {
-          Vdebugging = false;
-          Vtrack_line_num = true;
-
-          tw.set_dbstep_flag (-1);
-        }
+        n = -1;
       else if (arg == "out")
-        {
-          Vdebugging = false;
-          Vtrack_line_num = true;
-
-          tw.set_dbstep_flag (-2);
-        }
+        n = -2;
       else
         {
-          int n = atoi (arg.c_str ());
+          n = atoi (arg.c_str ());
 
           if (n < 1)
             error ("dbstep: invalid argument");
-
-          Vdebugging = false;
-          Vtrack_line_num = true;
-
-          tw.set_dbstep_flag (n);
         }
     }
   else
+    n = 1;
+
+  if (n != 0)
     {
-      Vdebugging = false;
       Vtrack_line_num = true;
 
-      tw.set_dbstep_flag (1);
+      tw.set_dbstep_flag (n);
+
+      // If we set the dbstep flag, we also need to reset debug_mode.
+      tw.reset_debug_state ();
+
     }
 
   return ovl ();
@@ -1159,18 +1133,17 @@
 @seealso{dbstep, dbquit}
 @end deftypefn */)
 {
-  if (! Vdebugging)
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  if (! tw.in_debug_repl ())
     error ("dbcont: can only be called in debug mode");
 
   if (args.length () != 0)
     print_usage ();
 
-  Vdebugging = false;
   Vtrack_line_num = true;
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
-
-  tw.reset_debug_state ();
+  tw.exit_debug_repl (true);
 
   return ovl ();
 }
@@ -1178,26 +1151,37 @@
 DEFMETHOD (dbquit, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {} dbquit
-Quit debugging mode immediately without further code execution and return to
-the Octave prompt.
+@deftypefnx {} {} dbquit all
+Quit debugging mode immediately without further code execution.  With no
+arguments, exit the current debugging level.  With argument @code{all},
+exit all debugging levels and return to the Octave prompt.
 @seealso{dbcont, dbstep}
 @end deftypefn */)
 {
-  if (! Vdebugging)
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  if (! tw.in_debug_repl ())
     error ("dbquit: can only be called in debug mode");
 
-  if (args.length () != 0)
+  int nargin = args.length ();
+
+  if (nargin > 1)
     print_usage ();
 
-  // FIXME: there are too many debug mode flags!
-
-  Vdebugging = false;
+  if (nargin == 1)
+    {
+      std::string arg
+        = args(0).xstring_value ("dbquit: input argument must be a string");
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
+      if (arg == "all")
+        tw.abort_debug_repl (true);
+      else
+        error ("dbquit: unrecognized argument '%s'", arg.c_str ());
+    }
+  else
+    tw.exit_debug_repl (true);
 
-  tw.reset_debug_state (false);
-
-  throw octave::interrupt_exception ();
+  tw.debug_mode (false);
 
   return ovl ();
 }
@@ -1212,7 +1196,9 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (Vdebugging);
+  octave::tree_evaluator& tw = octave::__get_evaluator__ ("Fisdebugmode");
+
+  return ovl (tw.in_debug_repl ());
 }
 
 DEFMETHOD (__db_next_breakpoint_quiet__, interp, args, ,
--- a/libinterp/corefcn/defun-dld.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/defun-dld.h	Fri Jul 12 12:14:43 2019 -0400
@@ -36,13 +36,13 @@
 //! For detailed information, see \ref Macros.
 //!
 //! @param name The **unqouted** name of the function that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the function name is prepended by an
-//!             `F`.
+//!             'F'.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this function.  If this value is
 //!                  omitted, the function cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this function is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the function cannot access this number.
@@ -70,17 +70,17 @@
 //! For detailed information, see \ref Macros.
 //!
 //! @param name The **unqouted** name of the method that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the method name is prepended by an
-//!             `F`.
-//! @param interp_name The name of the `octave::interpreter` reference that can
+//!             'F'.
+//! @param interp_name The name of the 'octave::interpreter' reference that can
 //!                    be used by this method.  If this value is omitted,
 //!                    there is no access to the interpreter and one should
 //!                    use #DEFUN to define a function instead.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this method.  If this value is
 //!                  omitted, the method cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this method is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the method cannot access this number.
--- a/libinterp/corefcn/defun-int.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/defun-int.h	Fri Jul 12 12:14:43 2019 -0400
@@ -80,41 +80,6 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::auto_shlib' instead")
-typedef octave::auto_shlib octave_auto_shlib;
-
-OCTAVE_DEPRECATED (4.4, "use 'tree_evaluator::isargout' instead")
-extern OCTINTERP_API bool
-defun_isargout (int, int);
-
-OCTAVE_DEPRECATED (4.4, "use 'tree_evaluator::isargout' instead")
-extern OCTINTERP_API void
-defun_isargout (int, int, bool *);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::symbol_table::install_built_in_function' instead")
-extern OCTINTERP_API void
-install_builtin_function (octave_builtin::fcn f, const std::string& name,
-                          const std::string& file, const std::string& doc,
-                          bool can_hide_function = true);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::symbol_table::install_built_in_function' instead")
-extern OCTINTERP_API void
-install_builtin_function (octave_builtin::meth m, const std::string& name,
-                          const std::string& file, const std::string& doc,
-                          bool can_hide_function = true);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::symbol_table::alias_built_in_function' instead")
-extern OCTINTERP_API void
-alias_builtin (const std::string& alias, const std::string& name);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::symbol_table::install_built_in_dispatch' instead")
-extern OCTINTERP_API void
-install_builtin_dispatch (const std::string& name, const std::string& klass);
-
-#endif
-
 #define FORWARD_DECLARE_FUNX(name)              \
   extern OCTAVE_EXPORT octave_value_list        \
   name (const octave_value_list&, int)
--- a/libinterp/corefcn/defun.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/defun.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include <string>
 
-#include "call-stack.h"
 #include "defun.h"
 #include "dynamic-ld.h"
 #include "error.h"
@@ -40,7 +39,6 @@
 #include "ovl.h"
 #include "oct-lvalue.h"
 #include "pager.h"
-#include "pt-eval.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "symtab.h"
@@ -51,9 +49,9 @@
 void
 print_usage (void)
 {
-  octave::call_stack& cs = octave::__get_call_stack__ ("print_usage");
+  octave::tree_evaluator& tw = octave::__get_evaluator__ ("print_usage");
 
-  const octave_function *cur = cs.current ();
+  const octave_function *cur = tw.current_function ();
 
   if (cur)
     print_usage (cur->name ());
@@ -83,32 +81,6 @@
 // Install variables and functions in the symbol tables.
 
 void
-install_builtin_function (octave_builtin::fcn f, const std::string& name,
-                          const std::string& file, const std::string& doc,
-                          bool /* can_hide_function -- not yet implemented */)
-{
-  octave_value fcn (new octave_builtin (f, name, file, doc));
-
-  octave::symbol_table& symtab
-    = octave::__get_symbol_table__ ("install_builtin_function");
-
-  symtab.install_built_in_function (name, fcn);
-}
-
-void
-install_builtin_function (octave_builtin::meth m, const std::string& name,
-                          const std::string& file, const std::string& doc,
-                          bool /* can_hide_function -- not yet implemented */)
-{
-  octave_value fcn (new octave_builtin (m, name, file, doc));
-
-  octave::symbol_table& symtab
-    = octave::__get_symbol_table__ ("install_builtin_function");
-
-  symtab.install_built_in_function (name, fcn);
-}
-
-void
 install_dld_function (octave_dld_function::fcn f, const std::string& name,
                       const octave::dynamic_library& shl, const std::string& doc,
                       bool relative)
@@ -161,31 +133,14 @@
   symtab.install_built_in_function (name, fval);
 }
 
-void
-alias_builtin (const std::string& alias, const std::string& name)
-{
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ("alias_builtin");
-
-  symtab.alias_built_in_function (alias, name);
-}
-
-void
-install_builtin_dispatch (const std::string& name, const std::string& klass)
-{
-  octave::symbol_table& symtab
-    = octave::__get_symbol_table__ ("install_builtin_dispatch");
-
-  symtab.install_built_in_dispatch (name, klass);
-}
-
 octave::dynamic_library
 get_current_shlib (void)
 {
   octave::dynamic_library retval;
 
-  octave::call_stack& cs = octave::__get_call_stack__ ("get_current_shlib");
+  octave::tree_evaluator& tw = octave::__get_evaluator__ ("get_current_shlib");
 
-  octave_function *curr_fcn = cs.current ();
+  octave_function *curr_fcn = tw.current_function ();
 
   if (curr_fcn)
     {
@@ -205,19 +160,3 @@
 
   return retval;
 }
-
-bool
-defun_isargout (int nargout, int iout)
-{
-  octave::tree_evaluator& tw = octave::__get_evaluator__ ("defun_isargout");
-
-  return tw.isargout (nargout, iout);
-}
-
-void
-defun_isargout (int nargout, int nout, bool *isargout)
-{
-  octave::tree_evaluator& tw = octave::__get_evaluator__ ("defun_isargout");
-
-  return tw.isargout (nargout, nout, isargout);
-}
--- a/libinterp/corefcn/defun.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/defun.h	Fri Jul 12 12:14:43 2019 -0400
@@ -36,13 +36,13 @@
 //! For detailed information, see \ref Macros.
 //!
 //! @param name The **unqouted** name of the function that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the function name is prepended by an
-//!             `F`.
+//!             'F'.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this function.  If this value is
 //!                  omitted, the function cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this function is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the function cannot access this number.
@@ -67,11 +67,11 @@
 //! @param name The **qouted** name of the function that should be callable
 //!             by the interpreter.
 //! @param fname The internal **unqouted** name of the function.  This internal
-//!              name is by convention prepended by an `F`.
+//!              name is by convention prepended by an 'F'.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this function.  If this value is
 //!                  omitted, the function cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this function is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the function cannot access this number.
@@ -88,17 +88,17 @@
 //!
 //! For detailed information, see \ref Macros.
 //!
-//! The function gets installed to the `octave::symbol_table` in a way, such
+//! The function gets installed to the 'octave::symbol_table' in a way, such
 //! that no variable is allowed to hide this function name.
 //!
 //! @param name The **unqouted** name of the function that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the function name is prepended by an
-//!             `F`.
+//!             'F'.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this function.  If this value is
 //!                  omitted, the function cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this function is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the function cannot access this number.
@@ -114,17 +114,17 @@
 //! For detailed information, see \ref Macros.
 //!
 //! @param name The **unqouted** name of the method that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the method name is prepended by an
-//!             `F`.
-//! @param interp_name The name of the `octave::interpreter` reference that can
+//!             'F'.
+//! @param interp_name The name of the 'octave::interpreter' reference that can
 //!                    be used by this method.  If this value is omitted,
 //!                    there is no access to the interpreter and one should
 //!                    use #DEFUN to define a function instead.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this method.  If this value is
 //!                  omitted, the method cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this method is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the method cannot access this number.
@@ -149,15 +149,15 @@
 //! @param name The **qouted** name of the method that should be callable
 //!             by the interpreter.
 //! @param fname The internal **unqouted** name of the method.  This internal
-//!              name is by convention prepended by an `F`.
-//! @param interp_name The name of the `octave::interpreter` reference that can
+//!              name is by convention prepended by an 'F'.
+//! @param interp_name The name of the 'octave::interpreter' reference that can
 //!                    be used by this method.  If this value is omitted,
 //!                    there is no access to the interpreter and one should
 //!                    use #DEFUNX to define a function instead.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this method.  If this value is
 //!                  omitted, the method cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this method is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the method cannot access this number.
@@ -174,21 +174,21 @@
 //!
 //! For detailed information, see \ref Macros.
 //!
-//! The method gets installed to the `octave::symbol_table` in a way, such
+//! The method gets installed to the 'octave::symbol_table' in a way, such
 //! that no variable is allowed to hide this method name.
 //!
 //! @param name The **unqouted** name of the method that should be installed
-//!             on the `octave::symbol_table` and can be called by the
+//!             on the 'octave::symbol_table' and can be called by the
 //!             interpreter.  Internally, the method name is prepended by an
-//!             `F`.
-//! @param interp_name The name of the `octave::interpreter` reference that can
+//!             'F'.
+//! @param interp_name The name of the 'octave::interpreter' reference that can
 //!                    be used by this method.  If this value is omitted,
 //!                    there is no access to the interpreter and one should
 //!                    use #DEFCONSTFUN to define a function instead.
 //! @param args_name The name of the octave_value_list variable used to pass
 //!                  the argument list to this method.  If this value is
 //!                  omitted, the method cannot access the argument list.
-//! @param nargout_name The name of the `int` variable used to pass the number
+//! @param nargout_name The name of the 'int' variable used to pass the number
 //!                     of output arguments this method is expected to
 //!                     produce from the caller.  If this value is
 //!                     omitted, the method cannot access this number.
--- a/libinterp/corefcn/dirfns.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/dirfns.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -97,12 +97,13 @@
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} cd @var{dir}
 @deftypefnx {} {} cd
+@deftypefnx {} {@var{old_dir} =} cd
 @deftypefnx {} {@var{old_dir} =} cd (@var{dir})
 @deftypefnx {} {} chdir @dots{}
 Change the current working directory to @var{dir}.
 
-If @var{dir} is omitted, the current directory is changed to the user's home
-directory (@qcode{"~"}).
+If called with no input or output arguments, the current directory is
+changed to the user's home directory (@qcode{"~"}).
 
 For example,
 
@@ -140,7 +141,7 @@
       if (! dirname.empty ())
         octave_change_to_directory (dirname);
     }
-  else
+  else if (nargout == 0)
     {
       std::string home_dir = octave::sys::env::get_home_directory ();
 
--- a/libinterp/corefcn/display.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/display.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -66,14 +66,9 @@
     if (! instance)
       {
         instance = new display_info (query);
-
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
+        singleton_cleanup_list::add (cleanup_instance);
       }
 
-    if (! instance)
-      error ("unable to create display_info object!");
-
     return retval;
   }
 }
--- a/libinterp/corefcn/dlmread.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/dlmread.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -148,7 +148,10 @@
     }
   else if (range_spec.is_real_matrix () && range_spec.numel () == 4)
     {
-      ColumnVector range (range_spec.vector_value ());
+      NDArray range (range_spec.array_value ());
+      if (range.any_element_is_nan ())
+        error ("dlmread: NaN is not a valid row or column specifier");
+
       // double --> unsigned int avoiding any overflow
       rlo = static_cast<octave_idx_type> (std::min (range(0), idx_max_dbl));
       clo = static_cast<octave_idx_type> (std::min (range(1), idx_max_dbl));
@@ -181,10 +184,11 @@
 The @var{range} parameter specifies exactly which data elements are read.
 The first form of the parameter is a 4-element vector containing the upper
 left and lower right corners @code{[@var{R0},@var{C0},@var{R1},@var{C1}]}
-where the indices are zero-based.  Alternatively, a spreadsheet style
-form such as @qcode{"A2..Q15"} or @qcode{"T1:AA5"} can be used.  The
-lowest alphabetical index @qcode{'A'} refers to the first column.  The
-lowest row index is 1.
+where the indices are zero-based.  To specify the last column---the equivalent
+of @code{end} when indexing---use the specifier @code{Inf}.  Alternatively, a
+spreadsheet style form such as @qcode{"A2..Q15"} or @qcode{"T1:AA5"} can be
+used.  The lowest alphabetical index @qcode{'A'} refers to the first column.
+The lowest row index is 1.
 
 @var{file} should be a filename or a file id given by @code{fopen}.  In the
 latter case, the file is read until end of file is reached.
@@ -274,7 +278,7 @@
         }
 
       if (r0 < 0 || c0 < 0)
-        error ("dlmread: left & top must be positive");
+        error ("dlmread: left (R0) and top (C0) must be positive");
 
       // Short-circuit and return if range is empty
       if (r1 < r0 || c1 < c0)
--- a/libinterp/corefcn/dot.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/dot.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,8 +26,10 @@
 
 #include "lo-blas-proto.h"
 #include "mx-base.h"
+
+#include "builtin-defun-decls.h"
+#include "defun.h"
 #include "error.h"
-#include "defun.h"
 #include "parse.h"
 
 static void
@@ -75,11 +77,12 @@
 If the optional argument @var{dim} is given, calculate the dot products
 along this dimension.
 
-This is equivalent to
-@code{sum (conj (@var{X}) .* @var{Y}, @var{dim})},
-but avoids forming a temporary array and is faster.  When @var{X} and
-@var{Y} are column vectors, the result is equivalent to
-@code{@var{X}' * @var{Y}}.
+Implementation Note: This is equivalent to
+@code{sum (conj (@var{X}) .* @var{Y}, @var{dim})}, but avoids forming a
+temporary array and is faster.  When @var{X} and @var{Y} are column vectors,
+the result is equivalent to @code{@var{X}' * @var{Y}}.  Although, @code{dot}
+is defined for integer arrays, the output may differ from the expected result
+due to the limited range of integer objects.
 @seealso{cross, divergence}
 @end deftypefn */)
 {
@@ -177,11 +180,16 @@
   else
     {
       // Non-optimized evaluation.
+      // FIXME: This may *not* do what the user expects.
+      // It might be more useful to issue a warning, or even an error, instead
+      // of calculating possibly garbage results.
+      // Think of the dot product of two int8 vectors where the multiplications
+      // exceed intmax.
       octave_value_list tmp;
       tmp(1) = dim + 1;
       tmp(0) = do_binary_op (octave_value::op_el_mul, argx, argy);
 
-      tmp = octave::feval ("sum", tmp, 1);
+      tmp = Fsum (tmp, 1);
       if (! tmp.empty ())
         retval = tmp(0);
     }
@@ -204,17 +212,23 @@
 %! assert (dot (single (x), single (x)), single ([4, 20]));
 
 %!test
-%! x = int8 ([1 2]);
-%! y = int8 ([2 3]);
+%! x = int8 ([1, 2]);
+%! y = int8 ([2, 3]);
 %! assert (dot (x, y), 8);
 
 %!test
-%! x = int8 ([1 2; 3 4]);
-%! y = int8 ([5 6; 7 8]);
+%! x = int8 ([1, 2; 3, 4]);
+%! y = int8 ([5, 6; 7, 8]);
 %! assert (dot (x, y), [26 44]);
 %! assert (dot (x, y, 2), [17; 53]);
 %! assert (dot (x, y, 3), [5 12; 21 32]);
 
+## This is, perhaps, surprising.  Integer maximums and saturation mechanics
+## prevent accurate value from being calculated.
+%!test
+%! x = int8 ([127]);
+%! assert (dot (x, x), 127);
+
 ## Test input validation
 %!error dot ()
 %!error dot (1)
--- a/libinterp/corefcn/environment.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/environment.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -38,35 +38,35 @@
 #include "interpreter.h"
 #include "variables.h"
 
-static void append_to_shell_path (const std::string& exec_path)
-{
-  // FIXME: should there be a way to remove a previous setting from
-  // PATH?
-
-  if (exec_path.empty ())
-    return;
-
-  // FIXME: should we really be modifying PATH in the environment?
-
-  std::string shell_path = octave::sys::env::getenv ("PATH");
-
-  if (shell_path.empty ())
-    octave::sys::env::putenv ("PATH", exec_path);
-  else
-    {
-      // If PATH doesn't already have exec_path, append it.
-      // FIXME: should we search for the elements individually, and
-      // only append those that are missing?
-
-      std::string path_sep = octave::directory_path::path_sep_str ();
-
-      if (shell_path.find (exec_path) == std::string::npos)
-        octave::sys::env::putenv ("PATH", shell_path + path_sep + exec_path);
-    }
-}
-
 namespace octave
 {
+  static void append_to_shell_path (const std::string& exec_path)
+  {
+    // FIXME: should there be a way to remove a previous setting from
+    // PATH?
+
+    if (exec_path.empty ())
+      return;
+
+    // FIXME: should we really be modifying PATH in the environment?
+
+    std::string shell_path = sys::env::getenv ("PATH");
+
+    if (shell_path.empty ())
+      sys::env::putenv ("PATH", exec_path);
+    else
+      {
+        // If PATH doesn't already have exec_path, append it.
+        // FIXME: should we search for the elements individually, and
+        // only append those that are missing?
+
+        std::string path_sep = directory_path::path_sep_str ();
+
+        if (shell_path.find (exec_path) == std::string::npos)
+          sys::env::putenv ("PATH", shell_path + path_sep + exec_path);
+      }
+  }
+
   octave_value
   environment::editor (const octave_value_list& args, int nargout)
   {
--- a/libinterp/corefcn/error.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/error.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -35,7 +35,6 @@
 
 #include "bp-table.h"
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "error.h"
 #include "input.h"
@@ -52,193 +51,17 @@
 #include "utils.h"
 #include "variables.h"
 
-// TRUE means that Octave will try to beep obnoxiously before printing
-// error messages.
-static bool Vbeep_on_error = false;
-
-// TRUE means that Octave will try to enter the debugger when an error
-// is encountered.  This will also inhibit printing of the normal
-// traceback message (you will only see the top-level error message).
-bool Vdebug_on_error = false;
-
-// TRUE means that Octave will try to enter the debugger when an error
-// is encountered within the 'try' section of a 'try' / 'catch' block.
-bool Vdebug_on_caught = false;
-
-// TRUE means that Octave will try to enter the debugger when a warning
-// is encountered.
-bool Vdebug_on_warning = false;
-
-// TRUE means that Octave will try to display a stack trace when a
-// warning is encountered.
-static bool Vbacktrace_on_warning = true;
-
-// TRUE means that Octave will print a verbose warning.  Currently unused.
-static bool Vverbose_warning;
-
-// TRUE means that Octave will print no warnings, but lastwarn will be updated
-static bool Vquiet_warning = false;
-
-// A structure containing (most of) the current state of warnings.
-static octave_map warning_options;
-
-// The text of the last error message.
-static std::string Vlast_error_message;
-
-// The text of the last warning message.
-static std::string Vlast_warning_message;
-
-// The last warning message id.
-static std::string Vlast_warning_id;
-
-// The last error message id.
-static std::string Vlast_error_id;
-
-// The last file in which an error occurred
-static octave_map Vlast_error_stack;
-
-// Current error state.
-//
-// Valid values:
-//
-//    0: no error
-//    1: an error has occurred
-//
-int error_state = 0;
-
-// Tell the error handler whether to print messages, or just store
-// them for later.  Used for handling errors in eval() and
-// the 'unwind_protect' statement.
-int buffer_error_messages = 0;
-
-// The number of layers of try / catch blocks we're in.  Used to print
-// "caught error" instead of error when "dbstop if caught error" is on.
-int in_try_catch = 0;
-
-// TRUE means error messages are turned off.
-bool discard_error_messages = false;
-
-// TRUE means warning messages are turned off.
-bool discard_warning_messages = false;
-
-void
-reset_error_handler (void)
+static void verror (bool save_last_error, std::ostream& os, const char *name,
+                    const char *id, const char *fmt, va_list args,
+                    bool with_cfn = false)
 {
-  buffer_error_messages = 0;
-  in_try_catch = 0;
-  discard_error_messages = false;
+  octave::error_system& es = octave::__get_error_system__ ("verror");
+
+  es.verror (save_last_error, os, name, id, fmt, args, with_cfn);
 }
 
 static void
-initialize_warning_options (const std::string& state)
-{
-  octave_scalar_map initw;
-
-  initw.setfield ("identifier", "all");
-  initw.setfield ("state", state);
-
-  warning_options = initw;
-}
-
-static octave_map
-initialize_last_error_stack (void)
-{
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("initialize_last_error_stack");
-
-  return cs.empty_backtrace ();
-}
-
-static void
-verror (bool save_last_error, std::ostream& os,
-        const char *name, const char *id, const char *fmt, va_list args,
-        bool with_cfn = false)
-{
-  if (discard_error_messages && ! Vdebug_on_caught)
-    return;
-
-  if (! buffer_error_messages || Vdebug_on_caught)
-    octave::flush_stdout ();
-
-  // FIXME: we really want to capture the message before it has all the
-  //        formatting goop attached to it.  We probably also want just the
-  //        message, not the traceback information.
-
-  std::ostringstream output_buf;
-
-  octave::vformat (output_buf, fmt, args);
-
-  std::string base_msg = output_buf.str ();
-
-  bool to_beep_or_not_to_beep_p = Vbeep_on_error;
-
-  std::string msg_string;
-
-  if (to_beep_or_not_to_beep_p)
-    msg_string = "\a";
-
-  if (name)
-    {
-      if (in_try_catch && ! strcmp (name, "error"))
-        msg_string += "caught error: ";
-      else
-        msg_string += std::string (name) + ": ";
-    }
-
-  octave::call_stack& cs = octave::__get_call_stack__ ("verror");
-
-  // If with_fcn is specified, we'll attempt to prefix the message with the name
-  // of the current executing function.  But we'll do so only if:
-  // 1. the name is not empty (anonymous function)
-  // 2. it is not already there (including the following colon)
-  if (with_cfn)
-    {
-      octave_function *curfcn = cs.current ();
-      if (curfcn)
-        {
-          std::string cfn = curfcn->name ();
-          if (! cfn.empty ())
-            {
-              cfn += ':';
-              if (cfn.length () > base_msg.length ()
-                  || base_msg.compare (0, cfn.length (), cfn) != 0)
-                {
-                  msg_string += cfn + ' ';
-                }
-            }
-        }
-    }
-
-  msg_string += base_msg + '\n';
-
-  if (save_last_error)
-    {
-      // This is the first error in a possible series.
-
-      Vlast_error_id = id;
-      Vlast_error_message = base_msg;
-
-      octave_user_code *fcn = cs.caller_user_code ();
-
-      if (fcn)
-        {
-          octave_idx_type curr_frame = -1;
-
-          Vlast_error_stack = cs.backtrace (0, curr_frame);
-        }
-      else
-        Vlast_error_stack = initialize_last_error_stack ();
-    }
-
-  if (! buffer_error_messages || Vdebug_on_caught)
-    {
-      octave_diary << msg_string;
-      os << msg_string;
-    }
-}
-
-static void
-pr_where_2 (std::ostream& os, const char *fmt, va_list args)
+vpr_where (std::ostream& os, const char *fmt, va_list args)
 {
   if (fmt)
     {
@@ -262,15 +85,15 @@
         }
     }
   else
-    panic ("pr_where_2: invalid format");
+    panic ("vpr_where: invalid format");
 }
 
 static void
-pr_where_1 (std::ostream& os, const char *fmt, ...)
+pr_where_internal (std::ostream& os, const char *fmt, ...)
 {
   va_list args;
   va_start (args, fmt);
-  pr_where_2 (os, fmt, args);
+  vpr_where (os, fmt, args);
   va_end (args);
 }
 
@@ -289,7 +112,7 @@
   size_t nframes = frames.size ();
 
   if (nframes > 0)
-    pr_where_1 (os, "%s: called from\n", who);
+    pr_where_internal (os, "%s: called from\n", who);
 
   for (const auto& frm : frames)
     {
@@ -300,36 +123,36 @@
       if (line > 0)
         {
           if (column > 0)
-            pr_where_1 (os, "    %s at line %d column %d\n",
+            pr_where_internal (os, "    %s at line %d column %d\n",
                         fcn_name.c_str (), line, column);
           else
-            pr_where_1 (os, "    %s at line %d\n", fcn_name.c_str (), line);
+            pr_where_internal (os, "    %s at line %d\n",
+                               fcn_name.c_str (), line);
         }
       else
-        pr_where_1 (os, "    %s\n", fcn_name.c_str ());
+        pr_where_internal (os, "    %s\n", fcn_name.c_str ());
     }
 }
 
 static void
 pr_where (std::ostream& os, const char *who)
 {
-  octave::call_stack& cs = octave::__get_call_stack__ ("pr_where");
-
-  std::list<octave::call_stack::stack_frame> call_stack_frames
-    = cs.backtrace_frames ();
+  octave::tree_evaluator& tw = octave::__get_evaluator__ ("pr_where");
+
+  std::list<octave::stack_frame *> call_stack_frames = tw.backtrace_frames ();
 
   // Print the error message only if it is different from the previous one;
   // Makes the output more concise and readable.
   call_stack_frames.unique ();
 
   std::list<error_stack_frame> frames;
-  for (const auto& frm : call_stack_frames)
+  for (const auto *frm : call_stack_frames)
     {
       error_stack_frame frame;
 
-      frame.name = frm.fcn_name ();
-      frame.line = frm.line ();
-      frame.column = frm.column ();
+      frame.name = frm->fcn_name ();
+      frame.line = frm->line ();
+      frame.column = frm->column ();
 
       frames.push_back (frame);
     }
@@ -337,6 +160,999 @@
   pr_where (os, who, frames);
 }
 
+static void
+maybe_enter_debugger (octave::execution_exception& e,
+                      bool show_stack_trace = false)
+{
+  octave::error_system& es
+    = octave::__get_error_system__ ("maybe_enter_debugger");
+
+  es.maybe_enter_debugger (e, show_stack_trace);
+}
+
+OCTAVE_NORETURN
+static void
+vusage (octave::execution_exception& e, const char *id,
+        const char *fmt, va_list args)
+{
+  verror (true, std::cerr, "usage", id, fmt, args);
+
+  maybe_enter_debugger (e);
+
+  throw e;
+}
+
+OCTAVE_NORETURN
+static void
+error_1 (octave::execution_exception& e, std::ostream& os,
+         const char *name, const char *id, const char *fmt,
+         va_list args, bool with_cfn = false)
+{
+  octave::error_system& es = octave::__get_error_system__ ("error_1");
+
+  es.error_1 (e, os, name, id, fmt, args, with_cfn);
+}
+
+OCTAVE_NORETURN
+static void
+error_1 (std::ostream& os, const char *name, const char *id,
+         const char *fmt, va_list args, bool with_cfn = false)
+{
+  octave::error_system& es = octave::__get_error_system__ ("error_1");
+
+  es.error_1 (os, name, id, fmt, args, with_cfn);
+}
+
+static int
+check_state (const std::string& state)
+{
+  // -1: not found
+  //  0: found, "off"
+  //  1: found, "on"
+  //  2: found, "error"
+
+  if (state == "off")
+    return 0;
+  else if (state == "on")
+    return 1;
+  else if (state == "error")
+    return 2;
+  else
+    return -1;
+}
+
+static void
+vwarning (const char *id, const char *fmt, va_list args)
+{
+  octave::error_system& es = octave::__get_error_system__ ("warning");
+
+  es.vwarning (id, fmt, args);
+}
+
+static std::list<error_stack_frame>
+make_stack_frame_list (const octave_map& stack)
+{
+  std::list<error_stack_frame> frames;
+
+  Cell name = stack.contents ("name");
+  Cell line = stack.contents ("line");
+  Cell column;
+  bool have_column = false;
+  if (stack.contains ("column"))
+    {
+      have_column = true;
+      column = stack.contents ("column");
+    }
+
+  octave_idx_type nel = name.numel ();
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    {
+      error_stack_frame frame;
+
+      frame.name = name(i).string_value ();
+      frame.line = line(i).int_value ();
+      frame.column = (have_column ? column(i).int_value () : -1);
+
+      frames.push_back (frame);
+    }
+
+  return frames;
+}
+
+static void
+defun_usage_message (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  error_1 (octave_stdout, nullptr, "", fmt, args);
+  va_end (args);
+}
+
+typedef void (*error_fun)(const char *, const char *, ...);
+
+static std::string
+handle_message (error_fun f, const char *id, const char *msg,
+                const octave_value_list& args, bool have_fmt)
+{
+  std::string retval;
+
+  std::string tmpstr;
+
+  if (args.length () > 0)
+    {
+      octave_value arg;
+
+      if (have_fmt)
+        {
+          octave_value_list tmp = Fsprintf (args, 1);
+          arg = tmp(0);
+        }
+      else
+        arg = args(0);
+
+      if (arg.is_defined ())
+        {
+          if (arg.isempty ())
+            return retval;
+          else if (arg.is_string ())
+            {
+              tmpstr = arg.string_value ();  // 2-stage assignment required
+              msg = tmpstr.c_str ();         // in order to generate pointer
+                                             // to valid memory.
+            }
+        }
+    }
+
+  // Ugh.
+
+  size_t len = strlen (msg);
+
+  if (len > 0)
+    {
+      if (msg[len - 1] == '\n')
+        {
+          if (len > 1)
+            {
+              std::string tmp_msg (msg, len - 1);
+              f (id, "%s\n", tmp_msg.c_str ());
+              retval = tmp_msg;
+            }
+        }
+      else
+        {
+          f (id, "%s", msg);
+          retval = msg;
+        }
+    }
+
+  return retval;
+}
+
+// Determine whether the first argument to error or warning function
+// should be handled as the message identifier or as the format string.
+
+static bool
+maybe_extract_message_id (const std::string& caller,
+                          const octave_value_list& args,
+                          octave_value_list& nargs,
+                          std::string& id)
+{
+  nargs = args;
+  id = "";
+
+  int nargin = args.length ();
+
+  bool have_fmt = nargin > 1;
+
+  if (nargin > 0)
+    {
+      std::string arg1 = args(0).string_value ();
+
+      // For compatibility with Matlab, an identifier must contain ':',
+      // but not at the beginning or the end, and it must not contain '%'
+      // (even if it is not a valid conversion operator) or whitespace.
+
+      if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos
+          && arg1.find (':') != std::string::npos
+          && arg1[0] != ':'
+          && arg1.back () != ':')
+        {
+          if (nargin > 1)
+            {
+              id = arg1;
+
+              nargs.resize (nargin-1);
+
+              for (int i = 1; i < nargin; i++)
+                nargs(i-1) = args(i);
+            }
+          else
+            nargs(0) = "call to " + caller
+                       + " with message identifier '" + arg1
+                       + "' requires message";
+        }
+    }
+
+  return have_fmt;
+}
+
+namespace octave
+{
+  static octave_scalar_map
+  init_warning_options (const std::string& state)
+  {
+    octave_scalar_map initw;
+
+    initw.setfield ("identifier", "all");
+    initw.setfield ("state", state);
+
+    return initw;
+  }
+
+  static octave_map
+  init_error_stack (interpreter& interp)
+  {
+    tree_evaluator& tw = interp.get_evaluator ();
+
+    return tw.empty_backtrace ();
+  }
+
+  error_system::error_system (interpreter& interp)
+    : m_interpreter (interp),
+      m_debug_on_error (false),
+      m_debug_on_caught (false),
+      m_debug_on_warning (false),
+      m_buffer_error_messages (0),
+      m_in_try_catch (0),
+      m_discard_error_messages (false),
+      m_discard_warning_messages (false),
+      m_beep_on_error (false),
+      m_backtrace_on_warning (true),
+      m_verbose_warning (false),
+      m_quiet_warning (false),
+      m_warning_options (init_warning_options ("on")),
+      m_last_error_message (),
+      m_last_warning_message (),
+      m_last_warning_id (),
+      m_last_error_id (),
+      m_last_error_stack (init_error_stack (interp))
+  {
+    initialize_default_warning_state ();
+  }
+
+  octave_value
+  error_system::debug_on_error (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_error, args, nargout,
+                                  "debug_on_error");
+  }
+
+  octave_value
+  error_system::debug_on_caught (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_caught, args, nargout,
+                                  "debug_on_caught");
+  }
+
+  octave_value
+  error_system::debug_on_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_warning, args, nargout,
+                                  "debug_on_warning");
+  }
+
+  octave_value
+  error_system::buffer_error_messages (const octave_value_list& args,
+                                        int nargout)
+  {
+    return set_internal_variable (m_buffer_error_messages, args, nargout,
+                                  "buffer_error_messages");
+  }
+
+  octave_value
+  error_system::in_try_catch (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_in_try_catch, args, nargout,
+                                  "in_try_catch");
+  }
+
+  octave_value
+  error_system::discard_error_messages (const octave_value_list& args,
+                                        int nargout)
+  {
+    return set_internal_variable (m_discard_error_messages, args, nargout,
+                                  "discard_error_messages");
+  }
+
+  octave_value
+  error_system::discard_warning_messages (const octave_value_list& args,
+                                          int nargout)
+  {
+    return set_internal_variable (m_discard_warning_messages, args, nargout,
+                                  "discard_warning_messages");
+  }
+
+  octave_value
+  error_system::beep_on_error (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_beep_on_error, args, nargout,
+                                  "beep_on_error");
+  }
+
+  octave_value
+  error_system::backtrace_on_warning (const octave_value_list& args,
+                                      int nargout)
+  {
+    return set_internal_variable (m_backtrace_on_warning, args, nargout,
+                                  "backtrace_on_warning");
+  }
+
+  octave_value
+  error_system::verbose_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_verbose_warning, args, nargout,
+                                  "verbose_warning");
+  }
+
+  octave_value
+  error_system::quiet_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_quiet_warning, args, nargout,
+                                  "quiet_warning");
+  }
+
+  octave_value
+  error_system::last_error_message (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_error_message, args, nargout,
+                                  "last_error_message");
+  }
+
+  octave_value
+  error_system::last_warning_message (const octave_value_list& args,
+                                      int nargout)
+  {
+    return set_internal_variable (m_last_warning_message, args, nargout,
+                                  "last_warning_message");
+  }
+
+  octave_value
+  error_system::last_warning_id (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_warning_id, args, nargout,
+                                  "last_warning_id");
+  }
+
+  octave_value
+  error_system::last_error_id (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_error_id, args, nargout,
+                                  "last_error_id");
+  }
+
+  // For given warning ID, return 0 if warnings are disabled, 1 if
+  // enabled, and 2 if the given ID should be an error instead of a
+  // warning.
+
+  int error_system::warning_enabled (const std::string& id)
+  {
+    int retval = 0;
+
+    int all_state = -1;
+    int id_state = -1;
+
+    octave_map opts = warning_options ();
+
+    octave_idx_type nel = opts.numel ();
+
+    if (nel > 0)
+      {
+        Cell identifier = opts.contents ("identifier");
+        Cell state = opts.contents ("state");
+
+        bool all_found = false;
+        bool id_found = false;
+
+        for (octave_idx_type i = 0; i < nel; i++)
+          {
+            octave_value ov = identifier(i);
+            std::string ovs = ov.string_value ();
+
+            if (! all_found && ovs == "all")
+              {
+                all_state = check_state (state(i).string_value ());
+
+                if (all_state >= 0)
+                  all_found = true;
+              }
+
+            if (! id_found && ovs == id)
+              {
+                id_state = check_state (state(i).string_value ());
+
+                if (id_state >= 0)
+                  id_found = true;
+              }
+
+            if (all_found && id_found)
+              break;
+          }
+      }
+
+    // If "all" is not present, assume warnings are enabled.
+    if (all_state == -1)
+      all_state = 1;
+
+    if (all_state == 0)
+      {
+        if (id_state >= 0)
+          retval = id_state;
+      }
+    else if (all_state == 1)
+      {
+        if (id_state == 0 || id_state == 2)
+          retval = id_state;
+        else
+          retval = all_state;
+      }
+    else if (all_state == 2)
+      {
+        if (id_state == 0)
+          retval= id_state;
+        else
+          retval = all_state;
+      }
+
+    return retval;
+  }
+
+  void error_system::verror (bool save_last_error, std::ostream& os,
+                             const char *name, const char *id,
+                             const char *fmt, va_list args, bool with_cfn)
+  {
+    if (discard_error_messages () && ! debug_on_caught ())
+      return;
+
+    if (! buffer_error_messages () || debug_on_caught ())
+      flush_stdout ();
+
+    // FIXME: we really want to capture the message before it has all the
+    //        formatting goop attached to it.  We probably also want just the
+    //        message, not the traceback information.
+
+    std::ostringstream output_buf;
+
+    vformat (output_buf, fmt, args);
+
+    std::string base_msg = output_buf.str ();
+
+    bool to_beep_or_not_to_beep_p = beep_on_error ();
+
+    std::string msg_string;
+
+    if (to_beep_or_not_to_beep_p)
+      msg_string = "\a";
+
+    if (name)
+      {
+        if (in_try_catch () && ! strcmp (name, "error"))
+          msg_string += "caught error: ";
+        else
+          msg_string += std::string (name) + ": ";
+      }
+
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+    // If with_fcn is specified, we'll attempt to prefix the message with the name
+    // of the current executing function.  But we'll do so only if:
+    // 1. the name is not empty (anonymous function)
+    // 2. it is not already there (including the following colon)
+    if (with_cfn)
+      {
+        std::string cfn = tw.current_function_name ();
+
+        if (! cfn.empty ())
+          {
+            cfn += ':';
+            if (cfn.length () > base_msg.length ()
+                || base_msg.compare (0, cfn.length (), cfn) != 0)
+              msg_string += cfn + ' ';
+          }
+      }
+
+    msg_string += base_msg + '\n';
+
+    if (save_last_error)
+      {
+        // This is the first error in a possible series.
+
+        last_error_id (id);
+        last_error_message (base_msg);
+        last_error_stack (tw.in_user_code ()
+                          ? tw.backtrace () : tw.empty_backtrace ());
+      }
+
+    if (! buffer_error_messages () || debug_on_caught ())
+      {
+        octave_diary << msg_string;
+        os << msg_string;
+      }
+  }
+
+  void error_system::maybe_enter_debugger (execution_exception& e,
+                                           bool show_stack_trace)
+  {
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
+    bp_table& bptab = tw.get_bp_table ();
+
+    if ((application::interactive ()
+         || application::forced_interactive ())
+        && ((debug_on_error ()
+             && bptab.debug_on_err (last_error_id ()))
+            || (debug_on_caught ()
+                && bptab.debug_on_caught (last_error_id ())))
+        && tw.in_user_code ())
+      {
+        unwind_protect frame;
+
+        frame.protect_var (m_debug_on_error);
+        m_debug_on_error = false;
+
+        if (show_stack_trace)
+          {
+            std::string stack_trace = e.info ();
+
+            if (! stack_trace.empty ())
+              {
+                std::cerr << stack_trace;
+
+                e.set_stack_trace ();
+              }
+          }
+
+        tw.enter_debugger ();
+      }
+  }
+
+  void error_system::vwarning (const char *name, const char *id,
+                               const char *fmt, va_list args)
+  {
+    if (discard_warning_messages ())
+      return;
+
+    flush_stdout ();
+
+    std::ostringstream output_buf;
+
+    vformat (output_buf, fmt, args);
+
+    // FIXME: we really want to capture the message before it has all the
+    //        formatting goop attached to it.  We probably also want just the
+    //        message, not the traceback information.
+
+    std::string base_msg = output_buf.str ();
+    std::string msg_string;
+
+    if (name)
+      msg_string = std::string (name) + ": ";
+
+    msg_string += base_msg + '\n';
+
+    last_warning_id (id);
+    last_warning_message (base_msg);
+
+    if (! quiet_warning ())
+      {
+        octave_diary << msg_string;
+
+        std::cerr << msg_string;
+      }
+  }
+
+  void error_system::error_1 (execution_exception& e, std::ostream& os,
+                              const char *name, const char *id,
+                              const char *fmt, va_list args, bool with_cfn)
+  {
+    bool show_stack_trace = false;
+
+    if (fmt)
+      {
+        if (*fmt)
+          {
+            size_t len = strlen (fmt);
+
+            if (len > 0)
+              {
+                if (fmt[len - 1] == '\n')
+                  {
+                    if (len > 1)
+                      {
+                        std::string tmp_fmt (fmt, len - 1);
+                        verror (true, os, name, id, tmp_fmt.c_str (),
+                                args, with_cfn);
+                      }
+
+                    // If format ends with newline, suppress stack trace.
+                    e.set_stack_trace ();
+                  }
+                else
+                  {
+                    verror (true, os, name, id, fmt, args, with_cfn);
+
+                    tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+                    if (tw.in_user_code () && ! discard_error_messages ())
+                      show_stack_trace = true;
+                  }
+              }
+          }
+      }
+    else
+      panic ("error_1: invalid format");
+
+    maybe_enter_debugger (e, show_stack_trace);
+
+    throw e;
+  }
+
+  void error_system::error_1 (std::ostream& os, const char *name,
+                              const char *id, const char *fmt,
+                              va_list args, bool with_cfn = false)
+  {
+    execution_exception e = make_execution_exception ("error");
+
+    error_1 (e, os, name, id, fmt, args, with_cfn);
+  }
+
+  void error_system::vwarning (const char *id, const char *fmt, va_list args)
+  {
+    int warn_opt = warning_enabled (id);
+
+    if (warn_opt == 2)
+      {
+        // Handle this warning as an error.
+
+        error_1 (std::cerr, "error", id, fmt, args);
+      }
+    else if (warn_opt == 1)
+      {
+        bool fmt_suppresses_backtrace = false;
+        size_t fmt_len = (fmt ? strlen (fmt) : 0);
+        fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\n');
+
+        if (fmt_suppresses_backtrace && fmt_len > 1)
+          {
+            // Strip newline before issuing warning
+            std::string tmp_fmt (fmt, fmt_len - 1);
+            vwarning ("warning", id, tmp_fmt.c_str (), args);
+          }
+        else
+          vwarning ("warning", id, fmt, args);
+
+        tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+        bool in_user_code = tw.in_user_code ();
+
+        if (! fmt_suppresses_backtrace && in_user_code
+            && backtrace_on_warning ()
+            && ! discard_warning_messages ())
+          pr_where (std::cerr, "warning");
+
+        bp_table& bptab = tw.get_bp_table ();
+
+        if ((application::interactive ()
+             || application::forced_interactive ())
+            && debug_on_warning () && in_user_code && bptab.debug_on_warn (id))
+          {
+            unwind_protect frame;
+
+            frame.protect_var (m_debug_on_warning);
+            m_debug_on_warning = false;
+
+            tw.enter_debugger ();
+          }
+      }
+  }
+
+  void error_system::rethrow_error (const char *id, const char *fmt, ...)
+  {
+    va_list args;
+    va_start (args, fmt);
+    verror (false, std::cerr, nullptr, id, fmt, args);
+    va_end (args);
+  }
+
+  void error_system::rethrow_error (const std::string& id,
+                                    const std::string& msg,
+                                    const octave_map& stack)
+  {
+    execution_exception e = make_execution_exception ("error");
+
+    if (! stack.isempty ()
+        && ! (stack.contains ("file") && stack.contains ("name")
+              && stack.contains ("line")))
+      error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'");
+
+    last_error_id (id);
+    last_error_message (msg);
+    last_error_stack (stack);
+
+    size_t len = msg.length ();
+
+    std::string tmp_msg (msg);
+    if (len > 1 && tmp_msg[len-1] == '\n')
+      {
+        tmp_msg.erase (len - 1);
+
+        rethrow_error (id.c_str (), "%s\n", tmp_msg.c_str ());
+      }
+    else
+      rethrow_error (id.c_str (), "%s", tmp_msg.c_str ());
+
+    if (! stack.isempty ())
+      {
+        std::ostringstream buf;
+
+        pr_where (buf, "error", make_stack_frame_list (stack));
+
+        e.set_stack_trace (buf.str ());
+      }
+
+    throw e;
+  }
+
+  void error_system::vpanic (const char *fmt, va_list args)
+  {
+    buffer_error_messages (0);
+    discard_error_messages (false);
+
+    verror (false, std::cerr, "panic", "", fmt, args);
+
+    abort ();
+  }
+
+  void error_system::panic (const char *fmt, ...)
+  {
+    va_list args;
+    va_start (args, fmt);
+    vpanic (fmt, args);
+    va_end (args);
+  }
+
+  octave_scalar_map error_system::warning_query (const std::string& id_arg)
+  {
+    octave_scalar_map retval;
+
+    std::string id = id_arg;
+
+    if (id == "last")
+      id = last_warning_id ();
+
+    octave_map opts = warning_options ();
+
+    Cell ident = opts.contents ("identifier");
+    Cell state = opts.contents ("state");
+
+    octave_idx_type nel = ident.numel ();
+
+    assert (nel != 0);
+
+    bool found = false;
+
+    std::string val;
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        if (ident(i).string_value () == id)
+          {
+            val = state(i).string_value ();
+            found = true;
+            break;
+          }
+      }
+
+    if (! found)
+      {
+        for (octave_idx_type i = 0; i < nel; i++)
+          {
+            if (ident(i).string_value () == "all")
+              {
+                val = state(i).string_value ();
+                found = true;
+                break;
+              }
+          }
+      }
+
+    // The warning state "all" is always supposed to remain in the list,
+    // so we should always find a state, either explicitly or by using the
+    // state for "all".
+
+    assert (found);
+
+    retval.assign ("identifier", id);
+    retval.assign ("state", val);
+
+    return retval;
+  }
+
+  std::string error_system::default_warning_state (void)
+  {
+    std::string retval = "on";
+
+    octave_map opts = warning_options ();
+
+    Cell ident = opts.contents ("identifier");
+    Cell state = opts.contents ("state");
+
+    octave_idx_type nel = ident.numel ();
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        if (ident(i).string_value () == "all")
+          {
+            retval = state(i).string_value ();
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  void error_system::display_warning_options (std::ostream& os)
+  {
+    octave_map opts = warning_options ();
+
+    Cell ident = opts.contents ("identifier");
+    Cell state = opts.contents ("state");
+
+    octave_idx_type nel = ident.numel ();
+
+    std::string all_state = default_warning_state ();
+
+    if (all_state == "on")
+      os << "By default, warnings are enabled.";
+    else if (all_state == "off")
+      os << "By default, warnings are disabled.";
+    else if (all_state == "error")
+      os << "By default, warnings are treated as errors.";
+    else
+      panic_impossible ();
+
+    if (nel > 1)
+      os << "\n\n";
+
+    // The state for all is always supposed to be first in the list.
+
+    for (octave_idx_type i = 1; i < nel; i++)
+      {
+        std::string tid = ident(i).string_value ();
+        std::string tst = state(i).string_value ();
+
+        os << std::setw (7) << tst << "  " << tid << "\n";
+      }
+
+    os << std::endl;
+  }
+
+  void error_system::set_warning_option (const std::string& state,
+                                         const std::string& ident)
+  {
+    std::string all_state = default_warning_state ();
+
+    if (state != "on" && state != "off" && state != "error")
+      error ("invalid warning state: %s", state.c_str ());
+
+    octave_map opts = warning_options ();
+
+    Cell tid = opts.contents ("identifier");
+    Cell tst = opts.contents ("state");
+
+    octave_idx_type nel = tid.numel ();
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        if (tid(i).string_value () == ident)
+          {
+            // We found it in the current list of options.  If the state
+            // for "all" is same as arg1, we can simply remove the item
+            // from the list.
+
+            if (state == all_state && ident != "all")
+              {
+                for (i = i + 1; i < nel; i++)
+                  {
+                    tid(i-1) = tid(i);
+                    tst(i-1) = tst(i);
+                  }
+
+                tid.resize (dim_vector (1, nel-1));
+                tst.resize (dim_vector (1, nel-1));
+              }
+            else
+              tst(i) = state;
+
+            opts.clear ();
+
+            opts.assign ("identifier", tid);
+            opts.assign ("state", tst);
+
+            warning_options (opts);
+
+            return;
+          }
+      }
+
+    // The option wasn't already in the list.  Append it.
+
+    tid.resize (dim_vector (1, nel+1));
+    tst.resize (dim_vector (1, nel+1));
+
+    tid(nel) = ident;
+    tst(nel) = state;
+
+    opts.clear ();
+
+    opts.assign ("identifier", tid);
+    opts.assign ("state", tst);
+
+    warning_options (opts);
+  }
+
+  void error_system::disable_warning (const std::string& id)
+  {
+    set_warning_option ("off", id);
+  }
+
+  void error_system::initialize_default_warning_state (void)
+  {
+    warning_options (octave::init_warning_options ("on"));
+
+    // Most people will want to have the following disabled.
+
+    disable_warning ("Octave:array-as-logical");
+    disable_warning ("Octave:array-to-scalar");
+    disable_warning ("Octave:array-to-vector");
+    disable_warning ("Octave:imag-to-real");
+    disable_warning ("Octave:language-extension");
+    disable_warning ("Octave:missing-semicolon");
+    disable_warning ("Octave:neg-dim-as-zero");
+    disable_warning ("Octave:resize-on-range-error");
+    disable_warning ("Octave:separator-insert");
+    disable_warning ("Octave:single-quote-string");
+    disable_warning ("Octave:str-to-num");
+    disable_warning ("Octave:mixed-string-concat");
+    disable_warning ("Octave:variable-switch-label");
+  }
+
+  void error_system::interpreter_try (octave::unwind_protect& frame,
+                                      try_option opt)
+  {
+    switch (opt)
+      {
+      case buffer:
+        frame.protect_var (m_buffer_error_messages);
+        m_buffer_error_messages++;
+        break;
+
+      case discard:
+        frame.protect_var (m_discard_error_messages);
+        m_discard_error_messages = true;
+        break;
+      }
+
+    frame.protect_var (m_debug_on_error);
+    m_debug_on_error = false;
+
+    frame.protect_var (m_debug_on_warning);
+    m_debug_on_warning = false;
+
+    // Leave debug_on_caught as it was, so errors in try/catch are still
+    // caught.
+  }
+}
+
 octave::execution_exception
 make_execution_exception (const char *who)
 {
@@ -351,85 +1167,6 @@
   return retval;
 }
 
-static void
-maybe_enter_debugger (octave::execution_exception& e,
-                      bool show_stack_trace = false)
-{
-  octave::call_stack& cs = octave::__get_call_stack__ ("maybe_enter_debugger");
-  octave::bp_table& bptab = octave::__get_bp_table__ ("maybe_enter_debugger");
-
-  if ((octave::application::interactive ()
-       || octave::application::forced_interactive ())
-      && ((Vdebug_on_error && bptab.debug_on_err (last_error_id ()))
-          || (Vdebug_on_caught && bptab.debug_on_caught (last_error_id ())))
-      && cs.caller_user_code ())
-    {
-      octave::unwind_protect frame;
-      frame.protect_var (Vdebug_on_error);
-      Vdebug_on_error = false;
-
-      octave::tree_evaluator& tw
-        = octave::__get_evaluator__ ("maybe_enter_debugger");
-
-      tw.debug_mode (true);
-      tw.current_frame (cs.current_frame ());
-
-      if (show_stack_trace)
-        {
-          std::string stack_trace = e.info ();
-
-          if (! stack_trace.empty ())
-            {
-              std::cerr << stack_trace;
-
-              e.set_stack_trace ();
-            }
-        }
-
-      octave::input_system& input_sys
-        = octave::__get_input_system__ ("maybe_enter_debugger");
-
-      input_sys.keyboard ();
-    }
-}
-
-// Warning messages are never buffered.
-
-static void
-vwarning (const char *name, const char *id, const char *fmt, va_list args)
-{
-  if (discard_warning_messages)
-    return;
-
-  octave::flush_stdout ();
-
-  std::ostringstream output_buf;
-
-  octave::vformat (output_buf, fmt, args);
-
-  // FIXME: we really want to capture the message before it has all the
-  //        formatting goop attached to it.  We probably also want just the
-  //        message, not the traceback information.
-
-  std::string base_msg = output_buf.str ();
-  std::string msg_string;
-
-  if (name)
-    msg_string = std::string (name) + ": ";
-
-  msg_string += base_msg + '\n';
-
-  Vlast_warning_id = id;
-  Vlast_warning_message = base_msg;
-
-  if (! Vquiet_warning)
-    {
-      octave_diary << msg_string;
-
-      std::cerr << msg_string;
-    }
-}
-
 void
 vmessage (const char *name, const char *fmt, va_list args)
 {
@@ -461,31 +1198,12 @@
   va_end (args);
 }
 
-OCTAVE_NORETURN static
-void
-usage_1 (octave::execution_exception& e, const char *id,
-         const char *fmt, va_list args)
-{
-  verror (true, std::cerr, "usage", id, fmt, args);
-
-  maybe_enter_debugger (e);
-
-  throw e;
-}
-
-OCTAVE_NORETURN static
-void
-usage_1 (const char *id, const char *fmt, va_list args)
-{
-  octave::execution_exception e = make_execution_exception ("usage");
-
-  usage_1 (e, id, fmt, args);
-}
-
 void
 vusage_with_id (const char *id, const char *fmt, va_list args)
 {
-  usage_1 (id, fmt, args);
+  octave::execution_exception e = make_execution_exception ("usage");
+
+  vusage (e, id, fmt, args);
 }
 
 void
@@ -497,67 +1215,6 @@
   va_end (args);
 }
 
-OCTAVE_NORETURN static
-void
-error_1 (octave::execution_exception& e, std::ostream& os,
-         const char *name, const char *id, const char *fmt,
-         va_list args, bool with_cfn = false)
-{
-  bool show_stack_trace = false;
-
-  if (fmt)
-    {
-      if (*fmt)
-        {
-          size_t len = strlen (fmt);
-
-          if (len > 0)
-            {
-              if (fmt[len - 1] == '\n')
-                {
-                  if (len > 1)
-                    {
-                      std::string tmp_fmt (fmt, len - 1);
-                      verror (true, os, name, id, tmp_fmt.c_str (),
-                              args, with_cfn);
-                    }
-
-                  // If format ends with newline, suppress stack trace.
-                  e.set_stack_trace ();
-                }
-              else
-                {
-                  verror (true, os, name, id, fmt, args, with_cfn);
-
-                  octave::call_stack& cs
-                    = octave::__get_call_stack__ ("error_1");
-
-                  bool in_user_code = cs.caller_user_code () != nullptr;
-
-                  if (in_user_code && ! discard_error_messages)
-                    show_stack_trace = true;
-                }
-            }
-        }
-    }
-  else
-    panic ("error_1: invalid format");
-
-  maybe_enter_debugger (e, show_stack_trace);
-
-  throw e;
-}
-
-OCTAVE_NORETURN static
-void
-error_1 (std::ostream& os, const char *name, const char *id,
-         const char *fmt, va_list args, bool with_cfn = false)
-{
-  octave::execution_exception e = make_execution_exception ("error");
-
-  error_1 (e, os, name, id, fmt, args, with_cfn);
-}
-
 void
 verror (const char *fmt, va_list args)
 {
@@ -633,163 +1290,17 @@
   va_end (args);
 }
 
-static int
-check_state (const std::string& state)
-{
-  // -1: not found
-  //  0: found, "off"
-  //  1: found, "on"
-  //  2: found, "error"
-
-  if (state == "off")
-    return 0;
-  else if (state == "on")
-    return 1;
-  else if (state == "error")
-    return 2;
-  else
-    return -1;
-}
-
-// For given warning ID, return 0 if warnings are disabled, 1 if
-// enabled, and 2 if the given ID should be an error instead of a
-// warning.
-
-int
-warning_enabled (const std::string& id)
+int warning_enabled (const std::string& id)
 {
-  int retval = 0;
-
-  int all_state = -1;
-  int id_state = -1;
-
-  octave_idx_type nel = warning_options.numel ();
-
-  if (nel > 0)
-    {
-      Cell identifier = warning_options.contents ("identifier");
-      Cell state = warning_options.contents ("state");
-
-      bool all_found = false;
-      bool id_found = false;
-
-      for (octave_idx_type i = 0; i < nel; i++)
-        {
-          octave_value ov = identifier(i);
-          std::string ovs = ov.string_value ();
-
-          if (! all_found && ovs == "all")
-            {
-              all_state = check_state (state(i).string_value ());
-
-              if (all_state >= 0)
-                all_found = true;
-            }
-
-          if (! id_found && ovs == id)
-            {
-              id_state = check_state (state(i).string_value ());
-
-              if (id_state >= 0)
-                id_found = true;
-            }
-
-          if (all_found && id_found)
-            break;
-        }
-    }
-
-  // If "all" is not present, assume warnings are enabled.
-  if (all_state == -1)
-    all_state = 1;
-
-  if (all_state == 0)
-    {
-      if (id_state >= 0)
-        retval = id_state;
-    }
-  else if (all_state == 1)
-    {
-      if (id_state == 0 || id_state == 2)
-        retval = id_state;
-      else
-        retval = all_state;
-    }
-  else if (all_state == 2)
-    {
-      if (id_state == 0)
-        retval= id_state;
-      else
-        retval = all_state;
-    }
-
-  return retval;
-}
-
-static void
-warning_1 (const char *id, const char *fmt, va_list args)
-{
-  int warn_opt = warning_enabled (id);
-
-  if (warn_opt == 2)
-    {
-      // Handle this warning as an error.
-
-      error_1 (std::cerr, "error", id, fmt, args);
-    }
-  else if (warn_opt == 1)
-    {
-      bool fmt_suppresses_backtrace = false;
-      size_t fmt_len = (fmt ? strlen (fmt) : 0);
-      fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\n');
-
-      if (fmt_suppresses_backtrace && fmt_len > 1)
-        {
-          // Strip newline before issuing warning
-          std::string tmp_fmt (fmt, fmt_len - 1);
-          vwarning ("warning", id, tmp_fmt.c_str (), args);
-        }
-      else
-        vwarning ("warning", id, fmt, args);
-
-      octave::call_stack& cs = octave::__get_call_stack__ ("warning_1");
-
-      bool in_user_code = cs.caller_user_code () != nullptr;
-
-      if (! fmt_suppresses_backtrace && in_user_code
-          && Vbacktrace_on_warning
-          && ! discard_warning_messages)
-        pr_where (std::cerr, "warning");
-
-      octave::bp_table& bptab
-        = octave::__get_bp_table__ ("warning_1");
-
-      if ((octave::application::interactive ()
-           || octave::application::forced_interactive ())
-          && Vdebug_on_warning && in_user_code && bptab.debug_on_warn (id))
-        {
-          octave::unwind_protect frame;
-          frame.protect_var (Vdebug_on_warning);
-          Vdebug_on_warning = false;
-
-          octave::tree_evaluator& tw
-            = octave::__get_evaluator__ ("warning_1");
-
-          tw.debug_mode (true);
-          tw.current_frame (cs.current_frame ());
-
-          octave::input_system& input_sys
-            = octave::__get_input_system__ ("warning_1");
-
-          input_sys.keyboard ();
-        }
-    }
+  octave::error_system& es = octave::__get_error_system__ ("warning_enabled");
+
+  return es.warning_enabled (id);
 }
 
 void
 vwarning (const char *fmt, va_list args)
 {
-  warning_1 ("", fmt, args);
+  vwarning ("", fmt, args);
 }
 
 void
@@ -804,7 +1315,7 @@
 void
 vwarning_with_id (const char *id, const char *fmt, va_list args)
 {
-  warning_1 (id, fmt, args);
+  vwarning (id, fmt, args);
 }
 
 void
@@ -812,7 +1323,7 @@
 {
   va_list args;
   va_start (args, fmt);
-  vwarning_with_id (id, fmt, args);
+  vwarning (id, fmt, args);
   va_end (args);
 }
 
@@ -855,177 +1366,33 @@
   va_end (args);
 }
 
-static std::list<error_stack_frame>
-make_stack_frame_list (const octave_map& stack)
+OCTAVE_NORETURN
+void
+vpanic (const char *fmt, va_list args)
 {
-  std::list<error_stack_frame> frames;
-
-  Cell name = stack.contents ("name");
-  Cell line = stack.contents ("line");
-  Cell column;
-  bool have_column = false;
-  if (stack.contains ("column"))
-    {
-      have_column = true;
-      column = stack.contents ("column");
-    }
-
-  octave_idx_type nel = name.numel ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      error_stack_frame frame;
-
-      frame.name = name(i).string_value ();
-      frame.line = line(i).int_value ();
-      frame.column = (have_column ? column(i).int_value () : -1);
-
-      frames.push_back (frame);
-    }
-
-  return frames;
-}
-
-static void
-rethrow_error_1 (const char *id, const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  verror (false, std::cerr, nullptr, id, fmt, args);
-  va_end (args);
+  octave::error_system& es = octave::__get_error_system__ ("vpanic");
+
+  es.vpanic (fmt, args);
 }
 
-OCTAVE_NORETURN static
-void
-rethrow_error (const std::string& id, const std::string& msg,
-               const octave_map& stack)
-{
-  octave::execution_exception e = make_execution_exception ("error");
-
-  if (! stack.isempty ()
-      && ! (stack.contains ("file") && stack.contains ("name")
-            && stack.contains ("line")))
-    error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'");
-
-  Vlast_error_id = id;
-  Vlast_error_message = msg;
-  Vlast_error_stack = stack;
-
-  size_t len = msg.length ();
-
-  std::string tmp_msg (msg);
-  if (len > 1 && tmp_msg[len-1] == '\n')
-    {
-      tmp_msg.erase (len - 1);
-
-      rethrow_error_1 (id.c_str (), "%s\n", tmp_msg.c_str ());
-    }
-  else
-    rethrow_error_1 (id.c_str (), "%s", tmp_msg.c_str ());
-
-  if (! stack.isempty ())
-    {
-      std::ostringstream buf;
-
-      pr_where (buf, "error", make_stack_frame_list (stack));
-
-      e.set_stack_trace (buf.str ());
-    }
-
-  throw e;
-}
-
+OCTAVE_NORETURN
 void
 panic (const char *fmt, ...)
 {
   va_list args;
   va_start (args, fmt);
-  buffer_error_messages = 0;
-  discard_error_messages = false;
-  verror (false, std::cerr, "panic", "", fmt, args);
-  va_end (args);
-  abort ();
-}
-
-static void
-defun_usage_message_1 (const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  error_1 (octave_stdout, nullptr, "", fmt, args);
+  vpanic (fmt, args);
   va_end (args);
 }
 
 void
 defun_usage_message (const std::string& msg)
 {
-  defun_usage_message_1 ("%s", msg.c_str ());
+  defun_usage_message ("%s", msg.c_str ());
 }
 
-typedef void (*error_fun)(const char *, const char *, ...);
-
-extern octave_value_list Fsprintf (const octave_value_list&, int);
-
-static std::string
-handle_message (error_fun f, const char *id, const char *msg,
-                const octave_value_list& args, bool have_fmt)
-{
-  std::string retval;
-
-  std::string tmpstr;
-
-  if (args.length () > 0)
-    {
-      octave_value arg;
-
-      if (have_fmt)
-        {
-          octave_value_list tmp = Fsprintf (args, 1);
-          arg = tmp(0);
-        }
-      else
-        arg = args(0);
-
-      if (arg.is_defined ())
-        {
-          if (arg.isempty ())
-            return retval;
-          else if (arg.is_string ())
-            {
-              tmpstr = arg.string_value ();  // 2-stage assignment required
-              msg = tmpstr.c_str ();         // in order to generate pointer
-                                             // to valid memory.
-            }
-        }
-    }
-
-  // Ugh.
-
-  size_t len = strlen (msg);
-
-  if (len > 0)
-    {
-      if (msg[len - 1] == '\n')
-        {
-          if (len > 1)
-            {
-              std::string tmp_msg (msg, len - 1);
-              f (id, "%s\n", tmp_msg.c_str ());
-              retval = tmp_msg;
-            }
-        }
-      else
-        {
-          f (id, "%s", msg);
-          retval = msg;
-        }
-    }
-
-  return retval;
-}
-
-DEFUN (rethrow, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (rethrow, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} rethrow (@var{err})
 Reissue a previous error as defined by @var{err}.
 
@@ -1047,64 +1414,18 @@
   std::string msg = err.contents ("message").string_value ();
   std::string id = err.contents ("identifier").string_value ();
 
-  octave_map err_stack = initialize_last_error_stack ();
+  octave_map err_stack = octave::init_error_stack (interp);
 
   if (err.contains ("stack"))
     err_stack = err.contents ("stack").xmap_value ("ERR.STACK must be a struct");
 
-  rethrow_error (id, msg, err_stack);
+  octave::error_system& es = interp.get_error_system ();
+
+  es.rethrow_error (id, msg, err_stack);
 
   return ovl ();
 }
 
-// Determine whether the first argument to error or warning function
-// should be handled as the message identifier or as the format string.
-
-static bool
-maybe_extract_message_id (const std::string& caller,
-                          const octave_value_list& args,
-                          octave_value_list& nargs,
-                          std::string& id)
-{
-  nargs = args;
-  id = "";
-
-  int nargin = args.length ();
-
-  bool have_fmt = nargin > 1;
-
-  if (nargin > 0)
-    {
-      std::string arg1 = args(0).string_value ();
-
-      // For compatibility with Matlab, an identifier must contain ':',
-      // but not at the beginning or the end, and it must not contain '%'
-      // (even if it is not a valid conversion operator) or whitespace.
-
-      if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos
-          && arg1.find (':') != std::string::npos
-          && arg1[0] != ':'
-          && arg1.back () != ':')
-        {
-          if (nargin > 1)
-            {
-              id = arg1;
-
-              nargs.resize (nargin-1);
-
-              for (int i = 1; i < nargin; i++)
-                nargs(i-1) = args(i);
-            }
-          else
-            nargs(0) = "call to " + caller
-                       + " with message identifier '" + arg1
-                       + "' requires message";
-        }
-    }
-
-  return have_fmt;
-}
-
 DEFUN (error, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} error (@var{template}, @dots{})
@@ -1248,177 +1569,6 @@
   return retval;
 }
 
-static octave_scalar_map
-warning_query (const std::string& id_arg)
-{
-  octave_scalar_map retval;
-
-  std::string id = id_arg;
-
-  if (id == "last")
-    id = Vlast_warning_id;
-
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
-
-  octave_idx_type nel = ident.numel ();
-
-  assert (nel != 0);
-
-  bool found = false;
-
-  std::string val;
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      if (ident(i).string_value () == id)
-        {
-          val = state(i).string_value ();
-          found = true;
-          break;
-        }
-    }
-
-  if (! found)
-    {
-      for (octave_idx_type i = 0; i < nel; i++)
-        {
-          if (ident(i).string_value () == "all")
-            {
-              val = state(i).string_value ();
-              found = true;
-              break;
-            }
-        }
-    }
-
-  // The warning state "all" is always supposed to remain in the list,
-  // so we should always find a state, either explicitly or by using the
-  // state for "all".
-
-  assert (found);
-
-  retval.assign ("identifier", id);
-  retval.assign ("state", val);
-
-  return retval;
-}
-
-static std::string
-default_warning_state (void)
-{
-  std::string retval = "on";
-
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
-
-  octave_idx_type nel = ident.numel ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      if (ident(i).string_value () == "all")
-        {
-          retval = state(i).string_value ();
-          break;
-        }
-    }
-
-  return retval;
-}
-
-static void
-display_warning_options (std::ostream& os)
-{
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
-
-  octave_idx_type nel = ident.numel ();
-
-  std::string all_state = default_warning_state ();
-
-  if (all_state == "on")
-    os << "By default, warnings are enabled.";
-  else if (all_state == "off")
-    os << "By default, warnings are disabled.";
-  else if (all_state == "error")
-    os << "By default, warnings are treated as errors.";
-  else
-    panic_impossible ();
-
-  if (nel > 1)
-    os << "\n\n";
-
-  // The state for all is always supposed to be first in the list.
-
-  for (octave_idx_type i = 1; i < nel; i++)
-    {
-      std::string tid = ident(i).string_value ();
-      std::string tst = state(i).string_value ();
-
-      os << std::setw (7) << tst << "  " << tid << "\n";
-    }
-
-  os << std::endl;
-}
-
-static void
-set_warning_option (const std::string& state, const std::string& ident)
-{
-  std::string all_state = default_warning_state ();
-
-  if (state != "on" && state != "off" && state != "error")
-    error ("invalid warning state: %s", state.c_str ());
-
-  Cell tid = warning_options.contents ("identifier");
-  Cell tst = warning_options.contents ("state");
-
-  octave_idx_type nel = tid.numel ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      if (tid(i).string_value () == ident)
-        {
-          // We found it in the current list of options.  If the state
-          // for "all" is same as arg1, we can simply remove the item
-          // from the list.
-
-          if (state == all_state && ident != "all")
-            {
-              for (i = i + 1; i < nel; i++)
-                {
-                  tid(i-1) = tid(i);
-                  tst(i-1) = tst(i);
-                }
-
-              tid.resize (dim_vector (1, nel-1));
-              tst.resize (dim_vector (1, nel-1));
-            }
-          else
-            tst(i) = state;
-
-          warning_options.clear ();
-
-          warning_options.assign ("identifier", tid);
-          warning_options.assign ("state", tst);
-
-          return;
-        }
-    }
-
-  // The option wasn't already in the list.  Append it.
-
-  tid.resize (dim_vector (1, nel+1));
-  tst.resize (dim_vector (1, nel+1));
-
-  tid(nel) = ident;
-  tst(nel) = state;
-
-  warning_options.clear ();
-
-  warning_options.assign ("identifier", tid);
-  warning_options.assign ("state", tst);
-}
-
 DEFMETHOD (warning, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} warning (@var{template}, @dots{})
@@ -1546,6 +1696,8 @@
   int nargin = args.length ();
   bool done = false;
 
+  octave::error_system& es = interp.get_error_system ();
+
   if (nargin > 0 && args.all_strings_p ())
     {
       string_vector argv = args.make_argv ("warning");
@@ -1561,26 +1713,22 @@
           // Prepare output structure
           octave_map old_warning_options;
           if (arg2 == "all")
-            old_warning_options = warning_options;
+            old_warning_options = es.warning_options ();
           else
-            old_warning_options = octave_map (warning_query (arg2));
-
-          octave::symbol_table& symtab = interp.get_symbol_table ();
-
-          if (nargin == 3 && argv[3] == "local"
-              && ! symtab.at_top_level ())
+            old_warning_options = octave_map (es.warning_query (arg2));
+
+          if (nargin == 3 && argv[3] == "local" && ! interp.at_top_level ())
             {
-              octave::symbol_scope scope
-                = symtab.require_current_scope ("warning");
-
-              octave_scalar_map val = warning_query (arg2);
+              octave_scalar_map val = es.warning_query (arg2);
 
               octave_value curr_state = val.contents ("state");
 
               // FIXME: this might be better with a dictionary object.
 
+              octave::tree_evaluator& tw = interp.get_evaluator ();
+
               octave_value curr_warning_states
-                = scope.varval (".saved_warning_states.");
+                = tw.get_auto_fcn_var (octave::stack_frame::SAVED_WARNING_STATES);
 
               octave_map m;
 
@@ -1628,7 +1776,7 @@
               m.contents ("identifier") = ids;
               m.contents ("state") = states;
 
-              scope.force_assign (".saved_warning_states.", m);
+              tw.set_auto_fcn_var (octave::stack_frame::SAVED_WARNING_STATES, m);
 
               // Now ignore the "local" argument and continue to
               // handle the current setting.
@@ -1665,7 +1813,7 @@
               tmp.assign ("identifier", id);
               tmp.assign ("state", st);
 
-              warning_options = tmp;
+              es.warning_options (tmp);
 
               done = true;
             }
@@ -1673,7 +1821,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vbacktrace_on_warning = (arg1 == "on");
+                  es.backtrace_on_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1681,7 +1829,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vdebug_on_warning = (arg1 == "on");
+                  es.debug_on_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1689,7 +1837,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vverbose_warning = (arg1 == "on");
+                  es.verbose_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1697,16 +1845,16 @@
             {
               if (arg1 != "error")
                 {
-                  Vquiet_warning = (arg1 == "on");
+                  es.quiet_warning (arg1 == "on");
                   done = true;
                 }
             }
           else
             {
               if (arg2 == "last")
-                arg2 = Vlast_warning_id;
-
-              set_warning_option (arg1, arg2);
+                arg2 = es.last_warning_id ();
+
+              es.set_warning_option (arg1, arg2);
 
               done = true;
             }
@@ -1717,25 +1865,25 @@
       else if (arg1 == "query")
         {
           if (arg2 == "all")
-            retval = warning_options;
+            retval = es.warning_options ();
           else if (arg2 == "backtrace" || arg2 == "debug"
                    || arg2 == "verbose" || arg2 == "quiet")
             {
               octave_scalar_map tmp;
               tmp.assign ("identifier", arg2);
               if (arg2 == "backtrace")
-                tmp.assign ("state", Vbacktrace_on_warning ? "on" : "off");
+                tmp.assign ("state", es.backtrace_on_warning () ? "on" : "off");
               else if (arg2 == "debug")
-                tmp.assign ("state", Vdebug_on_warning ? "on" : "off");
+                tmp.assign ("state", es.debug_on_warning () ? "on" : "off");
               else if (arg2 == "verbose")
-                tmp.assign ("state", Vverbose_warning ? "on" : "off");
+                tmp.assign ("state", es.verbose_warning () ? "on" : "off");
               else
-                tmp.assign ("state", Vquiet_warning ? "on" : "off");
+                tmp.assign ("state", es.quiet_warning () ? "on" : "off");
 
               retval = tmp;
             }
           else
-            retval = warning_query (arg2);
+            retval = es.warning_query (arg2);
 
           done = true;
         }
@@ -1743,9 +1891,9 @@
   else if (nargin == 0)
     {
       if (nargout > 0)
-        retval = warning_options;
+        retval = es.warning_options ();
       else
-        display_warning_options (octave_stdout);
+        es.display_warning_options (octave_stdout);
 
       done = true;
     }
@@ -1776,7 +1924,7 @@
           for (octave_idx_type i = 0; i < nel; i++)
             {
               std::string tid = ident(i).string_value ();
-              oldstate(i) = warning_query (tid).getfield ("state");
+              oldstate(i) = es.warning_query (tid).getfield ("state");
             }
           old_warning_options.setfield ("state", oldstate);
 
@@ -1786,7 +1934,7 @@
               std::string tst = state(i).string_value ();
               std::string tid = ident(i).string_value ();
 
-              set_warning_option (tst, tid);
+              es.set_warning_option (tst, tid);
             }
 
           done = true;
@@ -1804,7 +1952,7 @@
 
       bool have_fmt = maybe_extract_message_id ("warning", args, nargs, id);
 
-      std::string prev_msg = Vlast_warning_message;
+      std::string prev_msg = es.last_warning_message ();
 
       std::string curr_msg = handle_message (warning_with_id, id.c_str (),
                                              "unspecified warning", nargs,
@@ -1825,7 +1973,7 @@
 
 /*
 %!test <*51997>
-%! id = "Octave:divide-by-zero";
+%! id = "Octave:logical-conversion";
 %! current = warning ("query", id);
 %! current_all = warning ();
 %! previous = warning (current_all);
@@ -1862,29 +2010,9 @@
 void
 disable_warning (const std::string& id)
 {
-  set_warning_option ("off", id);
-}
-
-void
-initialize_default_warning_state (void)
-{
-  initialize_warning_options ("on");
-
-  // Most people will want to have the following disabled.
-
-  disable_warning ("Octave:array-as-logical");
-  disable_warning ("Octave:array-to-scalar");
-  disable_warning ("Octave:array-to-vector");
-  disable_warning ("Octave:imag-to-real");
-  disable_warning ("Octave:language-extension");
-  disable_warning ("Octave:missing-semicolon");
-  disable_warning ("Octave:neg-dim-as-zero");
-  disable_warning ("Octave:resize-on-range-error");
-  disable_warning ("Octave:separator-insert");
-  disable_warning ("Octave:single-quote-string");
-  disable_warning ("Octave:str-to-num");
-  disable_warning ("Octave:mixed-string-concat");
-  disable_warning ("Octave:variable-switch-label");
+  octave::error_system& es = octave::__get_error_system__ ("disable_warning");
+
+  es.disable_warning (id);
 }
 
 DEFMETHOD (lasterror, interp, args, ,
@@ -1939,24 +2067,28 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave_scalar_map err;
 
-  err.assign ("message", Vlast_error_message);
-  err.assign ("identifier", Vlast_error_id);
-
-  err.assign ("stack", octave_value (Vlast_error_stack));
+  err.assign ("message", es.last_error_message ());
+  err.assign ("identifier", es.last_error_id ());
+
+  err.assign ("stack", octave_value (es.last_error_stack ()));
 
   if (nargin == 1)
     {
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
       if (args(0).is_string ())
         {
           if (args(0).string_value () != "reset")
             error ("lasterror: unrecognized string argument");
 
-          Vlast_error_message = "";
-          Vlast_error_id = "";
-
-          Vlast_error_stack = initialize_last_error_stack ();
+          es.last_error_message ("");
+          es.last_error_id ("");
+
+          es.last_error_stack (tw.empty_backtrace ());
         }
       else if (args(0).isstruct ())
         {
@@ -2023,28 +2155,22 @@
                 }
             }
 
-          Vlast_error_message = new_error_message;
-          Vlast_error_id = new_error_id;
+          es.last_error_message (new_error_message);
+          es.last_error_id (new_error_id);
 
           if (initialize_stack)
-            Vlast_error_stack = initialize_last_error_stack ();
+            es.last_error_stack (tw.empty_backtrace ());
           else if (new_err.contains ("stack"))
             {
               new_err_stack.setfield ("file", new_error_file);
               new_err_stack.setfield ("name", new_error_name);
               new_err_stack.setfield ("line", new_error_line);
               new_err_stack.setfield ("column", new_error_column);
-              Vlast_error_stack = new_err_stack;
+
+              es.last_error_stack (new_err_stack);
             }
           else
-            {
-              // No stack field.  Fill it in with backtrace info.
-              octave_idx_type curr_frame = -1;
-
-              octave::call_stack& cs = interp.get_call_stack ();
-
-              Vlast_error_stack = cs.backtrace (0, curr_frame);
-            }
+            es.last_error_stack (tw.backtrace ());
         }
       else
         error ("lasterror: argument must be a structure or a string");
@@ -2066,8 +2192,8 @@
 %! assert (y, x);
 */
 
-DEFUN (lasterr, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (lasterr, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {[@var{msg}, @var{msgid}] =} lasterr ()
 @deftypefnx {} {} lasterr (@var{msg})
 @deftypefnx {} {} lasterr (@var{msg}, @var{msgid})
@@ -2087,20 +2213,22 @@
   if (nargin > 2)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   string_vector argv = args.make_argv ("lasterr");
 
-  std::string prev_error_id = Vlast_error_id;
-  std::string prev_error_message = Vlast_error_message;
+  std::string prev_error_id = es.last_error_id ();
+  std::string prev_error_message = es.last_error_message ();
 
   if (nargin == 2)
     {
-      Vlast_error_id = argv[2];
-      Vlast_error_message = argv[1];
+      es.last_error_id (argv[2]);
+      es.last_error_message (argv[1]);
     }
   else if (nargin == 1)
     {
-      Vlast_error_id = "";
-      Vlast_error_message = argv[1];
+      es.last_error_id ("");
+      es.last_error_message (argv[1]);
     }
 
   if (nargin == 0 || nargout > 0)
@@ -2109,8 +2237,8 @@
     return ovl ();
 }
 
-DEFUN (lastwarn, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (lastwarn, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {[@var{msg}, @var{msgid}] =} lastwarn ()
 @deftypefnx {} {} lastwarn (@var{msg})
 @deftypefnx {} {} lastwarn (@var{msg}, @var{msgid})
@@ -2130,20 +2258,22 @@
   if (nargin > 2)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   string_vector argv = args.make_argv ("lastwarn");
 
-  std::string prev_warning_id = Vlast_warning_id;
-  std::string prev_warning_message = Vlast_warning_message;
+  std::string prev_warning_id = es.last_warning_id ();
+  std::string prev_warning_message = es.last_warning_message ();
 
   if (nargin == 2)
     {
-      Vlast_warning_id = argv[2];
-      Vlast_warning_message = argv[1];
+      es.last_warning_id (argv[2]);
+      es.last_warning_message (argv[1]);
     }
   else if (nargin == 1)
     {
-      Vlast_warning_id = "";
-      Vlast_warning_message = argv[1];
+      es.last_warning_id ("");
+      es.last_warning_message (argv[1]);
     }
 
   if (nargin == 0 || nargout > 0)
@@ -2152,8 +2282,8 @@
     return ovl ();
 }
 
-DEFUN (beep_on_error, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (beep_on_error, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} beep_on_error ()
 @deftypefnx {} {@var{old_val} =} beep_on_error (@var{new_val})
 @deftypefnx {} {} beep_on_error (@var{new_val}, "local")
@@ -2165,11 +2295,13 @@
 The original variable value is restored when exiting the function.
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (beep_on_error);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.beep_on_error (args, nargout);
 }
 
-DEFUN (debug_on_error, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (debug_on_error, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} debug_on_error ()
 @deftypefnx {} {@var{old_val} =} debug_on_error (@var{new_val})
 @deftypefnx {} {} debug_on_error (@var{new_val}, "local")
@@ -2185,11 +2317,13 @@
 @seealso{debug_on_warning, debug_on_interrupt}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (debug_on_error);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.debug_on_error (args, nargout);
 }
 
-DEFUN (debug_on_warning, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (debug_on_warning, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} debug_on_warning ()
 @deftypefnx {} {@var{old_val} =} debug_on_warning (@var{new_val})
 @deftypefnx {} {} debug_on_warning (@var{new_val}, "local")
@@ -2202,48 +2336,76 @@
 @seealso{debug_on_error, debug_on_interrupt}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (debug_on_warning);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.debug_on_warning (args, nargout);
 }
 
 std::string
 last_error_message (void)
 {
-  return Vlast_error_message;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_message");
+
+  return es.last_error_message ();
 }
 
 std::string
 last_error_id (void)
 {
-  return Vlast_error_id;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_id");
+
+  return es.last_error_id ();
 }
 
 octave_map
 last_error_stack (void)
 {
-  return Vlast_error_stack;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_stack");
+
+  return es.last_error_stack ();
 }
 
 std::string
 last_warning_message (void)
 {
-  return Vlast_warning_message;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_warning_message");
+
+  return es.last_warning_message ();
 }
 
 std::string
 last_warning_id (void)
 {
-  return Vlast_warning_id;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_warning_id");
+
+  return es.last_warning_id ();
 }
 
 void
-interpreter_try (octave::unwind_protect& frame)
+interpreter_try (octave::unwind_protect& frame,
+                 octave::error_system::try_option opt)
 {
-  frame.protect_var (buffer_error_messages);
-  frame.protect_var (Vdebug_on_error);
-  frame.protect_var (Vdebug_on_warning);
-
-  buffer_error_messages++;
-  Vdebug_on_error = false;
-  Vdebug_on_warning = false;
-  // leave Vdebug_on_caught as it was, so errors in try/catch are still caught
+  octave::error_system& es
+    = octave::__get_error_system__ ("interpreter_try");
+
+  es.interpreter_try (frame, opt);
 }
+
+// Deprecated variables and functions.
+
+// This variable is obsolete and always has the value 0.
+int error_state = 0;
+
+void
+reset_error_handler (void)
+{
+  octave::error_system& es
+    = octave::__get_error_system__ ("reset_error_handler");
+
+  es.reset ();
+}
--- a/libinterp/corefcn/error.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/error.h	Fri Jul 12 12:14:43 2019 -0400
@@ -31,18 +31,398 @@
 
 #include "unwind-prot.h"
 
-class octave_map;
+#include "oct-map.h"
+
 class octave_value_list;
 namespace octave
 {
   class execution_exception;
 }
 
+namespace octave
+{
+  class error_system
+  {
+  public:
+
+    enum try_option
+      {
+        buffer = 1,
+        discard = 2,
+      };
+
+    error_system (interpreter& interp);
+
+    error_system (const error_system&) = delete;
+
+    error_system& operator = (const error_system&) = delete;
+
+    ~error_system (void) = default;
+
+    void reset (void)
+    {
+      m_buffer_error_messages = 0;
+      m_in_try_catch = 0;
+      m_discard_error_messages = false;
+    }
+
+    octave_value debug_on_error (const octave_value_list& args, int nargout);
+
+    void set_debug_on_error (bool flag) { m_debug_on_error = flag; }
+
+    bool debug_on_error (void) const { return m_debug_on_error; }
+
+    bool debug_on_error (bool flag)
+    {
+      bool val = m_debug_on_error;
+      m_debug_on_error = flag;
+      return val;
+    }
+
+    octave_value debug_on_caught (const octave_value_list& args, int nargout);
+
+    void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; }
+
+    bool debug_on_caught (void) const { return m_debug_on_caught; }
+
+    bool debug_on_caught (bool flag)
+    {
+      bool val = m_debug_on_caught;
+      m_debug_on_caught = flag;
+      return val;
+    }
+
+    octave_value debug_on_warning (const octave_value_list& args, int nargout);
+
+    void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; }
+
+    bool debug_on_warning (void) const { return m_debug_on_warning; }
+
+    bool debug_on_warning (bool flag)
+    {
+      bool val = m_debug_on_warning;
+      m_debug_on_warning = flag;
+      return val;
+    }
+
+    octave_value buffer_error_messages (const octave_value_list& args, int nargout);
+
+    void set_buffer_error_messages (int val) { m_buffer_error_messages = val; }
+
+    int buffer_error_messages (void) const { return m_buffer_error_messages; }
+
+    int buffer_error_messages (int new_val)
+    {
+      int val = m_buffer_error_messages;
+      m_buffer_error_messages = new_val;
+      return val;
+    }
+
+    octave_value in_try_catch (const octave_value_list& args, int nargout);
+
+    void set_in_try_catch (int val) { m_in_try_catch = val; }
+
+    int in_try_catch (void) const { return m_in_try_catch; }
+
+    int in_try_catch (int new_val)
+    {
+      int val = m_in_try_catch;
+      m_in_try_catch = new_val;
+      return val;
+    }
+
+    octave_value discard_error_messages (const octave_value_list& args, int nargout);
+
+    void set_discard_error_messages (bool flag) { m_discard_error_messages = flag; }
+
+    bool discard_error_messages (void) const { return m_discard_error_messages; }
+
+    bool discard_error_messages (bool flag)
+    {
+      bool val = m_discard_error_messages;
+      m_discard_error_messages = flag;
+      return val;
+    }
+
+    octave_value discard_warning_messages (const octave_value_list& args, int nargout);
+
+    void set_discard_warning_messages (bool flag) { m_discard_warning_messages = flag; }
+
+    bool discard_warning_messages (void) const { return m_discard_warning_messages; }
+
+    bool discard_warning_messages (bool flag)
+    {
+      bool val = m_discard_warning_messages;
+      m_discard_warning_messages = flag;
+      return val;
+    }
+
+    octave_value beep_on_error (const octave_value_list& args, int nargout);
+
+    void set_beep_on_error (bool flag) { m_beep_on_error = flag; }
+
+    bool beep_on_error (void) const { return m_beep_on_error; }
+
+    bool beep_on_error (bool flag)
+    {
+      bool val = m_beep_on_error;
+      m_beep_on_error = flag;
+      return val;
+    }
+
+    octave_value backtrace_on_warning (const octave_value_list& args, int nargout);
+
+    void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; }
+
+    bool backtrace_on_warning (void) const { return m_backtrace_on_warning; }
+
+    bool backtrace_on_warning (bool flag)
+    {
+      bool val = m_backtrace_on_warning;
+      m_backtrace_on_warning = flag;
+      return val;
+    }
+
+    octave_value verbose_warning (const octave_value_list& args, int nargout);
+
+    void set_verbose_warning (bool flag) { m_verbose_warning = flag; }
+
+    bool verbose_warning (void) const { return m_verbose_warning; }
+
+    bool verbose_warning (bool flag)
+    {
+      bool val = m_verbose_warning;
+      m_verbose_warning = flag;
+      return val;
+    }
+
+    octave_value quiet_warning (const octave_value_list& args, int nargout);
+
+    void set_quiet_warning (bool flag) { m_quiet_warning = flag; }
+
+    bool quiet_warning (void) const { return m_quiet_warning; }
+
+    bool quiet_warning (bool flag)
+    {
+      bool val = m_quiet_warning;
+      m_quiet_warning = flag;
+      return val;
+    }
+
+    octave_map warning_options (void) const { return m_warning_options; }
+
+    void set_warning_options (const octave_map& val) { m_warning_options = val; }
+
+    octave_map warning_options (const octave_map& new_val)
+    {
+      octave_map val = m_warning_options;
+      m_warning_options = new_val;
+      return val;
+    }
+
+    octave_value last_error_message (const octave_value_list& args, int nargout);
+
+    void set_last_error_message (const std::string& val) { m_last_error_message = val; }
+
+    std::string last_error_message (void) const { return m_last_error_message; }
+
+    std::string last_error_message (const std::string& s)
+    {
+      std::string val = m_last_error_message;
+      m_last_error_message = s;
+      return val;
+    }
+
+    octave_value last_warning_message (const octave_value_list& args, int nargout);
+
+    void set_last_warning_message (const std::string& val) { m_last_warning_message = val; }
+
+    std::string last_warning_message (void) const { return m_last_warning_message; }
+
+    std::string last_warning_message (const std::string& s)
+    {
+      std::string val = m_last_warning_message;
+      m_last_warning_message = s;
+      return val;
+    }
+
+    octave_value last_warning_id (const octave_value_list& args, int nargout);
+
+    void set_last_warning_id (const std::string& val) { m_last_warning_id = val; }
+
+    std::string last_warning_id (void) const { return m_last_warning_id; }
+
+    std::string last_warning_id (const std::string& s)
+    {
+      std::string val = m_last_warning_id;
+      m_last_warning_id = s;
+      return val;
+    }
+
+    octave_value last_error_id (const octave_value_list& args, int nargout);
+
+    void set_last_error_id (const std::string& val) { m_last_error_id = val; }
+
+    std::string last_error_id (void) const { return m_last_error_id; }
+
+    std::string last_error_id (const std::string& s)
+    {
+      std::string val = m_last_error_id;
+      m_last_error_id = s;
+      return val;
+    }
+
+    void set_last_error_stack (const octave_map& val)
+    {
+      m_last_error_stack = val;
+    }
+
+    octave_map last_error_stack (void) const { return m_last_error_stack; }
+
+    octave_map last_error_stack (const octave_map& new_val)
+    {
+      octave_map val = m_last_error_stack;
+      m_last_error_stack = new_val;
+      return val;
+    }
+
+    //! For given warning ID, return 0 if warnings are disabled, 1 if
+    //! enabled, and 2 if the given ID should be an error instead of a
+    //! warning.
+
+    int warning_enabled (const std::string& id);
+
+    void verror (bool save_last_error, std::ostream& os, const char *name,
+                 const char *id, const char *fmt, va_list args,
+                 bool with_cfn = false);
+
+    void maybe_enter_debugger (execution_exception& e,
+                               bool show_stack_trace = false);
+
+    void vwarning (const char *name, const char *id, const char *fmt,
+                   va_list args);
+
+    OCTAVE_NORETURN
+    void error_1 (execution_exception& e, std::ostream& os,
+                  const char *name, const char *id, const char *fmt,
+                  va_list args, bool with_cfn = false);
+
+    OCTAVE_NORETURN
+    void error_1 (std::ostream& os, const char *name, const char *id,
+                  const char *fmt, va_list args, bool with_cfn);
+
+    void vwarning (const char *id, const char *fmt, va_list args);
+
+    void rethrow_error (const char *id, const char *fmt, ...);
+
+    void rethrow_error (const std::string& id, const std::string& msg,
+                        const octave_map& stack);
+
+    OCTAVE_NORETURN
+    void vpanic (const char *fmt, va_list args);
+
+    OCTAVE_NORETURN
+    void panic (const char *fmt, ...);
+
+    octave_scalar_map warning_query (const std::string& id_arg);
+
+    std::string default_warning_state (void);
+
+    void display_warning_options (std::ostream& os);
+
+    void set_warning_option (const std::string& state, const std::string& id);
+
+    void disable_warning (const std::string& id);
+
+    void initialize_default_warning_state (void);
+
+    void interpreter_try (octave::unwind_protect& frame,
+                          try_option = buffer);
+
+  private:
+
+    interpreter& m_interpreter;
+
+    //! TRUE means that Octave will try to enter the debugger when an error
+    //! is encountered.  This will also inhibit printing of the normal
+    //! traceback message (you will only see the top-level error message).
+
+    bool m_debug_on_error;
+
+    //! TRUE means that Octave will try to enter the debugger when an error
+    //! is encountered within the 'try' section of a 'try' / 'catch' block.
+
+    bool m_debug_on_caught;
+
+    //! TRUE means that Octave will try to enter the debugger when a warning
+    //! is encountered.
+
+    bool m_debug_on_warning;
+
+    //! Tell the error handler whether to print messages, or just store
+    //! them for later.  Used for handling errors in eval() and
+    //! the 'unwind_protect' statement.
+
+    int m_buffer_error_messages;
+
+    //! The number of layers of try / catch blocks we're in.  Used to print
+    //! "caught error" instead of "error" when "dbstop if caught error" is on.
+
+    int m_in_try_catch;
+
+    //! TRUE means error messages are turned off.
+
+    bool m_discard_error_messages;
+
+    //! TRUE means warning messages are turned off.
+
+    bool m_discard_warning_messages;
+
+    //! TRUE means that Octave will try to beep obnoxiously before
+    //! printing error messages.
+    bool m_beep_on_error;
+
+    //! TRUE means that Octave will try to display a stack trace when a
+    //! warning is encountered.
+    bool m_backtrace_on_warning;
+
+    //! TRUE means that Octave will print a verbose warning.  Currently
+    //! unused.
+    bool m_verbose_warning;
+
+    //! TRUE means that Octave will print no warnings, but lastwarn will
+    //! be updated
+    bool m_quiet_warning;
+
+    //! A structure containing (most of) the current state of warnings.
+    octave_map m_warning_options;
+
+    //! The text of the last error message.
+    std::string m_last_error_message;
+
+    //! The text of the last warning message.
+    std::string m_last_warning_message;
+
+    //! The last warning message id.
+    std::string m_last_warning_id;
+
+    //! The last error message id.
+    std::string m_last_error_id;
+
+    //! The last file in which an error occurred.
+    octave_map m_last_error_stack;
+  };
+}
+
+// FIXME: should we move the following functions inside the octave
+// namespace?  If so, should the functions outside of the namespace be
+// deprecated?  Doing that might cause a lot of trouble...  If they are
+// not deprecated and eventually removed, does it make sense to also
+// define them inside the octave namespace?
+
 #define panic_impossible()                                              \
   panic ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
 
-extern OCTINTERP_API void reset_error_handler (void);
-
 extern OCTINTERP_API int warning_enabled (const std::string& id);
 
 extern OCTINTERP_API octave::execution_exception
@@ -55,51 +435,60 @@
 extern OCTINTERP_API void message (const char *name, const char *fmt, ...);
 
 extern OCTINTERP_API void vwarning (const char *fmt, va_list args);
+
 OCTAVE_FORMAT_PRINTF (1, 2)
 extern OCTINTERP_API void warning (const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void verror (const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void verror (const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (1, 2)
-OCTAVE_NORETURN OCTINTERP_API extern
-void error (const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void error (const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void verror (octave::execution_exception&, const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+verror (octave::execution_exception&, const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (2, 3)
-OCTAVE_NORETURN OCTINTERP_API extern
-void error (octave::execution_exception&, const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+error (octave::execution_exception&, const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void verror_with_cfn (const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+verror_with_cfn (const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (1, 2)
-OCTAVE_NORETURN OCTINTERP_API extern
-void error_with_cfn (const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+error_with_cfn (const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void vparse_error (const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+vparse_error (const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (1, 2)
-OCTAVE_NORETURN OCTINTERP_API extern
-void parse_error (const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+parse_error (const char *fmt, ...);
 
 extern OCTINTERP_API void
-vmessage_with_id (const char *id, const char *name,
-                  const char *fmt, va_list args);
+vmessage_with_id (const char *id, const char *name, const char *fmt,
+                  va_list args);
 
 OCTAVE_FORMAT_PRINTF (3, 4)
 extern OCTINTERP_API void
 message_with_id (const char *id, const char *name, const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void vusage_with_id (const char *id, const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+vusage_with_id (const char *id, const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (2, 3)
-OCTAVE_NORETURN OCTINTERP_API extern
-void usage_with_id (const char *id, const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+usage_with_id (const char *id, const char *fmt, ...);
 
 extern OCTINTERP_API void
 vwarning_with_id (const char *id, const char *fmt, va_list args);
@@ -108,30 +497,39 @@
 extern OCTINTERP_API void
 warning_with_id (const char *id, const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void verror_with_id (const char *id, const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+verror_with_id (const char *id, const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (2, 3)
-OCTAVE_NORETURN OCTINTERP_API extern
-void error_with_id (const char *id, const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+error_with_id (const char *id, const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void verror_with_id_cfn (const char *id, const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+verror_with_id_cfn (const char *id, const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (2, 3)
-OCTAVE_NORETURN OCTINTERP_API extern
-void error_with_id_cfn (const char *id, const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+error_with_id_cfn (const char *id, const char *fmt, ...);
 
-OCTAVE_NORETURN OCTINTERP_API extern
-void vparse_error_with_id (const char *id, const char *fmt, va_list args);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+vparse_error_with_id (const char *id, const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (2, 3)
-OCTAVE_NORETURN OCTINTERP_API extern
-void parse_error_with_id (const char *id, const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void
+parse_error_with_id (const char *id, const char *fmt, ...);
+
+OCTAVE_NORETURN
+extern OCTINTERP_API void vpanic (const char *fmt, va_list args);
 
 OCTAVE_FORMAT_PRINTF (1, 2)
-OCTAVE_NORETURN OCTINTERP_API extern
-void panic (const char *fmt, ...);
+OCTAVE_NORETURN
+extern OCTINTERP_API void panic (const char *fmt, ...);
 
 //! Helper function for print_usage defined in defun.cc.
 
@@ -144,62 +542,15 @@
 set_warning_state (const octave_value_list& args);
 
 extern OCTINTERP_API void disable_warning (const std::string& id);
-extern OCTINTERP_API void initialize_default_warning_state (void);
-
-//! TRUE means that Octave will try to enter the debugger when an error
-//! is encountered.  This will also inhibit printing of the normal
-//! traceback message (you will only see the top-level error message).
-
-extern OCTINTERP_API bool Vdebug_on_error;
 
-//! TRUE means that Octave will try to enter the debugger when an error
-//! is encountered within the 'try' section of a 'try' / 'catch' block.
-
-extern OCTINTERP_API bool Vdebug_on_caught;
+extern OCTINTERP_API void
+interpreter_try (octave::unwind_protect&,
+                 octave::error_system::try_option = octave::error_system::buffer);
 
-//! TRUE means that Octave will try to enter the debugger when a warning
-//! is encountered.
-
-extern OCTINTERP_API bool Vdebug_on_warning;
-
-//! Current error state.
-
+OCTAVE_DEPRECATED (6, "this variable is obsolete and always has the value 0")
 extern OCTINTERP_API int error_state;
 
-//! Current warning state.
-
-extern OCTINTERP_API int warning_state;
-
-//! Tell the error handler whether to print messages, or just store
-//! them for later.  Used for handling errors in eval() and
-//! the 'unwind_protect' statement.
-
-extern OCTINTERP_API int buffer_error_messages;
-
-//! The number of layers of try / catch blocks we're in.  Used to print
-//! "caught error" instead of "error" when "dbstop if caught error" is on.
-
-extern OCTINTERP_API int in_try_catch;
-
-//! TRUE means error messages are turned off.
-
-extern OCTINTERP_API bool discard_error_messages;
-
-//! TRUE means warning messages are turned off.
-
-extern OCTINTERP_API bool discard_warning_messages;
-
-//! Helper functions to pass last error and warning messages and ids.
-//! @{
-
-extern OCTINTERP_API std::string last_error_message (void);
-extern OCTINTERP_API std::string last_error_id (void);
-extern OCTINTERP_API octave_map last_error_stack (void);
-extern OCTINTERP_API std::string last_warning_message (void);
-extern OCTINTERP_API std::string last_warning_id (void);
-
-//! @}
-
-extern OCTINTERP_API void interpreter_try (octave::unwind_protect&);
+OCTAVE_DEPRECATED (6, "use 'error_system::reset' instead")
+extern OCTINTERP_API void reset_error_handler (void);
 
 #endif
--- a/libinterp/corefcn/errwarn.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/errwarn.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -324,15 +324,17 @@
 }
 
 void
-warn_divide_by_zero (void)
+warn_empty_arg (const char *name)
 {
-  warning_with_id ("Octave:divide-by-zero", "division by zero");
+  warning ("%s: argument is empty matrix", name);
 }
 
 void
-warn_empty_arg (const char *name)
+warn_empty_index (const std::string& type_name)
 {
-  warning ("%s: argument is empty matrix", name);
+  warning_with_id ("Octave:empty-index",
+                   "'%s' object indexed with empty index list",
+                   type_name.c_str ());
 }
 
 void
--- a/libinterp/corefcn/errwarn.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/errwarn.h	Fri Jul 12 12:14:43 2019 -0400
@@ -164,10 +164,10 @@
                        const std::string& pkg = "Octave");
 
 OCTINTERP_API extern void
-warn_divide_by_zero (void);
+warn_empty_arg (const char *name);
 
 OCTINTERP_API extern void
-warn_empty_arg (const char *name);
+warn_empty_index (const std::string& type_name);
 
 OCTINTERP_API extern void
 warn_implicit_conversion (const char *id, const char *from, const char *to);
@@ -185,4 +185,13 @@
 OCTINTERP_API extern void
 warn_wrong_type_arg (const char *name, const octave_value& tc);
 
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (6, "this function will be removed in a future version of Octave")
+inline void
+warn_divide_by_zero (void)
+{ }
+
 #endif
+
+#endif
--- a/libinterp/corefcn/event-queue.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/event-queue.h	Fri Jul 12 12:14:43 2019 -0400
@@ -122,14 +122,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::event_queue' instead")
-typedef octave::event_queue event_queue;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::event_queue_safe' instead")
-typedef octave::event_queue_safe event_queue_safe;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/fcn-info.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/fcn-info.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,11 @@
 #endif
 
 #include "file-ops.h"
+#include "file-stat.h"
+#include "oct-env.h"
 
+#include "defun.h"
+#include "dirfns.h"
 #include "fcn-info.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
@@ -34,9 +38,13 @@
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "parse.h"
-#include "symrec.h"
 #include "symscope.h"
 #include "symtab.h"
+#include "utils.h"
+
+// Should Octave always check to see if function files have changed
+// since they were last compiled?
+static int Vignore_function_time_stamp = 1;
 
 namespace octave
 {
@@ -333,21 +341,26 @@
 
   // Find function definition according to the following precedence list:
   //
+  //   nested functions (and subfunctions)
+  //   local functions in the current file
   //   private function
   //   class method
   //   class constructor
   //   command-line function
   //   autoload function
-  //   function on the path
+  //   functions on the load_path (current directory is always first)
+  //   package (FIXME: does this belong here?)
   //   built-in function
-  //
-  // Matlab documentation states that constructors have higher precedence
-  // than methods, but that does not seem to be the case.
 
   octave_value
-  fcn_info::fcn_info_rep::find (const octave_value_list& args)
+  fcn_info::fcn_info_rep::find (const symbol_scope& scope,
+                                const octave_value_list& args)
   {
-    octave_value retval = xfind (args);
+    symbol_scope search_scope
+      = (scope
+         ? scope : __get_current_scope__("fcn_info::fcn_info_rep::find"));
+
+    octave_value retval = xfind (search_scope, args);
 
     if (retval.is_undefined ())
       {
@@ -359,20 +372,278 @@
 
         lp.update ();
 
-        retval = xfind (args);
+        retval = xfind (search_scope, args);
+      }
+
+    return retval;
+  }
+
+
+  static void
+  split_name_with_package (const std::string& name, std::string& fname,
+                           std::string& pname)
+  {
+    size_t pos = name.rfind ('.');
+
+    fname.clear ();
+    pname.clear ();
+
+    if (pos != std::string::npos)
+      {
+        fname = name.substr (pos + 1);
+        pname = name.substr (0, pos);
+      }
+    else
+      fname = name;
+  }
+
+  // Check the load path to see if file that defined this is still
+  // visible.  If the file is no longer visible, then erase the
+  // definition and move on.  If the file is visible, then we also
+  // need to check to see whether the file has changed since the
+  // function was loaded/parsed.  However, this check should only
+  // happen once per prompt (for files found from relative path
+  // elements, we also check if the working directory has changed
+  // since the last time the function was loaded/parsed).
+  //
+  // FIXME: perhaps this should be done for all loaded functions when
+  // the prompt is printed or the directory has changed, and then we
+  // would not check for it when finding symbol definitions.
+
+  static inline bool
+  load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
+                        octave_value& function,
+                        const std::string& dispatch_type = "",
+                        const std::string& package_name = "")
+  {
+    bool retval = false;
+
+    octave_value ov_fcn
+      = load_fcn_from_file (ff, dir_name, dispatch_type,
+                            package_name);
+
+    if (ov_fcn.is_defined ())
+      {
+        retval = true;
+
+        function = ov_fcn;
+      }
+    else
+      function = octave_value ();
+
+    return retval;
+  }
+
+  static bool
+  out_of_date_check (octave_value& function,
+                     const std::string& dispatch_type = "",
+                     bool check_relative = true)
+  {
+    bool retval = false;
+
+    octave_function *fcn = function.function_value (true);
+
+    if (fcn)
+      {
+        // FIXME: we need to handle subfunctions properly here.
+
+        if (! (fcn->is_subfunction () || fcn->is_anonymous_function ()))
+          {
+            std::string ff = fcn->fcn_file_name ();
+
+            if (! ff.empty ())
+              {
+                sys::time tc = fcn->time_checked ();
+
+                bool relative = check_relative && fcn->is_relative ();
+
+                if (tc <= Vlast_prompt_time
+                    || (relative && tc < Vlast_chdir_time))
+                  {
+                    bool clear_breakpoints = false;
+                    std::string nm = fcn->name ();
+                    std::string pack = fcn->package_name ();
+                    std::string canonical_nm = fcn->canonical_name ();
+
+                    bool is_same_file = false;
+
+                    std::string file;
+                    std::string dir_name;
+
+                    if (check_relative)
+                      {
+                        int nm_len = nm.length ();
+
+                        if (sys::env::absolute_pathname (nm)
+                            && ((nm_len > 4
+                                 && (nm.substr (nm_len-4) == ".oct"
+                                     || nm.substr (nm_len-4) == ".mex"))
+                                || (nm_len > 2
+                                    && nm.substr (nm_len-2) == ".m")))
+                          file = nm;
+                        else
+                          {
+                            // We don't want to make this an absolute name,
+                            // because load_fcn_file looks at the name to
+                            // decide whether it came from a relative lookup.
+
+                            if (! dispatch_type.empty ())
+                              {
+                                load_path& lp
+                                  = __get_load_path__ ("out_of_date_check");
+
+                                file = lp.find_method (dispatch_type, nm,
+                                                       dir_name, pack);
+
+                                if (file.empty ())
+                                  {
+                                    std::string s_name;
+                                    std::string s_pack;
+
+                                    symbol_table& symtab
+                                      = __get_symbol_table__ ("out_of_date_check");
+
+                                    const std::list<std::string>& plist
+                                      = symtab.parent_classes (dispatch_type);
+
+                                    std::list<std::string>::const_iterator it
+                                      = plist.begin ();
+
+                                    while (it != plist.end ())
+                                      {
+                                        split_name_with_package (*it, s_name,
+                                                                 s_pack);
+
+                                        file = lp.find_method (*it, nm, dir_name,
+                                                               s_pack);
+                                        if (! file.empty ())
+                                          {
+                                            pack = s_pack;
+                                            break;
+                                          }
+
+                                        it++;
+                                      }
+                                  }
+                              }
+
+                            // Maybe it's an autoload?
+                            if (file.empty ())
+                              {
+                                tree_evaluator& tw
+                                  = __get_evaluator__ ("out_of_data_check");
+
+                                file = tw.lookup_autoload (nm);
+                              }
+
+                            if (file.empty ())
+                              {
+                                load_path& lp
+                                  = __get_load_path__ ("out_of_date_check");
+                                file = lp.find_fcn (nm, dir_name, pack);
+                              }
+                          }
+
+                        if (! file.empty ())
+                          is_same_file = same_file (file, ff);
+                      }
+                    else
+                      {
+                        is_same_file = true;
+                        file = ff;
+                      }
+
+                    if (file.empty ())
+                      {
+                        // Can't see this function from current
+                        // directory, so we should clear it.
+
+                        function = octave_value ();
+
+                        clear_breakpoints = true;
+                      }
+                    else if (is_same_file)
+                      {
+                        // Same file.  If it is out of date, then reload it.
+
+                        sys::time ottp = fcn->time_parsed ();
+                        time_t tp = ottp.unix_time ();
+
+                        fcn->mark_fcn_file_up_to_date (sys::time ());
+
+                        if (! (Vignore_function_time_stamp == 2
+                               || (Vignore_function_time_stamp
+                                   && fcn->is_system_fcn_file ())))
+                          {
+                            sys::file_stat fs (ff);
+
+                            if (fs)
+                              {
+                                if (fs.is_newer (tp))
+                                  {
+                                    retval = load_out_of_date_fcn (ff, dir_name,
+                                                                   function,
+                                                                   dispatch_type,
+                                                                   pack);
+
+                                    clear_breakpoints = true;
+                                  }
+                              }
+                            else
+                              {
+                                function = octave_value ();
+
+                                clear_breakpoints = true;
+                              }
+                          }
+                      }
+                    else
+                      {
+                        // Not the same file, so load the new file in
+                        // place of the old.
+
+                        retval = load_out_of_date_fcn (file, dir_name, function,
+                                                       dispatch_type, pack);
+
+                        clear_breakpoints = true;
+                      }
+
+                    // If the function has been replaced then clear any
+                    // breakpoints associated with it
+                    if (clear_breakpoints)
+                      {
+                        bp_table& bptab
+                          = __get_bp_table__ ("out_of_date_check");
+
+                        bptab.remove_all_breakpoints_in_file (canonical_nm,
+                                                              true);
+                      }
+                  }
+              }
+          }
       }
 
     return retval;
   }
 
   octave_value
-  fcn_info::fcn_info_rep::xfind (const octave_value_list& args)
+  fcn_info::fcn_info_rep::xfind (const symbol_scope& search_scope,
+                                 const octave_value_list& args)
   {
-    symbol_scope curr_scope
-      = __get_current_scope__ ("fcn_info::fcn_info_rep::xfind");
+    octave_user_function *current_fcn
+      = search_scope ? search_scope.function () : nullptr;
+
+    // Subfunction.  I think it only makes sense to check for
+    // subfunctions if we are currently executing a function defined
+    // from a .m file.
 
-    octave_user_function *current_fcn
-      = curr_scope ? curr_scope.function () : nullptr;
+    if (search_scope)
+      {
+        octave_value fcn = search_scope.find_subfunction (name);
+
+        if (fcn.is_defined ())
+          return fcn;
+      }
 
     // Local function.
 
@@ -384,15 +655,6 @@
         // they were defined within class methods and use local functions
         // (helper functions) we can still use those anonymous functions
 
-        if (current_fcn->is_anonymous_function ())
-          {
-            if (fcn_file.empty ()
-                && curr_scope.parent_scope ()
-                && curr_scope.parent_scope ()->function () != nullptr)
-              fcn_file
-                = curr_scope.parent_scope ()->function ()->fcn_file_name();
-          }
-
         if (! fcn_file.empty ())
           {
             auto r = local_functions.find (fcn_file);
@@ -537,9 +799,13 @@
   // so class methods and constructors are skipped.
 
   octave_value
-  fcn_info::fcn_info_rep::builtin_find (void)
+  fcn_info::fcn_info_rep::builtin_find (const symbol_scope& scope)
   {
-    octave_value retval = x_builtin_find ();
+    symbol_scope search_scope
+      = (scope
+         ? scope : __get_current_scope__("fcn_info::fcn_info_rep::find"));
+
+    octave_value retval = x_builtin_find (search_scope);
 
     if (! retval.is_defined ())
       {
@@ -551,14 +817,14 @@
 
         lp.update ();
 
-        retval = x_builtin_find ();
+        retval = x_builtin_find (search_scope);
       }
 
     return retval;
   }
 
   octave_value
-  fcn_info::fcn_info_rep::x_builtin_find (void)
+  fcn_info::fcn_info_rep::x_builtin_find (const symbol_scope& search_scope)
   {
     // Built-in function.
     if (built_in_function.is_defined ())
@@ -585,11 +851,8 @@
 
     // Private function.
 
-    symbol_scope curr_scope
-      = __get_current_scope__ ("fcn_info::fcn_info_rep::x_builtin_find");
-
-    octave_user_function *current_fcn = curr_scope ? curr_scope.function ()
-                                                   : nullptr;
+    octave_user_function *current_fcn
+      = search_scope ? search_scope.function () : nullptr;
 
     if (current_fcn)
       {
@@ -651,9 +914,9 @@
     // subfunctions if we are currently executing a function defined
     // from a .m file.
 
-    if (curr_scope)
+    if (search_scope)
       {
-        octave_value val = curr_scope.find_subfunction (name);
+        octave_value val = search_scope.find_subfunction (name);
 
         if (val.is_defined ())
           return val;
@@ -707,7 +970,10 @@
 
     if (! autoload_function.is_defined ())
       {
-        std::string file_name = lookup_autoload (name);
+        tree_evaluator& tw
+          = __get_evaluator__ ("fcn_info::fcn_info_rep::x_builtin_find");
+
+        std::string file_name = tw.lookup_autoload (name);
 
         if (! file_name.empty ())
           {
@@ -835,3 +1101,82 @@
     return octave_value (info_map);
   }
 }
+
+DEFUN (ignore_function_time_stamp, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{val} =} ignore_function_time_stamp ()
+@deftypefnx {} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})
+Query or set the internal variable that controls whether Octave checks
+the time stamp on files each time it looks up functions defined in
+function files.
+
+If the internal variable is set to @qcode{"system"}, Octave will not
+automatically recompile function files in subdirectories of
+@file{@var{octave-home}/lib/@var{version}} if they have changed since they were last compiled, but will recompile other function files in the search path if they change.
+
+If set to @qcode{"all"}, Octave will not recompile any function files
+unless their definitions are removed with @code{clear}.
+
+If set to @qcode{"none"}, Octave will always check time stamps on files to
+determine whether functions defined in function files need to recompiled.
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin > 1)
+    print_usage ();
+
+  octave_value retval;
+
+  if (nargout > 0 || nargin == 0)
+    {
+      switch (Vignore_function_time_stamp)
+        {
+        case 1:
+          retval = "system";
+          break;
+
+        case 2:
+          retval = "all";
+          break;
+
+        default:
+          retval = "none";
+          break;
+        }
+    }
+
+  if (nargin == 1)
+    {
+      std::string sval = args(0).xstring_value ("ignore_function_time_stamp: first argument must be a string");
+
+      if (sval == "all")
+        Vignore_function_time_stamp = 2;
+      else if (sval == "system")
+        Vignore_function_time_stamp = 1;
+      else if (sval == "none")
+        Vignore_function_time_stamp = 0;
+      else
+        error (R"(ignore_function_time_stamp: argument must be one of "all", "system", or "none")");
+    }
+
+  return retval;
+}
+
+/*
+%!shared old_state
+%! old_state = ignore_function_time_stamp ();
+%!test
+%! state = ignore_function_time_stamp ("all");
+%! assert (state, old_state);
+%! assert (ignore_function_time_stamp (), "all");
+%! state = ignore_function_time_stamp ("system");
+%! assert (state, "all");
+%! assert (ignore_function_time_stamp (), "system");
+%! ignore_function_time_stamp (old_state);
+
+## Test input validation
+%!error (ignore_function_time_stamp ("all", "all"))
+%!error (ignore_function_time_stamp ("UNKNOWN_VALUE"))
+%!error (ignore_function_time_stamp (42))
+*/
--- a/libinterp/corefcn/fcn-info.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/fcn-info.h	Fri Jul 12 12:14:43 2019 -0400
@@ -33,6 +33,7 @@
 
 #include "ov.h"
 #include "ovl.h"
+#include "symscope.h"
 
 namespace octave
 {
@@ -81,9 +82,10 @@
 
       octave_value load_class_method (const std::string& dispatch_type);
 
-      octave_value find (const octave_value_list& args);
+      octave_value find (const symbol_scope& search_scope,
+                         const octave_value_list& args);
 
-      octave_value builtin_find (void);
+      octave_value builtin_find (const symbol_scope& search_scope);
 
       octave_value find_method (const std::string& dispatch_type);
 
@@ -98,9 +100,10 @@
         return function_on_path.is_defined ();
       }
 
-      octave_value find_function (const octave_value_list& args)
+      octave_value find_function (const symbol_scope& search_scope,
+                                  const octave_value_list& args)
       {
-        return find (args);
+        return find (search_scope, args);
       }
 
       void install_cmdline_function (const octave_value& f)
@@ -221,9 +224,10 @@
 
     private:
 
-      octave_value xfind (const octave_value_list& args);
+      octave_value xfind (const symbol_scope& search_scope,
+                          const octave_value_list& args);
 
-      octave_value x_builtin_find (void);
+      octave_value x_builtin_find (const symbol_scope& search_scope);
     };
 
   public:
@@ -237,14 +241,16 @@
 
     ~fcn_info (void) = default;
 
-    octave_value find (const octave_value_list& args = octave_value_list ())
+    octave_value find (const symbol_scope& search_scope,
+                       const octave_value_list& args = octave_value_list ())
     {
-      return m_rep->find (args);
+      return m_rep->find (search_scope, args);
     }
 
-    octave_value builtin_find (void)
+    octave_value
+    builtin_find (const symbol_scope& search_scope)
     {
-      return m_rep->builtin_find ();
+      return m_rep->builtin_find (search_scope);
     }
 
     octave_value find_method (const std::string& dispatch_type) const
@@ -267,6 +273,7 @@
       return m_rep->find_autoload ();
     }
 
+    // FIXME: find_function_on_path might be a better name?
     octave_value find_user_function (void)
     {
       return m_rep->find_user_function ();
@@ -277,10 +284,11 @@
       return m_rep->is_user_function_defined ();
     }
 
-    octave_value find_function (const octave_value_list& args
-                                = octave_value_list ())
+    octave_value
+    find_function (const symbol_scope& search_scope,
+                   const octave_value_list& args = octave_value_list ())
     {
-      return m_rep->find_function (args);
+      return m_rep->find_function (search_scope, args);
     }
 
     void install_cmdline_function (const octave_value& f)
--- a/libinterp/corefcn/file-io.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/file-io.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -52,6 +52,7 @@
 
 #include "file-ops.h"
 #include "file-stat.h"
+#include "iconv-wrappers.h"
 #include "lo-ieee.h"
 #include "lo-sysdep.h"
 #include "mkostemp-wrapper.h"
@@ -296,7 +297,7 @@
 @seealso{fgets, fscanf, fread, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fgetl";
+  static const std::string who = "fgetl";
 
   int nargin = args.length ();
 
@@ -338,7 +339,7 @@
 @seealso{fputs, fgetl, fscanf, fread, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fgets";
+  static const std::string who = "fgets";
 
   int nargin = args.length ();
 
@@ -380,7 +381,7 @@
 @seealso{fgetl, fgets, fscanf, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fskipl";
+  static const std::string who = "fskipl";
 
   int nargin = args.length ();
 
@@ -405,12 +406,29 @@
 
 static octave::stream
 do_stream_open (const std::string& name, const std::string& mode_arg,
-                const std::string& arch, int& fid)
+                const std::string& arch, std::string encoding, int& fid)
 {
   octave::stream retval;
 
   fid = -1;
 
+  // Valid names for encodings consist of ASCII characters only.
+  std::transform (encoding.begin (), encoding.end (), encoding.begin (),
+                  ::tolower);
+  if (encoding.compare ("utf-8"))
+  {
+    // check if encoding is valid
+    void *codec = octave_iconv_open_wrapper (encoding.c_str (), "utf-8");
+    if (codec == reinterpret_cast<void *> (-1))
+      {
+        if (errno == EINVAL)
+          error ("fopen: conversion from codepage '%s' not supported",
+                 encoding.c_str ());
+      }
+    else
+      octave_iconv_close_wrapper (codec);
+  }
+
   std::string mode = mode_arg;
   bool use_zlib = false;
   normalize_fopen_mode (mode, use_zlib);
@@ -440,8 +458,8 @@
 
               gzFile gzf = ::gzdopen (fd, mode.c_str ());
 
-              retval = octave_zstdiostream::create (fname, gzf, fd,
-                                                    md, flt_fmt);
+              retval = octave_zstdiostream::create (fname, gzf, fd, md,
+                                                    flt_fmt, encoding);
             }
           else
             retval.error (std::strerror (errno));
@@ -451,8 +469,8 @@
         {
           FILE *fptr = octave::sys::fopen (fname.c_str (), mode.c_str ());
 
-          retval = octave_stdiostream::create (fname, fptr, md,
-                                               flt_fmt);
+          retval = octave_stdiostream::create (fname, fptr, md, flt_fmt,
+                                               encoding);
 
           if (! fptr)
             retval.error (std::strerror (errno));
@@ -465,7 +483,8 @@
 
 static octave::stream
 do_stream_open (const octave_value& tc_name, const octave_value& tc_mode,
-                const octave_value& tc_arch, const char *fcn, int& fid)
+                const octave_value& tc_arch, const octave_value& tc_encoding,
+                const char *fcn, int& fid)
 {
   octave::stream retval;
 
@@ -474,8 +493,9 @@
   std::string name = tc_name.xstring_value ("%s: filename must be a string", fcn);
   std::string mode = tc_mode.xstring_value ("%s: file mode must be a string", fcn);
   std::string arch = tc_arch.xstring_value ("%s: architecture type must be a string", fcn);
-
-  retval = do_stream_open (name, mode, arch, fid);
+  std::string encoding = tc_encoding.xstring_value ("%s: ENCODING must be a string", fcn);
+
+  retval = do_stream_open (name, mode, arch, encoding, fid);
 
   return retval;
 }
@@ -485,19 +505,22 @@
 @deftypefn  {} {@var{fid} =} fopen (@var{name})
 @deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode})
 @deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch})
+@deftypefnx {} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch}, @var{encoding})
 @deftypefnx {} {[@var{fid}, @var{msg}] =} fopen (@dots{})
 @deftypefnx {} {@var{fid_list} =} fopen ("all")
-@deftypefnx {} {[@var{file}, @var{mode}, @var{arch}] =} fopen (@var{fid})
+@deftypefnx {} {[@var{file}, @var{mode}, @var{arch}, @var{encoding}] =} fopen (@var{fid})
 Open a file for low-level I/O or query open files and file descriptors.
 
 The first form of the @code{fopen} function opens the named file with
-the specified mode (read-write, read-only, etc.@:) and architecture
-interpretation (IEEE big endian, IEEE little endian, etc.), and returns
-an integer value that may be used to refer to the file later.  If an
-error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the
+the specified mode (read-write, read-only, etc.@:), architecture
+interpretation (IEEE big endian, IEEE little endian, etc.) and file encoding,
+and returns an integer value that may be used to refer to the file later.  If
+an error occurs, @var{fid} is set to @minus{}1 and @var{msg} contains the
 corresponding system error message.  The @var{mode} is a one or two
 character string that specifies whether the file is to be opened for
-reading, writing, or both.
+reading, writing, or both.  The @var{encoding} is a character string with a
+valid code page identifier.  This code page is used when strings are read from
+or written to the file.
 
 The second form of the @code{fopen} function returns a vector of file ids
 corresponding to all the currently open files, excluding the
@@ -571,10 +594,6 @@
 IEEE little endian format.
 @end table
 
-@noindent
-However, conversions are currently only supported for @samp{native},
-@samp{ieee-be}, and @samp{ieee-le} formats.
-
 When opening a new file that does not yet exist, permissions will be set to
 @code{0666 - @var{umask}}.
 
@@ -590,7 +609,7 @@
 {
   int nargin = args.length ();
 
-  if (nargin < 1 || nargin > 3)
+  if (nargin < 1 || nargin > 4)
     print_usage ();
 
   octave_value_list retval = ovl (-1.0);
@@ -612,21 +631,22 @@
         {
           string_vector tmp = streams.get_info (args(0));
 
-          retval = ovl (tmp(0), tmp(1), tmp(2));
+          retval = ovl (tmp(0), tmp(1), tmp(2), tmp(3));
 
           return retval;
         }
     }
 
-  octave_value mode = (nargin == 2 || nargin == 3)
-                      ? args(1) : octave_value ("r");
-
-  octave_value arch = (nargin == 3)
-                      ? args(2) : octave_value ("native");
+  octave_value mode = (nargin > 1) ? args(1) : octave_value ("r");
+
+  octave_value arch = (nargin > 2) ? args(2) : octave_value ("native");
+
+  octave_value encoding = (nargin > 3) ? args(3) : octave_value ("utf-8");
 
   int fid = -1;
 
-  octave::stream os = do_stream_open (args(0), mode, arch, "fopen", fid);
+  octave::stream os = do_stream_open (args(0), mode, arch, encoding, "fopen",
+                                      fid);
 
   if (os)
     retval = ovl (streams.insert (os), "");
@@ -641,11 +661,12 @@
 }
 
 /*
-## FIXME: Only have tests for query mode.  Need others for regular fopen call.
+## Further tests are in io.tst
 %!test   # Uses hardcoded value of 1 for stdout
-%! [name, mode, arch] = fopen (1);
+%! [name, mode, arch, encoding] = fopen (1);
 %! assert (name, "stdout");
 %! assert (mode, "w");
+%! assert (encoding, "utf-8");
 
 %!test   # Query of non-existent stream returns all ""
 %! [name, mode, arch] = fopen (-1);
@@ -831,7 +852,7 @@
 @seealso{fputs, fdisp, fwrite, fscanf, printf, sprintf, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fprintf";
+  static const std::string who = "fprintf";
 
   return printf_internal (interp, who, args, nargout);
 }
@@ -854,7 +875,7 @@
 @seealso{fprintf, sprintf, scanf}
 @end deftypefn */)
 {
-  static std::string who = "printf";
+  static const std::string who = "printf";
 
   octave_value_list tmp_args = args;
 
@@ -890,7 +911,7 @@
 @seealso{fdisp, fprintf, fwrite, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fputs";
+  static const std::string who = "fputs";
 
   return puts_internal (interp, who, args);
 }
@@ -908,7 +929,7 @@
 @seealso{fputs, disp}
 @end deftypefn */)
 {
-  static std::string who = "puts";
+  static const std::string who = "puts";
 
   octave_value_list tmp_args = args;
 
@@ -931,7 +952,7 @@
 @seealso{printf, fprintf, sscanf}
 @end deftypefn */)
 {
-  static std::string who = "sprintf";
+  static const std::string who = "sprintf";
 
   int nargin = args.length ();
 
@@ -1067,7 +1088,7 @@
 @seealso{fgets, fgetl, fread, scanf, sscanf, fopen}
 @end deftypefn */)
 {
-  static std::string who = "fscanf";
+  static const std::string who = "fscanf";
 
   return scanf_internal (interp, who, args);
 }
@@ -1100,7 +1121,7 @@
 @seealso{fscanf, scanf, sprintf}
 @end deftypefn */)
 {
-  static std::string who = "sscanf";
+  static const std::string who = "sscanf";
 
   int nargin = args.length ();
 
@@ -1145,6 +1166,15 @@
   return retval;
 }
 
+/*
+%!test <*56396>
+%! [val, count, errmsg, nextpos] = sscanf ('1234a6', '%2d', 3);
+%! assert (val, [12; 34]);
+%! assert (count, 2);
+%! assert (errmsg, "sscanf: format failed to match");
+%! assert (nextpos, 5);
+*/
+
 DEFMETHOD (scanf, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {[@var{val}, @var{count}, @var{errmsg}] =} scanf (@var{template}, @var{size})
@@ -1155,7 +1185,7 @@
 @seealso{fscanf, sscanf, printf}
 @end deftypefn */)
 {
-  static std::string who = "scanf";
+  static const std::string who = "scanf";
 
   octave_value_list tmp_args = args;
 
@@ -1500,7 +1530,7 @@
 @seealso{dlmread, fscanf, load, strread, textread}
 @end deftypefn */)
 {
-  static std::string who = "textscan";
+  static const std::string who = "textscan";
 
   return textscan_internal (interp, who, args);
 }
@@ -2214,43 +2244,56 @@
 %! ret = textscan (str, "%s", "delimiter", "\t");
 %! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });
 
-%!test <52479>
+%!test <*52479>
 %! str = "\t\ta\tb\tc\n";
 %! ret = textscan (str, "%s", "delimiter", {"\t"});
 %! assert (ret, { {''; ''; 'a'; 'b'; 'c'} });
 
-%!test <52550>
+%!test <*52550>
 %! str = ",,1,2,3\n";
 %! obs = textscan (str, "%d", "delimiter", ",");
 %! assert (obs, { [0; 0; 1; 2; 3] });
 %! obs = textscan (str, "%d", "delimiter", {","});
 %! assert (obs, { [0; 0; 1; 2; 3] });
 
-%!test <52550>
+%!test <*52550>
 %! str = " , ,1,2,3\n";
 %! obs = textscan (str, "%d", "delimiter", ",");
 %! assert (obs, { [0; 0; 1; 2; 3] });
 %! textscan (str, "%d", "delimiter", {","});
 %! assert (obs, { [0; 0; 1; 2; 3] });
 
-%!test <52550>
+%!test <*52550>
 %! str = " 0 , 5+6j , -INF+INFj ,NaN,3\n";
 %! obs = textscan (str, "%f", "delimiter", ",");
 %! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });
 %! obs = textscan (str, "%f", "delimiter", {","});
 %! assert (obs, { [0; 5+6i; complex(-Inf,Inf); NaN; 3] });
 
-%!test <52550>
+%!test <*52550>
 %! str = " 0;,;,1;,2;,3\n";
 %! assert (textscan (str, "%f", "delimiter", {";,"}), { [0; NaN; 1; 2; 3] });
 
-%!test <52550>
+%!test <*52550>
 %! str = " 0 ;1 , $ 2 ;3\n";
 %! obs = textscan (str, "%f", "delimiter", ",;$");
 %! assert (obs, { [0; 1; NaN; 2; 3] });
 %! obs = textscan (str, "%f", "delimiter", {",",";","$"});
 %! assert (obs, { [0; 1; NaN; 2; 3] });
 
+## file stream with encoding
+%!test
+%! f = tempname ();
+%! fid = fopen (f, "w+", "n", "iso-8859-1");
+%! unwind_protect
+%!   fprintf (fid, "abc,äöü\n");
+%!   fseek (fid, 0, "bof");
+%!   obs = textscan (fid, "%s", "delimiter", ",");
+%!   fclose (fid);
+%!   assert (obs, { {"abc"; "äöü"} });
+%! unwind_protect_cleanup
+%!   unlink (f);
+%! end_unwind_protect
 */
 
 // These tests have end-comment sequences, so can't just be in a comment
--- a/libinterp/corefcn/ft-text-renderer.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/ft-text-renderer.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -149,14 +149,9 @@
       if (! instance)
         {
           instance = new ft_manager ();
-
-          if (instance)
-            singleton_cleanup_list::add (cleanup_instance);
+          singleton_cleanup_list::add (cleanup_instance);
         }
 
-      if (! instance)
-        error ("unable to create ft_manager!");
-
       return retval;
     }
 
@@ -245,10 +240,6 @@
 
           if (weight == "bold")
             fc_weight = FC_WEIGHT_BOLD;
-          else if (weight == "light")
-            fc_weight = FC_WEIGHT_LIGHT;
-          else if (weight == "demi")
-            fc_weight = FC_WEIGHT_DEMIBOLD;
           else
             fc_weight = FC_WEIGHT_NORMAL;
 
@@ -378,7 +369,7 @@
         xoffset (0), line_yoffset (0), yoffset (0), mode (MODE_BBOX),
         color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (),
         line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0),
-        m_max_fontsize (0)
+        m_max_fontsize (0), m_antialias (true)
     { }
 
     // No copying!
@@ -422,6 +413,8 @@
     Matrix get_extent (const std::string& txt, double rotation,
                        const caseless_str& interpreter);
 
+    void set_anti_aliasing (bool val) { m_antialias = val; };
+
     void set_font (const std::string& name, const std::string& weight,
                    const std::string& angle, double size);
 
@@ -547,6 +540,9 @@
     // Used for computing the distance between lines.
     double m_max_fontsize;
 
+    // Anti-aliasing.
+    bool m_antialias;
+
   };
 
   void
@@ -712,6 +708,16 @@
         break;
       }
   }
+  bool is_opaque (const FT_GlyphSlot &glyph, const int x, const int y)
+  {
+    // Borrowed from https://stackoverflow.com/questions/14800827/
+    //    indexing-pixels-in-a-monochrome-freetype-glyph-buffer
+    int pitch = std::abs (glyph->bitmap.pitch);
+    unsigned char *row = &glyph->bitmap.buffer[pitch * y];
+    char cvalue = row[x >> 3];
+
+    return ((cvalue & (128 >> (x & 7))) != 0);
+  }
 
   FT_UInt
   ft_text_renderer::process_character (FT_ULong code, FT_UInt previous)
@@ -754,7 +760,9 @@
             switch (mode)
               {
               case MODE_RENDER:
-                if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                if (FT_Render_Glyph (face->glyph, (m_antialias
+                                                   ? FT_RENDER_MODE_NORMAL
+                                                   : FT_RENDER_MODE_MONO)))
                   {
                     glyph_index = 0;
                     warn_glyph_render (code);
@@ -786,7 +794,11 @@
                     for (int r = 0; static_cast<unsigned int> (r) < bitmap.rows; r++)
                       for (int c = 0; static_cast<unsigned int> (c) < bitmap.width; c++)
                         {
-                          unsigned char pix = bitmap.buffer[r*bitmap.width+c];
+                          unsigned char pix
+                            = (m_antialias
+                               ? bitmap.buffer[r*bitmap.width+c]
+                               : (is_opaque (face->glyph, c, r) ? 255 : 0));
+
                           if (x0+c < 0 || x0+c >= pixels.dim2 ()
                               || y0-r < 0 || y0-r >= pixels.dim3 ())
                             {
@@ -866,7 +878,7 @@
 
     m_strlist = std::list<text_renderer::string> ();
 
-    octave::unwind_protect frame;
+    unwind_protect frame;
     frame.protect_var (m_do_strlist);
     frame.protect_var (m_strlist);
     m_do_strlist = true;
--- a/libinterp/corefcn/gl-render.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/gl-render.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -191,6 +191,25 @@
         //        Should we check for dimensions larger than intmax?
         int h, w, tw, th;
         h = dv(0), w = dv(1);
+
+        // Return early if the image data are larger than the texture
+        // can hold
+        int max_size;
+        glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size);
+        static bool warned = false;
+        if (h > max_size || w > max_size)
+          {
+            if (! warned)
+              {
+                warning ("opengl_texture::create: the opengl library in use "
+                         "doesn't support images with either dimension larger "
+                         "than %d. Not rendering.", max_size);
+                warned = true;
+              }
+
+            return opengl_texture (glfcns);
+          }
+
         GLuint id;
         bool ok = true;
 
@@ -204,7 +223,7 @@
           {
             const NDArray xdata = data.array_value ();
 
-            OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
+            OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th));
 
             for (int i = 0; i < h; i++)
               {
@@ -216,13 +235,53 @@
                   }
               }
 
-            glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, GL_FLOAT, a);
+            glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB,
+                                 GL_FLOAT, a);
+          }
+
+        else if (data.is_single_type ())
+          {
+            const FloatNDArray xdata = data.float_array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th));
+
+            for (int i = 0; i < h; i++)
+              {
+                for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
+                  {
+                    a[idx]   = xdata(i,j,0);
+                    a[idx+1] = xdata(i,j,1);
+                    a[idx+2] = xdata(i,j,2);
+                  }
+              }
+
+            glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB,
+                                 GL_FLOAT, a);
+          }
+        else if (data.is_uint16_type ())
+          {
+            const uint16NDArray xdata = data.uint16_array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLushort, a, (3*tw*th));
+
+            for (int i = 0; i < h; i++)
+              {
+                for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
+                  {
+                    a[idx]   = xdata(i,j,0);
+                    a[idx+1] = xdata(i,j,1);
+                    a[idx+2] = xdata(i,j,2);
+                  }
+              }
+
+            glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
+                                 GL_RGB, GL_UNSIGNED_SHORT, a);
           }
         else if (data.is_uint8_type ())
           {
             const uint8NDArray xdata = data.uint8_array_value ();
 
-            OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
+            OCTAVE_LOCAL_BUFFER (GLubyte, a, (3*tw*th));
 
             for (int i = 0; i < h; i++)
               {
@@ -240,7 +299,7 @@
         else
           {
             ok = false;
-            warning ("opengl_texture::create: invalid texture data type (double or uint8 required)");
+            warning ("opengl_texture::create: invalid image data type, expected double, single, uint8, or uint16");
           }
 
         if (ok)
@@ -619,11 +678,11 @@
 #endif
 
   opengl_renderer::opengl_renderer (opengl_functions& glfcns)
-    : m_glfcns (glfcns), toolkit (), xform (), xmin (), xmax (), ymin (),
-      ymax (), zmin (), zmax (), xZ1 (), xZ2 (), marker_id (),
+    : m_glfcns (glfcns), xmin (), xmax (), ymin (), ymax (), zmin (), zmax (),
+      m_devpixratio (1.), xform (), toolkit (), xZ1 (), xZ2 (), marker_id (),
       filled_marker_id (), camera_pos (), camera_dir (), view_vector (),
       interpreter ("none"), txt_renderer (), m_current_light (0),
-      m_max_lights (0), selecting (false), m_devpixratio (1.)
+      m_max_lights (0), selecting (false)
   {
     // This constructor will fail if we don't have OpenGL or if the data
     // types we assumed in our public interface aren't compatible with the
@@ -710,7 +769,6 @@
   opengl_renderer::draw_figure (const figure::properties& props)
   {
     // Initialize OpenGL context
-
     init_gl_context (props.is_graphicssmoothing (), props.get_color_rgb ());
 
 #if defined (HAVE_OPENGL)
@@ -1349,59 +1407,71 @@
       std::swap (zpTick, zpTickN);
 
     // X box
-    set_color (props.get_xcolor_rgb ());
-
-    if (! isXOrigin || props.is_box() || ! is2D)
-      {
-        m_glfcns.glVertex3d (xPlaneN, ypTick, zpTick);
-        m_glfcns.glVertex3d (xPlane, ypTick, zpTick);
-      }
-
-    if (props.is_box ())
+    Matrix color = props.get_xcolor_rgb ();
+
+    if (! color.isempty ())
       {
-        m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTick);
-        m_glfcns.glVertex3d (xPlane, ypTickN, zpTick);
-        if (! is2D)
+        set_color (color);
+
+        if (! isXOrigin || props.is_box() || ! is2D)
+          {
+            m_glfcns.glVertex3d (xPlaneN, ypTick, zpTick);
+            m_glfcns.glVertex3d (xPlane, ypTick, zpTick);
+          }
+
+        if (props.is_box ())
           {
-            m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTickN);
-            m_glfcns.glVertex3d (xPlane, ypTickN, zpTickN);
-            if (boxFull)
+            m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTick);
+            m_glfcns.glVertex3d (xPlane, ypTickN, zpTick);
+            if (! is2D)
               {
-                m_glfcns.glVertex3d (xPlaneN, ypTick, zpTickN);
-                m_glfcns.glVertex3d (xPlane, ypTick, zpTickN);
+                m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTickN);
+                m_glfcns.glVertex3d (xPlane, ypTickN, zpTickN);
+                if (boxFull)
+                  {
+                    m_glfcns.glVertex3d (xPlaneN, ypTick, zpTickN);
+                    m_glfcns.glVertex3d (xPlane, ypTick, zpTickN);
+                  }
               }
           }
       }
 
     // Y box
-    set_color (props.get_ycolor_rgb ());
-    if (! isYOrigin || props.is_box() || ! is2D)
-      {
-        m_glfcns.glVertex3d (xpTick, yPlaneN, zpTick);
-        m_glfcns.glVertex3d (xpTick, yPlane, zpTick);
-      }
-
-    if (props.is_box () && ! plotyy)
+    color = props.get_ycolor_rgb ();
+
+    if (! color.isempty ())
       {
-        m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTick);
-        m_glfcns.glVertex3d (xpTickN, yPlane, zpTick);
-
-        if (! is2D)
+        set_color (color);
+        if (! isYOrigin || props.is_box() || ! is2D)
+          {
+            m_glfcns.glVertex3d (xpTick, yPlaneN, zpTick);
+            m_glfcns.glVertex3d (xpTick, yPlane, zpTick);
+          }
+
+        if (props.is_box () && ! plotyy)
           {
-            m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTickN);
-            m_glfcns.glVertex3d (xpTickN, yPlane, zpTickN);
-            if (boxFull)
+            m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTick);
+            m_glfcns.glVertex3d (xpTickN, yPlane, zpTick);
+
+            if (! is2D)
               {
-                m_glfcns.glVertex3d (xpTick, yPlaneN, zpTickN);
-                m_glfcns.glVertex3d (xpTick, yPlane, zpTickN);
+                m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTickN);
+                m_glfcns.glVertex3d (xpTickN, yPlane, zpTickN);
+                if (boxFull)
+                  {
+                    m_glfcns.glVertex3d (xpTick, yPlaneN, zpTickN);
+                    m_glfcns.glVertex3d (xpTick, yPlane, zpTickN);
+                  }
               }
           }
       }
 
     // Z box
-    if (! is2D)
+    color = props.get_zcolor_rgb ();
+
+    if (! color.isempty () && ! is2D)
       {
-        set_color (props.get_zcolor_rgb ());
+        set_color (color);
 
         if (xySym)
           {
@@ -1487,8 +1557,14 @@
         double zpTick = props.get_zpTick ();
         double zpTickN = props.get_zpTickN ();
 
-        // X grid
-
+        // X ticks and grid properties
+        Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
+        Matrix xmticks = xform.xscale (props.get_xminortickvalues ().matrix_value ());
+        bool do_xminortick = props.is_xminortick () && ! xticks.isempty ();
+        string_vector xticklabels = props.get_xticklabel ().string_vector_value ();
+        int wmax = 0;
+        int hmax = 0;
+        bool tick_along_z = nearhoriz || math::isinf (fy);
         double linewidth = props.get_linewidth ();
         std::string gridstyle = props.get_gridlinestyle ();
         std::string minorgridstyle = props.get_minorgridlinestyle ();
@@ -1498,27 +1574,29 @@
         double minorgridalpha = props.get_minorgridalpha ();
         bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
         bool do_xminorgrid = (props.is_xminorgrid ()
-                              && (minorgridstyle != "none"));
-        bool do_xminortick = props.is_xminortick ();
+                              && (minorgridstyle != "none")
+                              && ! xticks.isempty ());
         bool is_origin = props.xaxislocation_is ("origin") && props.get_is2D ()
                          && ! props.yscale_is ("log");
         bool is_origin_low = is_origin && (y_min + y_max) < 0;
-        Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
-        Matrix xmticks = xform.xscale (props.get_xminortickvalues ().matrix_value ());
-        string_vector xticklabels = props.get_xticklabel ().string_vector_value ();
-        int wmax = 0;
-        int hmax = 0;
-        bool tick_along_z = nearhoriz || math::isinf (fy);
         bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
 
-        if (props.xcolormode_is ("manual"))
-          {
-            // use axis color for (minor)gridcolor
-            if (props.gridcolormode_is ("auto"))
-              gridcolor = props.get_xcolor_rgb ();
-            if (props.minorgridcolormode_is ("auto"))
-              minorgridcolor = props.get_xcolor_rgb ();
-          }
+        // X grid
+
+        // possibly use axis color for gridcolor & minorgridcolor
+        if (props.gridcolormode_is ("auto"))
+          if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none"))
+            gridcolor = props.get_xcolor_rgb ();
+
+        if (props.minorgridcolormode_is ("auto"))
+          if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none"))
+            minorgridcolor = props.get_xcolor_rgb ();
+
+        if (gridcolor.isempty ())
+          do_xgrid = false;
+
+        if (minorgridcolor.isempty ())
+          do_xminorgrid = false;
 
         // set styles when drawing only minor grid
         if (do_xminorgrid && ! do_xgrid)
@@ -1545,6 +1623,10 @@
                        yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
                        0, (zstate != AXE_DEPTH_DIR));
 
+        // Skip drawing axis, ticks, and ticklabels when color is "none"
+        if (props.xcolor_is ("none"))
+          return;
+
         set_color (props.get_xcolor_rgb ());
 
         // axis line
@@ -1669,8 +1751,14 @@
         double zpTick = props.get_zpTick ();
         double zpTickN = props.get_zpTickN ();
 
-        // Y grid
-
+        // Y ticks and grid properties
+        Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
+        Matrix ymticks = xform.yscale (props.get_yminortickvalues ().matrix_value ());
+        bool do_yminortick = props.is_yminortick () && ! yticks.isempty ();
+        string_vector yticklabels = props.get_yticklabel ().string_vector_value ();
+        int wmax = 0;
+        int hmax = 0;
+        bool tick_along_z = nearhoriz || math::isinf (fx);
         double linewidth = props.get_linewidth ();
         std::string gridstyle = props.get_gridlinestyle ();
         std::string minorgridstyle = props.get_minorgridlinestyle ();
@@ -1680,28 +1768,30 @@
         double minorgridalpha = props.get_minorgridalpha ();
         bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
         bool do_yminorgrid = (props.is_yminorgrid ()
-                              && (minorgridstyle != "none"));
-        bool do_yminortick = props.is_yminortick ();
+                              && (minorgridstyle != "none")
+                              && ! yticks.isempty ());
         bool is_origin = props.yaxislocation_is ("origin") && props.get_is2D ()
                          && ! props.xscale_is ("log");
         bool is_origin_low = is_origin && (x_min + x_max) < 0;
-        Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
-        Matrix ymticks = xform.yscale (props.get_yminortickvalues ().matrix_value ());
-        string_vector yticklabels = props.get_yticklabel ().string_vector_value ();
-        int wmax = 0;
-        int hmax = 0;
-        bool tick_along_z = nearhoriz || math::isinf (fx);
         bool mirror = props.is_box () && ystate != AXE_ANY_DIR
                       && (! props.has_property ("__plotyy_axes__"));
 
-        if (props.ycolormode_is ("manual"))
-          {
-            // use axis color for (minor)gridcolor
-            if (props.gridcolormode_is ("auto"))
-              gridcolor = props.get_ycolor_rgb ();
-            if (props.minorgridcolormode_is ("auto"))
-              minorgridcolor = props.get_ycolor_rgb ();
-          }
+        // Y grid
+
+        // possibly use axis color for gridcolor & minorgridcolor
+        if (props.gridcolormode_is ("auto"))
+          if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none"))
+            gridcolor = props.get_ycolor_rgb ();
+
+        if (props.minorgridcolormode_is ("auto"))
+          if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none"))
+            minorgridcolor = props.get_ycolor_rgb ();
+
+        if (gridcolor.isempty ())
+          do_ygrid = false;
+
+        if (minorgridcolor.isempty ())
+          do_yminorgrid = false;
 
         // set styles when drawing only minor grid
         if (do_yminorgrid && ! do_ygrid)
@@ -1728,6 +1818,10 @@
                        xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN,
                        1, (zstate != AXE_DEPTH_DIR));
 
+        // Skip drawing axis, ticks, and ticklabels when color is "none"
+        if (props.ycolor_is ("none"))
+          return;
+
         set_color (props.get_ycolor_rgb ());
 
         // axis line
@@ -1841,8 +1935,13 @@
         double z_min = props.get_z_min ();
         double z_max = props.get_z_max ();
 
-        // Z Grid
-
+        // Z ticks and grid properties
+        Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
+        Matrix zmticks = xform.zscale (props.get_zminortickvalues ().matrix_value ());
+        bool do_zminortick = props.is_zminortick () && ! zticks.isempty ();
+        string_vector zticklabels = props.get_zticklabel ().string_vector_value ();
+        int wmax = 0;
+        int hmax = 0;
         double linewidth = props.get_linewidth ();
         std::string gridstyle = props.get_gridlinestyle ();
         std::string minorgridstyle = props.get_minorgridlinestyle ();
@@ -1852,23 +1951,26 @@
         double minorgridalpha = props.get_minorgridalpha ();
         bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
         bool do_zminorgrid = (props.is_zminorgrid ()
-                              && (minorgridstyle != "none"));
-        bool do_zminortick = props.is_zminortick ();
-        Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
-        Matrix zmticks = xform.zscale (props.get_zminortickvalues ().matrix_value ());
-        string_vector zticklabels = props.get_zticklabel ().string_vector_value ();
-        int wmax = 0;
-        int hmax = 0;
+                              && (minorgridstyle != "none")
+                              && ! zticks.isempty ());
         bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
 
-        if (props.zcolormode_is ("manual"))
-          {
-            // use axis color for (minor)gridcolor
-            if (props.gridcolormode_is ("auto"))
-              gridcolor = props.get_zcolor_rgb ();
-            if (props.minorgridcolormode_is ("auto"))
-              minorgridcolor = props.get_zcolor_rgb ();
-          }
+        // Z grid
+
+        // possibly use axis color for gridcolor & minorgridcolor
+        if (props.gridcolormode_is ("auto"))
+          if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none"))
+            gridcolor = props.get_zcolor_rgb ();
+
+        if (props.minorgridcolormode_is ("auto"))
+          if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none"))
+            minorgridcolor = props.get_zcolor_rgb ();
+
+        if (gridcolor.isempty ())
+          do_zgrid = false;
+
+        if (minorgridcolor.isempty ())
+          do_zminorgrid = false;
 
         // set styles when drawing only minor grid
         if (do_zminorgrid && ! do_zgrid)
@@ -1893,6 +1995,10 @@
                        zticks, z_min, z_max,
                        xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
 
+        // Skip drawing axis, ticks, and ticklabels when color is "none"
+        if (props.zcolor_is ("none"))
+          return;
+
         set_color (props.get_zcolor_rgb ());
 
         // minor tick marks
@@ -3631,7 +3737,7 @@
   {
 #if defined (HAVE_OPENGL)
 
-    if (props.get_string ().isempty ())
+    if (props.get_string ().isempty () || props.color_is ("none"))
       return;
 
     Matrix pos = xform.scale (props.get_data_position ());
@@ -3786,256 +3892,55 @@
     dim_vector dv (cdata.dims ());
     int h = dv(0);
     int w = dv(1);
+    double x0, x1, y0, y1;
 
     Matrix x = props.get_xdata ().matrix_value ();
+    double dx = 1.0;
+    if (w > 1)
+      dx = (x(1) - x(0)) / (w - 1);
+
+    x0 = x(0)-dx/2;
+    x1 = x(1)+dx/2;
+
     Matrix y = props.get_ydata ().matrix_value ();
-
-    // Someone wants us to draw an empty image?  No way.
-    if (x.isempty () || y.isempty ())
-      return;
-
-    // Sort x/ydata and mark flipped dimensions
-    bool xflip = false;
-    if (x(0) > x(1))
-      {
-        std::swap (x(0), x(1));
-        xflip = true;
-      }
-    else if (w > 1 && x(1) == x(0))
-      x(1) = x(1) + (w-1);
-
-    bool yflip = false;
-    if (y(0) > y(1))
-      {
-        std::swap (y(0), y(1));
-        yflip = true;
-      }
-    else if (h > 1 && y(1) == y(0))
-      y(1) = y(1) + (h-1);
-
-    const ColumnVector p0 = xform.transform (x(0), y(0), 0);
-    const ColumnVector p1 = xform.transform (x(1), y(1), 0);
-
-    if (math::isnan (p0(0)) || math::isnan (p0(1))
-        || math::isnan (p1(0)) || math::isnan (p1(1)))
-      {
-        warning ("opengl_renderer: image X,Y data too large to draw");
-        return;
-      }
-
-    // image pixel size in screen pixel units
-    float pix_dx, pix_dy;
-    // image pixel size in normalized units
-    float nor_dx, nor_dy;
-
-    if (w > 1)
-      {
-        pix_dx = (p1(0) - p0(0)) / (w-1);
-        nor_dx = (x(1) - x(0)) / (w-1);
-      }
-    else
-      {
-        const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
-        pix_dx = p1w(0) - p0(0);
-        nor_dx = 1;
-      }
-
+    double dy = 1.0;
     if (h > 1)
-      {
-        pix_dy = (p1(1) - p0(1)) / (h-1);
-        nor_dy = (y(1) - y(0)) / (h-1);
-      }
-    else
-      {
-        const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
-        pix_dy = p1h(1) - p0(1);
-        nor_dy = 1;
-      }
-
-    // OpenGL won't draw any of the image if its origin is outside the
-    // viewport/clipping plane so we must do the clipping ourselves.
-
-    int j0, j1, jj, i0, i1, ii;
-    j0 = 0, j1 = w;
-    i0 = 0, i1 = h;
-
-    float im_xmin = x(0) - nor_dx/2;
-    float im_xmax = x(1) + nor_dx/2;
-    float im_ymin = y(0) - nor_dy/2;
-    float im_ymax = y(1) + nor_dy/2;
-
-    // Clip to axes or viewport
-    bool do_clip = props.is_clipping ();
-    Matrix vp = get_viewport_scaled ();
-
-    ColumnVector vp_lim_min =
-      xform.untransform (std::numeric_limits <float>::epsilon (),
-                         std::numeric_limits <float>::epsilon ());
-    ColumnVector vp_lim_max = xform.untransform (vp(2), vp(3));
-
-    if (vp_lim_min(0) > vp_lim_max(0))
-      std::swap (vp_lim_min(0), vp_lim_max(0));
-
-    if (vp_lim_min(1) > vp_lim_max(1))
-      std::swap (vp_lim_min(1), vp_lim_max(1));
-
-    float clip_xmin =
-      (do_clip ? (vp_lim_min(0) > xmin ? vp_lim_min(0) : xmin) : vp_lim_min(0));
-    float clip_ymin =
-      (do_clip ? (vp_lim_min(1) > ymin ? vp_lim_min(1) : ymin) : vp_lim_min(1));
-
-    float clip_xmax =
-      (do_clip ? (vp_lim_max(0) < xmax ? vp_lim_max(0) : xmax) : vp_lim_max(0));
-    float clip_ymax =
-      (do_clip ? (vp_lim_max(1) < ymax ? vp_lim_max(1) : ymax) : vp_lim_max(1));
-
-    if (im_xmin < clip_xmin)
-      j0 += (clip_xmin - im_xmin)/nor_dx + 1;
-    if (im_xmax > clip_xmax)
-      j1 -= (im_xmax - clip_xmax)/nor_dx;
-
-    if (im_ymin < clip_ymin)
-      i0 += (clip_ymin - im_ymin)/nor_dy + 1;
-    if (im_ymax > clip_ymax)
-      i1 -= (im_ymax - clip_ymax)/nor_dy;
-
-    if (i0 >= i1 || j0 >= j1)
-      return;
-
-    m_glfcns.glPixelZoom (m_devpixratio * pix_dx,
-                          - m_devpixratio * pix_dy);
-    m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
-
-    // by default this is 4
-    m_glfcns.glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+      dy = (y(1) - y(0)) / (h - 1);
+
+    y0 = y(0)-dy/2;
+    y1 = y(1)+dy/2;
 
     // Expect RGB data
     if (dv.ndims () == 3 && dv(2) == 3)
       {
-        if (cdata.is_double_type ())
+        opengl_texture tex  = opengl_texture::create (m_glfcns, cdata);
+        if (tex.is_valid ())
           {
-            const NDArray xcdata = cdata.array_value ();
-
-            OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
-
-            for (int i = i0; i < i1; i++)
-              {
-                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                  {
-                    if (! yflip)
-                      ii = i;
-                    else
-                      ii = h - i - 1;
-
-                    if (! xflip)
-                      jj = j;
-                    else
-                      jj = w - j - 1;
-
-                    a[idx]   = xcdata(ii,jj,0);
-                    a[idx+1] = xcdata(ii,jj,1);
-                    a[idx+2] = xcdata(ii,jj,2);
-                  }
-              }
-
-            draw_pixels (j1-j0, i1-i0, a);
-
-          }
-        else if (cdata.is_single_type ())
-          {
-            const FloatNDArray xcdata = cdata.float_array_value ();
-
-            OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
-
-            for (int i = i0; i < i1; i++)
-              {
-                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                  {
-                    if (! yflip)
-                      ii = i;
-                    else
-                      ii = h - i - 1;
-
-                    if (! xflip)
-                      jj = j;
-                    else
-                      jj = w - j - 1;
-
-                    a[idx]   = xcdata(ii,jj,0);
-                    a[idx+1] = xcdata(ii,jj,1);
-                    a[idx+2] = xcdata(ii,jj,2);
-                  }
-              }
-
-            draw_pixels (j1-j0, i1-i0, a);
-
+            m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0);
+
+            m_glfcns.glEnable (GL_TEXTURE_2D);
+
+            m_glfcns.glBegin (GL_QUADS);
+
+            tex.tex_coord (0.0, 0.0);
+            m_glfcns.glVertex3d (x0, y0, 0.0);
+
+            tex.tex_coord (1.0, 0.0);
+            m_glfcns.glVertex3d (x1, y0, 0.0);
+
+            tex.tex_coord (1.0, 1.0);
+            m_glfcns.glVertex3d (x1, y1, 0.0);
+
+            tex.tex_coord (0.0, 1.0);
+            m_glfcns.glVertex3d (x0, y1, 0.0);
+
+            m_glfcns.glEnd ();
+            m_glfcns.glDisable (GL_TEXTURE_2D);
           }
-        else if (cdata.is_uint8_type ())
-          {
-            const uint8NDArray xcdata = cdata.uint8_array_value ();
-
-            OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
-
-            for (int i = i0; i < i1; i++)
-              {
-                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                  {
-                    if (! yflip)
-                      ii = i;
-                    else
-                      ii = h - i - 1;
-
-                    if (! xflip)
-                      jj = j;
-                    else
-                      jj = w - j - 1;
-
-                    a[idx]   = xcdata(ii,jj,0);
-                    a[idx+1] = xcdata(ii,jj,1);
-                    a[idx+2] = xcdata(ii,jj,2);
-                  }
-              }
-
-            draw_pixels (j1-j0, i1-i0, a);
-
-          }
-        else if (cdata.is_uint16_type ())
-          {
-            const uint16NDArray xcdata = cdata.uint16_array_value ();
-
-            OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
-
-            for (int i = i0; i < i1; i++)
-              {
-                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                  {
-                    if (! yflip)
-                      ii = i;
-                    else
-                      ii = h - i - 1;
-
-                    if (! xflip)
-                      jj = j;
-                    else
-                      jj = w - j - 1;
-
-                    a[idx]   = xcdata(ii,jj,0);
-                    a[idx+1] = xcdata(ii,jj,1);
-                    a[idx+2] = xcdata(ii,jj,2);
-                  }
-              }
-
-            draw_pixels (j1-j0, i1-i0, a);
-
-          }
-        else
-          warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)");
       }
     else
       warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)");
 
-    m_glfcns.glPixelZoom (1, 1);
-
 #else
 
     octave_unused_parameter (props);
@@ -4098,76 +4003,14 @@
   }
 
   void
-  opengl_renderer::draw_pixels (int width, int height, const float *data)
-  {
-#if defined (HAVE_OPENGL)
-
-    m_glfcns.glDrawPixels (width, height, GL_RGB, GL_FLOAT, data);
-
-#else
-
-    octave_unused_parameter (width);
-    octave_unused_parameter (height);
-    octave_unused_parameter (data);
-
-    // This shouldn't happen because construction of opengl_renderer
-    // objects is supposed to be impossible if OpenGL is not available.
-
-    panic_impossible ();
-
-#endif
-  }
-
-  void
-  opengl_renderer::draw_pixels (int width, int height, const uint8_t *data)
-  {
-#if defined (HAVE_OPENGL)
-
-    m_glfcns.glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
-
-#else
-
-    octave_unused_parameter (width);
-    octave_unused_parameter (height);
-    octave_unused_parameter (data);
-
-    // This shouldn't happen because construction of opengl_renderer
-    // objects is supposed to be impossible if OpenGL is not available.
-
-    panic_impossible ();
-
-#endif
-  }
-
-  void
-  opengl_renderer::draw_pixels (int width, int height, const uint16_t *data)
-  {
-#if defined (HAVE_OPENGL)
-
-    m_glfcns.glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_SHORT, data);
-
-#else
-
-    octave_unused_parameter (width);
-    octave_unused_parameter (height);
-    octave_unused_parameter (data);
-
-    // This shouldn't happen because construction of opengl_renderer
-    // objects is supposed to be impossible if OpenGL is not available.
-
-    panic_impossible ();
-
-#endif
-  }
-
-  void
   opengl_renderer::set_color (const Matrix& c)
   {
 #if defined (HAVE_OPENGL)
 
     m_glfcns.glColor3dv (c.data ());
 
-    txt_renderer.set_color (c);
+    if (! c.isempty ())
+      txt_renderer.set_color (c);
 
 #else
 
@@ -4184,6 +4027,8 @@
   void
   opengl_renderer::set_font (const base_properties& props)
   {
+    bool do_anti_alias = props.get ("fontsmoothing").string_value () == "on";
+    txt_renderer.set_anti_aliasing (do_anti_alias);
     txt_renderer.set_font (props.get ("fontname").string_value (),
                            props.get ("fontweight").string_value (),
                            props.get ("fontangle").string_value (),
@@ -4225,8 +4070,15 @@
   opengl_renderer::set_linewidth (float w)
   {
 #if defined (HAVE_OPENGL)
-
-    m_glfcns.glLineWidth (w * m_devpixratio);
+    // FIXME: See bug #53056 (measure LineWidth in points).
+    //        pts2pix and m_devpixratio should eventually be combined in to a
+    //        a single conversion factor so that only one multiplication per
+    //        function call is required.
+    const static double pts2pix =
+      gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      / 72.0;
+
+    m_glfcns.glLineWidth (w * pts2pix * m_devpixratio);
 
 #else
 
@@ -4246,7 +4098,11 @@
   {
 #if defined (HAVE_OPENGL)
 
-    int factor = math::round (linewidth * m_devpixratio);
+    // FIXME: See bug #53056 (measure LineWidth in points).
+    const static double pts2pix =
+      gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      / 72.0;
+    int factor = math::round (linewidth * pts2pix * m_devpixratio);
     if (factor < 1)
       factor = 1;
 
@@ -4257,11 +4113,25 @@
     if (s == "-")
       solid = true;
     else if (s == ":")
-      pattern = 0x5555;
+      {
+        if (factor > 1)
+          pattern = 0x5555;
+        else
+          pattern = 0x1111;
+      }
     else if (s == "--")
-      pattern = 0x0F0F;
+        if (factor > 1)
+          pattern = 0x0F0F;
+        else
+          pattern = 0x01FF;
+
     else if (s == "-.")
-      pattern = 0x6F6F;
+      {
+        if (factor > 1)
+          pattern = 0x6F6F;
+        else
+          pattern = 0x18FF;
+      }
     else
       pattern = 0x0000;
 
@@ -4571,7 +4441,13 @@
       return 0;
 
     unsigned int ID = m_glfcns.glGenLists (1);
-    double sz = size * toolkit.get_screen_resolution () / 72.0;
+
+    // FIXME: See bug #53056 (measure LineWidth in points).
+    const static double pts2pix =
+      gh_manager::get_object (0).get ("screenpixelsperinch").double_value ()
+      / 72.0;
+
+    double sz = size * pts2pix;
 
     // constants for the * marker
     const double sqrt2d4 = 0.35355339059327;
--- a/libinterp/corefcn/gl-render.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/gl-render.h	Fri Jul 12 12:14:43 2019 -0400
@@ -52,7 +52,10 @@
 
     virtual void draw (const graphics_object& go, bool toplevel = true);
 
-    virtual void draw (const Matrix& hlist, bool toplevel = false)
+    // The following version of the draw method is not declared virtual
+    // because no derived class overrides it.
+
+    void draw (const Matrix& hlist, bool toplevel = false)
     {
       int len = hlist.numel ();
 
@@ -140,10 +143,6 @@
                                 double x, double y, double z,
                                 int halign, int valign, double rotation = 0.0);
 
-    virtual void draw_pixels (int w, int h, const float *data);
-    virtual void draw_pixels (int w, int h, const uint8_t *data);
-    virtual void draw_pixels (int w, int h, const uint16_t *data);
-
     virtual void render_grid (const double linewidth,
                               const std::string& gridstyle,
                               const Matrix& gridcolor, const double gridalpha,
@@ -212,19 +211,22 @@
 
     opengl_functions& m_glfcns;
 
+    // axis limits in model scaled coordinate
+    double xmin, xmax;
+    double ymin, ymax;
+    double zmin, zmax;
+
+    // Factor used for translating Octave pixels to actual device pixels
+    double m_devpixratio;
+
+    // axes transformation data
+    graphics_xform xform;
+
   private:
 
     // The graphics toolkit associated with the figure being rendered.
     graphics_toolkit toolkit;
 
-    // axes transformation data
-    graphics_xform xform;
-
-    // axis limits in model scaled coordinate
-    double xmin, xmax;
-    double ymin, ymax;
-    double zmin, zmax;
-
     // Z projection limits in windows coordinate
     double xZ1, xZ2;
 
@@ -246,9 +248,6 @@
     // Indicate we are drawing for selection purpose
     bool selecting;
 
-    // Factor used for translating Octave pixels to actual device pixels
-    double m_devpixratio;
-
   private:
     class patch_tesselator;
   };
--- a/libinterp/corefcn/gl2ps-print.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/gl2ps-print.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -175,6 +175,7 @@
 
     void draw_text (const text::properties& props);
 
+    void draw_image (const image::properties& props);
     void draw_pixels (int w, int h, const float *data);
     void draw_pixels (int w, int h, const uint8_t *data);
     void draw_pixels (int w, int h, const uint16_t *data);
@@ -1042,6 +1043,266 @@
   }
 
   void
+  gl2ps_renderer::draw_image (const image::properties& props)
+  {
+    octave_value cdata = props.get_color_data ();
+    dim_vector dv (cdata.dims ());
+    int h = dv(0);
+    int w = dv(1);
+
+    Matrix x = props.get_xdata ().matrix_value ();
+    Matrix y = props.get_ydata ().matrix_value ();
+
+    // Someone wants us to draw an empty image?  No way.
+    if (x.isempty () || y.isempty ())
+      return;
+
+    // Sort x/ydata and mark flipped dimensions
+    bool xflip = false;
+    if (x(0) > x(1))
+      {
+        std::swap (x(0), x(1));
+        xflip = true;
+      }
+    else if (w > 1 && x(1) == x(0))
+      x(1) = x(1) + (w-1);
+
+    bool yflip = false;
+    if (y(0) > y(1))
+      {
+        std::swap (y(0), y(1));
+        yflip = true;
+      }
+    else if (h > 1 && y(1) == y(0))
+      y(1) = y(1) + (h-1);
+
+
+    const ColumnVector p0 = xform.transform (x(0), y(0), 0);
+    const ColumnVector p1 = xform.transform (x(1), y(1), 0);
+
+    if (math::isnan (p0(0)) || math::isnan (p0(1))
+        || math::isnan (p1(0)) || math::isnan (p1(1)))
+      {
+        warning ("opengl_renderer: image X,Y data too large to draw");
+        return;
+      }
+
+    // image pixel size in screen pixel units
+    float pix_dx, pix_dy;
+    // image pixel size in normalized units
+    float nor_dx, nor_dy;
+
+    if (w > 1)
+      {
+        pix_dx = (p1(0) - p0(0)) / (w-1);
+        nor_dx = (x(1) - x(0)) / (w-1);
+      }
+    else
+      {
+        const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
+        pix_dx = p1w(0) - p0(0);
+        nor_dx = 1;
+      }
+
+    if (h > 1)
+      {
+        pix_dy = (p1(1) - p0(1)) / (h-1);
+        nor_dy = (y(1) - y(0)) / (h-1);
+      }
+    else
+      {
+        const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
+        pix_dy = p1h(1) - p0(1);
+        nor_dy = 1;
+      }
+
+    // OpenGL won't draw any of the image if its origin is outside the
+    // viewport/clipping plane so we must do the clipping ourselves.
+
+    int j0, j1, jj, i0, i1, ii;
+    j0 = 0, j1 = w;
+    i0 = 0, i1 = h;
+
+    float im_xmin = x(0) - nor_dx/2;
+    float im_xmax = x(1) + nor_dx/2;
+    float im_ymin = y(0) - nor_dy/2;
+    float im_ymax = y(1) + nor_dy/2;
+
+    // Clip to axes or viewport
+    bool do_clip = props.is_clipping ();
+    Matrix vp = get_viewport_scaled ();
+
+    ColumnVector vp_lim_min =
+      xform.untransform (std::numeric_limits <float>::epsilon (),
+                         std::numeric_limits <float>::epsilon ());
+    ColumnVector vp_lim_max = xform.untransform (vp(2), vp(3));
+
+    if (vp_lim_min(0) > vp_lim_max(0))
+      std::swap (vp_lim_min(0), vp_lim_max(0));
+
+    if (vp_lim_min(1) > vp_lim_max(1))
+      std::swap (vp_lim_min(1), vp_lim_max(1));
+
+    float clip_xmin =
+      (do_clip ? (vp_lim_min(0) > xmin ? vp_lim_min(0) : xmin) : vp_lim_min(0));
+    float clip_ymin =
+      (do_clip ? (vp_lim_min(1) > ymin ? vp_lim_min(1) : ymin) : vp_lim_min(1));
+
+    float clip_xmax =
+      (do_clip ? (vp_lim_max(0) < xmax ? vp_lim_max(0) : xmax) : vp_lim_max(0));
+    float clip_ymax =
+      (do_clip ? (vp_lim_max(1) < ymax ? vp_lim_max(1) : ymax) : vp_lim_max(1));
+
+    if (im_xmin < clip_xmin)
+      j0 += (clip_xmin - im_xmin)/nor_dx + 1;
+    if (im_xmax > clip_xmax)
+      j1 -= (im_xmax - clip_xmax)/nor_dx;
+
+    if (im_ymin < clip_ymin)
+      i0 += (clip_ymin - im_ymin)/nor_dy + 1;
+    if (im_ymax > clip_ymax)
+      i1 -= (im_ymax - clip_ymax)/nor_dy;
+
+    if (i0 >= i1 || j0 >= j1)
+      return;
+
+    float zoom_x;
+    m_glfcns.glGetFloatv (GL_ZOOM_X, &zoom_x);
+    float zoom_y;
+    m_glfcns.glGetFloatv (GL_ZOOM_Y, &zoom_y);
+
+    m_glfcns.glPixelZoom (m_devpixratio * pix_dx,
+                          - m_devpixratio * pix_dy);
+    m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
+
+    // Expect RGB data
+    if (dv.ndims () == 3 && dv(2) == 3)
+      {
+        if (cdata.is_double_type ())
+          {
+            const NDArray xcdata = cdata.array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+            for (int i = i0; i < i1; i++)
+              {
+                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                  {
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
+                  }
+              }
+
+            draw_pixels (j1-j0, i1-i0, a);
+
+          }
+        else if (cdata.is_single_type ())
+          {
+            const FloatNDArray xcdata = cdata.float_array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+            for (int i = i0; i < i1; i++)
+              {
+                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                  {
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
+                  }
+              }
+
+            draw_pixels (j1-j0, i1-i0, a);
+
+          }
+        else if (cdata.is_uint8_type ())
+          {
+            const uint8NDArray xcdata = cdata.uint8_array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
+
+            for (int i = i0; i < i1; i++)
+              {
+                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                  {
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
+                  }
+              }
+
+            draw_pixels (j1-j0, i1-i0, a);
+
+          }
+        else if (cdata.is_uint16_type ())
+          {
+            const uint16NDArray xcdata = cdata.uint16_array_value ();
+
+            OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
+
+            for (int i = i0; i < i1; i++)
+              {
+                for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                  {
+                    if (! yflip)
+                      ii = i;
+                    else
+                      ii = h - i - 1;
+
+                    if (! xflip)
+                      jj = j;
+                    else
+                      jj = w - j - 1;
+
+                    a[idx]   = xcdata(ii,jj,0);
+                    a[idx+1] = xcdata(ii,jj,1);
+                    a[idx+2] = xcdata(ii,jj,2);
+                  }
+              }
+
+            draw_pixels (j1-j0, i1-i0, a);
+
+          }
+        else
+          warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)");
+
+        m_glfcns.glPixelZoom (zoom_x, zoom_y);
+
+      }
+  }
+
+  void
   gl2ps_renderer::draw_pixels (int w, int h, const float *data)
   {
     // Clip data between 0 and 1 for float values
@@ -1154,7 +1415,7 @@
 
         std::string cmd = stream.substr (1);
 
-        fp = octave::popen (cmd.c_str (), "w");
+        fp = popen (cmd.c_str (), "w");
 
         if (! fp)
           error (R"(print: failed to open pipe "%s")", stream.c_str ());
@@ -1165,7 +1426,7 @@
       {
         // Write gl2ps output directly to file.
 
-        fp = octave::sys::fopen (stream.c_str (), "w");
+        fp = sys::fopen (stream.c_str (), "w");
 
         if (! fp)
           error (R"(gl2ps_print: failed to create file "%s")", stream.c_str ());
--- a/libinterp/corefcn/graphics.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/graphics.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -308,6 +308,19 @@
 }
 
 static Matrix
+default_data_lim (void)
+{
+  Matrix retval (1, 4);
+
+  retval(0) = 0;
+  retval(1) = 1;
+  retval(2) = 1;  // minimum positive
+  retval(3) = -octave::numeric_limits<double>::Inf (); // maximum negative
+
+  return retval;
+}
+
+static Matrix
 default_image_cdata (void)
 {
   Matrix m (64, 64);
@@ -1013,10 +1026,22 @@
     }                                                                   \
   while (0)
 
-  if (cdata.is_uint8_type ())
+  if (cdata.is_int8_type ())
+    CONVERT_CDATA_1 (int8NDArray, int8_, false);
+  else if (cdata.is_int16_type ())
+    CONVERT_CDATA_1 (int16NDArray, int16_, false);
+  else if (cdata.is_int32_type ())
+    CONVERT_CDATA_1 (int32NDArray, int32_, false);
+  else if (cdata.is_int64_type ())
+    CONVERT_CDATA_1 (int64NDArray, int64_, false);
+  else if (cdata.is_uint8_type ())
     CONVERT_CDATA_1 (uint8NDArray, uint8_, false);
   else if (cdata.is_uint16_type ())
     CONVERT_CDATA_1 (uint16NDArray, uint16_, false);
+  else if (cdata.is_uint32_type ())
+    CONVERT_CDATA_1 (uint32NDArray, uint32_, false);
+  else if (cdata.is_uint64_type ())
+    CONVERT_CDATA_1 (uint64NDArray, uint64_, false);
   else if (cdata.is_double_type ())
     CONVERT_CDATA_1 (NDArray, , true);
   else if (cdata.is_single_type ())
@@ -1027,7 +1052,8 @@
     {
       // Don't throw an error; leads to an incomplete FLTK object (bug #46933).
       warning ("unsupported type for cdata (= %s).  "
-               "Valid types are uint8, uint16, double, single, and bool.",
+               "Valid types are int8, int16, int32, int64, uint8, uint16, "
+               "uint32, uint64, double, single, and bool.",
                cdata.type_name ().c_str ());
       a = NDArray (dv, 0);  // return 0 instead
     }
@@ -1772,12 +1798,6 @@
 }
 
 void
-children_property::do_delete_children (bool clear)
-{
-  do_delete_children (clear, false);
-}
-
-void
 children_property::do_delete_children (bool clear, bool from_root)
 {
   for (graphics_handle hchild : children_list)
@@ -2732,12 +2752,6 @@
 }
 
 void
-gh_manager::do_free (const graphics_handle& h)
-{
-  do_free (h, false);
-}
-
-void
 gh_manager::do_free (const graphics_handle& h, bool from_root)
 {
   if (h.ok ())
@@ -3556,13 +3570,7 @@
 
       octave::unwind_protect frame;
 
-      frame.protect_var (discard_error_messages);
-      frame.protect_var (Vdebug_on_error);
-      frame.protect_var (Vdebug_on_warning);
-
-      discard_error_messages = true;
-      Vdebug_on_error = false;
-      Vdebug_on_warning = false;
+      interpreter_try (frame, octave::error_system::discard);
 
       try
         {
@@ -3908,12 +3916,6 @@
 */
 
 void
-root_figure::properties::remove_child (const graphics_handle& h)
-{
-  remove_child (h, false);
-}
-
-void
 root_figure::properties::remove_child (const graphics_handle& h, bool)
 {
   gh_manager::pop_figure (h);
@@ -3950,12 +3952,6 @@
 }
 
 void
-figure::properties::remove_child (const graphics_handle& h)
-{
-  remove_child (h, false);
-}
-
-void
 figure::properties::remove_child (const graphics_handle& h, bool from_root)
 {
   base_properties::remove_child (h, from_root);
@@ -5077,7 +5073,7 @@
 void
 axes::properties::sync_positions (void)
 {
-  // First part is equivalent to `update_tightinset ()'
+  // First part is equivalent to 'update_tightinset ()'
   if (activepositionproperty.is ("position"))
     update_position ();
   else
@@ -5102,9 +5098,9 @@
 }
 
 /*
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
 %! hf = figure ("visible", "off");
-%! graphics_toolkit (hf, "fltk");
+%! graphics_toolkit (hf, "qt");
 %! unwind_protect
 %!   subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
 %!   hax = findall (gcf (), "type", "axes");
@@ -5122,9 +5118,9 @@
 %!   close (hf);
 %! end_unwind_protect
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
 %! hf = figure ("visible", "off");
-%! graphics_toolkit (hf, "fltk");
+%! graphics_toolkit (hf, "qt");
 %! fpos = get (hf, "position");
 %! unwind_protect
 %!   plot (rand (3));
@@ -5142,9 +5138,9 @@
 %!   close (hf);
 %! end_unwind_protect
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
 %! hf = figure ("visible", "off");
-%! graphics_toolkit (hf, "fltk");
+%! graphics_toolkit (hf, "qt");
 %! fpos = get (hf, "position");
 %! set (gca, "activepositionproperty", "position");
 %! unwind_protect
@@ -5303,8 +5299,6 @@
   // Note: dataspectratio (not mode) will be set through update_aspectratios
   dataaspectratiomode = "auto";
 
-  drawmode = "normal";
-
   fontangle = "normal";
   fontname = OCTAVE_DEFAULT_FONTNAME;
   fontsize = 10;
@@ -5479,12 +5473,6 @@
 }
 
 void
-axes::properties::delete_text_child (handle_property& hp)
-{
-  delete_text_child (hp, false);
-}
-
-void
 axes::properties::delete_text_child (handle_property& hp, bool from_root)
 {
   graphics_handle h = hp.handle_value ();
@@ -5514,12 +5502,6 @@
 }
 
 void
-axes::properties::remove_child (const graphics_handle& h)
-{
-  remove_child (h, false);
-}
-
-void
 axes::properties::remove_child (const graphics_handle& h, bool from_root)
 {
   graphics_object go = gh_manager::get_object (h);
@@ -6148,7 +6130,9 @@
   Matrix bbox = get_boundingbox (true);
   Matrix ticklen = get_ticklength ().matrix_value ();
   ticklen(0) *= std::max (bbox(2), bbox(3));
-  ticklen(1) *= std::max (bbox(2), bbox(3));
+  // FIXME: This algorithm is not Matlab-compatible.  See bug #55483.
+  //        Scale the results of Octave's algorithm for better visuals.
+  ticklen(1) *= (0.76 * std::max (bbox(2), bbox(3)));
 
   xticklen = ticksign * (mode2D ? ticklen(0) : ticklen(1));
   yticklen = ticksign * (mode2D ? ticklen(0) : ticklen(1));
@@ -7224,31 +7208,35 @@
                   double& min_pos, double& max_neg,
                   const octave_value& data)
 {
+  Matrix m;
+
   if (data.is_matrix_type ())
-    {
-      Matrix m = data.matrix_value ();
-
-      if (m.numel () == 4)
-        {
-          double val;
-
-          val = m(0);
-          if (octave::math::isfinite (val) && val < min_val)
-            min_val = val;
-
-          val = m(1);
-          if (octave::math::isfinite (val) && val > max_val)
-            max_val = val;
-
-          val = m(2);
-          if (octave::math::isfinite (val) && val > 0 && val < min_pos)
-            min_pos = val;
-
-          val = m(3);
-          if (octave::math::isfinite (val) && val < 0 && val > max_neg)
-            max_neg = val;
-        }
-    }
+    m = data.matrix_value ();
+
+  if (m.numel () != 4)
+    {
+      m = Matrix (1, 4, 0.0);
+      m(2) = octave::numeric_limits<double>::Inf ();
+      m(3) = -octave::numeric_limits<double>::Inf ();
+    }
+
+  double val;
+
+  val = m(0);
+  if (octave::math::isfinite (val) && val < min_val)
+    min_val = val;
+
+  val = m(1);
+  if (octave::math::isfinite (val) && val > max_val)
+    max_val = val;
+
+  val = m(2);
+  if (octave::math::isfinite (val) && val > 0 && val < min_pos)
+    min_pos = val;
+
+  val = m(3);
+  if (octave::math::isfinite (val) && val < 0 && val > max_neg)
+    max_neg = val;
 }
 
 // magform(x) Returns (a, b),
@@ -7642,18 +7630,17 @@
       do_update = true;
     }
   // FIXME: maybe this test should also be relative?
-  else if (std::abs (limits(0) - limits(1)) < sqrt (eps))
-    {
-      if (logscale)
-        {
-          limits(0) = (limits(0) < 0 ? 10.0 * limits(0) : 0.1 * limits(0));
-          limits(1) = (limits(1) < 0 ? 0.1 * limits(1) : 10.0 * limits(1));
-        }
-      else
-        {
-          limits(0) -= 0.1 * std::abs (limits(0));
-          limits(1) += 0.1 * std::abs (limits(1));
-        }
+  else if (! logscale && (std::abs (limits(0) - limits(1)) < sqrt (eps)))
+    {
+      limits(0) -= 0.1 * std::abs (limits(0));
+      limits(1) += 0.1 * std::abs (limits(1));
+      do_update = true;
+    }
+  else if (logscale
+           && (std::abs (std::log10 (limits(0) / limits(1))) < sqrt (eps)))
+    {
+      limits(0) = (limits(0) < 0 ? 10.0 * limits(0) : 0.1 * limits(0));
+      limits(1) = (limits(1) < 0 ? 0.1 * limits(1) : 10.0 * limits(1));
       do_update = true;
     }
 
@@ -9184,7 +9171,12 @@
                          get ("fontangle").string_value (),
                          get ("__fontsize_points__").double_value () * dpr);
 
-  txt_renderer.set_color (get_color_rgb ());
+  txt_renderer.set_anti_aliasing (is_fontsmoothing ());
+
+  Matrix c = get_color_rgb ();
+  if (! c.isempty ())
+    txt_renderer.set_color (c);
+
 }
 
 void
@@ -9430,6 +9422,104 @@
   facevertexcdata.set (fvc);
 }
 
+// core coplanar tester
+bool is_coplanar (const Matrix &cov)
+{
+  // Accuracy note: this test will also accept single precision input (although
+  // stored in double precision). This is because the error threshold is
+  // sqrt(tol) = 1.5e-7.
+  double tol = 100 * std::numeric_limits<double>::epsilon ();
+  EIG eig (cov, false, false, true);
+  ColumnVector ev = real (eig.eigenvalues ());
+  return ev.min () <= tol * ev.max ();
+}
+
+std::list<octave_idx_type>
+coplanar_partition (const Matrix &vert, const Matrix &idx,
+                    octave_idx_type nc, octave_idx_type jj)
+{
+  std::list<octave_idx_type> coplanar_ends;
+
+  Matrix plane_pivot = Matrix (1, 3, 0.0);
+  for (octave_idx_type i = 0; i < 3; i++)
+    plane_pivot(0,i) = vert(idx(0,jj)-1,i);
+
+  Matrix fc = Matrix (0, 3, 0.0);  // face corner vertex coordinates
+  Matrix fa = Matrix (1, 3, 0.0);  // for append face corner
+  Matrix coor_cov = Matrix (3, 3, 0.0);
+
+  if (nc >= 5)
+    {
+      // Coplanar test that involves all points.
+      // For nc == 4, this initial test is not beneficial at all.
+      // If the probability of coplanar input is more than half, for
+      // the best average performance, we should use nc >= 5.
+      // Higher threshold is meaningful only when input is known to be
+      // non-coplanar and nc is small.
+
+      fc.resize (nc - 1, 3);
+      for (octave_idx_type j = 1; j < nc; j++)
+        for (octave_idx_type i = 0; i < 3; i++)
+          fc(j-1,i) = vert(idx(j,jj)-1,i) - plane_pivot(i);
+
+      coor_cov = fc.transpose () * fc;
+      if (is_coplanar (coor_cov))
+        {
+          coplanar_ends.push_back (nc - 1);
+          return coplanar_ends;
+        }
+    }
+
+  fc.resize (3, 3);
+  octave_idx_type i_start = 1;
+  octave_idx_type i_end = 2;
+
+  // Split the polygon into coplanar segments.
+  // The first point is common corner of all planes.
+  while (i_start < nc - 1)
+    {
+      i_end = i_start + 2;
+      if (i_end > nc - 1)
+        {
+          coplanar_ends.push_back (nc - 1);
+          break;
+        }
+
+      // Algorithm: Start from 3 points, keep adding points until the point set
+      // is no more in a plane. Record the coplanar point set, then advance
+      // i_start.
+
+      // Prepare 1+3 points for coplanar test.
+      // The first point is implicitly included.
+      for (octave_idx_type j = 0; j < 3; j++)
+        for (octave_idx_type i = 0; i < 3; i++)
+          fc(j,i) = vert(idx(j+i_start,jj)-1,i) - plane_pivot(i);
+
+      // covariance matrix between coordinates of vertices
+      coor_cov = fc.transpose () * fc;
+
+      while (true)
+        {
+          // coplanar test
+          if (! is_coplanar (coor_cov))
+            break;
+
+          i_end++;
+          if (i_end > nc - 1)
+            break;
+
+          // add a point to plane
+          for (octave_idx_type i = 0; i < 3; i++)
+            fa(0,i) = vert(idx(i_end,jj)-1,i) - plane_pivot(i);
+          coor_cov += fa.transpose () * fa;
+        }
+
+      i_start = i_end - 1;
+      coplanar_ends.push_back (i_start);
+    }
+  return coplanar_ends;
+}
+
 void
 patch::properties::update_data (void)
 {
@@ -9478,48 +9568,32 @@
     {
       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 (nc < fcmax && ! octave::math::isnan (idx(nc,jj)))
-                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)
+          if (octave::math::isnan (idx(3,jj)))
+            continue;
+
+          // find first element that is NaN to get number of corners
+          octave_idx_type nc = 3;
+          while (nc < fcmax && ! octave::math::isnan (idx(nc,jj)))
+            nc++;
+
+          // If any of the corners is NaN or Inf, skip coplanar test.
+          // FIXME: Add support for non-coplanar faces with unclosed contour.
+          bool is_unclosed = false;
+          for (octave_idx_type j = 0; j < nc; j++)
+            {
+              const octave_idx_type k = idx(j, jj) - 1;
+              if (! (octave::math::isfinite (vert(k, 0))
+                  && octave::math::isfinite (vert(k, 1))
+                  && octave::math::isfinite (vert(k, 2))))
                 {
-                  // 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);
-
-                      // FIXME: Using  svd's to check for co-planarity is slow
-                      // for faces with many vertices. Is there a better way to
-                      // check this?
-
-                      // calculate rank of matrix
-                      octave::math::svd<Matrix> result
-                        (fc,
-                         octave::math::svd<Matrix>::Type::sigma_only,
-                         octave::math::svd<Matrix>::Driver::GESDD);
-                      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;
+                  is_unclosed = true;
+                  break;
                 }
-              coplanar_last_idx.push_back (coplanar_ends);
-            }
+            }
+          if (is_unclosed)
+            continue;
+
+          coplanar_last_idx.push_back (coplanar_partition (vert, idx, nc, jj));
         }
     }
 
@@ -10137,12 +10211,6 @@
 // ---------------------------------------------------------------------
 
 void
-hggroup::properties::remove_child (const graphics_handle& h)
-{
-  remove_child (h, false);
-}
-
-void
 hggroup::properties::remove_child (const graphics_handle& h, bool from_root)
 {
   graphics_object go = gh_manager::get_object (h);
@@ -11262,9 +11330,7 @@
 gh_manager::create_instance (void)
 {
   instance = new gh_manager ();
-
-  if (instance)
-    singleton_cleanup_list::add (cleanup_instance);
+  singleton_cleanup_list::add (cleanup_instance);
 }
 
 graphics_handle
@@ -11623,6 +11689,7 @@
   if (cb_arg.is_defined () && ! cb_arg.isempty ())
     {
       octave_value_list args;
+      octave_value ov_fcn;
       octave_function *fcn = nullptr;
 
       args(0) = h.as_octave_value ();
@@ -11647,8 +11714,15 @@
       // Copy CB because "function_value" method is non-const.
       octave_value cb = cb_arg;
 
-      if (cb.is_function () || cb.is_function_handle ())
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("gh_manager::do_execute_callback");
+
+      octave::error_system& es = interp.get_error_system ();
+
+      if (cb.is_function ())
         fcn = cb.function_value ();
+      else if (cb.is_function_handle ())
+        ov_fcn = cb;
       else if (cb.is_string ())
         {
           int status;
@@ -11656,16 +11730,16 @@
 
           try
             {
-              octave::interpreter& interp
-                = octave::__get_interpreter__ ("gh_manager::do_execute_callback");
-
               interp.eval_string (s, false, status, 0);
             }
           catch (octave::execution_exception&)
             {
               std::cerr << "execution error in graphics callback function"
                         << std::endl;
-              Flasterr (ovl ("execution error in graphics callback function"));
+
+              es.last_error_id ("");
+              es.last_error_message ("execution error in graphics callback function");
+
               octave::interpreter::recover_from_exception ();
             }
         }
@@ -11676,7 +11750,7 @@
         {
           Cell c = cb.cell_value ();
 
-          fcn = c(0).function_value ();
+          ov_fcn = c(0);
 
           for (int i = 1; i < c.numel () ; i++)
             args(1+i) = c(i);
@@ -11688,16 +11762,22 @@
                  nm.c_str ());
         }
 
-      if (fcn)
+      if (fcn || ov_fcn.is_defined ())
         try
           {
-            octave::feval (fcn, args);
+            if (ov_fcn.is_defined ())
+              octave::feval (ov_fcn, args);
+            else
+              octave::feval (fcn, args);
           }
         catch (octave::execution_exception&)
           {
             std::cerr << "execution error in graphics callback function"
                       << std::endl;
-            Flasterr (ovl ("execution error in graphics callback function"));
+
+            es.last_error_id ("");
+            es.last_error_message ("execution error in graphics callback function");
+
             octave::interpreter::recover_from_exception ();
           }
 
@@ -11877,8 +11957,9 @@
 %! setappdata (gcbf (), "cb_exec", [getappdata(gcbf (), "cb_exec") h]);
 %!endfunction
 %!
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
 %! hf = figure ("visible", "off", "resizefcn", @cb);
+%! graphics_toolkit (hf, "qt");
 %! unwind_protect
 %!   ## Default
 %!   hui1 = uicontrol ("parent", hf, "interruptible", "on", "callback", @cb);
--- a/libinterp/corefcn/graphics.in.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/graphics.in.h	Fri Jul 12 12:14:43 2019 -0400
@@ -1759,12 +1759,7 @@
     return octave_value (get_children ());
   }
 
-  void delete_children (bool clear = false)
-  {
-    do_delete_children (clear);
-  }
-
-  void delete_children (bool clear, bool from_root)
+  void delete_children (bool clear = false, bool from_root = false)
   {
     do_delete_children (clear, from_root);
   }
@@ -1890,8 +1885,6 @@
     children_list.push_front (val);
   }
 
-  void do_delete_children (bool clear);
-
   void do_delete_children (bool clear, bool from_root);
 };
 
@@ -2241,16 +2234,7 @@
 
   bool is_modified (void) const { return is___modified__ (); }
 
-  virtual void remove_child (const graphics_handle& h)
-  {
-    if (children.remove_child (h.value ()))
-      {
-        children.run_listeners ();
-        mark_modified ();
-      }
-  }
-
-  virtual void remove_child (const graphics_handle& h, bool)
+  virtual void remove_child (const graphics_handle& h, bool = false)
   {
     if (children.remove_child (h.value ()))
       {
@@ -2322,12 +2306,7 @@
 
   virtual void update_uicontextmenu (void) const;
 
-  virtual void delete_children (bool clear = false)
-  {
-    children.delete_children (clear);
-  }
-
-  virtual void delete_children (bool clear, bool from_root)
+  virtual void delete_children (bool clear = false, bool from_root = false)
   {
     children.delete_children (clear, from_root);
   }
@@ -2489,7 +2468,10 @@
     error ("base_graphics_object::set_defaults: invalid graphics object");
   }
 
-  virtual octave_value get (bool all = false) const
+  // The following version of the get method is not declared virtual
+  // because no derived class overrides it.
+
+  octave_value get (bool all = false) const
   {
     if (! valid_object ())
       error ("base_graphics_object::get: invalid graphics object");
@@ -2559,15 +2541,7 @@
     return get_properties ().get___myhandle__ ();
   }
 
-  virtual void remove_child (const graphics_handle& h)
-  {
-    if (! valid_object ())
-      error ("base_graphics_object::remove_child: invalid graphics object");
-
-    get_properties ().remove_child (h);
-  }
-
-  virtual void remove_child (const graphics_handle& h, bool from_root)
+  virtual void remove_child (const graphics_handle& h, bool from_root = false)
   {
     if (! valid_object ())
       error ("base_graphics_object::remove_child: invalid graphics object");
@@ -2921,9 +2895,7 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
-    void remove_child (const graphics_handle& h);
-
-    void remove_child (const graphics_handle& h, bool from_root);
+    void remove_child (const graphics_handle& h, bool from_root = false);
 
     Matrix get_boundingbox (bool internal = false,
                             const Matrix& parent_pix_size = Matrix ()) const;
@@ -2958,12 +2930,6 @@
       // Hide base properties which don't make sense for root object
       //radio_property beingdeleted h , "{off}|on"
     END_PROPERTIES
-
-  private:
-
-    // Even though this data member is now unused, keep it for now to
-    // ensure backward compatibility.  It will be removed in version 6.
-    std::list<graphics_handle> cbo_stack;
   };
 
 private:
@@ -3106,9 +3072,7 @@
       integerhandle = val;
     }
 
-    void remove_child (const graphics_handle& h);
-
-    void remove_child (const graphics_handle& h, bool from_root);
+    void remove_child (const graphics_handle& h, bool from_root = false);
 
     void set_visible (const octave_value& val);
 
@@ -3178,9 +3142,9 @@
       array_property papersize U , default_figure_papersize ()
       radio_property papertype SU , "{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|<custom>"
       radio_property paperunits Su , "{inches}|centimeters|normalized|points"
-      radio_property pointer , "crosshair|fullcrosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
-      array_property pointershapecdata , Matrix (16, 16, 0)
-      array_property pointershapehotspot , Matrix (1, 2, 0)
+      radio_property pointer , "crosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
+      array_property pointershapecdata , Matrix (16, 16, 1)
+      array_property pointershapehotspot , Matrix (1, 2, 1)
       array_property position s , default_figure_position ()
       radio_property renderer m , "{opengl}|painters"
       radio_property renderermode , "{auto}|manual"
@@ -3222,16 +3186,6 @@
       any_property __zoom_mode__ h , Matrix ()
       double_property __device_pixel_ratio__ hU , 1.0
 
-      // Obsolete properties: doublebuffer, mincolormap, wvisual, wvisualmode,
-      //                      xdisplay, xvisual, xvisualmode
-      // FIXME: DEPRECATED: Remove in version 6.
-      bool_property doublebuffer hd , "on"
-      double_property mincolormap hd , 64
-      string_property wvisual hmd , ""
-      radio_property wvisualmode hd , "{auto}|manual"
-      string_property xdisplay hd , ""
-      string_property xvisual hmd , ""
-      radio_property xvisualmode hd , "{auto}|manual"
     END_PROPERTIES
 
   protected:
@@ -3247,6 +3201,7 @@
       papersize.add_constraint (dim_vector (1, 2));
       papersize.add_constraint (FINITE);
       pointershapecdata.add_constraint (dim_vector (16, 16));
+      pointershapecdata.add_constraint (dim_vector (32, 32));
       pointershapehotspot.add_constraint (dim_vector (1, 2));
       position.add_constraint (dim_vector (1, 4));
       position.add_constraint (FINITE);
@@ -3443,9 +3398,7 @@
   public:
     void set_defaults (base_graphics_object& obj, const std::string& mode);
 
-    void remove_child (const graphics_handle& h);
-
-    void remove_child (const graphics_handle& h, bool from_root);
+    void remove_child (const graphics_handle& h, bool from_root = false);
 
     void adopt (const graphics_handle& h);
 
@@ -3643,9 +3596,7 @@
     void set_text_child (handle_property& h, const std::string& who,
                          const octave_value& v);
 
-    void delete_text_child (handle_property& h);
-
-    void delete_text_child (handle_property& h, bool from_root);
+    void delete_text_child (handle_property& h, bool from_root = false);
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -3676,16 +3627,15 @@
       array_property currentpoint , Matrix (2, 3, 0.0)
       row_vector_property dataaspectratio mu , Matrix (1, 3, 1.0)
       radio_property dataaspectratiomode u , "{auto}|manual"
-      radio_property drawmode hd , "{normal}|fast"
       radio_property fontangle u , "{normal}|italic"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
+      bool_property fontsmoothing u , "on"
       radio_property fontunits SU , "{points}|inches|centimeters|normalized|pixels"
-      bool_property fontsmoothing , "on"
       radio_property fontweight u , "{normal}|bold"
       double_property gridalpha m , 0.15
       radio_property gridalphamode , "{auto}|manual"
-      color_property gridcolor , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
+      color_property gridcolor m , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property gridcolormode , "{auto}|manual"
       radio_property gridlinestyle , "{-}|--|:|-.|none"
       double_property labelfontsizemultiplier u , 1.1
@@ -3719,7 +3669,7 @@
       radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
       array_property view u , default_axes_view ()
       radio_property xaxislocation u , "{bottom}|top|origin"
-      color_property xcolor mu , color_values (0.15, 0.15, 0.15)
+      color_property xcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property xcolormode , "{auto}|manual"
       radio_property xdir u , "{normal}|reverse"
       bool_property xgrid , "off"
@@ -3736,7 +3686,7 @@
       double_property xticklabelrotation , 0.0
       radio_property xtickmode u , "{auto}|manual"
       radio_property yaxislocation u , "{left}|right|origin"
-      color_property ycolor mu , color_values (0.15, 0.15, 0.15)
+      color_property ycolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property ycolormode , "{auto}|manual"
       radio_property ydir u , "{normal}|reverse"
       bool_property ygrid , "off"
@@ -3751,7 +3701,7 @@
       radio_property yticklabelmode u , "{auto}|manual"
       double_property yticklabelrotation , 0.0
       radio_property ytickmode u , "{auto}|manual"
-      color_property zcolor mu , color_values (0.15, 0.15, 0.15)
+      color_property zcolor mu , color_property (color_values (0.15, 0.15, 0.15), radio_values ("none"))
       radio_property zcolormode , "{auto}|manual"
       radio_property zdir u , "{normal}|reverse"
       bool_property zgrid , "off"
@@ -4018,6 +3968,10 @@
       update_font ("fontsize");
       sync_positions ();
     }
+    void update_fontsmoothing (void)
+    {
+      update_font ("fontsmoothing");
+    }
     void update_fontangle (void)
     {
       update_font ("fontangle");
@@ -4296,12 +4250,12 @@
       string_property zdatasource , ""
 
       // hidden properties for limit computation
-      row_vector_property xlim hlr , Matrix ()
-      row_vector_property ylim hlr , Matrix ()
+      row_vector_property xlim hlr , default_data_lim ()
+      row_vector_property ylim hlr , default_data_lim ()
       row_vector_property zlim hlr , Matrix ()
       bool_property xliminclude hl , "on"
       bool_property yliminclude hl , "on"
-      bool_property zliminclude hl , "off"
+      bool_property zliminclude hl , "on"
     END_PROPERTIES
 
   protected:
@@ -4319,11 +4273,7 @@
 
     void update_ydata (void) { set_ylim (compute_ylim ()); }
 
-    void update_zdata (void)
-    {
-      set_zlim (zdata.get_limits ());
-      set_zliminclude (get_zdata ().numel () > 0);
-    }
+    void update_zdata (void) { set_zlim (zdata.get_limits ()); }
   };
 
 private:
@@ -4393,7 +4343,7 @@
 
     BEGIN_PROPERTIES (text)
       color_property backgroundcolor , color_property (radio_values ("{none}"), color_values (1, 1, 1))
-      color_property color u , color_values (0, 0, 0)
+      color_property color u , color_property (color_values (0, 0, 0), radio_values ("none"))
       color_property edgecolor , color_property (radio_values ("{none}"), color_values (0, 0, 0))
       bool_property editing , "off"
       array_property extent rG , Matrix (1, 4, 0.0)
@@ -4401,8 +4351,9 @@
       radio_property fontangle u , "{normal}|italic|oblique"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
+      bool_property fontsmoothing u , "on"
       radio_property fontunits SU , "inches|centimeters|normalized|{points}|pixels"
-      radio_property fontweight u , "light|{normal}|demi|bold"
+      radio_property fontweight u , "{normal}|bold"
       radio_property horizontalalignment mu , "{left}|center|right"
       radio_property interpreter u , "{tex}|none|latex"
       radio_property linestyle , "{-}|--|:|-.|none"
@@ -4455,19 +4406,23 @@
       Matrix pos = get_data_position ();
       Matrix lim;
 
-      lim = Matrix (1, 3, pos(0));
+      lim = Matrix (1, 4, pos(0));
       lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf () : lim(2));
+      lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf () : lim(3));
       set_xlim (lim);
 
-      lim = Matrix (1, 3, pos(1));
+      lim = Matrix (1, 4, pos(1));
       lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf () : lim(2));
+      lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf () : lim(3));
       set_ylim (lim);
 
       if (pos.numel () == 3)
         {
-          lim = Matrix (1, 3, pos(2));
+          lim = Matrix (1, 4, pos(2));
           lim(2) = (lim(2) <= 0 ? octave::numeric_limits<double>::Inf ()
                                 : lim(2));
+          lim(3) = (lim(3) >= 0 ? -octave::numeric_limits<double>::Inf ()
+                                : lim(3));
           set_zliminclude ("on");
           set_zlim (lim);
         }
@@ -4483,21 +4438,30 @@
 
     void update_string (void) { request_autopos (); update_text_extent (); }
     void update_rotation (void) { update_text_extent (); }
-    void update_color (void) { update_font (); update_text_extent (); }
     void update_fontname (void) { update_font (); update_text_extent (); }
     void update_fontsize (void) { update_font (); update_text_extent (); }
-    void update_fontangle (void) { update_font (); update_text_extent (); }
-
-    void update_fontweight (void)
+    void update_fontsmoothing (void) { update_font (); update_text_extent (); }
+
+    void update_color (void)
+    {
+      if (! color.is ("none"))
+        {
+          update_font ();
+          update_text_extent ();
+        }
+    }
+
+    void update_fontangle (void)
     {
       update_font ();
       update_text_extent ();
-      // FIXME: DEPRECATED: Remove warning with demi and light in version 6.
-      if (fontweight.is ("demi") || fontweight.is ("light"))
+      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
+      if (fontangle.is ("oblique"))
         warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontweight' to '%s' is deprecated, \
-use 'normal' or 'bold'.", fontweight.current_value ().c_str ());
+                         "Setting 'fontangle' to '%s' is deprecated, \
+use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
+    void update_fontweight (void) { update_font (); update_text_extent (); }
 
     void update_interpreter (void) { update_text_extent (); }
     void update_horizontalalignment (void) { update_text_extent (); }
@@ -4594,9 +4558,14 @@
       cdata.add_constraint ("double");
       cdata.add_constraint ("single");
       cdata.add_constraint ("logical");
+      cdata.add_constraint ("int8");
+      cdata.add_constraint ("int16");
+      cdata.add_constraint ("int32");
+      cdata.add_constraint ("int64");
       cdata.add_constraint ("uint8");
       cdata.add_constraint ("uint16");
-      cdata.add_constraint ("int16");
+      cdata.add_constraint ("uint32");
+      cdata.add_constraint ("uint64");
       cdata.add_constraint ("real");
       cdata.add_constraint (dim_vector (-1, -1));
       cdata.add_constraint (dim_vector (-1, -1, 3));
@@ -4896,6 +4865,18 @@
       faces.add_constraint (dim_vector (-1, -1));
       vertices.add_constraint (dim_vector (-1, 2));
       vertices.add_constraint (dim_vector (-1, 3));
+      cdata.add_constraint ("double");
+      cdata.add_constraint ("single");
+      cdata.add_constraint ("logical");
+      cdata.add_constraint ("int8");
+      cdata.add_constraint ("int16");
+      cdata.add_constraint ("int32");
+      cdata.add_constraint ("int64");
+      cdata.add_constraint ("uint8");
+      cdata.add_constraint ("uint16");
+      cdata.add_constraint ("uint32");
+      cdata.add_constraint ("uint64");
+      cdata.add_constraint ("real");
       cdata.add_constraint (dim_vector (-1, -1));
       cdata.add_constraint (dim_vector (-1, -1, 3));
       facevertexcdata.add_constraint (dim_vector (-1, 1));
@@ -5148,6 +5129,16 @@
       zdata.add_constraint (dim_vector (-1, -1));
       cdata.add_constraint ("double");
       cdata.add_constraint ("single");
+      cdata.add_constraint ("logical");
+      cdata.add_constraint ("int8");
+      cdata.add_constraint ("int16");
+      cdata.add_constraint ("int32");
+      cdata.add_constraint ("int64");
+      cdata.add_constraint ("uint8");
+      cdata.add_constraint ("uint16");
+      cdata.add_constraint ("uint32");
+      cdata.add_constraint ("uint64");
+      cdata.add_constraint ("real");
       cdata.add_constraint (dim_vector (-1, -1));
       cdata.add_constraint (dim_vector (-1, -1, 3));
       alphadata.add_constraint ("double");
@@ -5270,9 +5261,7 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
-    void remove_child (const graphics_handle& h);
-
-    void remove_child (const graphics_handle& h, bool from_root);
+    void remove_child (const graphics_handle& h, bool from_root = false);
 
     void adopt (const graphics_handle& h);
 
@@ -5346,12 +5335,7 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
-    void remove_child (const graphics_handle& h)
-    {
-      base_properties::remove_child (h);
-    }
-
-    void remove_child (const graphics_handle& h, bool from_root)
+    void remove_child (const graphics_handle& h, bool from_root = false)
     {
       base_properties::remove_child (h, from_root);
     }
@@ -5510,7 +5494,7 @@
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
-      radio_property fontweight u , "light|{normal}|demi|bold"
+      radio_property fontweight u , "{normal}|bold"
       color_property foregroundcolor , color_values (0, 0, 0)
       radio_property horizontalalignment , "left|{center}|right"
       callback_property keypressfcn , Matrix ()
@@ -5553,17 +5537,16 @@
     void update_string (void) { update_text_extent (); }
     void update_fontname (void) { update_text_extent (); }
     void update_fontsize (void) { update_text_extent (); }
-    void update_fontangle (void) { update_text_extent (); }
-
-    void update_fontweight (void)
+    void update_fontangle (void)
     {
       update_text_extent ();
-      // FIXME: DEPRECATED: Remove warning with demi and light in version 6.
-      if (fontweight.is ("demi") || fontweight.is ("light"))
+      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
+      if (fontangle.is ("oblique"))
         warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontweight' to '%s' is deprecated, \
-use 'normal' or 'bold'.", fontweight.current_value ().c_str ());
+                         "Setting 'fontangle' to '%s' is deprecated, \
+use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
+    void update_fontweight (void) { update_text_extent (); }
 
     void update_fontunits (const caseless_str& old_units);
 
@@ -5623,7 +5606,7 @@
       string_property fontname , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
-      radio_property fontweight u , "light|{normal}|demi|bold"
+      radio_property fontweight , "{normal}|bold"
       color_property foregroundcolor , color_values (0, 0, 0)
       color_property highlightcolor , color_values (1, 1, 1)
       array_property position S , default_panel_position ()
@@ -5656,15 +5639,7 @@
     // void update_fontname (void) { update_text_extent (); }
     // void update_fontsize (void) { update_text_extent (); }
     // void update_fontangle (void) { update_text_extent (); }
-
-    void update_fontweight (void)
-    {
-      // FIXME: DEPRECATED: Remove warning with demi and light in version 6.
-      if (fontweight.is ("demi") || fontweight.is ("light"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontweight' to '%s' is deprecated, \
-use 'normal' or 'bold'.", fontweight.current_value ().c_str ());
-    }
+    // void update_fontweight (void) { update_fontweight (); }
 
     void update_units (const caseless_str& old_units);
     void update_fontunits (const caseless_str& old_units);
@@ -5723,7 +5698,7 @@
       string_property fontname , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
-      radio_property fontweight u , "light|{normal}|demi|bold"
+      radio_property fontweight , "{normal}|bold"
       color_property foregroundcolor , color_values (0, 0, 0)
       color_property highlightcolor , color_values (1, 1, 1)
       array_property position S , default_panel_position ()
@@ -5751,14 +5726,6 @@
     void update_units (const caseless_str& old_units);
     void update_fontunits (const caseless_str& old_units);
 
-    void update_fontweight (void)
-    {
-      // FIXME: DEPRECATED: Remove warning with demi and light in version 6.
-      if (fontweight.is ("demi") || fontweight.is ("light"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontweight' to '%s' is deprecated, \
-use 'normal' or 'bold'.", fontweight.current_value ().c_str ());
-    }
   };
 
 private:
@@ -5825,7 +5792,7 @@
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
       radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
-      radio_property fontweight u , "light|{normal}|demi|bold"
+      radio_property fontweight u , "{normal}|bold"
       color_property foregroundcolor , color_values (0, 0, 0)
       callback_property keypressfcn , Matrix ()
       callback_property keyreleasefcn , Matrix ()
@@ -5859,18 +5826,16 @@
     void update_data (void) { update_table_extent (); }
     void update_fontname (void) { update_table_extent (); }
     void update_fontsize (void) { update_table_extent (); }
-    void update_fontangle (void) { update_table_extent (); }
-
-    void update_fontweight (void)
+    void update_fontangle (void)
     {
-      // FIXME: DEPRECATED: Remove warning with demi and light in version 6.
-      if (fontweight.is ("demi") || fontweight.is ("light"))
+      update_table_extent ();
+      // FIXME: DEPRECATED: Remove warning for "oblique" in version 7.
+      if (fontangle.is ("oblique"))
         warning_with_id ("Octave:deprecated-property",
-                         "Setting 'fontweight' to '%s' is deprecated, \
-use 'normal' or 'bold'.", fontweight.current_value ().c_str ());
-
-      update_table_extent ();
+                         "Setting 'fontangle' to '%s' is deprecated, \
+use 'italic' or 'normal'.", fontangle.current_value ().c_str ());
     }
+    void update_fontweight (void) { update_table_extent (); }
   };
 
 private:
@@ -6019,6 +5984,7 @@
       string_property tooltipstring , ""
 
       // Octave-specific properties
+      string_property __named_icon__ , ""
       any_property __object__ h , Matrix ()
     END_PROPERTIES
 
@@ -6082,6 +6048,7 @@
       string_property tooltipstring , ""
 
       // Octave-specific properties
+      string_property __named_icon__ , ""
       any_property __object__ h , Matrix ()
     END_PROPERTIES
 
@@ -6254,13 +6221,7 @@
            : graphics_handle ();
   }
 
-  static void free (const graphics_handle& h)
-  {
-    if (instance_ok ())
-      instance->do_free (h);
-  }
-
-  static void free (const graphics_handle& h, bool from_root)
+  static void free (const graphics_handle& h, bool from_root = false)
   {
     if (instance_ok ())
       instance->do_free (h, from_root);
@@ -6515,8 +6476,6 @@
 
   graphics_handle do_get_handle (bool integer_figure_handle);
 
-  void do_free (const graphics_handle& h);
-
   void do_free (const graphics_handle& h, bool from_root);
 
   void do_renumber_figure (const graphics_handle& old_gh,
--- a/libinterp/corefcn/help.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/help.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -44,7 +44,6 @@
 
 #include "Cell.h"
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defaults.h"
 #include "defun.h"
 #include "dirfns.h"
@@ -72,86 +71,86 @@
 
 #include "default-defs.h"
 
-const static char * const operators[] =
-{
-  "!",
-  "~",
-  "!=",
-  "~=",
-  R"(")",
-  "#",
-  "%",
-  "#{",
-  "%{",
-  "#}",
-  "%}",
-  "...",
-  "&",
-  "&&",
-  "'",
-  "(",
-  ")",
-  "*",
-  "**",
-  "^",
-  "+",
-  "++",
-  ",",
-  "-",
-  "--",
-  ".'",
-  ".*",
-  ".**",
-  ".^",
-  "./",
-  "/",
-  R"(.\)",
-  R"(\)",
-  ":",
-  ";",
-  "<",
-  "<=",
-  "=",
-  "==",
-  ">",
-  ">=",
-  "[",
-  "]",
-  "|",
-  "||",
-  nullptr
-};
-
-const static string_vector operator_names (operators);
-
-static bool
-looks_like_html (const std::string& msg)
-{
-  const size_t p1 = msg.find ('\n');
-  std::string t = msg.substr (0, p1);
-  // FIXME: this comparison should be case-insensitive
-  const size_t p2 = t.find ("<html");
-
-  return (p2 != std::string::npos);
-}
-
-static bool
-looks_like_texinfo (const std::string& msg, size_t& p1)
-{
-  p1 = msg.find ('\n');
-
-  std::string t = msg.substr (0, p1);
-
-  if (p1 == std::string::npos)
-    p1 = 0;
-
-  size_t p2 = t.find ("-*- texinfo -*-");
-
-  return (p2 != std::string::npos);
-}
-
 namespace octave
 {
+  const static char * const operators[] =
+    {
+     "!",
+     "~",
+     "!=",
+     "~=",
+     R"(")",
+     "#",
+     "%",
+     "#{",
+     "%{",
+     "#}",
+     "%}",
+     "...",
+     "&",
+     "&&",
+     "'",
+     "(",
+     ")",
+     "*",
+     "**",
+     "^",
+     "+",
+     "++",
+     ",",
+     "-",
+     "--",
+     ".'",
+     ".*",
+     ".**",
+     ".^",
+     "./",
+     "/",
+     R"(.\)",
+     R"(\)",
+     ":",
+     ";",
+     "<",
+     "<=",
+     "=",
+     "==",
+     ">",
+     ">=",
+     "[",
+     "]",
+     "|",
+     "||",
+     nullptr
+    };
+
+  const static string_vector operator_names (operators);
+
+  static bool
+  looks_like_html (const std::string& msg)
+  {
+    const size_t p1 = msg.find ('\n');
+    std::string t = msg.substr (0, p1);
+    // FIXME: this comparison should be case-insensitive
+    const size_t p2 = t.find ("<html");
+
+    return (p2 != std::string::npos);
+  }
+
+  static bool
+  looks_like_texinfo (const std::string& msg, size_t& p1)
+  {
+    p1 = msg.find ('\n');
+
+    std::string t = msg.substr (0, p1);
+
+    if (p1 == std::string::npos)
+      p1 = 0;
+
+    size_t p2 = t.find ("-*- texinfo -*-");
+
+    return (p2 != std::string::npos);
+  }
+
   octave_value
   help_system::built_in_docstrings_file (const octave_value_list& args,
                                          int nargout)
@@ -319,7 +318,7 @@
     const string_vector cfl = symtab.cmdline_function_names ();
     const int cfl_len = cfl.numel ();
 
-    const string_vector lcl = symtab.variable_names ();
+    const string_vector lcl = m_interpreter.variable_names ();
     const int lcl_len = lcl.numel ();
 
     load_path& lp = m_interpreter.get_load_path ();
@@ -327,7 +326,7 @@
     const string_vector ffl = lp.fcn_names ();
     const int ffl_len = ffl.numel ();
 
-    const string_vector afl = autoloaded_functions ();
+    const string_vector afl = m_interpreter.autoloaded_functions ();
     const int afl_len = afl.numel ();
 
     const string_vector lfl = local_functions ();
@@ -487,9 +486,9 @@
   {
     string_vector retval;
 
-    call_stack& cs = m_interpreter.get_call_stack ();
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
 
-    octave_user_code *curr_fcn = cs.caller_user_code ();
+    octave_user_code *curr_fcn = tw.current_user_code ();
 
     if (! curr_fcn)
       return retval;
@@ -586,7 +585,7 @@
     if (! initialized)
       {
         std::string ascii_fname
-          = octave::sys::get_ASCII_filename (m_built_in_docstrings_file);
+          = sys::get_ASCII_filename (m_built_in_docstrings_file);
 
         std::ifstream file (ascii_fname.c_str (),
                             std::ios::in | std::ios::binary);
@@ -672,7 +671,7 @@
         std::streamoff len = txt_limits.second;
 
         std::string ascii_fname
-          = octave::sys::get_ASCII_filename (m_built_in_docstrings_file);
+          = sys::get_ASCII_filename (m_built_in_docstrings_file);
 
         std::ifstream file (ascii_fname.c_str (),
                             std::ios::in | std::ios::binary);
@@ -766,7 +765,7 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  return ovl (Cell (operator_names));
+  return ovl (Cell (octave::operator_names));
 }
 
 // Return a cell array of strings containing the names of all keywords.
@@ -812,8 +811,8 @@
   Cell retval;
 
   // Find the main function we are in.
-  octave::call_stack& cs = interp.get_call_stack ();
-  octave_user_code *parent_fcn = cs.debug_user_code ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+  octave_user_code *parent_fcn = tw.debug_user_code ();
 
   if (! parent_fcn)
     return ovl (retval);
@@ -841,10 +840,12 @@
 
 /*
 %!test
-%! f = tempname (".", "oct_");
-%! fcn_name = f(3:end);
+%! f = tempname (tempdir (), "oct_");
+%! [~, fcn_name] = fileparts (f);
 %! f = [f ".m"];
+%! save_path = path ();
 %! unwind_protect
+%!   addpath (tempdir ());
 %!   fid = fopen (f, "w+");
 %!   fprintf (fid, "function z = %s\n z = localfunctions; end\n", fcn_name);
 %!   fprintf (fid, "function z = b(x)\n z = x+1; end\n");
@@ -856,6 +857,7 @@
 %!   assert (d{2} (3), 6);
 %! unwind_protect_cleanup
 %!   unlink (f);
+%!   path (save_path);
 %! end_unwind_protect
 */
 
@@ -920,7 +922,7 @@
     {
       // Get list of all functions
       string_vector ffl = lp.fcn_names ();
-      string_vector afl = octave::autoloaded_functions ();
+      string_vector afl = interp.autoloaded_functions ();
 
       retval = Cell (ffl.append (afl));
     }
--- a/libinterp/corefcn/input.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/input.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -44,7 +44,6 @@
 #include "uniconv-wrappers.h"
 
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "dirfns.h"
 #include "error.h"
@@ -86,329 +85,311 @@
 // the next user prompt.
 bool Vdrawnow_requested = false;
 
-// TRUE if we are in debugging mode.
-bool Vdebugging = false;
-
 // TRUE if we are recording line numbers in a source file.
 // Always true except when debugging and taking input directly from
 // the terminal.
 bool Vtrack_line_num = true;
 
-static std::string
-quoting_filename (const std::string& text, int, char quote)
-{
-  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.
-static std::string
-find_indexed_expression (const std::string& text)
-{
-  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
-        curly_count++;
-
-      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--;
-        }
-
-      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 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;
-}
-
-static 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::interpreter& interp
-        = octave::__get_interpreter__ ("generate_struct_completions");
-
-      octave::symbol_table& symtab = interp.get_symbol_table ();
-
-      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
-                = interp.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".
-static 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);
-
-  return retval;
-}
-
-// FIXME: make this generate filenames when appropriate.
-
-static string_vector
-generate_possible_completions (const std::string& text, std::string& prefix,
-                               std::string& hint, bool& deemed_struct)
-{
-  string_vector names;
-
-  prefix = "";
-
-  char prev_char = octave::command_editor::get_prev_char (text.length ());
-  deemed_struct = looks_like_struct (text, prev_char);
-
-  if (deemed_struct)
-    names = generate_struct_completions (text, prefix, hint);
-  else
-    names = octave::make_name_list ();
-
-  // Sort and remove duplicates.
-
-  names.sort (true);
-
-  return names;
-}
-
-static bool
-is_completing_dirfns (void)
-{
-  static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"};
-  static const size_t dirfns_commands_length = 4;
-
-  bool retval = false;
-
-  std::string line = octave::command_editor::get_line_buffer ();
-
-  for (size_t i = 0; i < dirfns_commands_length; i++)
-    {
-      int index = line.find (dirfns_commands[i] + ' ');
-
-      if (index == 0)
-        {
-          retval = true;
-          break;
-        }
-    }
-
-  return retval;
-}
-
-static std::string
-generate_completion (const std::string& text, int state)
-{
-  std::string retval;
-
-  static std::string prefix;
-  static std::string hint;
-
-  static size_t hint_len = 0;
-
-  static int list_index = 0;
-  static int name_list_len = 0;
-  static int name_list_total_len = 0;
-  static string_vector name_list;
-  static string_vector file_name_list;
-
-  static int matches = 0;
-
-  if (state == 0)
-    {
-      list_index = 0;
-
-      prefix = "";
-
-      hint = text;
-
-      // No reason to display symbols while completing a
-      // file/directory operation.
-
-      bool deemed_struct = false;
-
-      if (is_completing_dirfns ())
-        name_list = string_vector ();
-      else
-        name_list = generate_possible_completions (text, prefix, hint,
-                                                   deemed_struct);
-
-      name_list_len = name_list.numel ();
-
-      // If the line was something like "a{1}." then text = "." but
-      // we don't want to expand all the . files.
-      if (! deemed_struct)
-        {
-
-          file_name_list = octave::command_editor::generate_filename_completions (text);
-
-          name_list.append (file_name_list);
-
-        }
-
-      name_list_total_len = name_list.numel ();
-
-      hint_len = hint.length ();
-
-      matches = 0;
-
-      for (int i = 0; i < name_list_len; i++)
-        if (hint == name_list[i].substr (0, hint_len))
-          matches++;
-    }
-
-  if (name_list_total_len > 0 && matches > 0)
-    {
-      while (list_index < name_list_total_len)
-        {
-          std::string name = name_list[list_index];
-
-          list_index++;
-
-          if (hint == name.substr (0, hint_len))
-            {
-              // Special case: array reference forces prefix="."
-              //               in generate_struct_completions ()
-              if (list_index <= name_list_len && ! prefix.empty ())
-                retval = (prefix == "." ? "" : prefix) + '.' + name;
-              else
-                retval = name;
-
-              char prev_char = octave::command_editor::get_prev_char
-                                                       (text.length ());
-              if (matches == 1 && looks_like_struct (retval, prev_char))
-                {
-                  // Don't append anything, since we don't know
-                  // whether it should be '(' or '.'.
-
-                  octave::command_editor::set_completion_append_character ('\0');
-                }
-              else
-                {
-                  octave::input_system& input_sys
-                    = octave::__get_input_system__ ("generate_completion");
-
-                  octave::command_editor::set_completion_append_character
-                    (input_sys.completion_append_char ());
-                }
-
-              break;
-            }
-        }
-    }
-
-  return retval;
-}
-
 namespace octave
 {
+  static std::string
+  quoting_filename (const std::string& text, int, char quote)
+  {
+    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.
+  static std::string
+  find_indexed_expression (const std::string& text)
+  {
+    std::string line = 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
+          curly_count++;
+
+        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--;
+          }
+
+        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 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);
+
+        interpreter& interp
+          = __get_interpreter__ ("generate_struct_completions");
+
+        if (interp.is_variable (base_name))
+          {
+            int parse_status;
+
+            error_system& es = interp.get_error_system ();
+
+            unwind_protect frame;
+
+            frame.add_method (es, &error_system::set_discard_error_messages,
+                              es.discard_error_messages ());
+            frame.add_method (es, &error_system::set_discard_warning_messages,
+                              es.discard_warning_messages ());
+
+            es.discard_error_messages (true);
+            es.discard_warning_messages (true);
+
+            try
+              {
+                octave_value tmp
+                  = interp.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 execution_exception&)
+              {
+                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".
+  static bool
+  looks_like_struct (const std::string& text, char prev_char)
+  {
+    bool retval = (! text.empty ()
+                   && (text != "." || prev_char == ')' || prev_char == '}')
+                   && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos
+                   && text.find ("..") == std::string::npos
+                   && text.rfind ('.') != std::string::npos);
+
+    return retval;
+  }
+
+  // FIXME: make this generate filenames when appropriate.
+
+  static string_vector
+  generate_possible_completions (const std::string& text, std::string& prefix,
+                                 std::string& hint, bool& deemed_struct)
+  {
+    string_vector names;
+
+    prefix = "";
+
+    char prev_char = command_editor::get_prev_char (text.length ());
+    deemed_struct = looks_like_struct (text, prev_char);
+
+    if (deemed_struct)
+      names = generate_struct_completions (text, prefix, hint);
+    else
+      names = make_name_list ();
+
+    // Sort and remove duplicates.
+
+    names.sort (true);
+
+    return names;
+  }
+
+  static bool
+  is_completing_dirfns (void)
+  {
+    static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"};
+    static const size_t dirfns_commands_length = 4;
+
+    bool retval = false;
+
+    std::string line = command_editor::get_line_buffer ();
+
+    for (size_t i = 0; i < dirfns_commands_length; i++)
+      {
+        int index = line.find (dirfns_commands[i] + ' ');
+
+        if (index == 0)
+          {
+            retval = true;
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  static std::string
+  generate_completion (const std::string& text, int state)
+  {
+    std::string retval;
+
+    static std::string prefix;
+    static std::string hint;
+
+    static size_t hint_len = 0;
+
+    static int list_index = 0;
+    static int name_list_len = 0;
+    static int name_list_total_len = 0;
+    static string_vector name_list;
+    static string_vector file_name_list;
+
+    static int matches = 0;
+
+    if (state == 0)
+      {
+        list_index = 0;
+
+        prefix = "";
+
+        hint = text;
+
+        // No reason to display symbols while completing a
+        // file/directory operation.
+
+        bool deemed_struct = false;
+
+        if (is_completing_dirfns ())
+          name_list = string_vector ();
+        else
+          name_list = generate_possible_completions (text, prefix, hint,
+                                                     deemed_struct);
+
+        name_list_len = name_list.numel ();
+
+        // If the line was something like "a{1}." then text = "." but
+        // we don't want to expand all the . files.
+        if (! deemed_struct)
+          {
+
+            file_name_list = command_editor::generate_filename_completions (text);
+
+            name_list.append (file_name_list);
+
+          }
+
+        name_list_total_len = name_list.numel ();
+
+        hint_len = hint.length ();
+
+        matches = 0;
+
+        for (int i = 0; i < name_list_len; i++)
+          if (hint == name_list[i].substr (0, hint_len))
+            matches++;
+      }
+
+    if (name_list_total_len > 0 && matches > 0)
+      {
+        while (list_index < name_list_total_len)
+          {
+            std::string name = name_list[list_index];
+
+            list_index++;
+
+            if (hint == name.substr (0, hint_len))
+              {
+                // Special case: array reference forces prefix="."
+                //               in generate_struct_completions ()
+                if (list_index <= name_list_len && ! prefix.empty ())
+                  retval = (prefix == "." ? "" : prefix) + '.' + name;
+                else
+                  retval = name;
+
+                char prev_char = command_editor::get_prev_char
+                  (text.length ());
+                if (matches == 1 && looks_like_struct (retval, prev_char))
+                  {
+                    // Don't append anything, since we don't know
+                    // whether it should be '(' or '.'.
+
+                    command_editor::set_completion_append_character ('\0');
+                  }
+                else
+                  {
+                    input_system& input_sys
+                      = __get_input_system__ ("generate_completion");
+
+                    command_editor::set_completion_append_character
+                      (input_sys.completion_append_char ());
+                  }
+
+                break;
+              }
+          }
+      }
+
+    return retval;
+  }
+
   // Use literal "octave" in default setting for PS1 instead of
   // "\\s" to avoid setting the prompt to "octave.exe" or
   // "octave-gui", etc.
@@ -426,7 +407,7 @@
 
     void input_system::initialize (bool line_editing)
     {
-// Force default line editor if we don't want readline editing.
+      // Force default line editor if we don't want readline editing.
       if (! line_editing)
         {
           command_editor::force_default_editor ();
@@ -436,26 +417,26 @@
       // If we are using readline, this allows conditional parsing of the
       // .inputrc file.
 
-      octave::command_editor::set_name ("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);
+      command_editor::set_basic_word_break_characters (s);
 
-      octave::command_editor::set_completer_word_break_characters (s);
+      command_editor::set_completer_word_break_characters (s);
 
-      octave::command_editor::set_basic_quote_characters (R"(")");
+      command_editor::set_basic_quote_characters (R"(")");
 
-      octave::command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
+      command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
 
-      octave::command_editor::set_completer_quote_characters (R"('")");
+      command_editor::set_completer_quote_characters (R"('")");
 
-      octave::command_editor::set_completion_function (generate_completion);
+      command_editor::set_completion_function (generate_completion);
 
-      octave::command_editor::set_quoting_function (quoting_filename);
+      command_editor::set_quoting_function (quoting_filename);
   }
 
   octave_value
@@ -541,8 +522,8 @@
       }
 
     // Synchronize the related gui preference for editor encoding
-    octave::feval ("__octave_link_gui_preference__",
-                   ovl ("editor/default_encoding", m_mfile_encoding));
+    feval ("__octave_link_gui_preference__",
+           ovl ("editor/default_encoding", m_mfile_encoding));
 
     return retval;
   }
@@ -570,7 +551,7 @@
   {
     Vlast_prompt_time.stamp ();
 
-    if (Vdrawnow_requested && octave::application::interactive ())
+    if (Vdrawnow_requested && application::interactive ())
       {
         bool eval_error = false;
 
@@ -578,7 +559,7 @@
           {
             Fdrawnow ();
           }
-        catch (const octave::execution_exception& e)
+        catch (const execution_exception& e)
           {
             eval_error = true;
 
@@ -587,11 +568,11 @@
             if (! stack_trace.empty ())
               std::cerr << stack_trace;
 
-            if (octave::application::interactive ())
-              octave::interpreter::recover_from_exception ();
+            if (application::interactive ())
+              interpreter::recover_from_exception ();
           }
 
-        octave::flush_stdout ();
+        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.
@@ -654,53 +635,15 @@
         retval
           = m_interpreter.eval_string (input_buf, true, parse_status, nargout);
 
-        if (! Vdebugging && retval.empty ())
+        tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+        if (! tw.in_debug_repl () && retval.empty ())
           retval(0) = Matrix ();
       }
 
     return retval;
   }
 
-  octave_value input_system::keyboard (const octave_value_list& args)
-  {
-    octave_value retval;
-
-    int nargin = args.length ();
-
-    assert (nargin == 0 || nargin == 1);
-
-    octave::unwind_protect frame;
-
-    frame.add_fcn (octave::command_history::ignore_entries,
-                   octave::command_history::ignoring_entries ());
-
-    octave::command_history::ignore_entries (false);
-
-    frame.protect_var (Vdebugging);
-
-    octave::call_stack& cs = m_interpreter.get_call_stack ();
-
-    frame.add_method (cs, &octave::call_stack::restore_frame,
-                      cs.current_frame ());
-
-    // 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 (prompt);
-
-    return retval;
-  }
-
   bool input_system::have_input_event_hooks (void) const
   {
     return ! m_input_event_hook_functions.empty ();
@@ -740,7 +683,7 @@
 
     eof = false;
 
-    std::string retval = octave::command_editor::readline (s, eof);
+    std::string retval = command_editor::readline (s, eof);
 
     if (! eof && retval.empty ())
       retval = "\n";
@@ -748,153 +691,6 @@
     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);
-  }
-
-  void input_system::get_debug_input (const std::string& prompt)
-  {
-    octave::unwind_protect frame;
-
-    octave::tree_evaluator& tw = m_interpreter.get_evaluator ();
-
-    bool silent = tw.quiet_breakpoint_flag (false);
-
-    octave::call_stack& cs = m_interpreter.get_call_stack ();
-
-    octave_user_code *caller = cs.caller_user_code ();
-    std::string nm;
-    int curr_debug_line;
-
-    if (caller)
-      {
-        nm = caller->fcn_file_name ();
-
-        if (nm.empty ())
-          nm = caller->name ();
-
-        curr_debug_line = cs.caller_user_code_line ();
-      }
-    else
-      curr_debug_line = cs.current_line ();
-
-    std::ostringstream buf;
-
-    if (! nm.empty ())
-      {
-        if (m_gud_mode)
-          {
-            static char ctrl_z = 'Z' & 0x1f;
-
-            buf << ctrl_z << ctrl_z << nm << ':' << curr_debug_line;
-          }
-        else
-          {
-            // FIXME: we should come up with a clean way to detect
-            // that we are stopped on the no-op command that marks the
-            // end of a function or script.
-
-            if (! silent)
-              {
-                buf << "stopped in " << nm;
-
-                if (curr_debug_line > 0)
-                  buf << " at line " << curr_debug_line;
-              }
-
-            octave_link::enter_debugger_event (nm, curr_debug_line);
-
-            octave_link::set_workspace ();
-
-            frame.add_fcn (execute_in_debugger_handler,
-                           std::pair<std::string, int> (nm, curr_debug_line));
-
-            if (! silent)
-              {
-                std::string line_buf;
-
-                if (caller)
-                  line_buf = caller->get_code_line (curr_debug_line);
-
-                if (! line_buf.empty ())
-                  buf << "\n" << curr_debug_line << ": " << line_buf;
-              }
-          }
-      }
-
-    if (silent)
-      octave::command_editor::erase_empty_line (true);
-
-    std::string msg = buf.str ();
-
-    if (! msg.empty ())
-      std::cerr << msg << std::endl;
-
-    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 (! app->interactive ())
-      {
-
-        frame.add_method (app, &octave::application::interactive,
-                          app->interactive ());
-
-        frame.add_method (app, &octave::application::forced_interactive,
-                          app->forced_interactive ());
-
-        app->interactive (true);
-
-        app->forced_interactive (true);
-      }
-
-    octave::parser curr_parser (m_interpreter);
-
-    while (Vdebugging)
-      {
-        try
-          {
-            Vtrack_line_num = false;
-
-            reset_error_handler ();
-
-            curr_parser.reset ();
-
-            int retval = curr_parser.run ();
-
-            if (octave::command_editor::interrupt (false))
-              break;
-            else
-              {
-                if (retval == 0 && curr_parser.m_stmt_list)
-                  {
-                    curr_parser.m_stmt_list->accept (tw);
-
-                    if (octave_completion_matches_called)
-                      octave_completion_matches_called = false;
-                  }
-
-                octave_quit ();
-              }
-          }
-        catch (const octave::execution_exception& e)
-          {
-            std::string stack_trace = e.info ();
-
-            if (! stack_trace.empty ())
-              std::cerr << stack_trace;
-
-            // Ignore errors when in debugging mode;
-            octave::interpreter::recover_from_exception ();
-          }
-      }
-  }
-
   std::string base_reader::octave_gets (bool& eof)
   {
     octave_quit ();
@@ -906,9 +702,13 @@
     // Process pre input event hook function prior to flushing output and
     // printing the prompt.
 
+    interpreter& interp = __get_interpreter__ ("base_reader::octave_gets");
+
+    tree_evaluator& tw = interp.get_evaluator ();
+
     if (application::interactive ())
       {
-        if (! Vdebugging)
+        if (! tw.in_debug_repl ())
           octave_link::exit_debugger_event ();
 
         octave_link::pre_input_event ();
@@ -918,7 +718,7 @@
 
     bool history_skip_auto_repeated_debugging_command = false;
 
-    input_system& input_sys = __get_input_system__ ("base_reader::octave_gets");
+    input_system& input_sys = interp.get_input_system ();
 
     std::string ps = (m_pflag > 0) ? input_sys.PS1 () : input_sys.PS2 ();
 
@@ -926,7 +726,7 @@
 
     pipe_handler_error_count = 0;
 
-    output_system& output_sys = __get_output_system__ ("do_sync");
+    output_system& output_sys = interp.get_output_system ();
 
     output_sys.reset ();
 
@@ -939,16 +739,16 @@
     if (retval != "\n"
         && retval.find_first_not_of (" \t\n\r") != std::string::npos)
       {
-        load_path& lp = __get_load_path__ ("base_reader::octave_gets");
+        load_path& lp = interp.get_load_path ();
 
         lp.update ();
 
-        if (Vdebugging)
+        if (tw.in_debug_repl ())
           input_sys.last_debugging_command (retval);
         else
           input_sys.last_debugging_command ("\n");
       }
-    else if (Vdebugging)
+    else if (tw.in_debug_repl ())
       {
         retval = input_sys.last_debugging_command ();
         history_skip_auto_repeated_debugging_command = true;
@@ -981,17 +781,17 @@
 
   bool base_reader::reading_fcn_file (void) const
   {
-    return m_lexer ? m_lexer->m_reading_fcn_file : false;
+    return m_lexer.m_reading_fcn_file;
   }
 
   bool base_reader::reading_classdef_file (void) const
   {
-    return m_lexer ? m_lexer->m_reading_classdef_file : false;
+    return m_lexer.m_reading_classdef_file;
   }
 
   bool base_reader::reading_script_file (void) const
   {
-    return m_lexer ? m_lexer->m_reading_script_file : false;
+    return m_lexer.m_reading_script_file;
   }
 
   class
@@ -999,7 +799,7 @@
   {
   public:
 
-    terminal_reader (base_lexer *lxr = nullptr)
+    terminal_reader (base_lexer& lxr)
       : base_reader (lxr)
     { }
 
@@ -1019,7 +819,7 @@
   {
   public:
 
-    file_reader (FILE *f_arg, base_lexer *lxr = nullptr)
+    file_reader (FILE *f_arg, base_lexer& lxr)
       : base_reader (lxr), m_file (f_arg) { }
 
     std::string get_input (bool& eof);
@@ -1040,7 +840,7 @@
   {
   public:
 
-    eval_string_reader (const std::string& str, base_lexer *lxr = nullptr)
+    eval_string_reader (const std::string& str, base_lexer& lxr)
       : base_reader (lxr), m_eval_string (str)
     { }
 
@@ -1057,15 +857,15 @@
     static const std::string s_in_src;
   };
 
-  input_reader::input_reader (base_lexer *lxr)
+  input_reader::input_reader (base_lexer& lxr)
     : m_rep (new terminal_reader (lxr))
   { }
 
-  input_reader::input_reader (FILE *file, base_lexer *lxr)
+  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)
+  input_reader::input_reader (const std::string& str, base_lexer& lxr)
     : m_rep (new eval_string_reader (str, lxr))
   { }
 
@@ -1094,8 +894,8 @@
 
     std::string src_str = octave_fgets (m_file, eof);
 
-    octave::input_system& input_sys
-      = octave::__get_input_system__ ("get_input");
+    input_system& input_sys
+      = __get_input_system__ ("get_input");
 
     std::string mfile_encoding = input_sys.mfile_encoding ();
 
@@ -1125,7 +925,7 @@
         error ("file_reader::get_input: converting from codepage '%s' to UTF-8: %s",
                encoding.c_str (), std::strerror (errno));
 
-      octave::unwind_protect frame;
+      unwind_protect frame;
       frame.add_fcn (::free, static_cast<void *> (utf8_str));
 
       src_str = std::string (reinterpret_cast<char *> (utf8_str), length);
@@ -1254,28 +1054,22 @@
 @seealso{dbstop, dbcont, dbquit}
 @end deftypefn */)
 {
-  if (args.length () > 1)
-    print_usage ();
-
-  octave::unwind_protect frame;
+  int nargin = args.length ();
 
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  frame.add_method (cs, &octave::call_stack::restore_frame,
-                    cs.current_frame ());
-
-  // Skip the frame assigned to the keyboard function.
-  cs.goto_frame_relative (0);
+  if (nargin > 1)
+    print_usage ();
 
   octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  tw.debug_mode (true);
-  tw.quiet_breakpoint_flag (false);
-  tw.current_frame (cs.current_frame ());
+  if (nargin == 1)
+    {
+      std::string prompt
+        = args(0).xstring_value ("keyboard: PROMPT must be a string");
 
-  octave::input_system& input_sys = interp.get_input_system ();
-
-  input_sys.keyboard (args);
+      tw.keyboard (prompt);
+    }
+  else
+    tw.keyboard ();
 
   return ovl ();
 }
@@ -1306,7 +1100,7 @@
 
   for (;;)
     {
-      std::string cmd = generate_completion (hint, k);
+      std::string cmd = octave::generate_completion (hint, k);
 
       if (! cmd.empty ())
         {
@@ -1412,18 +1206,20 @@
   return ovl ();
 }
 
-static int
-internal_input_event_hook_fcn (void)
+namespace octave
 {
-  octave::input_system& input_sys
-    = octave::__get_input_system__ ("internal_input_event_hook_fcn");
+  static int internal_input_event_hook_fcn (void)
+  {
+    input_system& input_sys
+      = __get_input_system__ ("internal_input_event_hook_fcn");
 
-  input_sys.run_input_event_hooks ();
+    input_sys.run_input_event_hooks ();
 
-  if (! input_sys.have_input_event_hooks ())
-    octave::command_editor::remove_event_hook (internal_input_event_hook_fcn);
+    if (! input_sys.have_input_event_hooks ())
+      command_editor::remove_event_hook (internal_input_event_hook_fcn);
 
-  return 0;
+    return 0;
+  }
 }
 
 DEFMETHOD (add_input_event_hook, interp, args, ,
@@ -1461,7 +1257,7 @@
   hook_function hook_fcn (args(0), user_data);
 
   if (! input_sys.have_input_event_hooks ())
-    octave::command_editor::add_event_hook (internal_input_event_hook_fcn);
+    octave::command_editor::add_event_hook (octave::internal_input_event_hook_fcn);
 
   input_sys.add_input_event_hook (hook_fcn);
 
@@ -1494,7 +1290,7 @@
              hook_fcn_id.c_str ());
 
   if (! input_sys.have_input_event_hooks ())
-    octave::command_editor::remove_event_hook (internal_input_event_hook_fcn);
+    octave::command_editor::remove_event_hook (octave::internal_input_event_hook_fcn);
 
   return ovl ();
 }
@@ -1644,15 +1440,6 @@
   return 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);
-}
-
 void
 remove_input_event_hook_functions (void)
 {
--- a/libinterp/corefcn/input.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/input.h	Fri Jul 12 12:14:43 2019 -0400
@@ -44,9 +44,6 @@
 // the next user prompt.
 extern OCTINTERP_API bool Vdrawnow_requested;
 
-// TRUE if we are in debugging mode.
-extern OCTINTERP_API bool Vdebugging;
-
 // TRUE if we are not executing a command direct from debug> prompt.
 extern OCTINTERP_API bool Vtrack_line_num;
 
@@ -155,9 +152,6 @@
     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);
@@ -196,8 +190,6 @@
     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
@@ -206,7 +198,7 @@
 
     friend class input_reader;
 
-    base_reader (base_lexer *lxr)
+    base_reader (base_lexer& lxr)
       : m_count (1), m_pflag (0), m_lexer (lxr)
     { }
 
@@ -255,7 +247,7 @@
 
     int m_pflag;
 
-    base_lexer *m_lexer;
+    base_lexer& m_lexer;
 
     static const std::string s_in_src;
   };
@@ -264,11 +256,11 @@
   {
   public:
 
-    input_reader (base_lexer *lxr = nullptr);
+    input_reader (base_lexer& lxr);
 
-    input_reader (FILE *file, base_lexer *lxr = nullptr);
+    input_reader (FILE *file, base_lexer& lxr);
 
-    input_reader (const std::string& str, base_lexer *lxr = nullptr);
+    input_reader (const std::string& str, base_lexer& lxr);
 
     input_reader (const input_reader& ir)
     {
@@ -339,10 +331,6 @@
 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);
 
--- a/libinterp/corefcn/interpreter-private.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/interpreter-private.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,10 +24,11 @@
 #  include "config.h"
 #endif
 
+#include <list>
 #include <string>
 
 #include "bp-table.h"
-#include "call-stack.h"
+#include "cdef-manager.h"
 #include "child-list.h"
 #include "error.h"
 #include "gtk-manager.h"
@@ -38,7 +39,8 @@
 #include "load-path.h"
 #include "load-save.h"
 #include "oct-hist.h"
-#include "ov-classdef.h"
+#include "ov.h"
+#include "ov-fcn-inline.h"
 #include "pager.h"
 #include "symtab.h"
 
@@ -64,6 +66,13 @@
     return interp.get_dynamic_loader ();
   }
 
+  error_system& __get_error_system__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_error_system ();
+  }
+
   help_system& __get_help_system__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
@@ -151,13 +160,6 @@
     return tw.get_bp_table ();
   }
 
-  call_stack& __get_call_stack__ (const std::string& who)
-  {
-    interpreter& interp = __get_interpreter__ (who);
-
-    return interp.get_call_stack ();
-  }
-
   child_list& __get_child_list__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
@@ -178,4 +180,44 @@
 
     return interp.get_gtk_manager ();
   }
+
+  octave_value
+  get_function_handle (interpreter& interp, const octave_value& arg,
+                       const std::string& parameter_name)
+  {
+    std::list<std::string> parameter_names;
+    parameter_names.push_back (parameter_name);
+    return get_function_handle (interp, arg, parameter_names);
+  }
+
+  octave_value
+  get_function_handle (interpreter& interp, const octave_value& arg,
+                       const std::list<std::string>& parameter_names)
+  {
+    if (arg.is_function_handle () || arg.is_inline_function ())
+      return arg;
+    else if (arg.is_string ())
+      {
+        std::string fstr = arg.string_value ();
+
+        if (fstr.empty ())
+          return octave_value ();
+
+        symbol_table& symtab = interp.get_symbol_table ();
+
+        octave_value fcn = symtab.find_function (fstr);
+
+        if (fcn.is_defined ())
+          return fcn;
+
+        fcn = octave_value (new octave_fcn_inline (fstr, parameter_names));
+
+        // Possibly warn here that passing the function body in a
+        // character string is discouraged.
+
+        return fcn;
+      }
+
+    return octave_value ();
+  }
 }
--- a/libinterp/corefcn/interpreter-private.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/interpreter-private.h	Fri Jul 12 12:14:43 2019 -0400
@@ -25,18 +25,18 @@
 
 #include "octave-config.h"
 
+#include <list>
 #include <string>
 
 #include "symtab.h"
 
-class cdef_manager;
-
 namespace octave
 {
   class bp_table;
-  class call_stack;
+  class cdef_manager;
   class child_list;
   class dynamic_loader;
+  class error_system;
   class gtk_manager;
   class help_system;
   class history_system;
@@ -52,6 +52,8 @@
 
   extern dynamic_loader& __get_dynamic_loader__ (const std::string& who);
 
+  extern error_system& __get_error_system__ (const std::string& who);
+
   extern help_system& __get_help_system__ (const std::string& who);
 
   extern history_system& __get_history_system__ (const std::string& who);
@@ -76,13 +78,29 @@
 
   extern bp_table& __get_bp_table__ (const std::string& who);
 
-  extern call_stack& __get_call_stack__ (const std::string& who);
-
   extern child_list& __get_child_list__ (const std::string& who);
 
   extern cdef_manager& __get_cdef_manager__ (const std::string& who);
 
   extern gtk_manager& __get_gtk_manager__ (const std::string& who);
+
+
+  // Functions that could be methods in the interpreter class but maybe
+  // shouldn't be exposed as part of the public interface.
+
+  // Convert octave_value object ARG to be a function handle object.  It
+  // may be a function handle, inline function, the name of a function,
+  // or the text of an inline function that has the given argument names
+  // PARAMETER_NAMES.  Use of the latter form is discouraged.
+
+  octave_value
+  get_function_handle (interpreter& interp, const octave_value& arg,
+                       const std::string& parameter_name);
+
+  octave_value
+  get_function_handle (interpreter& interp, const octave_value& arg,
+                       const std::list<std::string>& parameter_names
+                         = std::list<std::string> ());
 }
 
 #endif
--- a/libinterp/corefcn/interpreter.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/interpreter.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,6 +24,8 @@
 #  include "config.h"
 #endif
 
+#include <cstdio>
+
 #include <string>
 #include <iostream>
 
@@ -41,7 +43,6 @@
 #include "builtin-defun-decls.h"
 #include "defaults.h"
 #include "Cell.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "display.h"
 #include "error.h"
@@ -62,6 +63,7 @@
 #include "ov.h"
 #include "ov-classdef.h"
 #include "parse.h"
+#include "pt-classdef.h"
 #include "pt-eval.h"
 #include "pt-jump.h"
 #include "pt-stmt.h"
@@ -359,6 +361,7 @@
     : m_app_context (app_context),
       m_environment (),
       m_settings (),
+      m_error_system (*this),
       m_help_system (*this),
       m_input_system (*this),
       m_output_system (*this),
@@ -367,7 +370,7 @@
       m_load_path (),
       m_load_save_system (*this),
       m_type_info (),
-      m_symbol_table (),
+      m_symbol_table (*this),
       m_evaluator (*this),
       m_stream_list (*this),
       m_child_list (),
@@ -405,11 +408,6 @@
 
     thread::init ();
 
-    // Initialize default warning state before --traditional option
-    // that may reset them.
-
-    initialize_default_warning_state ();
-
     octave_ieee_init ();
 
     initialize_xerbla_error_handler ();
@@ -417,7 +415,10 @@
     initialize_error_handlers ();
 
     if (m_app_context)
-      install_signal_handlers ();
+      {
+        install_signal_handlers ();
+        octave_unblock_signal_by_name ("SIGTSTP");
+      }
     else
       quit_allowed = false;
 
@@ -536,14 +537,7 @@
 
   void interpreter::intern_nargin (octave_idx_type nargs)
   {
-    // FIXME: should this explicitly be top_scope?
-    symbol_scope scope = m_symbol_table.current_scope ();
-
-    if (scope)
-      {
-        scope.assign (".nargin.", nargs);
-        scope.mark_hidden (".nargin.");
-      }
+    m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs);
   }
 
   // Read the history file unless a command-line option inhibits that.
@@ -718,7 +712,7 @@
   // occurs when reading any of them, but don't exit early because of an
   // exception.
 
-  int interpreter::execute_startup_files (void) const
+  int interpreter::execute_startup_files (void)
   {
     bool read_site_files = m_read_site_files;
     bool read_init_files = m_read_init_files;
@@ -765,6 +759,37 @@
 
     if (read_init_files)
       {
+        // Try to execute commands from the Matlab compatible startup.m file
+        // if it exists anywhere in the load path when starting Octave.
+        std::string ff_startup_m = file_in_path ("startup.m", "");
+
+        if (! ff_startup_m.empty ())
+          {
+            int parse_status = 0;
+
+            try
+              {
+                eval_string (std::string ("startup"), false, parse_status, 0);
+              }
+            catch (const interrupt_exception&)
+              {
+                recover_from_exception ();
+              }
+            catch (const execution_exception& e)
+              {
+                std::string stack_trace = e.info ();
+
+                if (! stack_trace.empty ())
+                  std::cerr << stack_trace;
+
+                recover_from_exception ();
+              }
+          }
+
+        // Schedule the Matlab compatible finish.m file to run if it exists
+        // anywhere in the load path when exiting Octave.
+        add_atexit_function ("__finish__");
+
         // Try to execute commands from $HOME/$OCTAVE_INITFILE and
         // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set,
         // .octaverc is assumed.
@@ -966,19 +991,23 @@
     {                                                                   \
       try                                                               \
         {                                                               \
-          unwind_protect frame;                                 \
+          unwind_protect frame;                                         \
                                                                         \
-          frame.protect_var (Vdebug_on_error);                          \
-          frame.protect_var (Vdebug_on_warning);                        \
+          frame.add_method (m_error_system,                             \
+                            &error_system::set_debug_on_error,          \
+                            m_error_system.debug_on_error ());          \
+          frame.add_method (m_error_system,                             \
+                            &error_system::set_debug_on_warning,        \
+                            m_error_system.debug_on_warning ());        \
                                                                         \
-          Vdebug_on_error = false;                                      \
-          Vdebug_on_warning = false;                                    \
+          m_error_system.debug_on_error (false);                        \
+          m_error_system.debug_on_warning (false);                      \
                                                                         \
           F ARGS;                                                       \
         }                                                               \
-      OCTAVE_IGNORE_EXCEPTION (const exit_exception&)           \
-      OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)      \
-      OCTAVE_IGNORE_EXCEPTION (const execution_exception&)      \
+      OCTAVE_IGNORE_EXCEPTION (const exit_exception&)                   \
+      OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)              \
+      OCTAVE_IGNORE_EXCEPTION (const execution_exception&)              \
       OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&)                   \
     }                                                                   \
   while (0)
@@ -999,7 +1028,7 @@
 
         atexit_functions.pop_front ();
 
-        OCTAVE_SAFE_CALL (reset_error_handler, ());
+        OCTAVE_SAFE_CALL (m_error_system.reset, ());
 
         OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
 
@@ -1062,13 +1091,19 @@
   }
 
   symbol_scope
-  interpreter::get_current_scope (void)
+  interpreter::get_top_scope (void) const
   {
-    return m_symbol_table.current_scope ();
+    return m_evaluator.get_top_scope ();
   }
 
   symbol_scope
-  interpreter::require_current_scope (const std::string& who)
+  interpreter::get_current_scope (void) const
+  {
+    return m_evaluator.get_current_scope ();
+  }
+
+  symbol_scope
+  interpreter::require_current_scope (const std::string& who) const
   {
     symbol_scope scope = get_current_scope ();
 
@@ -1078,11 +1113,6 @@
     return scope;
   }
 
-  call_stack& interpreter::get_call_stack (void)
-  {
-    return m_evaluator.get_call_stack ();
-  }
-
   profiler& interpreter::get_profiler (void)
   {
     return m_evaluator.get_profiler ();
@@ -1090,14 +1120,7 @@
 
   void interpreter::mlock (void)
   {
-    call_stack& cs = get_call_stack ();
-
-    octave_function *fcn = cs.current ();
-
-    if (! fcn)
-      error ("mlock: invalid use outside a function");
-
-    fcn->lock ();
+    m_evaluator.mlock ();
   }
 
   void interpreter::munlock (const std::string& nm)
@@ -1130,6 +1153,11 @@
     return retval;
   }
 
+  std::string interpreter::mfilename (const std::string& opt) const
+  {
+    return m_evaluator.mfilename (opt);
+  }
+
   octave_value_list interpreter::eval_string (const std::string& eval_str,
                                               bool silent, int& parse_status,
                                               int nargout)
@@ -1150,6 +1178,449 @@
     return m_evaluator.eval_string (arg, silent, parse_status, nargout);
   }
 
+  octave_value_list interpreter::eval (const std::string& try_code,
+                                       int nargout)
+  {
+    return m_evaluator.eval (try_code, nargout);
+  }
+
+  octave_value_list interpreter::eval (const std::string& try_code,
+                                       const std::string& catch_code,
+                                       int nargout)
+  {
+    return m_evaluator.eval (try_code, catch_code, nargout);
+  }
+
+  octave_value_list interpreter::evalin (const std::string& context,
+                                         const std::string& try_code,
+                                         int nargout)
+  {
+    return m_evaluator.evalin (context, try_code, nargout);
+  }
+
+  octave_value_list interpreter::evalin (const std::string& context,
+                                         const std::string& try_code,
+                                         const std::string& catch_code,
+                                         int nargout)
+  {
+    return m_evaluator.evalin (context, try_code, catch_code, nargout);
+  }
+
+  //! Evaluate an Octave function (built-in or interpreted) and return
+  //! the list of result values.
+  //!
+  //! @param name The name of the function to call.
+  //! @param args The arguments to the function.
+  //! @param nargout The number of output arguments expected.
+  //! @return A list of output values.  The length of the list is not
+  //!         necessarily the same as @c nargout.
+
+  octave_value_list interpreter::feval (const char *name,
+                                        const octave_value_list& args,
+                                        int nargout)
+  {
+    return feval (std::string (name), args, nargout);
+  }
+
+  octave_value_list interpreter::feval (const std::string& name,
+                                        const octave_value_list& args,
+                                        int nargout)
+  {
+    octave_value fcn = m_symbol_table.find_function (name, args);
+
+    if (fcn.is_undefined ())
+      error ("feval: function '%s' not found", name.c_str ());
+
+    octave_function *of = fcn.function_value ();
+
+    return of->call (m_evaluator, nargout, args);
+  }
+
+  octave_value_list interpreter::feval (octave_function *fcn,
+                                        const octave_value_list& args,
+                                        int nargout)
+  {
+    if (fcn)
+      return fcn->call (m_evaluator, nargout, args);
+
+    return octave_value_list ();
+  }
+
+  octave_value_list interpreter::feval (const octave_value& val,
+                                        const octave_value_list& args,
+                                        int nargout)
+  {
+    // FIXME: do we really want to silently return an empty ovl if
+    // the function object is undefined?  It's essentially what the
+    // version above that accepts a pointer to an octave_function
+    // object does and some code was apparently written to rely on it
+    // (for example, __ode15__).
+
+    if (val.is_undefined ())
+      return ovl ();
+
+    if (val.is_function ())
+      {
+        return feval (val.function_value (), args, nargout);
+      }
+    else if (val.is_function_handle ())
+      {
+        // This covers function handles, inline functions, and anonymous
+        //  functions.
+
+        std::list<octave_value_list> arg_list;
+        arg_list.push_back (args);
+
+        // FIXME: could we make octave_value::subsref a const method?
+        // It would be difficult because there are instances of
+        // incrementing the reference count inside subsref methods,
+        // which means they can't be const with the current way of
+        // handling reference counting.
+
+        octave_value xval = val;
+        return xval.subsref ("(", arg_list, nargout);
+      }
+    else if (val.is_string ())
+      {
+        return feval (val.string_value (), args, nargout);
+      }
+    else
+      error ("feval: first argument must be a string, inline function, or a function handle");
+
+    return ovl ();
+  }
+
+  //! Evaluate an Octave function (built-in or interpreted) and return
+  //! the list of result values.
+  //!
+  //! @param args The first element of @c args is the function to call.
+  //!             It may be the name of the function as a string, a function
+  //!             handle, or an inline function.  The remaining arguments are
+  //!             passed to the function.
+  //! @param nargout The number of output arguments expected.
+  //! @return A list of output values.  The length of the list is not
+  //!         necessarily the same as @c nargout.
+
+  octave_value_list interpreter::feval (const octave_value_list& args,
+                                        int nargout)
+  {
+    if (args.length () == 0)
+      error ("feval: first argument must be a string, inline function, or a function handle");
+
+    octave_value f_arg = args(0);
+
+    octave_value_list tmp_args = args.slice (1, args.length () - 1, true);
+
+    return feval (f_arg, tmp_args, nargout);
+  }
+
+  void interpreter::install_variable (const std::string& name,
+                                      const octave_value& value, bool global)
+  {
+    m_evaluator.install_variable (name, value, global);
+  }
+
+  octave_value interpreter::global_varval (const std::string& name) const
+  {
+    return m_evaluator.global_varval (name);
+  }
+
+  void interpreter::global_assign (const std::string& name,
+                                   const octave_value& val)
+  {
+    m_evaluator.global_assign (name, val);
+  }
+
+  octave_value interpreter::top_level_varval (const std::string& name) const
+  {
+    return m_evaluator.top_level_varval (name);
+  }
+
+  void interpreter::top_level_assign (const std::string& name,
+                                      const octave_value& val)
+  {
+    m_evaluator.top_level_assign (name, val);
+  }
+
+  bool interpreter::is_variable (const std::string& name) const
+  {
+    return m_evaluator.is_variable (name);
+  }
+
+  bool interpreter::is_local_variable (const std::string& name) const
+  {
+    return m_evaluator.is_local_variable (name);
+  }
+
+  octave_value interpreter::varval (const std::string& name) const
+  {
+    return m_evaluator.varval (name);
+  }
+
+  void interpreter::assign (const std::string& name,
+                            const octave_value& val)
+  {
+    m_evaluator.assign (name, val);
+  }
+
+  void interpreter::assignin (const std::string& context,
+                              const std::string& name,
+                              const octave_value& val)
+  {
+    m_evaluator.assignin (context, name, val);
+  }
+
+  void interpreter::source_file (const std::string& file_name,
+                                 const std::string& context, bool verbose,
+                                 bool require_file,
+                                 const std::string& warn_for)
+  {
+    m_evaluator.source_file (file_name, context, verbose, require_file,
+                             warn_for);
+  }
+
+  static void
+  safe_fclose (FILE *f)
+  {
+    if (f)
+      fclose (static_cast<FILE *> (f));
+  }
+
+  octave_value
+  interpreter::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 = sys::fopen (full_file, "rb");
+
+    if (ffile)
+      {
+        frame.add_fcn (safe_fclose, ffile);
+
+        parser parser (ffile, *this);
+
+        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 (*this, is_at_folder);
+                  }
+                catch (const execution_exception&)
+                  {
+                    delete parser.m_classdef_object;
+                    throw;
+                  }
+
+                if (fcn_ptr)
+                  retval = octave_value (fcn_ptr);
+
+                delete parser.m_classdef_object;
+
+                parser.m_classdef_object = nullptr;
+              }
+            else if (fcn_ptr)
+              {
+                retval = octave_value (fcn_ptr);
+
+                fcn_ptr->maybe_relocate_end ();
+
+                if (parser.m_parsing_subfunctions)
+                  {
+                    if (! parser.m_endfunction_found)
+                      parser.m_subfunction_names.reverse ();
+
+                    fcn_ptr->stash_subfunction_names (parser.m_subfunction_names);
+                  }
+              }
+          }
+        else
+          error ("parse error while reading file %s", full_file.c_str ());
+      }
+    else if (require_file)
+      error ("no such file, '%s'", full_file.c_str ());
+    else if (! warn_for.empty ())
+      error ("%s: unable to open file '%s'", warn_for.c_str (),
+             full_file.c_str ());
+
+    return retval;
+  }
+
+  bool interpreter::at_top_level (void) const
+  {
+    return m_evaluator.at_top_level ();
+  }
+
+  bool interpreter::isglobal (const std::string& name) const
+  {
+    return m_evaluator.is_global (name);
+  }
+
+  octave_value interpreter::find (const std::string& name)
+  {
+    return m_evaluator.find (name);
+  }
+
+  void interpreter::clear_all (bool force)
+  {
+    m_evaluator.clear_all (force);
+  }
+
+  void interpreter::clear_objects (void)
+  {
+    m_evaluator.clear_objects ();
+  }
+
+  void interpreter::clear_variable (const std::string& name)
+  {
+    m_evaluator.clear_variable (name);
+  }
+
+  void interpreter::clear_variable_pattern (const std::string& pattern)
+  {
+    m_evaluator.clear_variable_pattern (pattern);
+  }
+
+  void interpreter::clear_variable_regexp (const std::string& pattern)
+  {
+    m_evaluator.clear_variable_regexp (pattern);
+  }
+
+  void interpreter::clear_variables (void)
+  {
+    m_evaluator.clear_variables ();
+  }
+
+  void interpreter::clear_global_variable (const std::string& name)
+  {
+    m_evaluator.clear_global_variable (name);
+  }
+
+  void interpreter::clear_global_variable_pattern (const std::string& pattern)
+  {
+    m_evaluator.clear_global_variable_pattern (pattern);
+  }
+
+  void interpreter::clear_global_variable_regexp (const std::string& pattern)
+  {
+    m_evaluator.clear_global_variable_regexp (pattern);
+  }
+
+  void interpreter::clear_global_variables (void)
+  {
+    m_evaluator.clear_global_variables ();
+  }
+
+  void interpreter::clear_functions (bool force)
+  {
+    m_symbol_table.clear_functions (force);
+  }
+
+  void interpreter::clear_function (const std::string& name)
+  {
+    m_symbol_table.clear_function (name);
+  }
+
+  void interpreter::clear_symbol (const std::string& name)
+  {
+    m_evaluator.clear_symbol (name);
+  }
+
+  void interpreter::clear_function_pattern (const std::string& pat)
+  {
+    m_symbol_table.clear_function_pattern (pat);
+  }
+
+  void interpreter::clear_function_regexp (const std::string& pat)
+  {
+    m_symbol_table.clear_function_regexp (pat);
+  }
+
+  void interpreter::clear_symbol_pattern (const std::string& pat)
+  {
+    return m_evaluator.clear_symbol_pattern (pat);
+  }
+
+  void interpreter::clear_symbol_regexp (const std::string& pat)
+  {
+    return m_evaluator.clear_symbol_regexp (pat);
+  }
+
+  std::list<std::string> interpreter::global_variable_names (void)
+  {
+    return m_evaluator.global_variable_names ();
+  }
+
+  std::list<std::string> interpreter::variable_names (void)
+  {
+    return m_evaluator.variable_names ();
+  }
+
+  std::list<std::string> interpreter::user_function_names (void)
+  {
+    return m_symbol_table.user_function_names ();
+  }
+
+  std::list<std::string> interpreter::autoloaded_functions (void) const
+  {
+    return m_evaluator.autoloaded_functions ();
+  }
+
   void interpreter::recover_from_exception (void)
   {
     can_interrupt = true;
@@ -1201,7 +1672,7 @@
 
     m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%");
 
-    Fbeep_on_error (octave_value (true));
+    m_error_system.beep_on_error (true);
     Fconfirm_recursive_rmdir (octave_value (false));
 
     Fdisable_diagonal_matrix (octave_value (true));
@@ -1223,13 +1694,13 @@
       {
         m_load_path.execute_pkg_add (dir);
       }
-    catch (const octave::interrupt_exception&)
+    catch (const interrupt_exception&)
       {
-        octave::interpreter::recover_from_exception ();
+        interpreter::recover_from_exception ();
       }
-    catch (const octave::execution_exception&)
+    catch (const execution_exception&)
       {
-        octave::interpreter::recover_from_exception ();
+        interpreter::recover_from_exception ();
       }
   }
 }
--- a/libinterp/corefcn/interpreter.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/interpreter.h	Fri Jul 12 12:14:43 2019 -0400
@@ -25,14 +25,17 @@
 
 #include "octave-config.h"
 
+#include <map>
 #include <string>
 
 #include "child-list.h"
 #include "quit.h"
 #include "str-vec.h"
 
+#include "cdef-manager.h"
 #include "dynamic-ld.h"
 #include "environment.h"
+#include "error.h"
 #include "gtk-manager.h"
 #include "help.h"
 #include "input.h"
@@ -40,7 +43,6 @@
 #include "load-save.h"
 #include "oct-hist.h"
 #include "oct-stream.h"
-#include "ov-classdef.h"
 #include "ov-typeinfo.h"
 #include "pager.h"
 #include "pt-eval.h"
@@ -60,7 +62,6 @@
 namespace octave
 {
   class profiler;
-  class call_stack;
   class child_list;
 
   // The application object contains a pointer to the current
@@ -97,7 +98,7 @@
     void initialize_history (bool read_history_file = false);
 
     // If creating an embedded interpreter, you may inhibit setting
-    // the default compiled-in path by calling intialize_load_path
+    // the default compiled-in path by calling initialize_load_path
     // with set_initial_path = false prior calling initialize.  After
     // that, you can add directories to the load path to set up a
     // custom path.
@@ -109,7 +110,7 @@
     void initialize (void);
 
     // Initialize the interpreter (if not already done by an explicit
-    // call to intialize), execute startup files, --eval option code,
+    // call to initialize), execute startup files, --eval option code,
     // script files, and/or interactive commands.
 
     int execute (void);
@@ -159,6 +160,11 @@
       return m_settings;
     }
 
+    error_system& get_error_system (void)
+    {
+      return m_error_system;
+    }
+
     help_system& get_help_system (void)
     {
       return m_help_system;
@@ -194,25 +200,24 @@
       return m_load_save_system;
     }
 
+    type_info& get_type_info (void)
+    {
+      return m_type_info;
+    }
+
     symbol_table& get_symbol_table (void)
     {
       return m_symbol_table;
     }
 
-    type_info& get_type_info (void)
-    {
-      return m_type_info;
-    }
+    tree_evaluator& get_evaluator (void);
 
-    symbol_scope get_current_scope (void);
-    symbol_scope require_current_scope (const std::string& who);
-
-    call_stack& get_call_stack (void);
+    symbol_scope get_top_scope (void) const;
+    symbol_scope get_current_scope (void) const;
+    symbol_scope require_current_scope (const std::string& who) const;
 
     profiler& get_profiler (void);
 
-    tree_evaluator& get_evaluator (void);
-
     stream_list& get_stream_list (void);
 
     child_list& get_child_list (void)
@@ -238,6 +243,8 @@
 
     bool mislocked (const std::string& nm);
 
+    std::string mfilename (const std::string& opt = "") const;
+
     octave_value_list eval_string (const std::string& eval_str, bool silent,
                                    int& parse_status, int nargout);
 
@@ -247,6 +254,129 @@
     octave_value_list eval_string (const octave_value& arg, bool silent,
                                    int& parse_status, int nargout);
 
+    octave_value_list eval (const std::string& try_code, int nargout);
+
+    octave_value_list eval (const std::string& try_code,
+                            const std::string& catch_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code,
+                              const std::string& catch_code, int nargout);
+
+    octave_value_list
+    feval (const char *name,
+           const octave_value_list& args = octave_value_list (),
+           int nargout = 0);
+
+    octave_value_list
+    feval (const std::string& name,
+           const octave_value_list& args = octave_value_list (),
+           int nargout = 0);
+
+    octave_value_list
+    feval (octave_function *fcn,
+           const octave_value_list& args = octave_value_list (),
+           int nargout = 0);
+
+    octave_value_list
+    feval (const octave_value& f_arg,
+           const octave_value_list& args = octave_value_list (),
+           int nargout = 0);
+
+    octave_value_list feval (const octave_value_list& args, int nargout = 0);
+
+    void install_variable (const std::string& name, const octave_value& value,
+                           bool global);
+
+    void set_global_value (const std::string& name, const octave_value& value);
+
+    octave_value global_varval (const std::string& name) const;
+
+    void global_assign (const std::string& name,
+                        const octave_value& val = octave_value ());
+
+    octave_value top_level_varval (const std::string& name) const;
+
+    void top_level_assign (const std::string& name,
+                           const octave_value& val = octave_value ());
+
+    bool is_variable (const std::string& name) const;
+
+    bool is_local_variable (const std::string& name) const;
+
+    octave_value varval (const std::string& name) const;
+
+    void assign (const std::string& name,
+                 const octave_value& val = octave_value ());
+
+    void assignin (const std::string& context, const std::string& varname,
+                   const octave_value& val = octave_value ());
+
+    void source_file (const std::string& file_name,
+                      const std::string& context = "",
+                      bool verbose = false, bool require_file = true,
+                      const std::string& warn_for = "");
+
+    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);
+
+    bool at_top_level (void) const;
+
+    bool isglobal (const std::string& name) const;
+
+    octave_value find (const std::string& name);
+
+    void clear_all (bool force = false);
+
+    void clear_objects (void);
+
+    void clear_variable (const std::string& name);
+
+    void clear_variable_pattern (const std::string& pattern);
+
+    void clear_variable_regexp (const std::string& pattern);
+
+    void clear_variables (void);
+
+    void clear_global_variable (const std::string& name);
+
+    void clear_global_variable_pattern (const std::string& pattern);
+
+    void clear_global_variable_regexp (const std::string& pattern);
+
+    void clear_global_variables (void);
+
+    void clear_functions (bool force = false);
+
+    void clear_function (const std::string& name);
+
+    void clear_symbol (const std::string& name);
+
+    void clear_function_pattern (const std::string& pat);
+
+    void clear_function_regexp (const std::string& pat);
+
+    void clear_symbol_pattern (const std::string& pat);
+
+    void clear_symbol_regexp (const std::string& pat);
+
+    std::list<std::string> global_variable_names (void);
+
+    std::list<std::string> variable_names (void);
+
+    std::list<std::string> user_function_names (void);
+
+    std::list<std::string> autoloaded_functions (void) const;
+
     static void recover_from_exception (void);
 
     static void add_atexit_function (const std::string& fname);
@@ -271,7 +401,7 @@
 
     void display_startup_message (void) const;
 
-    int execute_startup_files (void) const;
+    int execute_startup_files (void);
 
     int execute_eval_option_code (void);
 
@@ -287,6 +417,8 @@
 
     settings m_settings;
 
+    error_system m_error_system;
+
     help_system m_help_system;
 
     input_system m_input_system;
@@ -340,29 +472,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::interpreter::recover_from_exception' instead")
-static inline void
-recover_from_exception (void)
-{
-  octave::interpreter::recover_from_exception ();
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::interpreter::add_atexit_function' instead")
-static inline void
-add_atexit_function (const std::string& fname)
-{
-  octave::interpreter::add_atexit_function (fname);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::interpreter::remove_atexit_function' instead")
-static inline bool
-remove_atexit_function (const std::string& fname)
-{
-  return octave::interpreter::remove_atexit_function (fname);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/inv.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/inv.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -83,13 +83,17 @@
           if (isfloat)
             {
               result = arg.float_complex_diag_matrix_value ().inverse (info);
-              if (nargout > 1)
+              if (info == -1)
+                frcond = 0.0f;
+              else if (nargout > 1)
                 frcond = arg.float_complex_diag_matrix_value ().rcond ();
             }
           else
             {
               result = arg.complex_diag_matrix_value ().inverse (info);
-              if (nargout > 1)
+              if (info == -1)
+                rcond = 0.0;
+              else if (nargout > 1)
                 rcond = arg.complex_diag_matrix_value ().rcond ();
             }
         }
@@ -98,13 +102,17 @@
           if (isfloat)
             {
               result = arg.float_diag_matrix_value ().inverse (info);
-              if (nargout > 1)
+              if (info == -1)
+                frcond = 0.0f;
+              else if (nargout > 1)
                 frcond = arg.float_diag_matrix_value ().rcond ();
             }
           else
             {
               result = arg.diag_matrix_value ().inverse (info);
-              if (nargout > 1)
+              if (info == -1)
+                rcond = 0.0;
+              else if (nargout > 1)
                 rcond = arg.diag_matrix_value ().rcond ();
             }
         }
@@ -189,7 +197,7 @@
   if (isfloat)
     {
       volatile float xrcond = frcond;
-      rcond_plus_one_eq_one = xrcond + 1.0F == 1.0F;
+      rcond_plus_one_eq_one = xrcond + 1.0f == 1.0f;
     }
   else
     {
@@ -225,10 +233,29 @@
 %! assert (isa (xinv, "double"));
 %! assert (isa (rcond, "double"));
 
+%!testif HAVE_UMFPACK <*56232>
+%! fail ("A = inv (sparse ([1, 2;0 ,0]))", "warning", "matrix singular");
+%! assert (A, sparse ([Inf, Inf; 0, 0]));
+
+%!testif HAVE_UMFPACK <*56232>
+%! fail ("A = inv (sparse ([1i, 2;0 ,0]))", "warning", "matrix singular");
+%! assert (A, sparse ([Inf, Inf; 0, 0]));
+
+%!test
+%! fail ("A = inv (diag ([1, 0, 1]))", "warning", "matrix singular");
+%! assert (A, diag ([Inf, Inf, Inf]));
+
+%!error <inverse of the null matrix not defined> inv (diag ([0, 0]))
+%!error <inverse of the null matrix not defined> inv (diag (complex ([0, 0])))
+
+%!testif HAVE_UMFPACK <*56232>
+%! fail ("A = inv (sparse ([1, 0, 0; 0, 0, 0; 0, 0, 1]))", "warning", "matrix singular");
+%! assert (A, sparse ([Inf, 0, 0; 0, 0, 0; 0, 0, Inf]));
+
 %!error inv ()
 %!error inv ([1, 2; 3, 4], 2)
 %!error <must be a square matrix> inv ([1, 2; 3, 4; 5, 6])
-
+%!error <inverse of the null matrix not defined> inv (sparse (2, 2, 0))
 */
 
 DEFALIAS (inverse, inv);
--- a/libinterp/corefcn/load-path.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/load-path.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -46,146 +46,146 @@
 #include "unwind-prot.h"
 #include "utils.h"
 
-static void
-maybe_add_path_elts (std::string& path, const std::string& dir)
-{
-  std::string tpath = octave::genpath (dir);
-
-  if (! tpath.empty ())
-    {
-      if (path.empty ())
-        path = tpath;
-      else
-        path += octave::directory_path::path_sep_str () + tpath;
-    }
-}
-
-static std::list<std::string>
-split_path (const std::string& p)
-{
-  std::list<std::string> retval;
-
-  size_t beg = 0;
-  size_t end = p.find (octave::directory_path::path_sep_char ());
-
-  size_t len = p.length ();
-
-  while (end != std::string::npos)
-    {
-      std::string elt = p.substr (beg, end-beg);
-
-      if (! elt.empty ())
-        retval.push_back (elt);
-
-      beg = end + 1;
-
-      if (beg == len)
-        break;
-
-      end = p.find (octave::directory_path::path_sep_char (), beg);
-    }
-
-  std::string elt = p.substr (beg);
-
-  if (! elt.empty ())
-    retval.push_back (elt);
-
-  return retval;
-}
-
-// Strip trailing directory separators.
-
-static std::string
-strip_trailing_separators (const std::string& dir_arg)
-{
-  std::string dir = dir_arg;
-
-  size_t k = dir.length ();
-
-  while (k > 1 && octave::sys::file_ops::is_dir_sep (dir[k-1]))
-    k--;
-
-  if (k < dir.length ())
-    dir.resize (k);
-
-  return dir;
-}
-
-// Should we cache all files in private directories, or is it OK to just
-// look them up each time as needed?
-
-static std::string
-find_private_file (const std::string& fname)
-{
-  std::string retval;
-
-  // Look in private directory corresponding to current function (if
-  // any).
-
-  octave::symbol_scope scope = octave::__get_current_scope__ ("find_private_file");
-
-  octave_user_function *curr_fcn = scope ? scope.function () : nullptr;
-
-  if (curr_fcn)
-    {
-      // Even for private functions, dir_name doesn't contain the
-      // "private" directory component so we append it here in all
-      // cases.
-
-      std::string dir_name = curr_fcn->dir_name ();
-
-      if (! dir_name.empty ())
-        {
-          std::string pfname = dir_name + octave::sys::file_ops::dir_sep_str ()
-                               + "private" + octave::sys::file_ops::dir_sep_str () + fname;
-
-          octave::sys::file_stat fs (pfname);
-
-          if (fs.exists () && fs.is_reg ())
-            retval = pfname;
-        }
-    }
-
-  return retval;
-}
-
-// True if a path is contained in a path list separated by path_sep_char
-
-static bool
-in_path_list (const std::string& path_list, const std::string& path)
-{
-  size_t ps = path.size ();
-  size_t pls = path_list.size ();
-  size_t pos = path_list.find (path);
-  char psc = octave::directory_path::path_sep_char ();
-  while (pos != std::string::npos)
-    {
-      if ((pos == 0 || path_list[pos-1] == psc)
-          && (pos + ps == pls || path_list[pos + ps] == psc))
-        return true;
-      else
-        pos = path_list.find (path, pos + 1);
-    }
-
-  return false;
-}
-
-static void
-rehash_internal (void)
-{
-  octave::load_path& lp = octave::__get_load_path__ ("rehash_internal");
-
-  lp.update ();
-
-  // FIXME: maybe we should rename this variable since it is being
-  // used for more than keeping track of the prompt time.
-
-  // This will force updated functions to be found.
-  Vlast_prompt_time.stamp ();
-}
-
 namespace octave
 {
+  static void
+  maybe_add_path_elts (std::string& path, const std::string& dir)
+  {
+    std::string tpath = genpath (dir);
+
+    if (! tpath.empty ())
+      {
+        if (path.empty ())
+          path = tpath;
+        else
+          path += directory_path::path_sep_str () + tpath;
+      }
+  }
+
+  static std::list<std::string>
+  split_path (const std::string& p)
+  {
+    std::list<std::string> retval;
+
+    size_t beg = 0;
+    size_t end = p.find (directory_path::path_sep_char ());
+
+    size_t len = p.length ();
+
+    while (end != std::string::npos)
+      {
+        std::string elt = p.substr (beg, end-beg);
+
+        if (! elt.empty ())
+          retval.push_back (elt);
+
+        beg = end + 1;
+
+        if (beg == len)
+          break;
+
+        end = p.find (directory_path::path_sep_char (), beg);
+      }
+
+    std::string elt = p.substr (beg);
+
+    if (! elt.empty ())
+      retval.push_back (elt);
+
+    return retval;
+  }
+
+  // Strip trailing directory separators.
+
+  static std::string
+  strip_trailing_separators (const std::string& dir_arg)
+  {
+    std::string dir = dir_arg;
+
+    size_t k = dir.length ();
+
+    while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1]))
+      k--;
+
+    if (k < dir.length ())
+      dir.resize (k);
+
+    return dir;
+  }
+
+  // Should we cache all files in private directories, or is it OK to just
+  // look them up each time as needed?
+
+  static std::string
+  find_private_file (const std::string& fname)
+  {
+    std::string retval;
+
+    // Look in private directory corresponding to current function (if
+    // any).
+
+    symbol_scope scope = __get_current_scope__ ("find_private_file");
+
+    octave_user_function *curr_fcn = scope ? scope.function () : nullptr;
+
+    if (curr_fcn)
+      {
+        // Even for private functions, dir_name doesn't contain the
+        // "private" directory component so we append it here in all
+        // cases.
+
+        std::string dir_name = curr_fcn->dir_name ();
+
+        if (! dir_name.empty ())
+          {
+            std::string pfname = dir_name + sys::file_ops::dir_sep_str ()
+              + "private" + sys::file_ops::dir_sep_str () + fname;
+
+            sys::file_stat fs (pfname);
+
+            if (fs.exists () && fs.is_reg ())
+              retval = pfname;
+          }
+      }
+
+    return retval;
+  }
+
+  // True if a path is contained in a path list separated by path_sep_char
+
+  static bool
+  in_path_list (const std::string& path_list, const std::string& path)
+  {
+    size_t ps = path.size ();
+    size_t pls = path_list.size ();
+    size_t pos = path_list.find (path);
+    char psc = directory_path::path_sep_char ();
+    while (pos != std::string::npos)
+      {
+        if ((pos == 0 || path_list[pos-1] == psc)
+            && (pos + ps == pls || path_list[pos + ps] == psc))
+          return true;
+        else
+          pos = path_list.find (path, pos + 1);
+      }
+
+    return false;
+  }
+
+  static void
+  rehash_internal (void)
+  {
+    load_path& lp = __get_load_path__ ("rehash_internal");
+
+    lp.update ();
+
+    // FIXME: maybe we should rename this variable since it is being
+    // used for more than keeping track of the prompt time.
+
+    // This will force updated functions to be found.
+    Vlast_prompt_time.stamp ();
+  }
+
   std::string load_path::sys_path;
   load_path::abs_dir_cache_type load_path::abs_dir_cache;
 
@@ -846,14 +846,14 @@
     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);
+    unwind_protect frame;
+
+    std::string file = sys::file_ops::concat (dir, script_file);
+
+    sys::file_stat fs (file);
 
     if (fs.exists ())
-      octave::source_file (file, "base");
+      source_file (file, "base");
   }
 
   // FIXME: maybe we should also maintain a map to speed up this method of access.
@@ -1082,7 +1082,7 @@
     string_vector flist;
     std::string msg;
 
-    if (! octave::sys::get_dirlist (d, flist, msg))
+    if (! sys::get_dirlist (d, flist, msg))
       warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
     else
       {
@@ -2246,7 +2246,7 @@
 Reinitialize Octave's load path directory cache.
 @end deftypefn */)
 {
-  rehash_internal ();
+  octave::rehash_internal ();
 
   return ovl ();
 }
@@ -2337,7 +2337,7 @@
 
       lp.set (path, true);
 
-      rehash_internal ();
+      octave::rehash_internal ();
     }
 
   if (nargout > 0)
@@ -2438,7 +2438,7 @@
     {
       std::string arg = arglist(i).xstring_value ("addpath: all arguments must be strings");
 
-      std::list<std::string> dir_elts = split_path (arg);
+      std::list<std::string> dir_elts = octave::split_path (arg);
 
       if (! append)
         std::reverse (dir_elts.begin (), dir_elts.end ());
@@ -2483,7 +2483,7 @@
     }
 
   if (need_to_update)
-    rehash_internal ();
+    octave::rehash_internal ();
 
   return retval;
 }
@@ -2527,7 +2527,7 @@
   for (int i = 0; i < nargin; i++)
     {
       std::string arg = args(i).xstring_value ("rmpath: all arguments must be strings");
-      std::list<std::string> dir_elts = split_path (arg);
+      std::list<std::string> dir_elts = octave::split_path (arg);
 
       for (const auto& dir : dir_elts)
         {
@@ -2542,7 +2542,7 @@
     }
 
   if (need_to_update)
-    rehash_internal ();
+    octave::rehash_internal ();
 
   return retval;
 }
--- a/libinterp/corefcn/load-save.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/load-save.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -66,7 +66,6 @@
 #include "ov-cell.h"
 #include "pager.h"
 #include "syminfo.h"
-#include "symtab.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -685,17 +684,10 @@
 
         std::string struct_name = argv[argv_idx];
 
-        symbol_scope scope = m_interpreter.get_current_scope ();
-
-        octave_value struct_var;
+        if (! m_interpreter.is_variable (struct_name))
+          error ("save: no such variable: '%s'", struct_name.c_str ());
 
-        if (scope)
-          {
-            if (! scope.is_variable (struct_name))
-              error ("save: no such variable: '%s'", struct_name.c_str ());
-
-            struct_var = scope.varval (struct_name);
-          }
+        octave_value struct_var = m_interpreter.varval (struct_name);
 
         if (! struct_var.isstruct () || struct_var.numel () != 1)
           error ("save: '%s' is not a scalar structure", struct_name.c_str ());
@@ -914,9 +906,9 @@
                                       const load_save_format& fmt,
                                       bool save_as_floats)
   {
-    call_stack& cs = m_interpreter.get_call_stack ();
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
 
-    symbol_info_list syminfo_list = cs.glob_symbol_info (pattern);
+    symbol_info_list syminfo_list = tw.glob_symbol_info (pattern);
 
     size_t saved = 0;
 
@@ -1032,9 +1024,9 @@
   {
     write_header (os, fmt);
 
-    call_stack& cs = m_interpreter.get_call_stack ();
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
 
-    symbol_info_list syminfo_list = cs.top_scope_symbol_info ();
+    symbol_info_list syminfo_list = tw.top_scope_symbol_info ();
 
     double save_mem_size = 0;
 
@@ -1070,24 +1062,7 @@
                                                   bool global,
                                                   const std::string& /*doc*/)
   {
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-    symbol_scope scope = symtab.require_current_scope ("load_save_system::install_loaded_variable");
-
-    if (global)
-      {
-        symbol_record sym = scope.find_symbol (name);
-
-        if (! sym.is_global ())
-          {
-            symbol_scope global_scope = symtab.global_scope ();
-            symbol_record global_sym = global_scope.find_symbol (name);
-
-            sym.bind_fwd_rep (global_scope.get_rep (), global_sym);
-          }
-      }
-
-    scope.assign (name, val);
+    m_interpreter.install_variable (name, val, global);
   }
 
   std::string load_save_system::init_save_header_format (void)
--- a/libinterp/corefcn/ls-hdf5.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/ls-hdf5.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -414,6 +414,24 @@
 
 #if defined (HAVE_HDF5)
 
+// The following subroutine creates an HDF5 representation of the way
+// we will store Octave range types (triplets of floating-point numbers).
+// NUM_TYPE is the HDF5 numeric type to use for storage
+// (e.g., H5T_NATIVE_DOUBLE to save as 'double').
+// Note that any necessary conversions are handled automatically by HDF5.
+
+static hid_t
+hdf5_make_range_type (hid_t num_type)
+{
+  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3);
+
+  H5Tinsert (type_id, "base", 0 * sizeof (double), num_type);
+  H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type);
+  H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type);
+
+  return type_id;
+}
+
 // This function is designed to be passed to H5Giterate, which calls it
 // on each data item in an HDF5 file.  For the item whose name is NAME in
 // the group GROUP_ID, this function sets dv->tc to an Octave representation
@@ -686,6 +704,7 @@
       else if (type_class_id == H5T_COMPOUND)
         {
           hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
+          hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);
 
           if (hdf5_types_compatible (type_id, complex_type))
             {
@@ -700,17 +719,25 @@
 
               H5Sclose (space_id);
             }
-          else
-            // Assume that if its not complex its a range.
-            // If its not, it'll be rejected later in the range code.
-            d->tc = type_info.lookup_type ("range");
+          else if (hdf5_types_compatible (type_id, range_type))
+            {
+               // If it's not a complex, check if it's a range
+               d->tc = octave_value_typeinfo::lookup_type ("range");
+            }
+          else // Otherwise, just ignore it with a warning.
+            {
+               warning ("load: can't read '%s' (unknown datatype)", name);
+               retval = 0;  // unknown datatype; skip
+               return retval;
+            }
 
+          H5Tclose (range_type);
           H5Tclose (complex_type);
         }
       else
         {
           warning ("load: can't read '%s' (unknown datatype)", name);
-          retval = 0; // unknown datatype; skip
+          retval = 0;  // unknown datatype; skip
           return retval;
         }
 
--- a/libinterp/corefcn/ls-mat5.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/ls-mat5.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -51,7 +51,6 @@
 #include "str-vec.h"
 
 #include "Cell.h"
-#include "call-stack.h"
 #include "defaults.h"
 #include "defun.h"
 #include "error.h"
@@ -70,6 +69,7 @@
 #include "ovl.h"
 #include "pager.h"
 #include "parse.h"
+#include "pt-eval.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -861,7 +861,7 @@
           {
             if (fpath.empty ())
               // We have a builtin function
-              tc = make_fcn_handle (fname);
+              tc = make_fcn_handle (interp, fname);
             else
               {
                 std::string mroot =
@@ -976,15 +976,9 @@
             // Set up temporary scope to use for evaluating the text
             // that defines the anonymous function.
 
-            octave::symbol_table& symtab = interp.get_symbol_table ();
-
-            octave::symbol_scope local_scope;
-
-            symtab.set_scope (local_scope);
-
-            octave::call_stack& cs = interp.get_call_stack ();
-            cs.push (local_scope, 0);
-            frame.add_method (cs, &octave::call_stack::pop);
+            octave::tree_evaluator& tw = interp.get_evaluator ();
+            tw.push_dummy_scope ("read_mat5_binary_element");
+            frame.add_method (tw, &octave::tree_evaluator::pop_scope);
 
             if (m2.nfields () > 0)
               {
@@ -995,7 +989,7 @@
                     std::string key = m2.key (p0);
                     octave_value val = m2.contents (p0);
 
-                    local_scope.assign (key, val, 0);
+                    interp.assign (key, val);
                   }
               }
 
@@ -1013,8 +1007,6 @@
               error ("load: failed to load anonymous function handle");
 
             tc = new octave_fcn_handle (fh->fcn_val (), "@<anonymous>");
-
-            frame.run ();
           }
         else
           error ("load: invalid function handle type");
@@ -1191,7 +1183,7 @@
               }
             else
               {
-                cdef_manager& cdm = interp.get_cdef_manager ();
+                octave::cdef_manager& cdm = interp.get_cdef_manager ();
 
                 if (cdm.find_class (classname, false, true).ok ())
                   {
@@ -1495,9 +1487,9 @@
   is.read (reinterpret_cast<char *> (&magic), 2);
 
   if (magic == 0x4d49)
-    swap = 0;
+    swap = false;
   else if (magic == 0x494d)
-    swap = 1;
+    swap = true;
   else
     {
       if (! quiet)
--- a/libinterp/corefcn/ls-oct-text.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/ls-oct-text.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -251,8 +251,7 @@
       return "";
     }
 
-  if (! (name == ".nargin." || name == ".nargout."
-         || name == CELL_ELT_TAG || octave::valid_identifier (name)))
+  if (! (name == CELL_ELT_TAG || octave::valid_identifier (name)))
     error ("load: invalid identifier '%s' found in file '%s'",
            name.c_str (), filename.c_str ());
 
--- a/libinterp/corefcn/lsode.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/lsode.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,6 +24,7 @@
 #  include "config.h"
 #endif
 
+#include <list>
 #include <string>
 
 #include "LSODE.h"
@@ -32,6 +33,7 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
@@ -45,10 +47,10 @@
 #include "LSODE-opts.cc"
 
 // Global pointer for user defined function required by lsode.
-static octave_function *lsode_fcn;
+static octave_value lsode_fcn;
 
 // Global pointer for optional user defined jacobian function used by lsode.
-static octave_function *lsode_jac;
+static octave_value lsode_jac;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_fcn_imaginary = false;
@@ -66,7 +68,7 @@
   args(1) = t;
   args(0) = x;
 
-  if (lsode_fcn)
+  if (lsode_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -106,7 +108,7 @@
   args(1) = t;
   args(0) = x;
 
-  if (lsode_jac)
+  if (lsode_jac.is_defined ())
     {
       octave_value_list tmp;
 
@@ -275,11 +277,14 @@
   octave::symbol_table& symtab = interp.get_symbol_table ();
 
   std::string fcn_name, fname, jac_name, jname;
-  lsode_fcn = nullptr;
-  lsode_jac = nullptr;
+
+  lsode_fcn = octave_value ();
+  lsode_jac = octave_value ();
 
   octave_value f_arg = args(0);
 
+  std::list<std::string> parameter_names ({"x", "t"});
+
   if (f_arg.iscell ())
     {
       Cell c = f_arg.cell_value ();
@@ -287,92 +292,49 @@
         f_arg = c(0);
       else if (c.numel () == 2)
         {
-          if (c(0).is_function_handle () || c(0).is_inline_function ())
-            lsode_fcn = c(0).function_value ();
-          else
-            {
-              fcn_name = unique_symbol_name ("__lsode_fcn__");
-              fname = "function y = ";
-              fname.append (fcn_name);
-              fname.append (" (x, t) y = ");
-              lsode_fcn = extract_function (c(0), "lsode", fcn_name, fname,
-                                            "; endfunction");
-            }
+          lsode_fcn = octave::get_function_handle (interp, c(0),
+                                                   parameter_names);
 
-          if (lsode_fcn)
+          if (lsode_fcn.is_defined ())
             {
-              if (c(1).is_function_handle () || c(1).is_inline_function ())
-                lsode_jac = c(1).function_value ();
-              else
-                {
-                  jac_name = unique_symbol_name ("__lsode_jac__");
-                  jname = "function jac = ";
-                  jname.append (jac_name);
-                  jname.append (" (x, t) jac = ");
-                  lsode_jac = extract_function (c(1), "lsode", jac_name,
-                                                jname, "; endfunction");
+              lsode_jac = octave::get_function_handle (interp, c(1),
+                                                       parameter_names);
 
-                  if (! lsode_jac)
-                    {
-                      if (fcn_name.length ())
-                        symtab.clear_function (fcn_name);
-                      lsode_fcn = nullptr;
-                    }
-                }
+              if (lsode_jac.is_undefined ())
+                lsode_fcn = octave_value ();
             }
         }
       else
         error ("lsode: incorrect number of elements in cell array");
     }
 
-  if (! lsode_fcn && ! f_arg.iscell ())
+  if (lsode_fcn.is_undefined () && ! f_arg.iscell ())
     {
       if (f_arg.is_function_handle () || f_arg.is_inline_function ())
-        lsode_fcn = f_arg.function_value ();
+        lsode_fcn = f_arg;
       else
         {
           switch (f_arg.rows ())
             {
             case 1:
-              do
-                {
-                  fcn_name = unique_symbol_name ("__lsode_fcn__");
-                  fname = "function y = ";
-                  fname.append (fcn_name);
-                  fname.append (" (x, t) y = ");
-                  lsode_fcn = extract_function (f_arg, "lsode", fcn_name,
-                                                fname, "; endfunction");
-                }
-              while (0);
+              lsode_fcn = octave::get_function_handle (interp, f_arg,
+                                                       parameter_names);
               break;
 
             case 2:
               {
                 string_vector tmp = f_arg.string_vector_value ();
 
-                fcn_name = unique_symbol_name ("__lsode_fcn__");
-                fname = "function y = ";
-                fname.append (fcn_name);
-                fname.append (" (x, t) y = ");
-                lsode_fcn = extract_function (tmp(0), "lsode", fcn_name,
-                                              fname, "; endfunction");
+                lsode_fcn = octave::get_function_handle (interp, tmp(0),
+                                                         parameter_names);
 
-                if (lsode_fcn)
+                if (lsode_fcn.is_defined ())
                   {
-                    jac_name = unique_symbol_name ("__lsode_jac__");
-                    jname = "function jac = ";
-                    jname.append (jac_name);
-                    jname.append (" (x, t) jac = ");
-                    lsode_jac = extract_function (tmp(1), "lsode",
-                                                  jac_name, jname,
-                                                  "; endfunction");
+                    lsode_jac = octave::get_function_handle (interp, tmp(1),
+                                                             parameter_names);
 
-                    if (! lsode_jac)
-                      {
-                        if (fcn_name.length ())
-                          symtab.clear_function (fcn_name);
-                        lsode_fcn = nullptr;
-                      }
+                    if (lsode_jac.is_undefined ())
+                      lsode_fcn = octave_value ();
                   }
               }
               break;
@@ -383,7 +345,7 @@
         }
     }
 
-  if (! lsode_fcn)
+  if (lsode_fcn.is_undefined ())
     error ("lsode: FCN argument is not a valid function name or handle");
 
   ColumnVector state = args(1).xvector_value ("lsode: initial state X_0 must be a vector");
@@ -402,7 +364,8 @@
   double tzero = out_times (0);
 
   ODEFunc func (lsode_user_function);
-  if (lsode_jac)
+
+  if (lsode_jac.is_defined ())
     func.set_jacobian_function (lsode_user_jacobian);
 
   LSODE ode (state, tzero, func);
--- a/libinterp/corefcn/mappers.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/mappers.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -131,7 +131,7 @@
 %! v = [0, pi, pi/2, pi/2];
 %! assert (real (acos (x)), v);
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac and
 %! ## Windows.  Their trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
@@ -162,7 +162,7 @@
 %! v = [0, pi/2*i, pi*i, pi/2*i];
 %! assert (acosh (x), v, sqrt (eps));
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac.
 %! ## Mac trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
@@ -185,7 +185,7 @@
 %! v = single ([0, pi/2*i, pi*i, pi/2*i]);
 %! assert (acosh (x), v, sqrt (eps ("single")));
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac.
 %! ## Mac trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
@@ -206,7 +206,7 @@
 %! v = [0, pi, pi/2, -pi/2];
 %! assert (imag (acosh (x)), v);
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac and
 %! ## Windows.  Their trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
@@ -334,7 +334,7 @@
 %! v = [pi/2, -pi/2, 0, -0];
 %! assert (real (asin (x)), v);
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac and
 %! ## Windows. Their trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
@@ -377,7 +377,7 @@
 %! v = [0, 0, pi/2, -pi/2];
 %! assert (imag (asinh (x)), v);
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac and
 %! ## Windows.  Their trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
--- a/libinterp/corefcn/mex.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/mex.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -40,7 +40,6 @@
 #include "quit.h"
 
 #include "Cell.h"
-#include "call-stack.h"
 #include "error.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
@@ -50,6 +49,7 @@
 #include "oct-map.h"
 #include "ovl.h"
 #include "ov.h"
+#include "ov-classdef.h"
 #include "ov-mex-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
@@ -1490,12 +1490,15 @@
 
   mxArray_sparse (mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg,
                   mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, m, n), nzmax (nzmax_arg),
-      pr (mxArray::calloc (nzmax, get_element_size ())),
-      pi (flag == mxCOMPLEX ? mxArray::calloc (nzmax, get_element_size ()) : nullptr),
-      ir (static_cast<mwIndex *> (mxArray::calloc (nzmax, sizeof (mwIndex)))),
-      jc (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex))))
-  { }
+    : mxArray_matlab (id_arg, m, n)
+  {
+    nzmax = (nzmax_arg > 0 ? nzmax_arg : 1);
+    pr = mxArray::calloc (nzmax, get_element_size ());
+    pi = (flag == mxCOMPLEX ? mxArray::calloc (nzmax, get_element_size ())
+                            : nullptr);
+    ir = (static_cast<mwIndex *> (mxArray::calloc (nzmax, sizeof (mwIndex))));
+    jc = (static_cast<mwIndex *> (mxArray::calloc (n + 1, sizeof (mwIndex))));
+  }
 
 private:
 
@@ -1560,7 +1563,11 @@
 
   void set_jc (mwIndex *jc_arg) { jc = jc_arg; }
 
-  void set_nzmax (mwSize nzmax_arg) { nzmax = nzmax_arg; }
+  void set_nzmax (mwSize nzmax_arg)
+  {
+    /* Require storage for at least 1 element */
+    nzmax = (nzmax_arg > 0 ? nzmax_arg : 1);
+  }
 
   octave_value as_octave_value (void) const
   {
@@ -2155,10 +2162,10 @@
   {
     if (! fname)
       {
-        octave::call_stack& cs
-          = octave::__get_call_stack__ ("mex::function_name");
-
-        octave_function *fcn = cs.current ();
+        octave::tree_evaluator& tw
+          = octave::__get_evaluator__ ("mex::function_name");
+
+        octave_function *fcn = tw.current_function ();
 
         if (fcn)
           {
@@ -3484,13 +3491,10 @@
 
   octave_value val;
 
+  octave::interpreter& interp = octave::__get_interpreter__ ("mexGetVariable");
+
   if (! strcmp (space, "global"))
-    {
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("mexGetVariable");
-
-      val = symtab.global_varval (name);
-    }
+    val = interp.global_varval (name);
   else
     {
       // FIXME: should this be in variables.cc?
@@ -3507,18 +3511,15 @@
 
           if (base)
             {
-              octave::call_stack& cs
-                = octave::__get_call_stack__ ("mexGetVariable");
-
-              cs.goto_base_frame ();
-
-              frame.add_method (cs, &octave::call_stack::pop);
+              octave::tree_evaluator& tw = interp.get_evaluator ();
+
+              frame.add_method (tw, &octave::tree_evaluator::restore_frame,
+                                tw.current_call_stack_frame_number ());
+
+              tw.goto_base_frame ();
             }
 
-          octave::symbol_scope scope
-            = octave::__require_current_scope__ ("mexGetVariable");
-
-          val = scope.varval (name);
+          val = interp.varval (name);
         }
       else
         mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
@@ -3555,13 +3556,10 @@
   if (! name || name[0] == '\0')
     return 1;
 
+  octave::interpreter& interp = octave::__get_interpreter__ ("mexPutVariable");
+
   if (! strcmp (space, "global"))
-    {
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("mexPutVariable");
-
-      symtab.global_assign (name, mxArray::as_octave_value (ptr));
-    }
+    interp.global_assign (name, mxArray::as_octave_value (ptr));
   else
     {
       // FIXME: should this be in variables.cc?
@@ -3578,18 +3576,15 @@
 
           if (base)
             {
-              octave::call_stack& cs
-                = octave::__get_call_stack__ ("mexPutVariable");
-
-              cs.goto_base_frame ();
-
-              frame.add_method (cs, &octave::call_stack::pop);
+              octave::tree_evaluator& tw = interp.get_evaluator ();
+
+              frame.add_method (tw, &octave::tree_evaluator::restore_frame,
+                                tw.current_call_stack_frame_number ());
+
+              tw.goto_base_frame ();
             }
 
-          octave::symbol_scope scope
-            = octave::__require_current_scope__ ("mexPutVariable");
-
-          scope.assign (name, mxArray::as_octave_value (ptr));
+          interp.assign (name, mxArray::as_octave_value (ptr));
         }
       else
         mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
--- a/libinterp/corefcn/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -68,6 +68,7 @@
   %reldir%/oct-obj.h \
   %reldir%/oct-prcstrm.h \
   %reldir%/oct-procbuf.h \
+  %reldir%/oct-process.h \
   %reldir%/oct-stdstrm.h \
   %reldir%/oct-stream.h \
   %reldir%/oct-strstrm.h \
@@ -82,7 +83,10 @@
   %reldir%/sighandlers.h \
   %reldir%/sparse-xdiv.h \
   %reldir%/sparse-xpow.h \
+  %reldir%/stack-frame.h \
+  %reldir%/stack-frame-walker.h \
   %reldir%/syminfo.h \
+  %reldir%/syminfo-accumulator.h \
   %reldir%/symrec.h \
   %reldir%/symscope.h \
   %reldir%/symtab.h \
@@ -205,6 +209,7 @@
   %reldir%/oct-map.cc \
   %reldir%/oct-prcstrm.cc \
   %reldir%/oct-procbuf.cc \
+  %reldir%/oct-process.cc \
   %reldir%/oct-stream.cc \
   %reldir%/oct-strstrm.cc \
   %reldir%/oct-tex-lexer.ll \
@@ -232,6 +237,7 @@
   %reldir%/sparse.cc \
   %reldir%/spparms.cc \
   %reldir%/sqrtm.cc \
+  %reldir%/stack-frame.cc \
   %reldir%/strfind.cc \
   %reldir%/strfns.cc \
   %reldir%/sub2ind.cc \
--- a/libinterp/corefcn/nproc.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/nproc.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,8 +24,10 @@
 #  include "config.h"
 #endif
 
+#include "nproc-wrapper.h"
+
 #include "defun.h"
-#include "nproc-wrapper.h"
+#include "error.h"
 
 DEFUN (nproc, args, ,
        doc: /* -*- texinfo -*-
@@ -54,7 +56,7 @@
   if (nargin > 1)
     print_usage ();
 
-  octave_nproc_query query = OCTAVE_NPROC_CURRENT;
+  octave_nproc_query query = OCTAVE_NPROC_CURRENT_OVERRIDABLE;
 
   if (nargin == 1)
     {
@@ -81,6 +83,9 @@
 %!assert (nproc ("all") >= 1)
 %!assert (nproc ("current") >= 1)
 
+## Test that "overridable" is the default
+%!assert (nproc ("overridable"), nproc ())
+
 %!test
 %! c = nproc ("current");
 %! unwind_protect
--- a/libinterp/corefcn/oct-errno.in.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-errno.in.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -296,14 +296,9 @@
   if (! instance)
     {
       instance = new octave_errno ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
+      singleton_cleanup_list::add (cleanup_instance);
     }
 
-  if (! instance)
-    error ("unable to create errno object!");
-
   return retval;
 }
 
--- a/libinterp/corefcn/oct-fstrm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-fstrm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -40,11 +40,11 @@
 octave_fstream::octave_fstream (const std::string& nm_arg,
                                 std::ios::openmode arg_md,
                                 octave::mach_info::float_format ff)
-  : octave::base_stream (arg_md, ff), nm (nm_arg)
+  : octave::base_stream (arg_md, ff), m_name (nm_arg)
 {
-  fs.open (nm.c_str (), arg_md);
+  m_fstream.open (m_name.c_str (), arg_md);
 
-  if (! fs)
+  if (! m_fstream)
     // Note: error is inherited from octave::base_stream, not ::error.
     error (std::strerror (errno));
 }
@@ -76,13 +76,13 @@
 bool
 octave_fstream::eof (void) const
 {
-  return fs.eof ();
+  return m_fstream.eof ();
 }
 
 void
 octave_fstream::do_close (void)
 {
-  fs.close ();
+  m_fstream.close ();
 }
 
 std::istream *
@@ -91,7 +91,7 @@
   std::istream *retval = nullptr;
 
   if (mode () & std::ios::in)
-    retval = &fs;
+    retval = &m_fstream;
 
   return retval;
 }
@@ -102,7 +102,7 @@
   std::ostream *retval = nullptr;
 
   if (mode () & std::ios::out)
-    retval = &fs;
+    retval = &m_fstream;
 
   return retval;
 }
--- a/libinterp/corefcn/oct-fstrm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-fstrm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -68,7 +68,7 @@
 
   // The name of the file.
 
-  std::string name (void) const { return nm; }
+  std::string name (void) const { return m_name; }
 
   std::istream * input_stream (void);
 
@@ -80,9 +80,9 @@
 
 private:
 
-  std::string nm;
+  std::string m_name;
 
-  std::fstream fs;
+  std::fstream m_fstream;
 };
 
 #endif
--- a/libinterp/corefcn/oct-handle.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-handle.h	Fri Jul 12 12:14:43 2019 -0400
@@ -28,6 +28,7 @@
 #include "dMatrix.h"
 #include "lo-ieee.h"
 
+#include "error.h"
 #include "ov.h"
 
 // ---------------------------------------------------------------------
--- a/libinterp/corefcn/oct-hist.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-hist.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -134,7 +134,7 @@
           tmp.resize (len - 1);
 
         if (! tmp.empty ())
-          if (octave::command_history::add (tmp))
+          if (command_history::add (tmp))
             octave_link::append_history (tmp);
       }
   }
@@ -162,7 +162,7 @@
   mk_tmp_hist_file (const octave_value_list& args,
                     bool insert_curr, const char *warn_for)
   {
-    string_vector hlist = octave::command_history::list ();
+    string_vector hlist = command_history::list ();
 
     int hist_count = hlist.numel () - 1;  // switch to zero-based indexing
 
@@ -172,7 +172,7 @@
     // but the actual commands performed will.
 
     if (! insert_curr)
-      octave::command_history::remove (hist_count);
+      command_history::remove (hist_count);
 
     hist_count--;  // skip last entry in history list
 
@@ -225,7 +225,7 @@
         reverse = true;
       }
 
-    std::string name = octave::sys::tempnam ("", "oct-");
+    std::string name = sys::tempnam ("", "oct-");
 
     std::fstream file (name.c_str (), std::ios::out);
 
--- a/libinterp/corefcn/oct-iostrm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-iostrm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -69,7 +69,7 @@
 bool
 octave_istream::eof (void) const
 {
-  return is && is->eof ();
+  return m_istream && m_istream->eof ();
 }
 
 octave::stream
@@ -83,7 +83,7 @@
 bool
 octave_ostream::eof (void) const
 {
-  return os && os->eof ();
+  return m_ostream && m_ostream->eof ();
 }
 
 octave::stream
--- a/libinterp/corefcn/oct-iostrm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-iostrm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -38,7 +38,7 @@
                         std::ios::openmode m = std::ios::in | std::ios::out,
                         octave::mach_info::float_format ff
                           = octave::mach_info::native_float_format ())
-    : octave::base_stream (m, ff), nm (n) { }
+    : octave::base_stream (m, ff), m_name (n) { }
 
   // No copying!
 
@@ -66,7 +66,7 @@
 
   // The name of the file.
 
-  std::string name (void) const { return nm; }
+  std::string name (void) const { return m_name; }
 
 protected:
 
@@ -74,7 +74,7 @@
 
 private:
 
-  std::string nm;
+  std::string m_name;
 
   virtual const char * stream_type (void) const = 0;
 };
@@ -87,7 +87,7 @@
   octave_istream (std::istream *arg = nullptr, const std::string& n = "")
     : octave_base_iostream (n, std::ios::in,
                             octave::mach_info::native_float_format ()),
-      is (arg)
+      m_istream (arg)
   { }
 
   static octave::stream
@@ -97,7 +97,7 @@
 
   bool eof (void) const;
 
-  std::istream * input_stream (void) { return is; }
+  std::istream * input_stream (void) { return m_istream; }
 
   std::ostream * output_stream (void) { return nullptr; }
 
@@ -107,7 +107,7 @@
 
 private:
 
-  std::istream *is;
+  std::istream *m_istream;
 
   const char * stream_type (void) const { return "octave_istream"; }
 
@@ -126,7 +126,7 @@
   octave_ostream (std::ostream *arg, const std::string& n = "")
     : octave_base_iostream (n, std::ios::out,
                             octave::mach_info::native_float_format ()),
-      os (arg)
+      m_ostream (arg)
   { }
 
   static octave::stream
@@ -138,7 +138,7 @@
 
   std::istream * input_stream (void) { return nullptr; }
 
-  std::ostream * output_stream (void) { return os; }
+  std::ostream * output_stream (void) { return m_ostream; }
 
 protected:
 
@@ -146,7 +146,7 @@
 
 private:
 
-  std::ostream *os;
+  std::ostream *m_ostream;
 
   const char * stream_type (void) const { return "octave_ostream"; }
 
--- a/libinterp/corefcn/oct-map.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-map.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -557,11 +557,11 @@
 %! assert (fieldnames (reshape (x, 3, 8)), {"d"; "a"; "f"});
 
 ## test chopping of trailing singletons
-%!test <51634>
+%!test <*51634>
 %! x(1,1).d = 10;  x(4,6).a = "b";  x(2,4).f = 27;
 %! reshape (x, 3, 8, 1, 1);
 
-%!test <46385>
+%!test <*46385>
 %! M = repmat (struct ('a', ones(100), 'b', true), 1, 2);
 %! M = repmat(M, 1, 2);
 %! assert (size (M), [1, 4]);
--- a/libinterp/corefcn/oct-prcstrm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-prcstrm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -31,16 +31,18 @@
 
 octave::stream
 octave_iprocstream::create (const std::string& n, std::ios::openmode arg_md,
-                            octave::mach_info::float_format ff)
+                            octave::mach_info::float_format ff,
+                            const std::string& encoding)
 {
-  return octave::stream (new octave_iprocstream (n, arg_md, ff));
+  return octave::stream (new octave_iprocstream (n, arg_md, ff, encoding));
 }
 
 octave_iprocstream::octave_iprocstream (const std::string& n,
                                         std::ios::openmode arg_md,
-                                        octave::mach_info::float_format ff)
+                                        octave::mach_info::float_format ff,
+                                        const std::string& encoding)
   : octave_stdiostream (n, octave::popen (n.c_str (), "r"),
-                        arg_md, ff, octave::pclose)
+                        arg_md, ff, encoding, octave::pclose)
 { }
 
 octave_iprocstream::~octave_iprocstream (void)
@@ -50,16 +52,18 @@
 
 octave::stream
 octave_oprocstream::create (const std::string& n, std::ios::openmode arg_md,
-                            octave::mach_info::float_format ff)
+                            octave::mach_info::float_format ff,
+                            const std::string& encoding)
 {
-  return octave::stream (new octave_oprocstream (n, arg_md, ff));
+  return octave::stream (new octave_oprocstream (n, arg_md, ff, encoding));
 }
 
 octave_oprocstream::octave_oprocstream (const std::string& n,
                                         std::ios::openmode arg_md,
-                                        octave::mach_info::float_format ff)
+                                        octave::mach_info::float_format ff,
+                                        const std::string& encoding)
   : octave_stdiostream (n, octave::popen (n.c_str (), "w"),
-                        arg_md, ff, octave::pclose)
+                        arg_md, ff, encoding, octave::pclose)
 { }
 
 octave_oprocstream::~octave_oprocstream (void)
--- a/libinterp/corefcn/oct-prcstrm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-prcstrm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -38,7 +38,8 @@
   octave_iprocstream (const std::string& n,
                       std::ios::openmode arg_md = std::ios::in,
                       octave::mach_info::float_format flt_fmt
-                        = octave::mach_info::native_float_format ());
+                        = octave::mach_info::native_float_format (),
+                      const std::string& encoding = "utf-8");
 
   // No copying!
 
@@ -49,7 +50,8 @@
   static octave::stream
   create (const std::string& n, std::ios::openmode arg_md = std::ios::in,
           octave::mach_info::float_format flt_fmt
-            = octave::mach_info::native_float_format ());
+            = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8");
 
 protected:
 
@@ -64,7 +66,8 @@
   octave_oprocstream (const std::string& n,
                       std::ios::openmode arg_md = std::ios::out,
                       octave::mach_info::float_format flt_fmt
-                        = octave::mach_info::native_float_format ());
+                        = octave::mach_info::native_float_format (),
+                      const std::string& encoding = "utf-8");
 
   // No copying!
 
@@ -75,7 +78,8 @@
   static octave::stream
   create (const std::string& n, std::ios::openmode arg_md = std::ios::out,
           octave::mach_info::float_format flt_fmt
-            = octave::mach_info::native_float_format ());
+            = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8");
 
 protected:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/oct-process.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,88 @@
+/*
+
+Copyright (C) 2019 Andrew Janke
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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/>.
+
+*/
+
+#include <iostream>
+#include <sstream>
+
+#include "oct-process.h"
+#include "procstream.h"
+#include "sysdep.h"
+#include "oct-syscalls.h"
+
+namespace octave
+{
+  OCTINTERP_API
+  process_execution_result
+  process_execution_result::of_success (int exit_status,
+                                        const std::string& stdout_output)
+  {
+    return process_execution_result (0, exit_status, stdout_output, "");
+  }
+
+  OCTINTERP_API
+  process_execution_result
+  process_execution_result::of_error (int status, const std::string& err_msg)
+  {
+    return process_execution_result (status, -1, "", err_msg);
+  }
+
+  // Execute a shell command, returning results as a C++ object
+  OCTINTERP_API
+  process_execution_result
+  run_command_and_return_output (const std::string& cmd_str)
+  {
+    iprocstream cmd (cmd_str.c_str ());
+
+    if (! cmd)
+      {
+        std::string msg = "unable to start subprocess for '" + cmd_str + "'";
+
+        return process_execution_result::of_error (-1, msg);
+      }
+
+    std::ostringstream output_buf;
+
+    char ch;
+
+    for (;;)
+      {
+        if (cmd.get (ch))
+          output_buf.put (ch);
+        else
+          {
+            if (! cmd.eof () && errno == EAGAIN)
+              cmd.clear ();
+            else
+              break;
+          }
+      }
+
+    int cmd_status = cmd.close ();
+
+    if (sys::wifexited (cmd_status))
+      cmd_status = sys::wexitstatus (cmd_status);
+    else
+      cmd_status = 127;
+
+    return process_execution_result::of_success (cmd_status, output_buf.str ());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/oct-process.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,82 @@
+/*
+
+Copyright (C) 2019 Andrew Janke
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for 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 (oct_process_h)
+#define oct_process_h 1
+
+#include "octave-config.h"
+
+#include <string>
+
+namespace octave
+{
+  OCTINTERP_API
+  class
+  process_execution_result
+  {
+  public:
+
+    process_execution_result (void)
+      : m_status (-1), m_err_msg (), m_exit_status (-1), m_stdout_output ()
+    { }
+
+    process_execution_result (int status, int exit_status,
+                              const std::string& stdout_output,
+                              const std::string& err_msg)
+      : m_status (status), m_err_msg (err_msg), m_exit_status (exit_status),
+        m_stdout_output (stdout_output)
+    { }
+
+    static process_execution_result
+    of_success (int exit_status, const std::string& stdout_output);
+
+    static process_execution_result
+    of_error (int status, const std::string& err_msg);
+
+    int status (void) const { return m_status; }
+
+    int exit_status (void) const { return m_exit_status; }
+
+    std::string err_msg (void) const { return m_err_msg; }
+
+    std::string stdout_output (void) const { return m_stdout_output; }
+
+  private:
+
+    // Launch status of the process, 0 for success, nonzero for error.
+    int m_status;
+
+    // Error message if executing command failed.
+    std::string m_err_msg;
+
+    // Exit status of the process.
+    int m_exit_status;
+
+    // Collected stdout output of the process.
+    std::string m_stdout_output;
+  };
+
+  extern OCTINTERP_API process_execution_result
+  run_command_and_return_output (const std::string& cmd_str);
+}
+
+#endif
--- a/libinterp/corefcn/oct-stdstrm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-stdstrm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -40,9 +40,10 @@
                        std::ios::openmode m = std::ios::in | std::ios::out,
                        octave::mach_info::float_format ff
                          = octave::mach_info::native_float_format (),
+                       const std::string& encoding = "utf-8",
                        typename BUF_T::close_fcn cf = BUF_T::file_close)
-    : octave::base_stream (m, ff), nm (n), md (m),
-      s (f ? new STREAM_T (f, cf) : nullptr), fnum (fid)
+    : octave::base_stream (m, ff, encoding), m_name (n), m_mode (m),
+      m_stream (f ? new STREAM_T (f, cf) : nullptr), fnum (fid)
   { }
 
   // No copying!
@@ -54,48 +55,66 @@
   // Position a stream at OFFSET relative to ORIGIN.
 
   int seek (off_t offset, int origin)
-  { return s ? s->seek (offset, origin) : -1; }
+  {
+    return m_stream ? m_stream->seek (offset, origin) : -1;
+  }
 
   // Return current stream position.
 
-  off_t tell (void) { return s ? s->tell () : -1; }
+  off_t tell (void) { return m_stream ? m_stream->tell () : -1; }
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return s ? s->eof () : true; }
+  bool eof (void) const { return m_stream ? m_stream->eof () : true; }
 
   // The name of the file.
 
-  std::string name (void) const { return nm; }
+  std::string name (void) const { return m_name; }
 
-  std::istream * input_stream (void) { return (md & std::ios::in) ? s : nullptr; }
+  std::istream * input_stream (void)
+  {
+    return (m_mode & std::ios::in) ? m_stream : nullptr;
+  }
 
-  std::ostream * output_stream (void) { return (md & std::ios::out) ? s : nullptr; }
+  std::ostream * output_stream (void)
+  {
+    return (m_mode & std::ios::out) ? m_stream : nullptr;
+  }
 
   // FIXME: should not have to cast away const here.
   BUF_T * rdbuf (void) const
-  { return s ? (const_cast<STREAM_T *> (s))->rdbuf () : nullptr; }
+  {
+    return m_stream ? (const_cast<STREAM_T *> (m_stream))->rdbuf () : nullptr;
+  }
 
   int file_number (void) const { return fnum; }
 
-  bool bad (void) const { return s ? s->bad () : true; }
+  bool bad (void) const { return m_stream ? m_stream->bad () : true; }
 
-  void clear (void) { if (s) s->clear (); }
+  void clear (void)
+  {
+    if (m_stream)
+      m_stream->clear ();
+  }
 
-  void do_close (void) { if (s) s->stream_close (); }
+  void do_close (void)
+  {
+    if (m_stream)
+      m_stream->stream_close ();
+  }
 
 protected:
 
-  std::string nm;
+  std::string m_name;
 
-  std::ios::openmode md;
+  std::ios::openmode m_mode;
 
-  STREAM_T *s;
+  STREAM_T *m_stream;
 
   // The file number associated with this file.
   int fnum;
 
-  ~octave_tstdiostream (void) { delete s; }
+  ~octave_tstdiostream (void) { delete m_stream; }
 };
 
 class
@@ -108,18 +127,20 @@
                       std::ios::openmode m = std::ios::in | std::ios::out,
                       octave::mach_info::float_format ff
                         = octave::mach_info::native_float_format (),
+                      const std::string& encoding = "utf-8",
                       c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
     : octave_tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>
-       (n, f, f ? fileno (f) : -1, m, ff, cf) { }
+       (n, f, f ? fileno (f) : -1, m, ff, encoding, cf) { }
 
   static octave::stream
   create (const std::string& n, FILE *f = nullptr,
           std::ios::openmode m = std::ios::in | std::ios::out,
           octave::mach_info::float_format ff
             = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8",
           c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
   {
-    return octave::stream (new octave_stdiostream (n, f, m, ff, cf));
+    return octave::stream (new octave_stdiostream (n, f, m, ff, encoding, cf));
   }
 
   // No copying!
@@ -145,19 +166,22 @@
                        std::ios::openmode m = std::ios::in | std::ios::out,
                        octave::mach_info::float_format ff
                          = octave::mach_info::native_float_format (),
+                       const std::string& encoding = "utf-8",
                        c_zfile_ptr_buf::close_fcn cf
                          = c_zfile_ptr_buf::file_close)
     : octave_tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>
-       (n, f, fid, m, ff, cf) { }
+       (n, f, fid, m, ff, encoding, cf) { }
 
   static octave::stream
   create (const std::string& n, gzFile f = nullptr, int fid = 0,
           std::ios::openmode m = std::ios::in | std::ios::out,
           octave::mach_info::float_format ff
             = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8",
           c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)
   {
-    return octave::stream (new octave_zstdiostream (n, f, fid, m, ff, cf));
+    return octave::stream (new octave_zstdiostream (n, f, fid, m, ff, encoding,
+                                                    cf));
   }
 
   // No copying!
--- a/libinterp/corefcn/oct-stream.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-stream.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -54,6 +54,7 @@
 #include "octave.h"
 #include "oct-iostrm.h"
 #include "oct-stdstrm.h"
+#include "oct-string.h"
 #include "oct-stream.h"
 #include "ov.h"
 #include "ovl.h"
@@ -64,7 +65,7 @@
 {
   // Programming Note: There are two very different error functions used
   // in the stream code.  When invoked with "error (...)" the member
-  // function from octave::stream or octave::base_stream is called.  This
+  // function from stream or base_stream is called.  This
   // function sets the error state on the stream AND returns control to
   // the caller.  The caller must then return a value at the end of the
   // function.  When invoked with "::error (...)" the exception-based
@@ -1640,11 +1641,11 @@
     // or 64.  For floating point values, bitwidth may be 32 or 64.
     int bitwidth;
 
-    // The class of characters in a `[' or `^' format.
+    // The class of characters in a '[' or '^' format.
     std::string char_class;
 
     // Type of conversion
-    //  -- `d', `u', `f', `n', `s', `q', `c', `%', `C', `D', `[' or `^'.
+    //  -- 'd', 'u', 'f', 'n', 's', 'q', 'c', '%', 'C', 'D', '[' or '^'.
     char type;
 
     // TRUE if we are not storing the result of this conversion.
@@ -1774,7 +1775,8 @@
   {
   public:
 
-    textscan (const std::string& who_arg = "textscan");
+    textscan (const std::string& who_arg = "textscan",
+              const std::string& encoding = "utf-8");
 
     // No copying!
 
@@ -1796,6 +1798,8 @@
     // What function name should be shown when reporting errors.
     std::string who;
 
+    std::string m_encoding;
+
     std::string buf;
 
     // Three cases for delim_table and delim_list
@@ -2302,13 +2306,13 @@
             if (mask[ch]++ == 0)
               retval[out++] = ch;
             else if (ch != '-')
-              warning_with_id ("octave:textscan-pattern",
+              warning_with_id ("Octave:textscan-pattern",
                                "%s: [...] contains two '%c's",
                                who.c_str (), ch);
 
             if (prev == '-' && mask['-'] >= 2)
               warning_with_id
-                ("octave:textscan-pattern",
+                ("Octave:textscan-pattern",
                  "%s: [...] contains two '-'s outside range expressions",
                  who.c_str ());
           }
@@ -2421,8 +2425,8 @@
           std::cerr << elt->type << "\n";
 
         std::cerr
-          << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
-          << "text:       `" << undo_string_escapes (elt->text) << "'\n\n";
+          << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n"
+          << "text:       '" << undo_string_escapes (elt->text) << "'\n\n";
       }
   }
 
@@ -2505,13 +2509,13 @@
     return retval;             // May have returned 4 above.
   }
 
-  textscan::textscan (const std::string& who_arg)
-    : who (who_arg), buf (), whitespace_table (), delim_table (),
-      delims (), comment_style (), comment_len (0), comment_char (-2),
-      buffer_size (0), date_locale (), inf_nan (init_inf_nan ()),
-      empty_value (numeric_limits<double>::NaN ()), exp_chars ("edED"),
-      header_lines (0), treat_as_empty (), treat_as_empty_len (0),
-      whitespace (" \b\t"), eol1 ('\r'), eol2 ('\n'),
+  textscan::textscan (const std::string& who_arg, const std::string& encoding)
+    : who (who_arg), m_encoding (encoding), buf (), whitespace_table (),
+      delim_table (), delims (), comment_style (), comment_len (0),
+      comment_char (-2), buffer_size (0), date_locale (),
+      inf_nan (init_inf_nan ()), empty_value (numeric_limits<double>::NaN ()),
+      exp_chars ("edED"), header_lines (0), treat_as_empty (),
+      treat_as_empty_len (0), whitespace (" \b\t"), eol1 ('\r'), eol2 ('\n'),
       return_on_error (1), collect_output (false),
       multiple_delims_as_one (false), default_exp (true), lines (0)
   { }
@@ -3147,6 +3151,10 @@
         ends[i++] = eol2;
         val = textscan::read_until (is, delim_list, ends);
       }
+
+    // convert from codepage
+    if (m_encoding.compare ("utf-8"))
+      val = string::u8_from_encoding ("textscan", val, m_encoding);
   }
 
   // Return in VAL the run of characters from IS contained in PATTERN.
@@ -3194,6 +3202,10 @@
             is.get_undelim ();
           }
       }
+
+    // convert from codepage
+    if (m_encoding.compare ("utf-8"))
+      val = string::u8_from_encoding ("textscan", val, m_encoding);
   }
 
   // Read from IS into VAL a string of the next fmt.width characters,
@@ -3216,6 +3228,10 @@
             break;
           }
       }
+
+    // convert from codepage
+    if (m_encoding.compare ("utf-8"))
+      val = string::u8_from_encoding ("textscan", val, m_encoding);
   }
 
   //  Read a single '%...' conversion and place it in position ROW of OV.
@@ -3956,22 +3972,22 @@
   void
   base_stream::error (const std::string& msg)
   {
-    fail = true;
-    errmsg = msg;
+    m_fail = true;
+    m_errmsg = msg;
   }
 
   void
   base_stream::error (const std::string& who, const std::string& msg)
   {
-    fail = true;
-    errmsg = who + ": " + msg;
+    m_fail = true;
+    m_errmsg = who + ": " + msg;
   }
 
   void
   base_stream::clear (void)
   {
-    fail = false;
-    errmsg = "";
+    m_fail = false;
+    m_errmsg = "";
   }
 
   void
@@ -4253,14 +4269,40 @@
       {
         // Limit input to fmt.width characters by reading into a
         // temporary stringstream buffer.
-        std::string tmp;
+        std::string strbuf;
+
+        auto orig_pos = is.tellg ();
 
         is.width (fmt.width);
-        is >> tmp;
-
-        std::istringstream ss (tmp);
+        is >> strbuf;
+
+        std::istringstream ss (strbuf);
 
         octave_scan_1 (ss, fmt, valptr);
+
+        if (! ss.eof ())
+          {
+            // If fewer characters than width were used to read a number then
+            // the original istream object positioning is incorrect.
+            // Rather than attempt to update istream state and positioning,
+            // just redo the '>>' operation with the correct width so that
+            // all flags get set correctly.
+
+            is.clear ();  // Clear EOF, FAILBIT, BADBIT
+            is.seekg (orig_pos, is.beg);
+
+            int chars_read = ss.tellg ();
+            if (chars_read > 0)
+              {
+                is.width (chars_read);
+                is >> strbuf;
+              }
+          }
+
+        // If pattern failed to match then propagate fail bit to 'is' stream.
+        if (ss.fail ())
+          is.setstate (std::ios::failbit);
+
       }
     else
       octave_scan_1 (is, fmt, valptr);
@@ -4529,6 +4571,8 @@
 #define FINISH_CHARACTER_CONVERSION()                                   \
   do                                                                    \
     {                                                                   \
+      if (encoding ().compare ("utf-8"))                                \
+        tmp = string::u8_from_encoding (who, tmp, encoding ());         \
       width = tmp.length ();                                            \
                                                                         \
       if (is)                                                           \
@@ -4847,11 +4891,11 @@
                     break;
 
                   case 'p':
-                    error ("%s: unsupported format specifier", who.c_str ());
+                    error (who, "unsupported format specifier");
                     break;
 
                   default:
-                    error ("%s: internal format error", who.c_str ());
+                    error (who, "internal format error");
                     break;
                   }
 
@@ -4859,7 +4903,7 @@
                   {
                     break;
                   }
-                else if (! is)
+                else if (is.eof () || ! is)
                   {
                     if (all_char_conv)
                       {
@@ -4901,7 +4945,10 @@
                     // If it looks like we have a matching failure, then
                     // reset the failbit in the stream state.
                     if (is.rdstate () & std::ios::failbit)
-                      is.clear (is.rdstate () & (~std::ios::failbit));
+                      {
+                        error (who, "format failed to match");
+                        is.clear (is.rdstate () & (~std::ios::failbit));
+                      }
 
                     // FIXME: is this the right thing to do?
                     if (application::interactive ()
@@ -4920,7 +4967,7 @@
               }
             else
               {
-                error ("%s: internal format error", who.c_str ());
+                error (who, "internal format error");
                 break;
               }
 
@@ -4952,15 +4999,12 @@
           }
       }
 
-    if (ok ())
-      {
-        mval.resize (final_nr, final_nc, 0.0);
-
-        retval = mval;
-
-        if (all_char_conv)
-          retval = retval.convert_to_str (false, true);
-      }
+    mval.resize (final_nr, final_nc, 0.0);
+
+    retval = mval;
+
+    if (all_char_conv)
+      retval = retval.convert_to_str (false, true);
 
     return retval;
   }
@@ -5185,11 +5229,11 @@
             break;
 
           case 'p':
-            error ("%s: unsupported format specifier", who.c_str ());
+            error (who, "unsupported format specifier");
             break;
 
           default:
-            error ("%s: internal format error", who.c_str ());
+            error (who, "internal format error");
             break;
           }
       }
@@ -5306,7 +5350,7 @@
       invalid_operation (who, "reading");
     else
       {
-        textscan scanner (who);
+        textscan scanner (who, encoding ());
 
         retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
       }
@@ -5535,15 +5579,15 @@
     switch (nsa)
       {
       case 2:
-        retval = octave::format (os, fmt, sa_1, sa_2, arg);
+        retval = format (os, fmt, sa_1, sa_2, arg);
         break;
 
       case 1:
-        retval = octave::format (os, fmt, sa_1, arg);
+        retval = format (os, fmt, sa_1, arg);
         break;
 
       case 0:
-        retval = octave::format (os, fmt, arg);
+        retval = format (os, fmt, arg);
         break;
 
       default:
@@ -5557,7 +5601,7 @@
   static size_t
   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)
+                    const std::string& encoding, const std::string& who)
   {
     if (nsa > 2)
       ::error ("%s: internal error handling format", who.c_str ());
@@ -5568,12 +5612,19 @@
 
     size_t len = arg.length ();
 
+    size_t prec = (nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec));
+
+    std::string print_str = prec < arg.length () ? arg.substr (0, prec) : arg;
+    if (encoding.compare ("utf-8"))
+      {
+        size_t src_len = print_str.length ();
+        print_str = string::u8_to_encoding (who, print_str, encoding);
+        len -= src_len - print_str.length ();
+      }
+
     size_t fw = (nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw));
-    size_t prec = (nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec));
-
-    os << std::setw (fw)
-       << (left ? std::left : std::right)
-       << (prec < len ? arg.substr (0, prec) : arg);
+
+    os << std::setw (fw) << (left ? std::left : std::right) << print_str;
 
     return len > fw ? len : fw;
   }
@@ -5764,7 +5815,7 @@
           default:
             // Note: error is member fcn from base_stream, not ::error.
             // This error does not halt execution so "return ..." must exist.
-            error ("%s: invalid format specifier", who.c_str ());
+            error (who, "invalid format specifier");
             return -1;
             break;
           }
@@ -5846,7 +5897,8 @@
                         std::string sval = val.string_value ();
 
                         retval += do_printf_string (os, elt, nsa, sa_1,
-                                                    sa_2, sval, who);
+                                                    sa_2, sval, encoding (),
+                                                    who);
                       }
                     else
                       retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
@@ -5871,7 +5923,7 @@
 
             if (! os)
               {
-                error ("%s: write error", who.c_str ());
+                error (who, "write error");
                 break;
               }
 
@@ -5886,10 +5938,13 @@
   }
 
   int
-  base_stream::printf (const std::string& fmt,
+  base_stream::printf (std::string fmt,
                        const octave_value_list& args,
                        const std::string& who)
   {
+    if (encoding ().compare ("utf-8"))
+      fmt = string::u8_to_encoding (who, fmt, encoding ());
+
     printf_format_list fmt_list (fmt);
 
     if (fmt_list.num_conversions () == -1)
@@ -5914,7 +5969,7 @@
         os << s;
 
         if (! os)
-          error ("%s: write error", who.c_str ());
+          error (who, "write error");
         else
           {
             // FIXME: why does this seem to be necessary?
@@ -5928,7 +5983,7 @@
             if (os)
               retval = 0;
             else
-              error ("%s: write error", who.c_str ());
+              error (who, "write error");
           }
       }
 
@@ -5940,9 +5995,9 @@
   std::string
   base_stream::error (bool clear_err, int& err_num)
   {
-    err_num = (fail ? -1 : 0);
-
-    std::string tmp = errmsg;
+    err_num = (m_fail ? -1 : 0);
+
+    std::string tmp = m_errmsg;
 
     if (clear_err)
       clear ();
@@ -5958,37 +6013,37 @@
   }
 
   stream::stream (base_stream *bs)
-    : rep (bs)
-  {
-    if (rep)
-      rep->count = 1;
+    : m_rep (bs)
+  {
+    if (m_rep)
+      m_rep->m_count = 1;
   }
 
   stream::~stream (void)
   {
-    if (rep && --rep->count == 0)
-      delete rep;
+    if (m_rep && --m_rep->m_count == 0)
+      delete m_rep;
   }
 
   stream::stream (const stream& s)
-    : rep (s.rep)
-  {
-    if (rep)
-      rep->count++;
+    : m_rep (s.m_rep)
+  {
+    if (m_rep)
+      m_rep->m_count++;
   }
 
   stream&
   stream::operator = (const stream& s)
   {
-    if (rep != s.rep)
-      {
-        if (rep && --rep->count == 0)
-          delete rep;
-
-        rep = s.rep;
-
-        if (rep)
-          rep->count++;
+    if (m_rep != s.m_rep)
+      {
+        if (m_rep && --m_rep->m_count == 0)
+          delete m_rep;
+
+        m_rep = s.m_rep;
+
+        if (m_rep)
+          m_rep->m_count++;
       }
 
     return *this;
@@ -6000,7 +6055,7 @@
     int retval = -1;
 
     if (stream_ok ())
-      retval = rep->flush ();
+      retval = m_rep->flush ();
 
     return retval;
   }
@@ -6011,7 +6066,7 @@
     std::string retval;
 
     if (stream_ok ())
-      retval = rep->getl (max_len, err, who);
+      retval = m_rep->getl (max_len, err, who);
 
     return retval;
   }
@@ -6046,7 +6101,7 @@
     std::string retval;
 
     if (stream_ok ())
-      retval = rep->gets (max_len, err, who);
+      retval = m_rep->gets (max_len, err, who);
 
     return retval;
   }
@@ -6081,7 +6136,7 @@
     off_t retval = -1;
 
     if (stream_ok ())
-      retval = rep->skipl (count, err, who);
+      retval = m_rep->skipl (count, err, who);
 
     return retval;
   }
@@ -6126,31 +6181,31 @@
         clearerr ();
 
         // Find current position so we can return to it if needed.
-        off_t orig_pos = rep->tell ();
+        off_t orig_pos = m_rep->tell ();
 
         // Move to end of file.  If successful, find the offset of the end.
-        status = rep->seek (0, SEEK_END);
+        status = m_rep->seek (0, SEEK_END);
 
         if (status == 0)
           {
-            off_t eof_pos = rep->tell ();
+            off_t eof_pos = m_rep->tell ();
 
             if (origin == SEEK_CUR)
               {
                 // Move back to original position, otherwise we will be seeking
                 // from the end of file which is probably not the original
                 // location.
-                rep->seek (orig_pos, SEEK_SET);
+                m_rep->seek (orig_pos, SEEK_SET);
               }
 
             // Attempt to move to desired position; may be outside bounds of
             // existing file.
-            status = rep->seek (offset, origin);
+            status = m_rep->seek (offset, origin);
 
             if (status == 0)
               {
                 // Where are we after moving to desired position?
-                off_t desired_pos = rep->tell ();
+                off_t desired_pos = m_rep->tell ();
 
                 // I don't think save_pos can be less than zero,
                 // but we'll check anyway...
@@ -6158,7 +6213,7 @@
                   {
                     // Seek outside bounds of file.
                     // Failure should leave position unchanged.
-                    rep->seek (orig_pos, SEEK_SET);
+                    m_rep->seek (orig_pos, SEEK_SET);
 
                     status = -1;
                   }
@@ -6167,7 +6222,7 @@
               {
                 // Seeking to the desired position failed.
                 // Move back to original position and return failure status.
-                rep->seek (orig_pos, SEEK_SET);
+                m_rep->seek (orig_pos, SEEK_SET);
 
                 status = -1;
               }
@@ -6239,7 +6294,7 @@
     off_t retval = -1;
 
     if (stream_ok ())
-      retval = rep->tell ();
+      retval = m_rep->tell ();
 
     return retval;
   }
@@ -6256,7 +6311,7 @@
     bool retval = false;
 
     if (stream_ok ())
-      retval = rep->is_open ();
+      retval = m_rep->is_open ();
 
     return retval;
   }
@@ -6265,7 +6320,7 @@
   stream::close (void)
   {
     if (stream_ok ())
-      rep->close ();
+      m_rep->close ();
   }
 
   // FIXME: maybe these should be defined in lo-ieee.h?
@@ -7050,7 +7105,7 @@
     octave_value retval;
 
     if (stream_ok ())
-      retval = rep->scanf (fmt, size, count, who);
+      retval = m_rep->scanf (fmt, size, count, who);
 
     return retval;
   }
@@ -7085,7 +7140,7 @@
     octave_value_list retval;
 
     if (stream_ok ())
-      retval = rep->oscanf (fmt, who);
+      retval = m_rep->oscanf (fmt, who);
 
     return retval;
   }
@@ -7119,7 +7174,7 @@
                     const std::string& who, octave_idx_type& count)
   {
     return (stream_ok ()
-            ? rep->do_textscan (fmt, ntimes, options, who, count)
+            ? m_rep->do_textscan (fmt, ntimes, options, who, count)
             : octave_value ());
   }
 
@@ -7130,7 +7185,7 @@
     int retval = -1;
 
     if (stream_ok ())
-      retval = rep->printf (fmt, args, who);
+      retval = m_rep->printf (fmt, args, who);
 
     return retval;
   }
@@ -7165,7 +7220,7 @@
     int retval = -1;
 
     if (stream_ok ())
-      retval = rep->puts (s, who);
+      retval = m_rep->puts (s, who);
 
     return retval;
   }
@@ -7197,7 +7252,7 @@
     int retval = -1;
 
     if (stream_ok ())
-      retval = rep->eof ();
+      retval = m_rep->eof ();
 
     return retval;
   }
@@ -7208,7 +7263,7 @@
     std::string retval = "invalid stream object";
 
     if (stream_ok (false))
-      retval = rep->error (clear, err_num);
+      retval = m_rep->error (clear, err_num);
 
     return retval;
   }
@@ -7219,7 +7274,7 @@
     std::string retval;
 
     if (stream_ok ())
-      retval = rep->name ();
+      retval = m_rep->name ();
 
     return retval;
   }
@@ -7230,7 +7285,7 @@
     int retval = 0;
 
     if (stream_ok ())
-      retval = rep->mode ();
+      retval = m_rep->mode ();
 
     return retval;
   }
@@ -7241,7 +7296,7 @@
     mach_info::float_format retval = mach_info::flt_fmt_unknown;
 
     if (stream_ok ())
-      retval = rep->float_format ();
+      retval = m_rep->float_format ();
 
     return retval;
   }
@@ -7285,7 +7340,7 @@
   }
 
   stream_list::stream_list (interpreter& interp)
-    : list (), lookup_cache (list.end ()), m_stdin_file (-1),
+    : m_list (), m_lookup_cache (m_list.end ()), m_stdin_file (-1),
       m_stdout_file (-1), m_stderr_file (-1)
   {
     stream stdin_stream = octave_istream::create (&std::cin, "stdin");
@@ -7323,8 +7378,8 @@
 
     // Should we test for
     //
-    //  (list.find (stream_number) != list.end ()
-    //   && list[stream_number].is_open ())
+    //  (m_list.find (stream_number) != m_list.end ()
+    //   && m_list[stream_number].is_open ())
     //
     // and respond with "error ("internal error: ...")"?  It should not
     // happen except for some bug or if the user has opened a stream with
@@ -7334,10 +7389,10 @@
     // overwrite this entry, although the wrong entry might have done harm
     // before.
 
-    if (list.size () >= list.max_size ())
+    if (m_list.size () >= m_list.max_size ())
       ::error ("could not create file id");
 
-    list[stream_number] = os;
+    m_list[stream_number] = os;
 
     return stream_number;
   }
@@ -7359,17 +7414,17 @@
     if (fid < 0)
       err_invalid_file_id (fid, who);
 
-    if (lookup_cache != list.end () && lookup_cache->first == fid)
-      retval = lookup_cache->second;
+    if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid)
+      retval = m_lookup_cache->second;
     else
       {
-        ostrl_map::const_iterator iter = list.find (fid);
-
-        if (iter == list.end ())
+        ostrl_map::const_iterator iter = m_list.find (fid);
+
+        if (iter == m_list.end ())
           err_invalid_file_id (fid, who);
 
         retval = iter->second;
-        lookup_cache = iter;
+        m_lookup_cache = iter;
       }
 
     return retval;
@@ -7389,14 +7444,14 @@
     if (fid < 3)
       err_invalid_file_id (fid, who);
 
-    auto iter = list.find (fid);
-
-    if (iter == list.end ())
+    auto iter = m_list.find (fid);
+
+    if (iter == m_list.end ())
       err_invalid_file_id (fid, who);
 
     stream os = iter->second;
-    list.erase (iter);
-    lookup_cache = list.end ();
+    m_list.erase (iter);
+    m_lookup_cache = m_list.end ();
 
     // FIXME: is this check redundant?
     if (! os.is_valid ())
@@ -7432,11 +7487,11 @@
     if (flush)
       {
         // Flush stdout and stderr.
-        list[1].flush ();
-        list[2].flush ();
-      }
-
-    for (auto iter = list.begin (); iter != list.end (); )
+        m_list[1].flush ();
+        m_list[2].flush ();
+      }
+
+    for (auto iter = m_list.begin (); iter != m_list.end (); )
       {
         int fid = iter->first;
         if (fid < 3)  // Don't delete stdin, stdout, stderr
@@ -7458,35 +7513,35 @@
             continue;
           }
 
-        // Normal file handle.  Close and delete from list.
+        // Normal file handle.  Close and delete from m_list.
         if (os.is_valid ())
           os.close ();
 
-        list.erase (iter++);
-      }
-
-    lookup_cache = list.end ();
+        m_list.erase (iter++);
+      }
+
+    m_lookup_cache = m_list.end ();
   }
 
   string_vector stream_list::get_info (int fid) const
   {
-    string_vector retval (3);
+    string_vector retval (4);
 
     if (fid < 0)
       return retval;
 
     stream os;
-    if (lookup_cache != list.end () && lookup_cache->first == fid)
-      os = lookup_cache->second;
+    if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid)
+      os = m_lookup_cache->second;
     else
       {
-        ostrl_map::const_iterator iter = list.find (fid);
-
-        if (iter == list.end ())
+        ostrl_map::const_iterator iter = m_list.find (fid);
+
+        if (iter == m_list.end ())
           return retval;
 
         os = iter->second;
-        lookup_cache = iter;
+        m_lookup_cache = iter;
       }
 
     if (! os.is_valid ())
@@ -7495,6 +7550,7 @@
     retval(0) = os.name ();
     retval(1) = stream::mode_as_string (os.mode ());
     retval(2) = mach_info::float_format_as_string (os.float_format ());
+    retval(3) = os.encoding ();
 
     return retval;
   }
@@ -7522,7 +7578,7 @@
         << "  number  mode  arch       name\n"
         << "  ------  ----  ----       ----\n";
 
-    for (const auto& fid_strm : list)
+    for (const auto& fid_strm : m_list)
       {
         stream os = fid_strm.second;
 
@@ -7548,11 +7604,11 @@
 
   octave_value stream_list::open_file_numbers (void) const
   {
-    Matrix retval (1, list.size (), 0.0);
+    Matrix retval (1, m_list.size (), 0.0);
 
     int num_open = 0;
 
-    for (const auto& fid_strm : list)
+    for (const auto& fid_strm : m_list)
       {
         // Skip stdin, stdout, and stderr.
         if (fid_strm.first > 2 && fid_strm.second)
@@ -7572,7 +7628,7 @@
       {
         std::string nm = fid.string_value ();
 
-        for (const auto& fid_strm : list)
+        for (const auto& fid_strm : m_list)
           {
             // stdin, stdout, and stderr are unnamed.
             if (fid_strm.first > 2)
--- a/libinterp/corefcn/oct-stream.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-stream.h	Fri Jul 12 12:14:43 2019 -0400
@@ -67,9 +67,10 @@
   public:
 
     base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out,
-                 mach_info::float_format ff = mach_info::native_float_format ())
-      : count (0), md (arg_md), flt_fmt (ff), fail (false), open_state (true),
-        errmsg ()
+                 mach_info::float_format ff = mach_info::native_float_format (),
+                 const std::string& encoding = "utf-8")
+      : m_count (0), m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),
+        m_fail (false), m_open_state (true), m_errmsg ()
     { }
 
     // No copying!
@@ -113,7 +114,7 @@
 
     // Return TRUE if this stream is open.
 
-    bool is_open (void) const { return open_state; }
+    bool is_open (void) const { return m_open_state; }
 
     virtual void do_close (void) { }
 
@@ -121,7 +122,7 @@
     {
       if (is_open ())
         {
-          open_state = false;
+          m_open_state = false;
           do_close ();
         }
     }
@@ -140,7 +141,7 @@
         return -1;
     }
 
-    bool ok (void) const { return ! fail; }
+    bool ok (void) const { return ! m_fail; }
 
     // Return current error message for this stream.
 
@@ -148,9 +149,11 @@
 
   protected:
 
-    int mode (void) const { return md; }
+    int mode (void) const { return m_mode; }
 
-    mach_info::float_format float_format (void) const { return flt_fmt; }
+    mach_info::float_format float_format (void) const { return m_flt_fmt; }
+
+    std::string encoding (void) const { return m_encoding; }
 
     // Set current error state and set fail to TRUE.
 
@@ -168,23 +171,26 @@
   private:
 
     // A reference count.
-    refcount<octave_idx_type> count;
+    refcount<octave_idx_type> m_count;
 
     // The permission bits for the file.  Should be some combination of
     // std::ios::open_mode bits.
-    int md;
+    int m_mode;
 
     // Data format.
-    mach_info::float_format flt_fmt;
+    mach_info::float_format m_flt_fmt;
+
+    // Code page
+    std::string m_encoding;
 
     // TRUE if an error has occurred.
-    bool fail;
+    bool m_fail;
 
     // TRUE if this stream is open.
-    bool open_state;
+    bool m_open_state;
 
     // Should contain error message if fail is TRUE.
-    std::string errmsg;
+    std::string m_errmsg;
 
     // Functions that are defined for all input streams (input streams
     // are those that define is).
@@ -229,7 +235,7 @@
     int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
                    const std::string& who /* = "printf" */);
 
-    int printf (const std::string& fmt, const octave_value_list& args,
+    int printf (std::string fmt, const octave_value_list& args,
                 const std::string& who /* = "printf" */);
 
     int puts (const std::string& s, const std::string& who /* = "puts" */);
@@ -341,17 +347,17 @@
 
     void error (const std::string& msg)
     {
-      if (rep)
-        rep->error (msg);
+      if (m_rep)
+        m_rep->error (msg);
     }
 
     void error (const char *msg) { error (std::string (msg)); }
 
-    int file_number (void) { return rep ? rep->file_number () : -1; }
+    int file_number (void) { return m_rep ? m_rep->file_number () : -1; }
 
-    bool is_valid (void) const { return (rep != nullptr); }
+    bool is_valid (void) const { return (m_rep != nullptr); }
 
-    bool ok (void) const { return rep && rep->ok (); }
+    bool ok (void) const { return m_rep && m_rep->ok (); }
 
     operator bool () const { return ok (); }
 
@@ -363,31 +369,36 @@
 
     static std::string mode_as_string (int mode);
 
+    std::string encoding (void)
+    {
+      return m_rep ? m_rep->encoding () : std::string ();
+    }
+
     std::istream * input_stream (void)
     {
-      return rep ? rep->input_stream () : nullptr;
+      return m_rep ? m_rep->input_stream () : nullptr;
     }
 
     std::ostream * output_stream (void)
     {
-      return rep ? rep->output_stream () : nullptr;
+      return m_rep ? m_rep->output_stream () : nullptr;
     }
 
-    void clearerr (void) { if (rep) rep->clearerr (); }
+    void clearerr (void) { if (m_rep) m_rep->clearerr (); }
 
   private:
 
     // The actual representation of this stream.
-    base_stream *rep;
+    base_stream *m_rep;
 
     bool stream_ok (bool clear = true) const
     {
       bool retval = true;
 
-      if (rep)
+      if (m_rep)
         {
           if (clear)
-            rep->clear ();
+            m_rep->clear ();
         }
       else
         retval = false;
@@ -397,8 +408,8 @@
 
     void invalid_operation (const std::string& who, const char *rw)
     {
-      if (rep)
-        rep->invalid_operation (who, rw);
+      if (m_rep)
+        m_rep->invalid_operation (who, rw);
     }
 
     octave_value
@@ -451,9 +462,9 @@
 
     typedef std::map<int, stream> ostrl_map;
 
-    ostrl_map list;
+    ostrl_map m_list;
 
-    mutable ostrl_map::const_iterator lookup_cache;
+    mutable ostrl_map::const_iterator m_lookup_cache;
 
     int m_stdin_file;
     int m_stdout_file;
@@ -461,17 +472,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::base_stream' instead")
-typedef octave::base_stream octave_base_stream;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::stream' instead")
-typedef octave::stream octave_stream;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::stream_list' instead")
-typedef octave::stream_list octave_stream_list;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-strstrm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-strstrm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -50,21 +50,27 @@
 
 octave::stream
 octave_istrstream::create (const char *data, std::ios::openmode arg_md,
-                           octave::mach_info::float_format flt_fmt)
+                           octave::mach_info::float_format flt_fmt,
+                           const std::string& encoding)
 {
-  return octave::stream (new octave_istrstream (data, arg_md, flt_fmt));
+  return octave::stream (new octave_istrstream (data, arg_md, flt_fmt,
+                                                encoding));
 }
 
 octave::stream
 octave_istrstream::create (const std::string& data, std::ios::openmode arg_md,
-                           octave::mach_info::float_format flt_fmt)
+                           octave::mach_info::float_format flt_fmt,
+                           const std::string& encoding)
 {
-  return octave::stream (new octave_istrstream (data, arg_md, flt_fmt));
+  return octave::stream (new octave_istrstream (data, arg_md, flt_fmt,
+                                                encoding));
 }
 
 octave::stream
 octave_ostrstream::create (std::ios::openmode arg_md,
-                           octave::mach_info::float_format flt_fmt)
+                           octave::mach_info::float_format flt_fmt,
+                           const std::string& encoding)
 {
-  return octave::stream (new octave_ostrstream (arg_md, flt_fmt));
+  return octave::stream (new octave_ostrstream (arg_md, flt_fmt,
+                                                encoding));
 }
--- a/libinterp/corefcn/oct-strstrm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/oct-strstrm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -37,8 +37,9 @@
 
   octave_base_strstream (std::ios::openmode m = std::ios::out,
                          octave::mach_info::float_format ff
-                           = octave::mach_info::native_float_format ())
-    : octave::base_stream (m, ff) { }
+                           = octave::mach_info::native_float_format (),
+                         const std::string& encoding = "utf-8")
+    : octave::base_stream (m, ff, encoding) { }
 
   // No copying!
 
@@ -79,14 +80,16 @@
   octave_istrstream (const char *data,
                      std::ios::openmode arg_md = std::ios::out,
                      octave::mach_info::float_format ff
-                       = octave::mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), is (data) { }
+                       = octave::mach_info::native_float_format (),
+                     const std::string& encoding = "utf-8")
+    : octave_base_strstream (arg_md, ff, encoding), m_istream (data) { }
 
   octave_istrstream (const std::string& data,
                      std::ios::openmode arg_md = std::ios::out,
                      octave::mach_info::float_format ff
-                       = octave::mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), is (data) { }
+                       = octave::mach_info::native_float_format (),
+                     const std::string& encoding = "utf-8")
+    : octave_base_strstream (arg_md, ff, encoding), m_istream (data) { }
 
   // No copying!
 
@@ -104,32 +107,37 @@
   static octave::stream
   create (const char *data, std::ios::openmode arg_md = std::ios::out,
           octave::mach_info::float_format ff
-            = octave::mach_info::native_float_format ());
+            = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8");
 
   static octave::stream
   create (const std::string& data, std::ios::openmode arg_md = std::ios::out,
           octave::mach_info::float_format ff
-            = octave::mach_info::native_float_format ());
+            = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8");
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return is.eof (); }
+  bool eof (void) const { return m_istream.eof (); }
 
-  std::istream * input_stream (void) { return &is; }
+  std::istream * input_stream (void) { return &m_istream; }
 
   std::ostream * output_stream (void) { return nullptr; }
 
-  off_t tell (void) { return is.tellg (); }
-
-  std::streambuf * rdbuf (void) { return is ? is.rdbuf () : nullptr; }
+  off_t tell (void) { return m_istream.tellg (); }
 
-  bool bad (void) const { return is.bad (); }
+  std::streambuf * rdbuf (void)
+  {
+    return m_istream ? m_istream.rdbuf () : nullptr;
+  }
 
-  void clear (void) { is.clear (); }
+  bool bad (void) const { return m_istream.bad (); }
+
+  void clear (void) { m_istream.clear (); }
 
 private:
 
-  std::istringstream is;
+  std::istringstream m_istream;
 };
 
 class
@@ -139,8 +147,9 @@
 
   octave_ostrstream (std::ios::openmode arg_md = std::ios::out,
                      octave::mach_info::float_format ff
-                       = octave::mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), os () { }
+                       = octave::mach_info::native_float_format (),
+                     const std::string& encoding = "utf-8")
+    : octave_base_strstream (arg_md, ff, encoding), m_ostream () { }
 
   // No copying!
 
@@ -157,27 +166,31 @@
   static octave::stream
   create (std::ios::openmode arg_md = std::ios::out,
           octave::mach_info::float_format ff
-            = octave::mach_info::native_float_format ());
+            = octave::mach_info::native_float_format (),
+          const std::string& encoding = "utf-8");
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return os.eof (); }
+  bool eof (void) const { return m_ostream.eof (); }
 
   std::istream * input_stream (void) { return nullptr; }
 
-  std::ostream * output_stream (void) { return &os; }
+  std::ostream * output_stream (void) { return &m_ostream; }
 
-  std::string str (void) { return os.str (); }
+  std::string str (void) { return m_ostream.str (); }
 
-  std::streambuf * rdbuf (void) { return os ? os.rdbuf () : nullptr; }
+  std::streambuf * rdbuf (void)
+  {
+    return m_ostream ? m_ostream.rdbuf () : nullptr;
+  }
 
-  bool bad (void) const { return os.bad (); }
+  bool bad (void) const { return m_ostream.bad (); }
 
-  void clear (void) { os.clear (); }
+  void clear (void) { m_ostream.clear (); }
 
 private:
 
-  std::ostringstream os;
+  std::ostringstream m_ostream;
 };
 
 #endif
--- a/libinterp/corefcn/octave-link.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/octave-link.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -37,7 +37,6 @@
 #include "ovl.h"
 #include "pager.h"
 #include "syminfo.h"
-#include "symtab.h"
 
 static int
 octave_readline_hook (void)
@@ -69,15 +68,12 @@
 {
   if (enabled ())
     {
-      octave::symbol_table& symtab
-         = octave::__get_symbol_table__ ("octave_link::set_workspace");
+      octave::tree_evaluator& tw
+        = octave::__get_evaluator__ ("octave_link::set_workspace");
 
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_link::set_workspace");
-
-      instance->do_set_workspace (symtab.at_top_level (),
+      instance->do_set_workspace (tw.at_top_level (),
                                   instance->debugging,
-                                  cs.get_symbol_info (), true);
+                                  tw.get_symbol_info (), true);
     }
 }
 
@@ -251,7 +247,7 @@
 
 DEFUN (__octave_link_list_dialog__, args, ,
        doc: /* -*- texinfo -*-
-@deftypefn {} {} __octave_link_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{intial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})
+@deftypefn {} {} __octave_link_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{initial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})
 Undocumented internal function.
 @end deftypefn */)
 {
@@ -465,9 +461,7 @@
     warning ("openvar: GUI is not running, can't start Variable Editor");
   else
     {
-      octave::symbol_scope scope = interp.require_current_scope ("openvar");
-
-      octave_value val = scope.varval (name);
+      octave_value val = interp.varval (name);
 
       if (val.is_undefined ())
         error ("openvar: '%s' is not a variable", name.c_str ());
--- a/libinterp/corefcn/octave-link.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/octave-link.h	Fri Jul 12 12:14:43 2019 -0400
@@ -104,6 +104,14 @@
     return retval;
   }
 
+  template <typename F, typename... Args>
+  static void
+  post_event (F&& fcn, Args&&... args)
+  {
+    if (enabled ())
+      instance->do_post_event (fcn, std::forward<Args> (args)...);
+  }
+
   template <typename T, typename... Params, typename... Args>
   static void
   post_event (T *obj, void (T::*method) (Params...), Args&&... args)
@@ -465,6 +473,12 @@
   void do_process_events (void);
   void do_discard_events (void);
 
+  template <typename F, typename... Args>
+  void do_post_event (F&& fcn, Args&&... args)
+  {
+    gui_event_queue.add (fcn, std::forward<Args> (args)...);
+  }
+
   template <typename T, typename... Params, typename... Args>
   void do_post_event (T *obj, void (T::*method) (Params...), Args&&... args)
   {
--- a/libinterp/corefcn/pager.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/pager.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -58,7 +58,7 @@
 
     if (pid > 0)
       {
-        if (octave::sys::wifexited (status) || octave::sys::wifsignaled (status))
+        if (sys::wifexited (status) || sys::wifsignaled (status))
           {
             // Avoid warning() since that will put us back in the pager,
             // which would be bad news.
@@ -85,9 +85,9 @@
   {
     if (s)
       {
-        int available_rows = octave::command_editor::terminal_rows () - 2;
+        int available_rows = command_editor::terminal_rows () - 2;
 
-        int cols = octave::command_editor::terminal_cols ();
+        int cols = command_editor::terminal_cols ();
 
         int count = 0;
 
@@ -124,8 +124,7 @@
   int
   pager_buf::sync (void)
   {
-    octave::output_system& output_sys
-      = octave::__get_output_system__ ("pager_buf::sync");
+    output_system& output_sys = __get_output_system__ ("pager_buf::sync");
 
     char *buf = eback ();
 
@@ -426,13 +425,10 @@
       {
         m_external_pager = new oprocstream (pgr.c_str ());
 
-        if (m_external_pager)
-          {
-            octave::child_list& kids = m_interpreter.get_child_list ();
+        child_list& kids = m_interpreter.get_child_list ();
 
-            kids.insert (m_external_pager->pid (),
-                         pager_event_handler);
-          }
+        kids.insert (m_external_pager->pid (),
+                     pager_event_handler);
       }
   }
 
@@ -612,19 +608,44 @@
   return ovl ();
 }
 
-DEFUN (terminal_size, , ,
+DEFUN (terminal_size, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} terminal_size ()
-Return a two-element row vector containing the current size of the terminal
-window in characters (rows and columns).
+Query or set the size of the terminal window.  If called with no
+arguments, return a two-element row vector containing the current size
+of the terminal window in characters (rows and columns).  If called with
+a two-element vector of integer values, set the terminal size and return
+the previous setting.  Setting the size manually should not be needed
+when using readline for command-line editing.
 @seealso{list_in_columns}
 @end deftypefn */)
 {
+  int nargin = args.length ();
+
+  if (nargin > 1)
+    print_usage ();
+
   RowVector size (2, 0.0);
 
   size(0) = octave::command_editor::terminal_rows ();
   size(1) = octave::command_editor::terminal_cols ();
 
+  if (nargin == 1)
+    {
+      Matrix m = args(0).xmatrix_value ("argument must be a 2-element array");
+
+      if (m.numel () != 2)
+        error ("terminal_size: argument must be a 2-element array");
+
+      int rows = octave::math::x_nint (m(0));
+      int cols = octave::math::x_nint (m(1));
+
+      if (rows <= 0 || cols <= 0)
+        error ("terminal_size: rows and columns must be positive integers");
+
+      octave::command_editor::set_screen_size (rows, cols);
+    }
+
   return ovl (size);
 }
 
--- a/libinterp/corefcn/pager.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/pager.h	Fri Jul 12 12:14:43 2019 -0400
@@ -307,29 +307,6 @@
   extern std::ostream& __diary__ (void);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::diary_buf' instead")
-typedef octave::diary_buf octave_diary_buf;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::diary_stream' instead")
-typedef octave::diary_stream octave_diary_stream;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::pager_buf' instead")
-typedef octave::pager_buf octave_pager_buf;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::pager_stream' instead")
-typedef octave::pager_stream octave_pager_stream;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::flush_stdout' instead")
-static inline void
-flush_octave_stdout (void)
-{
-  return octave::flush_stdout ();
-}
-
-#endif
-
 #define octave_stdout (octave::__stdout__ ())
 
 #define octave_diary (octave::__diary__ ())
--- a/libinterp/corefcn/pr-flt-fmt.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/pr-flt-fmt.h	Fri Jul 12 12:14:43 2019 -0400
@@ -47,10 +47,10 @@
 public:
 
   float_format (int w = 0, int p = output_precision (), int f = 0)
-    : fw (w), ex (0), prec (p), fmt (f), up (0), sp (0) { }
+    : m_fw (w), m_ex (0), m_prec (p), m_fmt (f), m_up (0), m_sp (0) { }
 
   float_format (int w, int e, int p, int f)
-    : fw (w), ex (e), prec (p), fmt (f), up (0), sp (0) { }
+    : m_fw (w), m_ex (e), m_prec (p), m_fmt (f), m_up (0), m_sp (0) { }
 
   float_format (const float_format&) = default;
 
@@ -60,53 +60,114 @@
 
   float_format& scientific (void)
   {
-    fmt = std::ios::scientific;
+    m_fmt = std::ios::scientific;
     return *this;
   }
 
   float_format& fixed (void)
   {
-    fmt = std::ios::fixed;
+    m_fmt = std::ios::fixed;
     return *this;
   }
 
   float_format& general (void)
   {
-    fmt = 0;
+    m_fmt = 0;
     return *this;
   }
 
   float_format& uppercase (void)
   {
-    up = std::ios::uppercase;
+    m_up = std::ios::uppercase;
     return *this;
   }
 
   float_format& lowercase (void)
   {
-    up = 0;
+    m_up = 0;
     return *this;
   }
 
   float_format& precision (int p)
   {
-    prec = p;
+    m_prec = p;
     return *this;
   }
 
   float_format& width (int w)
   {
-    fw = w;
+    m_fw = w;
+    return *this;
+  }
+
+  float_format& exponent_width (int w)
+  {
+    m_ex = w;
     return *this;
   }
 
   float_format& trailing_zeros (bool tz = true)
 
   {
-    sp = (tz ? std::ios::showpoint : 0);
+    m_sp = (tz ? std::ios::showpoint : 0);
     return *this;
   }
 
+  std::ios::fmtflags format_flags (void) const
+  {
+    return static_cast<std::ios::fmtflags> (m_fmt | m_up | m_sp);
+  }
+
+  int format (void) const
+  {
+    return m_fmt;
+  }
+
+  bool is_scientific (void) const
+  {
+    return m_fmt == std::ios::scientific;
+  }
+
+  bool is_fixed (void) const
+  {
+    return m_fmt == std::ios::fixed;
+  }
+
+  bool is_general (void) const
+  {
+    return m_fmt == 0;
+  }
+
+  bool is_uppercase (void) const
+  {
+    return m_up == std::ios::uppercase;
+  }
+
+  bool is_lowercase (void) const
+  {
+    return m_up == 0;
+  }
+
+  int precision (void) const
+  {
+    return m_prec;
+  }
+
+  int width (void) const
+  {
+    return m_fw;
+  }
+
+  int exponent_width (void) const
+  {
+    return m_ex;
+  }
+
+  bool show_trailing_zeros (void) const
+  {
+    return m_sp == std::ios::showpoint;
+  }
+
   template <typename T>
   friend std::ostream&
   operator << (std::ostream& os, const pr_engineering_float<T>& pef);
@@ -119,23 +180,25 @@
   friend std::ostream&
   operator << (std::ostream& os, const pr_rational_float<T>& prf);
 
+private:
+
   // Field width.  Zero means as wide as necessary.
-  int fw;
+  int m_fw;
 
   // Exponent Field width.  Zero means as wide as necessary.
-  int ex;
+  int m_ex;
 
   // Precision.
-  int prec;
+  int m_prec;
 
   // Format.
-  int fmt;
+  int m_fmt;
 
   // E or e.
-  int up;
+  int m_up;
 
   // Show trailing zeros.
-  int sp;
+  int m_sp;
 };
 
 class
@@ -169,8 +232,8 @@
 
   void set_precision (int prec)
   {
-    m_real_fmt.prec = prec;
-    m_imag_fmt.prec = prec;
+    m_real_fmt.precision (prec);
+    m_imag_fmt.precision (prec);
   }
 
 private:
--- a/libinterp/corefcn/pr-output.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/pr-output.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -188,14 +188,13 @@
 
   float_format real_fmt = pef.m_ff;
 
-  if (real_fmt.fw >= 0)
-    os << std::setw (real_fmt.fw - real_fmt.ex);
-
-  if (real_fmt.prec >= 0)
-    os << std::setprecision (real_fmt.prec);
-
-  os.flags (static_cast<std::ios::fmtflags>
-            (real_fmt.fmt | real_fmt.up | real_fmt.sp));
+  if (real_fmt.width () >= 0)
+    os << std::setw (real_fmt.width () - real_fmt.exponent_width ());
+
+  if (real_fmt.precision () >= 0)
+    os << std::setprecision (real_fmt.precision ());
+
+  os.flags (real_fmt.format_flags ());
 
   os << pef.mantissa ();
 
@@ -208,7 +207,8 @@
   else
     os << std::setw (0) << "e+";
 
-  os << std::setw (real_fmt.ex - 2) << std::setfill ('0') << ex;
+  os << std::setw (real_fmt.exponent_width () - 2)
+     << std::setfill ('0') << ex;
 
   return os;
 }
@@ -221,14 +221,13 @@
 
   float_format real_fmt = pff.m_ff;
 
-  if (real_fmt.fw >= 0)
-    os << std::setw (real_fmt.fw);
-
-  if (real_fmt.prec >= 0)
-    os << std::setprecision (real_fmt.prec);
-
-  os.flags (static_cast<std::ios::fmtflags>
-            (real_fmt.fmt | real_fmt.up | real_fmt.sp));
+  if (real_fmt.width () >= 0)
+    os << std::setw (real_fmt.width ());
+
+  if (real_fmt.precision () >= 0)
+    os << std::setprecision (real_fmt.precision ());
+
+  os.flags (real_fmt.format_flags ());
 
   os << pff.m_val;
 
@@ -243,14 +242,13 @@
 
   float_format real_fmt = prf.m_ff;
 
-  int fw = (rat_string_len > 0 ? rat_string_len : real_fmt.fw);
+  int fw = (rat_string_len > 0 ? rat_string_len : real_fmt.width ());
   std::string s = rational_approx (prf.m_val, fw);
 
   if (fw >= 0)
     os << std::setw (fw);
 
-  os.flags (static_cast<std::ios::fmtflags>
-            (real_fmt.fmt | real_fmt.up | real_fmt.sp));
+  os.flags (real_fmt.format_flags ());
 
   if (fw > 0 && s.length () > static_cast<unsigned int> (fw))
     os << '*';
@@ -1300,7 +1298,7 @@
   //   {bit,hex}_format == 1: print big-endian
   //   {bit,hex}_format == 2: print native
 
-  int fw = fmt.fw;
+  int fw = fmt.width ();
 
   if (hex_format)
     {
@@ -1755,8 +1753,8 @@
 static inline int
 get_column_width (const float_display_format& fmt)
 {
-  int r_fw = fmt.real_format().fw;
-  int i_fw = fmt.imag_format().fw;
+  int r_fw = fmt.real_format().width ();
+  int i_fw = fmt.imag_format().width ();
 
   int retval = r_fw + i_fw + 2;
 
@@ -2807,7 +2805,7 @@
         {
           float_format r_fmt = fmt.real_format ();
 
-          pr_int (os, val, r_fmt.fw);
+          pr_int (os, val, r_fmt.width ());
         }
     }
 }
@@ -3169,17 +3167,23 @@
 }
 
 /*
-%!assert (rats (2.0005, 9), "4001/2000")
-%!assert (rats (-2.0005, 10), "-4001/2000")
-%!assert (strtrim (rats (2.0005, 30)), "4001/2000")
-%!assert (pi - str2num (rats (pi, 30)), 0, 4 * eps)
-%!assert (e - str2num (rats (e, 30)), 0, 4 * eps)
-%!assert (rats (123, 2), " *")
-
 %!test
-%! v = 1 / double (intmax);
-%! err = v - str2num (rats(v, 12));
-%! assert (err, 0, 4 * eps);
+%! [old_fmt, old_spacing] = format ();
+%! unwind_protect
+%!   format short;
+%!   assert (rats (2.0005, 9), "4001/2000");
+%!   assert (rats (-2.0005, 10), "-4001/2000");
+%!   assert (strtrim (rats (2.0005, 30)), "4001/2000");
+%!   assert (pi - str2num (rats (pi, 30)), 0, 4 * eps);
+%!   assert (e - str2num (rats (e, 30)), 0, 4 * eps);
+%!   assert (rats (123, 2), " *");
+%!   v = 1 / double (intmax);
+%!   err = v - str2num (rats (v, 12));
+%!   assert (err, 0, 4 * eps);
+%! unwind_protect_cleanup
+%!   format (old_fmt);
+%!   format (old_spacing);
+%! end_unwind_protect
 */
 
 DEFUN (disp, args, nargout,
--- a/libinterp/corefcn/procstream.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/procstream.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,7 @@
 {
   pb_init ();
 
-  if (! pb.open (command.c_str (), mode))
+  if (! m_pb.open (command.c_str (), mode))
     std::ios::setstate (std::ios::badbit);
 }
 
@@ -40,7 +40,7 @@
 {
   pb_init ();
 
-  if (! pb.open (command, mode))
+  if (! m_pb.open (command, mode))
     std::ios::setstate (std::ios::badbit);
 }
 
@@ -49,7 +49,7 @@
 {
   clear ();
 
-  if (! pb.open (command, mode))
+  if (! m_pb.open (command, mode))
     std::ios::setstate (std::ios::badbit);
 }
 
@@ -60,10 +60,10 @@
 
   if (is_open ())
     {
-      if (! pb.close ())
+      if (! m_pb.close ())
         std::ios::setstate (std::ios::failbit);
 
-      status = pb.wait_status ();
+      status = m_pb.wait_status ();
     }
 
   return status;
--- a/libinterp/corefcn/procstream.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/procstream.h	Fri Jul 12 12:14:43 2019 -0400
@@ -38,7 +38,7 @@
 {
 public:
 
-  procstreambase (void) : pb () { pb_init (); }
+  procstreambase (void) : m_pb () { pb_init (); }
 
   procstreambase (const std::string& name, int mode);
 
@@ -47,23 +47,30 @@
   ~procstreambase (void) { close (); }
 
   void open (const std::string& name, int mode)
-  { open (name.c_str (), mode); }
+  {
+    open (name.c_str (), mode);
+  }
 
   void open (const char *name, int mode);
 
-  int is_open (void) const { return pb.is_open (); }
+  int is_open (void) const { return m_pb.is_open (); }
 
   int close (void);
 
-  pid_t pid (void) const { return pb.pid (); }
+  pid_t pid (void) const { return m_pb.pid (); }
 
-  int file_number (void) const { return pb.file_number (); }
+  int file_number (void) const { return m_pb.file_number (); }
 
 private:
 
-  octave_procbuf pb;
+  octave_procbuf m_pb;
 
-  void pb_init (void) { init (&pb); }
+  void pb_init (void)
+  {
+    // Explicit initialization of the std::ios object is needed.
+    // FIXME: is there a better way to organize these classes?
+    init (&m_pb);
+  }
 
   procstreambase (const procstreambase&);
 
@@ -73,25 +80,30 @@
 class
 OCTINTERP_API
 iprocstream : public std::istream, public procstreambase
-// iprocstream : public procstreambase, public std::istream
 {
 public:
 
   iprocstream (void) : std::istream (nullptr), procstreambase () { }
 
   iprocstream (const std::string& name, int mode = std::ios::in)
-    : std::istream (nullptr), procstreambase (name, mode) { }
+    : std::istream (nullptr), procstreambase (name, mode)
+  { }
 
   iprocstream (const char *name, int mode = std::ios::in)
-    : std::istream (nullptr), procstreambase (name, mode) { }
+    : std::istream (nullptr), procstreambase (name, mode)
+  { }
 
   ~iprocstream (void) = default;
 
   void open (const std::string& name, int mode = std::ios::in)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
   void open (const char *name, int mode = std::ios::in)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
 private:
 
@@ -103,7 +115,6 @@
 class
 OCTINTERP_API
 oprocstream : public std::ostream, public procstreambase
-// oprocstream : public procstreambase, public std::ostream
 {
 public:
 
@@ -118,10 +129,14 @@
   ~oprocstream (void) = default;
 
   void open (const std::string& name, int mode = std::ios::out)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
   void open (const char *name, int mode = std::ios::out)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
 private:
 
@@ -133,25 +148,30 @@
 class
 OCTINTERP_API
 procstream : public std::iostream, public procstreambase
-// procstream : public procstreambase, public std::iostream
 {
 public:
 
   procstream (void) : std::iostream (nullptr), procstreambase () { }
 
   procstream (const std::string& name, int mode)
-    : std::iostream (nullptr), procstreambase (name, mode) { }
+    : std::iostream (nullptr), procstreambase (name, mode)
+  { }
 
   procstream (const char *name, int mode)
-    : std::iostream (nullptr), procstreambase (name, mode) { }
+    : std::iostream (nullptr), procstreambase (name, mode)
+  { }
 
   ~procstream (void) = default;
 
   void open (const std::string& name, int mode)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
   void open (const char *name, int mode)
-  { procstreambase::open (name, mode); }
+  {
+    procstreambase::open (name, mode);
+  }
 
 private:
 
--- a/libinterp/corefcn/quad.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/quad.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,10 +32,11 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "pager.h"
 #include "parse.h"
+#include "ov.h"
 #include "ovl.h"
-#include "ov-fcn.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -43,7 +44,7 @@
 #include "Quad-opts.cc"
 
 // Global pointer for user defined function required by quadrature functions.
-static octave_function *quad_fcn;
+static octave_value quad_fcn;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_imaginary = false;
@@ -59,7 +60,7 @@
   octave_value_list args;
   args(0) = x;
 
-  if (quad_fcn)
+  if (quad_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -95,7 +96,7 @@
   octave_value_list args;
   args(0) = x;
 
-  if (quad_fcn)
+  if (quad_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -184,24 +185,7 @@
   if (call_depth > 1)
     error ("quad: invalid recursive call");
 
-  std::string fcn_name;
-
-  if (args(0).is_function_handle () || args(0).is_inline_function ())
-    quad_fcn = args(0).function_value ();
-  else
-    {
-      fcn_name = unique_symbol_name ("__quad_fcn__");
-      std::string fname = "function y = ";
-      fname.append (fcn_name);
-      fname.append ("(x) y = ");
-      quad_fcn = extract_function (args(0), "quad", fcn_name, fname,
-                                   "; endfunction");
-      octave::symbol_table& symtab = interp.get_symbol_table ();
-      frame.add_method (symtab, &octave::symbol_table::clear_function, fcn_name);
-    }
-
-  if (! quad_fcn)
-    error ("quad: FCN argument is not a valid function name or handle");
+  quad_fcn = octave::get_function_handle (interp, args(0), "x");
 
   octave_value_list retval;
 
@@ -430,6 +414,33 @@
 %! assert (nfun > 0);
 
 %!test
+%!  [v, ier, nfun, err] = quad (@__f, 0.001, 3);
+%! assert (ier == 0 || ier == 1);
+%! assert (v, 1.98194120273598, sqrt (eps));
+%! assert (nfun > 0);
+
+%!test
+%!  fstr = "x .* sin (1 ./ x) .* sqrt (abs (1 - x))";
+%!  [v, ier, nfun, err] = quad (fstr, 0.001, 3);
+%! assert (ier == 0 || ier == 1);
+%! assert (v, 1.98194120273598, sqrt (eps));
+%! assert (nfun > 0);
+
+%!test
+%!  anon_fcn = @(x) x .* sin (1 ./ x) .* sqrt (abs (1 - x));
+%!  [v, ier, nfun, err] = quad (anon_fcn, 0.001, 3);
+%! assert (ier == 0 || ier == 1);
+%! assert (v, 1.98194120273598, sqrt (eps));
+%! assert (nfun > 0);
+
+%!test
+%!  inline_fcn = inline ("x .* sin (1 ./ x) .* sqrt (abs (1 - x))", "x");
+%!  [v, ier, nfun, err] = quad (inline_fcn, 0.001, 3);
+%! assert (ier == 0 || ier == 1);
+%! assert (v, 1.98194120273598, sqrt (eps));
+%! assert (nfun > 0);
+
+%!test
 %!  [v, ier, nfun, err] = quad ("__f", single (0.001), single (3));
 %! assert (ier == 0 || ier == 1);
 %! assert (v, 1.98194120273598, sqrt (eps ("single")));
--- a/libinterp/corefcn/quadcc.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/quadcc.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -33,6 +33,7 @@
 
 #include "defun.h"
 #include "error.h"
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "parse.h"
 #include "utils.h"
@@ -1483,8 +1484,8 @@
 
 // The actual integration routine.
 
-DEFUN (quadcc, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (quadcc, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b})
 @deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol})
 @deftypefnx {} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol}, @var{sing})
@@ -1575,7 +1576,7 @@
 
   // Arguments left and right.
   int nargin = args.length ();
-  octave_function *fcn;
+  octave_value fcn;
   double a, b, abstol, reltol, *sing;
   bool issingle;
 
@@ -1600,17 +1601,7 @@
   if (nargin < 3)
     print_usage ();
 
-  if (args(0).is_function_handle () || args(0).is_inline_function ())
-    fcn = args(0).function_value ();
-  else
-    {
-      std::string fcn_name = unique_symbol_name ("__quadcc_fcn__");
-      std::string fname = "function y = ";
-      fname.append (fcn_name);
-      fname.append ("(x) y = ");
-      fcn = extract_function (args(0), "quadcc", fcn_name, fname,
-                              "; endfunction");
-    }
+  fcn = octave::get_function_handle (interp, args(0), "x");
 
   if (! args(1).is_real_scalar ())
     error ("quadcc: lower limit of integration (A) must be a real scalar");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/stack-frame-walker.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,65 @@
+/*
+
+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_stack_frame_walker_h)
+#define octave_stack_frame_walker_h 1
+
+#include "octave-config.h"
+
+namespace octave
+{
+  class compiled_fcn_stack_frame;
+  class script_stack_frame;
+  class user_fcn_stack_frame;
+  class scope_stack_frame;
+
+  class stack_frame_walker
+  {
+  protected:
+
+    stack_frame_walker (void) { }
+
+    virtual ~stack_frame_walker (void) = default;
+
+  public:
+
+    // No copying!
+
+    stack_frame_walker (const stack_frame_walker&) = delete;
+
+    stack_frame_walker& operator = (const stack_frame_walker&) = delete;
+
+    virtual void
+    visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame&) = 0;
+
+    virtual void
+    visit_script_stack_frame (script_stack_frame&) = 0;
+
+    virtual void
+    visit_user_fcn_stack_frame (user_fcn_stack_frame&) = 0;
+
+    virtual void
+    visit_scope_stack_frame (scope_stack_frame&) = 0;
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/stack-frame.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,1546 @@
+/*
+
+Copyright (C) 1995-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 "lo-regexp.h"
+#include "str-vec.h"
+
+#include "defun.h"
+#include "interpreter.h"
+#include "interpreter-private.h"
+#include "oct-map.h"
+#include "ov.h"
+#include "ov-fcn.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "pager.h"
+#include "parse.h"
+#include "pt-eval.h"
+#include "stack-frame.h"
+#include "stack-frame-walker.h"
+#include "syminfo.h"
+#include "syminfo-accumulator.h"
+#include "symrec.h"
+#include "symscope.h"
+#include "variables.h"
+
+namespace octave
+{
+  // FIXME: There should probably be a display method for the script,
+  // fcn, and scope objects and the script and function objects should
+  // be responsible for displaying the scopes they contain.
+
+  static void display_scope (std::ostream& os, const symbol_scope& scope)
+  {
+    if (scope)
+      {
+        os << "scope: " << scope.name () << std::endl;
+
+        if (scope.num_symbols () > 0)
+          {
+            os << "name (frame offset, data offset, storage class):"
+               << std::endl;
+
+            std::list<symbol_record> symbols = scope.symbol_list ();
+
+            for (auto& sym : symbols)
+              {
+                os << "  " << sym.name () << " (" << sym.frame_offset ()
+                   << ", " << sym.data_offset () << ", " << sym.storage_class ()
+                   << ")" << std::endl;
+              }
+          }
+      }
+  }
+
+  class symbol_cleaner : public stack_frame_walker
+  {
+  public:
+
+    symbol_cleaner (const std::string& pattern, bool have_regexp = false)
+      : stack_frame_walker (), m_patterns (pattern),
+        m_clear_all_names (false), m_clear_objects (false),
+        m_have_regexp (have_regexp), m_cleared_names ()
+    { }
+
+    symbol_cleaner (const string_vector& patterns, bool have_regexp = false)
+      : stack_frame_walker (), m_patterns (patterns),
+        m_clear_all_names (false), m_clear_objects (false),
+        m_have_regexp (have_regexp), m_cleared_names ()
+    { }
+
+    symbol_cleaner (bool clear_all_names = true, bool clear_objects = false)
+      : stack_frame_walker (), m_patterns (),
+        m_clear_all_names (clear_all_names), m_clear_objects (clear_objects),
+        m_have_regexp (false), m_cleared_names ()
+    { }
+
+    symbol_cleaner (const symbol_cleaner&) = delete;
+
+    symbol_cleaner& operator = (const symbol_cleaner&) = delete;
+
+    ~symbol_cleaner (void) = default;
+
+    void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)
+    {
+      // This one follows static link always.  Hmm, should the access
+      // link for a compiled_fcn_stack_frame be the same as the static
+      // link?
+
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
+
+    void visit_script_stack_frame (script_stack_frame& frame)
+    {
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+    void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame)
+    {
+      clean_frame (frame);
+
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+    void visit_scope_stack_frame (scope_stack_frame& frame)
+    {
+      clean_frame (frame);
+
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+  private:
+
+    void maybe_clear_symbol (stack_frame& frame, const symbol_record& sym)
+    {
+      std::string name = sym.name ();
+
+      if (m_cleared_names.find (name) == m_cleared_names.end ())
+        {
+          // FIXME: Should we check that the name is defined and skip if
+          // it is not?  Is it possible for another symbol with the same
+          // name to appear in a later stack frame?
+
+          // FIXME: If we are clearing objects and a symbol is found,
+          // should we add it to the list of cleared names (since
+          // we did find a symbol) but skip clearing the object?
+
+          if (m_clear_objects && ! frame.is_object (sym))
+            return;
+
+          m_cleared_names.insert (name);
+
+          frame.clear (sym);
+        }
+    }
+
+    // FIXME: It would be nice to avoid the duplication in the following
+    // function.
+
+    void clear_symbols (stack_frame& frame,
+                        const std::list<symbol_record>& symbols)
+    {
+      if (m_clear_all_names)
+        {
+          for (const auto& sym : symbols)
+            maybe_clear_symbol (frame, sym);
+        }
+      else if (m_have_regexp)
+        {
+          octave_idx_type npatterns = m_patterns.numel ();
+
+          for (octave_idx_type j = 0; j < npatterns; j++)
+            {
+              std::string pattern = m_patterns[j];
+
+              regexp pat (pattern);
+
+              for (const auto& sym : symbols)
+                {
+                  if (pat.is_match (sym.name ()))
+                    maybe_clear_symbol (frame, sym);
+                }
+            }
+        }
+      else
+        {
+          octave_idx_type npatterns = m_patterns.numel ();
+
+          for (octave_idx_type j = 0; j < npatterns; j++)
+            {
+              std::string pattern = m_patterns[j];
+
+              glob_match pat (pattern);
+
+              for (const auto& sym : symbols)
+                {
+                  if (pat.match (sym.name ()))
+                    maybe_clear_symbol (frame, sym);
+                }
+            }
+        }
+    }
+
+    void clean_frame (stack_frame& frame)
+    {
+      symbol_scope scope = frame.get_scope ();
+
+      std::list<symbol_record> symbols = scope.symbol_list ();
+
+      if (m_clear_all_names || ! m_patterns.empty ())
+        clear_symbols (frame, symbols);
+    }
+
+    string_vector m_patterns;
+
+    bool m_clear_all_names;
+    bool m_clear_objects;
+    bool m_have_regexp;
+
+    std::set<std::string> m_cleared_names;
+  };
+
+  // This function is only implemented for user_fcn stack frames and
+  // only called for those objects using unwind_protect and the
+  // call_stack::clear_current_frame_values function.  Anything else
+  // indicates an error in the implementation.
+
+  void stack_frame::clear_values (void)
+  {
+    panic_impossible ();
+  }
+
+  // Return first occurrence of variables in current stack frame and any
+  // parent frames reachable through access links.
+
+  symbol_info_list stack_frame::all_variables (void)
+  {
+    symbol_info_accumulator sia (true, true);
+
+    accept (sia);
+
+    return sia.symbol_info ();
+  }
+
+  std::list<symbol_record>
+  stack_frame::glob (const std::string& pattern) const
+  {
+    std::list<symbol_record> retval;
+
+    symbol_scope scope = get_scope ();
+
+    const std::map<std::string, symbol_record>& symbols = scope.symbols ();
+
+    glob_match pat (pattern);
+
+    for (const auto& nm_sr : symbols)
+      {
+        if (pat.match (nm_sr.first))
+          {
+            symbol_record sr = nm_sr.second;
+
+            if (! is_variable (sr))
+              continue;
+
+            retval.push_back (sr);
+          }
+      }
+
+    return retval;
+  }
+
+  std::list<symbol_record>
+  stack_frame::regexp (const std::string& pattern) const
+  {
+    std::list<symbol_record> retval;
+
+    symbol_scope scope = get_scope ();
+
+    const std::map<std::string, symbol_record>& symbols = scope.symbols ();
+
+    octave::regexp pat (pattern);
+
+    for (const auto& nm_sr : symbols)
+      {
+        if (pat.is_match (nm_sr.first))
+          {
+            symbol_record sr = nm_sr.second;
+
+            if (! is_variable (sr))
+              continue;
+
+            retval.push_back (sr);
+          }
+      }
+
+    return retval;
+  }
+
+  std::list<std::string> stack_frame::variable_names (void) const
+  {
+    std::list<std::string> retval;
+
+    symbol_scope scope = get_scope ();
+
+    const std::map<std::string, symbol_record>& symbols = scope.symbols ();
+
+    for (const auto& nm_sr : symbols)
+      {
+        if (is_variable (nm_sr.second))
+          retval.push_back (nm_sr.first);
+      }
+
+    retval.sort ();
+
+    return retval;
+  }
+
+  size_t stack_frame::size (void) const
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  void stack_frame::resize (size_t)
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  stack_frame::scope_flags stack_frame::get_scope_flag (size_t) const
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  void stack_frame::set_scope_flag (size_t, scope_flags)
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  void stack_frame::install_variable (const symbol_record& sym,
+                                      const octave_value& value, bool global)
+  {
+    if (global && ! is_global (sym))
+      {
+        octave_value val = varval (sym);
+
+        if (val.is_defined ())
+          {
+            std::string nm = sym.name ();
+
+            warning_with_id ("Octave:global-local-conflict",
+                             "global: '%s' is defined in the current scope.\n",
+                             nm.c_str ());
+            warning_with_id ("Octave:global-local-conflict",
+                             "global: in a future version, global variables must be declared before use.\n");
+
+            // If the symbol is defined in the local but not the
+            // global scope, then use the local value as the
+            // initial value.  This value will also override any
+            // initializer in the global statement.
+            octave_value global_val = m_evaluator.global_varval (nm);
+
+            if (global_val.is_defined ())
+              {
+                warning_with_id ("Octave:global-local-conflict",
+                                 "global: global value overrides existing local value");
+
+                clear (sym);
+              }
+            else
+              {
+                warning_with_id ("Octave:global-local-conflict",
+                                 "global: existing local value used to initialize global variable");
+
+                m_evaluator.global_varref (nm) = val;
+              }
+          }
+
+        mark_global (sym);
+      }
+
+    if (value.is_defined ())
+      assign (sym, value);
+  }
+
+  octave_value stack_frame::varval (size_t) const
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  octave_value& stack_frame::varref (size_t)
+  {
+    // This function should only be called for user_fcn_stack_frame or
+    // scope_stack_frame objects.  Anything else indicates an error in
+    // the implementation.
+
+    panic_impossible ();
+  }
+
+  void stack_frame::clear_objects (void)
+  {
+    symbol_cleaner sc (true, true);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variable (const std::string& name)
+  {
+    symbol_cleaner sc (name);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variable_pattern (const std::string& pattern)
+  {
+    symbol_cleaner sc (pattern);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variable_pattern (const string_vector& patterns)
+  {
+    symbol_cleaner sc (patterns);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variable_regexp (const std::string& pattern)
+  {
+    symbol_cleaner sc (pattern, true);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variable_regexp (const string_vector& patterns)
+  {
+    symbol_cleaner sc (patterns, true);
+
+    accept (sc);
+  }
+
+  void stack_frame::clear_variables (void)
+  {
+    symbol_cleaner sc;
+
+    accept (sc);
+  }
+
+  void stack_frame::display_stopped_in_message (std::ostream& os) const
+  {
+    if (index () == 0)
+      os << "at top level" << std::endl;
+    else
+      {
+        os << "stopped in " << fcn_name ();
+
+        int l = line ();
+        if (l > 0)
+          os << " at line " << line ();
+
+        os << " [" << fcn_file_name () << "] " << std::endl;
+      }
+  }
+
+  void stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [stack_frame] (" << this << ") --" << std::endl;
+
+    os << "static link: ";
+    if (m_static_link)
+      os << m_static_link;
+    else
+      os << "NULL";
+    os << std::endl;
+
+    os << "access link: ";
+    if (m_access_link)
+      os << m_access_link;
+    else
+      os << "NULL";
+    os << std::endl;
+
+    os << "line: " << m_line << std::endl;
+    os << "column: " << m_column << std::endl;
+    os << "index: " << m_index << std::endl;
+
+    os << std::endl;
+
+    if (! follow)
+      return;
+
+    os << "FOLLOWING ACCESS LINKS:" << std::endl;
+    const stack_frame *frm = access_link ();
+    while (frm)
+      {
+        frm->display (false);
+        os << std::endl;
+
+        frm = frm->access_link ();
+      }
+  }
+
+  compiled_fcn_stack_frame *
+  compiled_fcn_stack_frame::dup (void) const
+  {
+    return new compiled_fcn_stack_frame (*this);
+  }
+
+  void compiled_fcn_stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [compiled_fcn_stack_frame] (" << this << ") --" << std::endl;
+    stack_frame::display (follow);
+
+    os << "fcn: " << m_fcn->name ()
+       << " (" << m_fcn->type_name () << ")" << std::endl;
+  }
+
+  void compiled_fcn_stack_frame::accept (stack_frame_walker& sfw)
+  {
+    sfw.visit_compiled_fcn_stack_frame (*this);
+  }
+
+  script_stack_frame::script_stack_frame (tree_evaluator& tw,
+                                          octave_user_script *script,
+                                          unwind_protect *up_frame,
+                                          size_t index,
+                                          stack_frame *static_link)
+    : stack_frame (tw, index, static_link, get_access_link (static_link)),
+      m_script (script), m_unwind_protect_frame (up_frame),
+      m_lexical_frame_offsets (get_num_symbols (script), 1),
+      m_value_offsets (get_num_symbols (script), 0)
+  {
+    set_script_offsets ();
+  }
+
+  script_stack_frame *
+  script_stack_frame::dup (void) const
+  {
+    return new script_stack_frame (*this);
+  }
+
+  size_t script_stack_frame::get_num_symbols (octave_user_script *script)
+  {
+    symbol_scope script_scope = script->scope ();
+
+    return script_scope.num_symbols ();
+  }
+
+  void script_stack_frame::set_script_offsets (void)
+  {
+    // Set frame and data offsets inside stack frame based on enclosing
+    // scope(s).
+
+    symbol_scope script_scope = m_script->scope ();
+
+    size_t num_script_symbols = script_scope.num_symbols ();
+
+    resize (num_script_symbols);
+
+    const std::map<std::string, symbol_record>& script_symbols
+      = script_scope.symbols ();
+
+    set_script_offsets_internal (script_symbols);
+  }
+
+  void script_stack_frame::set_script_offsets_internal
+   (const std::map<std::string, symbol_record>& script_symbols)
+  {
+    // This scope will be used to evaluate the script.  Find (or
+    // possibly insert) symbols from the dummy script scope here.
+
+    symbol_scope eval_scope = m_access_link->get_scope ();
+
+    if (eval_scope.is_nested ())
+      {
+        bool found = false;
+
+        for (const auto& nm_sr : script_symbols)
+          {
+            std::string name = nm_sr.first;
+            symbol_record script_sr = nm_sr.second;
+
+            symbol_scope parent_scope = eval_scope;
+
+            size_t count = 1;
+
+            while (parent_scope)
+              {
+                const std::map<std::string, symbol_record>& parent_scope_symbols
+                  = parent_scope.symbols ();
+
+                auto p = parent_scope_symbols.find (name);
+
+                if (p != parent_scope_symbols.end ())
+                  {
+                    found = true;
+                    symbol_record parent_scope_sr = p->second;
+
+                    size_t script_sr_data_offset = script_sr.data_offset ();
+
+                    m_lexical_frame_offsets.at (script_sr_data_offset)
+                      = parent_scope_sr.frame_offset () + 1;
+
+                    m_value_offsets.at (script_sr_data_offset)
+                      = parent_scope_sr.data_offset ();
+
+                    break;
+                  }
+                else
+                  {
+                    count++;
+                    parent_scope = parent_scope.parent_scope ();
+                  }
+              }
+
+            if (! found)
+              error ("symbol '%s' cannot be added to static scope",
+                     name.c_str ());
+          }
+      }
+    else
+      {
+        const std::map<std::string, symbol_record>& eval_scope_symbols
+          = eval_scope.symbols ();
+
+        for (const auto& nm_sr : script_symbols)
+          {
+            std::string name = nm_sr.first;
+            symbol_record script_sr = nm_sr.second;
+
+            auto p = eval_scope_symbols.find (name);
+
+            symbol_record eval_scope_sr;
+
+            if (p == eval_scope_symbols.end ())
+              eval_scope_sr = eval_scope.insert (name);
+            else
+              eval_scope_sr = p->second;
+
+            size_t script_sr_data_offset = script_sr.data_offset ();
+
+            // The +1 is for going from the script frame to the eval
+            // frame.  Only one access_link should need to be followed.
+
+            m_lexical_frame_offsets.at (script_sr_data_offset)
+              = eval_scope_sr.frame_offset () + 1;
+
+            m_value_offsets.at (script_sr_data_offset)
+              = eval_scope_sr.data_offset ();
+          }
+      }
+  }
+
+  void script_stack_frame::resize_and_update_script_offsets (const symbol_record& sym)
+  {
+    size_t data_offset = sym.data_offset ();
+
+    // This function is called when adding new symbols to a script
+    // scope.  If the symbol wasn't present before, it should be outside
+    // the range so we need to resize then update offsets.
+
+    assert (data_offset >= size ());
+
+    resize (data_offset+1);
+
+    // FIXME: We should be able to avoid creating the map object and the
+    // looping in the set_scripts_offsets_internal function.  Can we do
+    // that without (or with minimal) code duplication?
+
+    std::map<std::string, symbol_record> tmp_symbols;
+    tmp_symbols[sym.name ()] = sym;
+    set_script_offsets_internal (tmp_symbols);
+  }
+
+  // If this is a nested scope, set access_link to nearest parent
+  // stack frame that corresponds to the lexical parent of this scope.
+
+  stack_frame *
+  script_stack_frame::get_access_link (stack_frame *static_link)
+  {
+    stack_frame *alink = nullptr;
+
+    // If this script is called from another script, set access
+    // link to ultimate parent stack frame.
+
+    alink = static_link;
+
+    while (alink->is_user_script_frame ())
+      {
+        if (alink->access_link ())
+          alink = alink->access_link ();
+        else
+          break;
+      }
+
+    return alink;
+  }
+
+  symbol_record script_stack_frame::lookup_symbol (const std::string& name) const
+  {
+    symbol_scope scope = get_scope ();
+
+    symbol_record sym = scope.lookup_symbol (name);
+
+    if (sym)
+      {
+        assert (sym.frame_offset () == 0);
+
+        return sym;
+      }
+
+    sym = m_access_link->lookup_symbol (name);
+
+    // Return symbol record with adjusted frame offset.
+    symbol_record new_sym = sym.dup ();
+
+    new_sym.set_frame_offset (sym.frame_offset () + 1);
+
+    return new_sym;
+  }
+
+  symbol_record script_stack_frame::insert_symbol (const std::string& name)
+  {
+    // If the symbols is already in the immediate scope, there is
+    // nothing more to do.
+
+    symbol_scope scope = get_scope ();
+
+    symbol_record sym = scope.lookup_symbol (name);
+
+    if (sym)
+      {
+        // All symbol records in a script scope should have zero offset,
+        // which means we redirect our lookup using
+        // lexical_frame_offsets and values_offets.
+        assert (sym.frame_offset () == 0);
+
+        return sym;
+      }
+
+    // Insert the symbol in the current scope then resize and update
+    // offsets.  This operation should never fail.
+
+    sym = scope.find_symbol (name);
+
+    assert (sym);
+
+    resize_and_update_script_offsets (sym);
+
+    return sym;
+  }
+
+  // Similar to set_script_offsets_internal except that we only return
+  // frame and data offsets for symbols found by name in parent scopes
+  // instead of updating the offsets stored in the script frame itself.
+
+  bool
+  script_stack_frame::get_val_offsets_internal (const symbol_record& script_sr,
+                                                size_t& frame_offset,
+                                                size_t& data_offset) const
+  {
+    bool found = false;
+
+    // This scope will be used to evaluate the script.  Find symbols
+    // here by name.
+
+    symbol_scope eval_scope = m_access_link->get_scope ();
+
+    if (eval_scope.is_nested ())
+      {
+        std::string name = script_sr.name ();
+
+        symbol_scope parent_scope = eval_scope;
+
+        size_t count = 1;
+
+        while (parent_scope)
+          {
+            const std::map<std::string, symbol_record>& parent_scope_symbols
+              = parent_scope.symbols ();
+
+            auto p = parent_scope_symbols.find (name);
+
+            if (p != parent_scope_symbols.end ())
+              {
+                found = true;
+                symbol_record parent_scope_sr = p->second;
+
+                frame_offset = parent_scope_sr.frame_offset () + 1;
+
+                data_offset = parent_scope_sr.data_offset ();
+
+                break;
+              }
+            else
+              {
+                count++;
+                parent_scope = parent_scope.parent_scope ();
+              }
+          }
+      }
+    else
+      {
+        const std::map<std::string, symbol_record>& eval_scope_symbols
+          = eval_scope.symbols ();
+
+        std::string name = script_sr.name ();
+
+        auto p = eval_scope_symbols.find (name);
+
+        symbol_record eval_scope_sr;
+
+        if (p != eval_scope_symbols.end ())
+          {
+            found = true;
+            eval_scope_sr = p->second;
+
+            // The +1 is for going from the script frame to the eval
+            // frame.  Only one access_link should need to be followed.
+
+            frame_offset = eval_scope_sr.frame_offset () + 1;
+
+            data_offset = eval_scope_sr.data_offset ();
+          }
+      }
+
+    return found;
+  }
+
+  bool script_stack_frame::get_val_offsets (const symbol_record& sym,
+                                            size_t& frame_offset,
+                                            size_t& data_offset) const
+  {
+    data_offset = sym.data_offset ();
+    frame_offset = sym.frame_offset ();
+
+    if (frame_offset == 0)
+      {
+        // An out of range data_offset value here means that we have a
+        // symbol that was not originally in the script.  But this
+        // function is called in places where we can't insert a new
+        // symbol, so we fail and it is up to the caller to decide what
+        // to do.
+
+        if (data_offset >= size ())
+          return get_val_offsets_internal (sym, frame_offset, data_offset);
+
+        // Use frame and value offsets stored in this stack frame,
+        // indexed by data_offset from the symbol_record to find the
+        // values.  These offsets were determined by
+        // script_stack_frame::set_script_offsets when this script was
+        // invoked.
+
+        frame_offset = m_lexical_frame_offsets.at (data_offset);
+
+        if (frame_offset == 0)
+          {
+            // If the frame offset stored in m_lexical_frame_offsets is
+            // zero, then the data offset in the evaluation scope has
+            // not been determined so try to do that now.  The symbol
+            // may have been added by eval and without calling
+            // resize_and_update_script_offsets.
+
+            return get_val_offsets_internal (sym, frame_offset, data_offset);
+          }
+
+        data_offset = m_value_offsets.at (data_offset);
+      }
+    else
+      {
+        // If frame_offset is not zero, then then we must have a symbol
+        // that was not originally in the script.  The values should
+        // have been determined by the script_stack_frame::lookup function.
+      }
+
+    return true;
+  }
+
+  void script_stack_frame::get_val_offsets_with_insert (const symbol_record& sym,
+                                                        size_t& frame_offset,
+                                                        size_t& data_offset)
+  {
+    data_offset = sym.data_offset ();
+    frame_offset = sym.frame_offset ();
+
+    if (frame_offset == 0)
+      {
+        if (data_offset >= size ())
+          {
+            // If the data_offset is out of range, then we must have a
+            // symbol that was not originally in the script.  Resize and
+            // update the offsets.
+
+            resize_and_update_script_offsets (sym);
+          }
+
+        // Use frame and value offsets stored in this stack frame,
+        // indexed by data_offset from the symbol_record to find the
+        // values.  These offsets were determined by
+        // script_stack_frame::set_script_offsets when this script was
+        // invoked.
+
+        frame_offset = m_lexical_frame_offsets.at (data_offset);
+
+        if (frame_offset == 0)
+          {
+            // If the frame offset stored in m_lexical_frame_offsets is
+            // zero, then the data offset in the evaluation scope has
+            // not been determined so try to do that now.  The symbol
+            // may have been added by eval and without calling
+            // resize_and_update_script_offsets.
+
+            // We don't need to resize here.  That case is handled above.
+
+            // FIXME: We should be able to avoid creating the map object
+            // and the looping in the set_scripts_offsets_internal
+            // function.  Can we do that without (or with minimal) code
+            // duplication?
+
+            std::map<std::string, symbol_record> tmp_symbols;
+            tmp_symbols[sym.name ()] = sym;
+            set_script_offsets_internal (tmp_symbols);
+          }
+
+        data_offset = m_value_offsets.at (data_offset);
+      }
+    else
+      {
+        // If frame_offset is not zero, then then we must have a symbol
+        // that was not originally in the script.  The values were
+        // determined by the script_stack_frame::lookup function.
+      }
+  }
+
+  stack_frame::scope_flags
+  script_stack_frame::scope_flag (const symbol_record& sym) const
+  {
+    size_t frame_offset;
+    size_t data_offset;
+
+    bool found = get_val_offsets (sym, frame_offset, data_offset);
+
+    // It can't be global or persistent, so call it local.
+    if (! found)
+      return LOCAL;
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    const stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (! frame)
+      error ("internal error: invalid access link in function call stack");
+
+    if (data_offset >= frame->size ())
+      return LOCAL;
+
+    return frame->get_scope_flag (data_offset);
+  }
+
+  octave_value script_stack_frame::varval (const symbol_record& sym) const
+  {
+    size_t frame_offset;
+    size_t data_offset;
+
+    bool found = get_val_offsets (sym, frame_offset, data_offset);
+
+    if (! found)
+      return octave_value ();
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    const stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (! frame)
+      error ("internal error: invalid access link in function call stack");
+
+    if (data_offset >= frame->size ())
+      return octave_value ();
+
+    switch (frame->get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return frame->varval (data_offset);
+
+      case PERSISTENT:
+        {
+          symbol_scope scope = frame->get_scope ();
+
+          return scope.persistent_varval (data_offset);
+        }
+
+      case GLOBAL:
+        return m_evaluator.global_varval (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  octave_value& script_stack_frame::varref (const symbol_record& sym)
+  {
+    size_t frame_offset;
+    size_t data_offset;
+    get_val_offsets_with_insert (sym, frame_offset, data_offset);
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (data_offset >= frame->size ())
+      frame->resize (data_offset+1);
+
+    switch (frame->get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return frame->varref (data_offset);
+
+      case PERSISTENT:
+        {
+          symbol_scope scope = frame->get_scope ();
+
+          return scope.persistent_varref (data_offset);
+        }
+
+      case GLOBAL:
+        return m_evaluator.global_varref (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  void script_stack_frame::mark_scope (const symbol_record& sym,
+                                       scope_flags flag)
+  {
+    size_t data_offset = sym.data_offset ();
+
+    // Redirection to evaluation context for the script.
+
+    size_t frame_offset = m_lexical_frame_offsets.at (data_offset);
+    data_offset = m_value_offsets.at (data_offset);
+
+    if (frame_offset > 1)
+      error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used");
+
+    stack_frame *frame = access_link ();
+
+    if (data_offset >= frame->size ())
+      frame->resize (data_offset+1);
+
+    frame->set_scope_flag (data_offset, flag);
+  }
+
+  void script_stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [script_stack_frame] (" << this << ") --" << std::endl;
+    stack_frame::display (follow);
+
+    os << "script: " << m_script->name ()
+       << " (" << m_script->type_name () << ")" << std::endl;
+
+    os << "lexical_offsets: " << m_lexical_frame_offsets.size ()
+       << " elements:";
+
+    for (size_t i = 0; i < m_lexical_frame_offsets.size (); i++)
+      os << "  " << m_lexical_frame_offsets.at (i);
+    os << std::endl;
+
+    os << "value_offsets: " << m_value_offsets.size () << " elements:";
+    for (size_t i = 0; i < m_value_offsets.size (); i++)
+      os << "  " << m_value_offsets.at (i);
+    os << std::endl;
+
+    display_scope (os, get_scope ());
+  }
+
+  void script_stack_frame::accept (stack_frame_walker& sfw)
+  {
+    sfw.visit_script_stack_frame (*this);
+  }
+
+  void base_value_stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [base_value_stack_frame] (" << this << ") --" << std::endl;
+    stack_frame::display (follow);
+
+    os << "values: " << m_values.size ()
+       << " elements (idx, scope flag, type):" << std::endl;
+
+    for (size_t i = 0; i < m_values.size (); i++)
+      {
+        os << "  (" << i << ", " << m_flags.at (i) << ", ";
+
+        octave_value val = varval (i);
+
+        os << (val.is_defined () ? val.type_name () : " UNDEFINED") << ")"
+           << std::endl;
+      }
+  }
+
+  user_fcn_stack_frame *
+  user_fcn_stack_frame::dup (void) const
+  {
+    return new user_fcn_stack_frame (*this);
+  }
+
+  // If this is a nested scope, set access_link to nearest parent
+  // stack frame that corresponds to the lexical parent of this scope.
+
+  stack_frame *
+  user_fcn_stack_frame::get_access_link (octave_user_function *fcn,
+                                         stack_frame *static_link)
+  {
+    stack_frame *alink = nullptr;
+
+    symbol_scope fcn_scope = fcn->scope ();
+
+    if (fcn_scope.is_nested ())
+      {
+        if (! static_link)
+          error ("internal call stack error (invalid static link)");
+
+        symbol_scope caller_scope = static_link->get_scope ();
+
+        int nesting_depth = fcn_scope.nesting_depth ();
+        int caller_nesting_depth = caller_scope.nesting_depth ();
+
+        if (caller_nesting_depth < nesting_depth)
+          {
+            // FIXME: do we need to ensure that the called
+            // function is a child of the caller?  Does it hurt
+            // to assert this condition, at least for now?
+
+            alink = static_link;
+          }
+        else
+          {
+            // FIXME: do we need to check that the parent of the
+            // called function is also a parent of the caller?
+            // Does it hurt to assert this condition, at least
+            // for now?
+
+            int links_to_follow = caller_nesting_depth - nesting_depth + 1;
+
+            alink = static_link;
+
+            while (alink && --links_to_follow >= 0)
+              alink = alink->access_link ();
+
+            if (! alink)
+              error ("internal function nesting error (invalid access link)");
+          }
+      }
+
+    return alink;
+  }
+
+  void user_fcn_stack_frame::clear_values (void)
+  {
+    symbol_scope fcn_scope = m_fcn->scope ();
+
+    const std::list<symbol_record>& symbols = fcn_scope.symbol_list ();
+
+    if (size () == 0)
+      return;
+
+    for (const auto& sym : symbols)
+      {
+        size_t frame_offset = sym.frame_offset ();
+
+        if (frame_offset > 0)
+          continue;
+
+        size_t data_offset = sym.data_offset ();
+
+        if (data_offset >= size ())
+          continue;
+
+        if (get_scope_flag (data_offset) == LOCAL)
+          {
+            octave_value& ref = m_values.at (data_offset);
+
+            if (ref.get_count () == 1)
+              {
+                ref.call_object_destructor ();
+                ref = octave_value ();
+              }
+          }
+      }
+  }
+
+  symbol_record user_fcn_stack_frame::lookup_symbol (const std::string& name) const
+  {
+    const stack_frame *frame = this;
+
+    while (frame)
+      {
+        symbol_scope scope = frame->get_scope ();
+
+        symbol_record sym = scope.lookup_symbol (name);
+
+        if (sym)
+          return sym;
+
+        frame = frame->access_link ();
+      }
+
+    return symbol_record ();
+  }
+
+  symbol_record user_fcn_stack_frame::insert_symbol (const std::string& name)
+  {
+    // If the symbols is already in the immediate scope, there is
+    // nothing more to do.
+
+    symbol_scope scope = get_scope ();
+
+    symbol_record sym = scope.lookup_symbol (name);
+
+    if (sym)
+      return sym;
+
+    // FIXME: This needs some thought... We may need to add a symbol to
+    // a static workspace, but the symbol can never be defined as a
+    // variable.  This currently works by tagging the added symbol as
+    // "added_static".  Aside from the bad name, this doesn't seem like
+    // the best solution.  Maybe scopes should have a separate set of
+    // symbols that may only be defined as functions?
+
+    // Insert the symbol in the current scope.  This is not possible for
+    // anonymous functions, nested functions, or functions that contain
+    // nested functions (their scopes will all be marked static).
+
+    //    if (scope.is_static ())
+    //      error ("can not add variable '%s' to a static workspace",
+    //             name.c_str ());
+
+    // At this point, non-local references are not possible so we only
+    // need to look in the current scope and insert there.  This
+    // operation should never fail.
+
+    sym = scope.find_symbol (name);
+
+    assert (sym);
+
+    return sym;
+  }
+
+  stack_frame::scope_flags
+  user_fcn_stack_frame::scope_flag (const symbol_record& sym) const
+  {
+    size_t frame_offset = sym.frame_offset ();
+    size_t data_offset = sym.data_offset ();
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    const stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (! frame)
+      error ("internal error: invalid access link in function call stack");
+
+    if (data_offset >= frame->size ())
+      return LOCAL;
+
+    return frame->get_scope_flag (data_offset);
+  }
+
+  octave_value user_fcn_stack_frame::varval (const symbol_record& sym) const
+  {
+    size_t frame_offset = sym.frame_offset ();
+    size_t data_offset = sym.data_offset ();
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    const stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (! frame)
+      error ("internal error: invalid access link in function call stack");
+
+    if (data_offset >= frame->size ())
+      return octave_value ();
+
+    switch (frame->get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return frame->varval (data_offset);
+
+      case PERSISTENT:
+        {
+          symbol_scope scope = frame->get_scope ();
+
+          return scope.persistent_varval (data_offset);
+        }
+
+      case GLOBAL:
+        return m_evaluator.global_varval (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  octave_value& user_fcn_stack_frame::varref (const symbol_record& sym)
+  {
+    size_t frame_offset = sym.frame_offset ();
+    size_t data_offset = sym.data_offset ();
+
+    // Follow frame_offset access links to stack frame that holds
+    // the value.
+
+    stack_frame *frame = this;
+
+    for (size_t i = 0; i < frame_offset; i++)
+      frame = frame->access_link ();
+
+    if (data_offset >= frame->size ())
+      frame->resize (data_offset+1);
+
+    switch (frame->get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return frame->varref (data_offset);
+
+      case PERSISTENT:
+        {
+          symbol_scope scope = frame->get_scope ();
+
+          return scope.persistent_varref (data_offset);
+        }
+
+      case GLOBAL:
+        return m_evaluator.global_varref (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  void user_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag)
+  {
+    size_t frame_offset = sym.frame_offset ();
+
+    if (frame_offset > 0 && (flag == PERSISTENT || flag == GLOBAL))
+      error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used");
+
+    size_t data_offset = sym.data_offset ();
+
+    if (data_offset >= size ())
+      resize (data_offset+1);
+
+    set_scope_flag (data_offset, flag);
+  }
+
+  void user_fcn_stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [user_fcn_stack_frame] (" << this << ") --" << std::endl;
+    base_value_stack_frame::display (follow);
+
+    os << "fcn: " << m_fcn->name ()
+       << " (" << m_fcn->type_name () << ")" << std::endl;
+
+    display_scope (os, get_scope ());
+ }
+
+  void user_fcn_stack_frame::accept (stack_frame_walker& sfw)
+  {
+    sfw.visit_user_fcn_stack_frame (*this);
+  }
+
+  scope_stack_frame *
+  scope_stack_frame::dup (void) const
+  {
+    return new scope_stack_frame (*this);
+  }
+
+  symbol_record scope_stack_frame::insert_symbol (const std::string& name)
+  {
+    // There is no access link for scope frames, so there is no other
+    // frame to search in and the offset must be zero.
+
+    symbol_record sym = m_scope.lookup_symbol (name);
+
+    if (sym)
+      return sym;
+
+    // If the symbol is not found, insert it.  We only need to search in
+    // the local scope object.  This operation should never fail.
+
+    sym = m_scope.find_symbol (name);
+
+    assert (sym);
+
+    return sym;
+  }
+
+  stack_frame::scope_flags
+  scope_stack_frame::scope_flag (const symbol_record& sym) const
+  {
+    // There is no access link for scope frames, so the frame
+    // offset must be zero.
+
+    size_t data_offset = sym.data_offset ();
+
+    if (data_offset >= size ())
+      return LOCAL;
+
+    return get_scope_flag (data_offset);
+  }
+
+  octave_value scope_stack_frame::varval (const symbol_record& sym) const
+  {
+    // There is no access link for scope frames, so the frame
+    // offset must be zero.
+
+    size_t data_offset = sym.data_offset ();
+
+    if (data_offset >= size ())
+      return octave_value ();
+
+    switch (get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return m_values.at (data_offset);
+
+      case PERSISTENT:
+        return m_scope.persistent_varval (data_offset);
+
+      case GLOBAL:
+        return m_evaluator.global_varval (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  octave_value& scope_stack_frame::varref (const symbol_record& sym)
+  {
+    // There is no access link for scope frames, so the frame
+    // offset must be zero.
+
+    size_t data_offset = sym.data_offset ();
+
+    if (data_offset >= size ())
+      resize (data_offset+1);
+
+    switch (get_scope_flag (data_offset))
+      {
+      case LOCAL:
+        return m_values.at (data_offset);
+
+      case PERSISTENT:
+        return m_scope.persistent_varref (data_offset);
+
+      case GLOBAL:
+        return m_evaluator.global_varref (sym.name ());
+      }
+
+    error ("internal error: invalid switch case");
+  }
+
+  void scope_stack_frame::mark_scope (const symbol_record& sym,
+                                      scope_flags flag)
+  {
+    // There is no access link for scope frames, so the frame
+    // offset must be zero.
+
+    size_t data_offset = sym.data_offset ();
+
+    if (data_offset >= size ())
+      resize (data_offset+1);
+
+    set_scope_flag (data_offset, flag);
+  }
+
+  void scope_stack_frame::display (bool follow) const
+  {
+    std::ostream& os = octave_stdout;
+
+    os << "-- [scope_stack_frame] (" << this << ") --" << std::endl;
+    base_value_stack_frame::display (follow);
+
+    display_scope (os, m_scope);
+  }
+
+  void scope_stack_frame::accept (stack_frame_walker& sfw)
+  {
+    sfw.visit_scope_stack_frame (*this);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/stack-frame.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,1063 @@
+/*
+
+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/>.
+
+*/
+
+#if ! defined (octave_stack_frame_h)
+#define octave_stack_frame_h 1
+
+#include "octave-config.h"
+
+#include <deque>
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+class octave_value;
+class octave_value_list;
+
+#include "error.h"
+#include "ov-fcn.h"
+#include "ov-fcn.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "syminfo.h"
+#include "symscope.h"
+
+// Variable values are stored in the stack_frame objects that make up
+// the call_stack.  There are four separate stack_frame objects
+// corresponding to the following language elements:
+//
+//  * user-defined functions
+//
+//    These are .m files.  They have local variables.
+//
+//  * scripts
+//
+//    These are .m files, but not functions.  They access variables,
+//    but do not store any values directly.  All values are stored in
+//    the stack frame corresponding to the scope in which they are
+//    executed.
+//
+//  * scopes that do not correspond to functions
+//
+//    This is primarily used by the top-level scope but the
+//    interpreter may also create temporary scopes in which to
+//    evaluate functions or scripts.
+//
+// * compiled functions
+//
+//   These are built-in functions and dynamically-loaded compiled
+//   functions (.mex and .oct files) and do not contain variable
+//   values of their own.  They are skipped when Octave displays a
+//   stack trace.
+//
+// All stack frames also contain the following data:
+//
+//  * a reference to the evaluator that contains the frame
+//
+//    Global variables are now stored in the evaluator and this link
+//    gives us immediate access to them.
+//
+//  * line and column in the source file where the stack frame was created
+//
+//    These values are used to print stack traces.
+//
+//  * A pointer to the nearest parent frame that contains variable
+//    info (the "static" link)
+//
+//    A frame that contains variable info may be a user-defined
+//    function, script, or scope frame.  This pointer should never
+//    point to a compiled function stack frame.
+//
+//  * A pointer to the nearest lexical parent frame (the "access" link)
+//
+//    Used to access non-local variables for nested and anonymous
+//    functions or as a link to the parent frame in which a script is
+//    executed.  This pointer should only point to a parent function
+//    stack frame.
+
+namespace octave
+{
+  class tree_evaluator;
+  class symbol_info_list;
+  class unwind_protect;
+
+  class compiled_fcn_stack_frame;
+  class script_stack_frame;
+  class user_fcn_stack_frame;
+  class scope_stack_frame;
+
+  class stack_frame_walker;
+
+  class stack_frame
+  {
+  public:
+
+    // Markers indicating the type of a variable.  Values for local
+    // variables are stored in the stack frame.  Values for
+    // global variables are stored in the tree_evaluator object that
+    // contains the stack frame.  Values for persistent variables are
+    // stored in the function scope corresponding to the stack frame.
+
+    enum scope_flags
+      {
+        LOCAL,
+        GLOBAL,
+        PERSISTENT
+      };
+
+    // Index into the list of automatic variables for user-defined
+    // function stack frames.
+
+    enum auto_var_type
+      {
+        ARG_NAMES,
+        IGNORED,
+        NARGIN,
+        NARGOUT,
+        SAVED_WARNING_STATES,
+        NUM_AUTO_VARS
+      };
+
+    stack_frame (void) = delete;
+
+    stack_frame (tree_evaluator& tw, size_t index,
+                 stack_frame *static_link, stack_frame *access_link)
+      : m_evaluator (tw), m_line (-1), m_column (-1), m_index (index),
+        m_static_link (static_link), m_access_link (access_link),
+        m_dispatch_class ()
+    { }
+
+    stack_frame (const stack_frame& elt) = default;
+
+    stack_frame& operator = (const stack_frame& elt) = delete;
+
+    virtual ~stack_frame (void) = default;
+
+    virtual stack_frame * dup (void) const = 0;
+
+    // FIXME: It would be nice to eliminate these but there are a few
+    // places where we still need to know the specific type of the
+    // stack frame that we are handling.
+
+    virtual bool is_compiled_fcn_frame (void) const { return false; }
+    virtual bool is_user_script_frame (void) const { return false; }
+    virtual bool is_user_fcn_frame (void) const { return false; }
+    virtual bool is_scope_frame (void) const { return false; }
+
+    virtual void clear_values (void);
+
+    size_t index (void) const { return m_index; }
+
+    void line (int l) { m_line = l; }
+    int line (void) const { return m_line; }
+
+    void column (int c) { m_column = c; }
+    int column (void) const { return m_column; }
+
+    std::string fcn_file_name (void) const
+    {
+      octave_function *fcn = function ();
+
+      return fcn ? fcn->fcn_file_name () : "";
+    }
+
+    std::string fcn_name (bool print_subfn = true) const
+    {
+      std::string retval;
+
+      octave_function *fcn = function ();
+
+      if (fcn)
+        {
+          std::string parent_fcn_name = fcn->parent_fcn_name ();
+
+          if (print_subfn && ! parent_fcn_name.empty ())
+            retval = parent_fcn_name + '>';
+
+          if (fcn->is_anonymous_function ())
+            retval += octave_fcn_handle::anonymous;
+          else
+            retval += fcn->name ();
+        }
+      else
+        retval = "<unknown>";
+
+      return retval;
+    }
+
+    virtual symbol_scope get_scope (void) const = 0;
+
+    virtual octave_function * function (void) const { return nullptr; }
+
+    virtual unwind_protect *
+    unwind_protect_frame (void) const { return nullptr; }
+
+    // FIXME: Should this function be private?
+
+    symbol_info_list
+    make_symbol_info_list (const std::list<symbol_record>& symrec_list) const
+    {
+      symbol_info_list symbol_stats;
+
+      for (const auto& sym : symrec_list)
+        {
+          octave_value value = varval (sym);
+
+          if (value.is_defined ())
+            {
+              symbol_info syminf (sym.name (), value, sym.is_formal (),
+                                  is_global (sym), is_persistent (sym));
+
+              symbol_stats.append (syminf);
+            }
+        }
+
+      return symbol_stats;
+    }
+
+    symbol_info_list all_variables (void);
+
+    // FIXME: Should these exist?  Probably we should avoid returning
+    // lists of symbol_record objects, so maybe they should be
+    // private functions?
+
+    std::list<symbol_record> glob (const std::string& pattern) const;
+
+    std::list<symbol_record> regexp (const std::string& pattern) const;
+
+    std::list<std::string> variable_names (void) const;
+
+    // Look for named symbol visible from current scope.  Don't
+    // attempt to insert if missing.
+    virtual symbol_record lookup_symbol (const std::string&) const = 0;
+
+    // Look for named symbol visible from current scope.  Attempt to
+    // insert if missing.
+    virtual symbol_record insert_symbol (const std::string&) = 0;
+
+    // FIXME: should these functions should return all symbols visible in
+    // the current stack frame including those that come from a parent
+    // scope/frame?
+
+    symbol_info_list glob_symbol_info (const std::string& pattern) const
+    {
+      return make_symbol_info_list (glob (pattern));
+    }
+
+    symbol_info_list regexp_symbol_info (const std::string& pattern) const
+    {
+      return make_symbol_info_list (regexp (pattern));
+    }
+
+    symbol_info_list get_symbol_info (void)
+    {
+      return all_variables ();
+    }
+
+    void make_persistent (const symbol_record& sym)
+    {
+      if (sym.is_formal ())
+        {
+          std::string nm = sym.name ();
+          error ("can't make function parameter %s persistent", nm.c_str ());
+        }
+
+      if (is_global (sym))
+        {
+          std::string nm = sym.name ();
+          error ("can't make global variable '%s' persistent", nm.c_str ());
+        }
+
+      install_variable (sym, octave_value (), false);
+
+      mark_persistent (sym);
+    }
+
+    void make_global (const symbol_record& sym)
+    {
+      if (is_persistent (sym))
+        {
+          std::string nm = sym.name ();
+          error ("can't make persistent variable '%s' global", nm.c_str ());
+        }
+
+      install_variable (sym, octave_value (), true);
+
+      mark_global (sym);
+    }
+
+    stack_frame * static_link (void) const {return m_static_link; }
+
+    stack_frame * access_link (void) const {return m_access_link; }
+
+    void set_closure_links (stack_frame *dup_frame)
+    {
+      m_static_link = dup_frame;
+      m_access_link = dup_frame;
+    }
+
+    virtual size_t size (void) const;
+
+    virtual void resize (size_t);
+
+    void mark_global (const symbol_record& sym)
+    {
+      mark_scope (sym, GLOBAL);
+    }
+
+    void unmark_global (const symbol_record& sym)
+    {
+      mark_scope (sym, LOCAL);
+    }
+
+    void mark_persistent (const symbol_record& sym)
+    {
+      mark_scope (sym, PERSISTENT);
+    }
+
+    void unmark_persistent (const symbol_record& sym)
+    {
+      mark_scope (sym, LOCAL);
+    }
+
+    bool is_defined (const symbol_record& sym) const
+    {
+      octave_value val = varval (sym);
+
+      return val.is_defined ();
+    }
+
+    bool is_variable (const symbol_record& sym) const
+    {
+      octave_value val = varval (sym);
+
+      return val.is_defined ();
+    }
+
+    bool is_variable (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? is_variable (sym) : false;
+    }
+
+    bool is_local_variable (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? (is_variable (sym) && ! is_global (sym)) : false;
+    }
+
+    bool is_object (const symbol_record& sym) const
+    {
+      octave_value val = varval (sym);
+
+      return val.isobject ();
+    }
+
+    bool is_object (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? is_object (sym) : false;
+    }
+
+    virtual scope_flags scope_flag (const symbol_record&) const = 0;
+
+    virtual scope_flags get_scope_flag (size_t) const;
+
+    virtual void set_scope_flag (size_t, scope_flags);
+
+    bool is_global (const symbol_record& sym) const
+    {
+      return scope_flag (sym) == GLOBAL;
+    }
+
+    bool is_global (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? is_global (sym) : false;
+    }
+
+    bool is_persistent (const symbol_record& sym) const
+    {
+      return scope_flag (sym) == PERSISTENT;
+    }
+
+    bool is_persistent (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? is_persistent (sym) : false;
+    }
+
+    void install_variable (const symbol_record& sym,
+                           const octave_value& value, bool global);
+
+    void install_variable (const std::string& name,
+                           const octave_value& value, bool global)
+    {
+      symbol_record sym = insert_symbol (name);
+
+      install_variable (sym, value, global);
+    }
+
+    virtual octave_value get_auto_fcn_var (auto_var_type) const = 0;
+
+    virtual void set_auto_fcn_var (auto_var_type, const octave_value&) = 0;
+
+    virtual octave_value varval (const symbol_record& sym) const = 0;;
+
+    virtual octave_value varval (size_t data_offset) const;
+
+    octave_value varval (const std::string& name) const
+    {
+      symbol_record sym = lookup_symbol (name);
+
+      return sym ? varval (sym) : octave_value ();
+    }
+
+    virtual octave_value& varref (const symbol_record& sym) = 0;
+
+    virtual octave_value& varref (size_t data_offset);
+
+    void assign (const symbol_record& sym, const octave_value& val)
+    {
+      octave_value& lhs = varref (sym);
+
+      if (lhs.get_count () == 1)
+        lhs.call_object_destructor ();
+
+      // Regularize a null matrix if stored into a variable.
+      lhs = val.storable_value ();
+    }
+
+    void assign (const std::string& name, const octave_value& val)
+    {
+      symbol_record sym = insert_symbol (name);
+
+      assign (sym, val);
+    }
+
+    void assign (octave_value::assign_op op, const symbol_record& sym,
+                 const std::string& type,
+                 const std::list<octave_value_list>& idx,
+                 const octave_value& rhs)
+    {
+      if (idx.empty ())
+        {
+          if (op == octave_value::op_asn_eq)
+            assign (sym, rhs);
+          else
+            varref (sym).assign (op, rhs);
+        }
+      else
+        varref (sym).assign (op, type, idx, rhs);
+    }
+
+    void do_non_const_unary_op (octave_value::unary_op op,
+                                const symbol_record& sym,
+                                const std::string& type,
+                                const std::list<octave_value_list>& idx)
+    {
+      if (idx.empty ())
+        varref (sym).do_non_const_unary_op (op);
+      else
+        varref (sym).do_non_const_unary_op (op, type, idx);
+    }
+
+    octave_value value (const symbol_record& sym, const std::string& type,
+                        const std::list<octave_value_list>& idx) const
+    {
+      octave_value retval = varval (sym);
+
+      if (! idx.empty ())
+        {
+          if (retval.is_constant ())
+            retval = retval.subsref (type, idx);
+          else
+            {
+              octave_value_list t = retval.subsref (type, idx, 1);
+
+              retval = t.length () > 0 ? t(0) : octave_value ();
+            }
+        }
+
+      return retval;
+    }
+
+    octave_value find_subfunction (const std::string& name) const
+    {
+      symbol_scope scope = get_scope ();
+
+      return scope.find_subfunction (name);
+    }
+
+    void clear (const symbol_record& sym)
+    {
+      if (is_global (sym))
+        unmark_global (sym);
+
+      assign (sym, octave_value ());
+
+      if (is_persistent (sym))
+        unmark_persistent (sym);
+    }
+
+    void clear_objects (void);
+
+    void clear_variable (const std::string& name);
+
+    void clear_variable_pattern (const std::string& pattern);
+    void clear_variable_pattern (const string_vector& patterns);
+
+    void clear_variable_regexp (const std::string& pattern);
+    void clear_variable_regexp (const string_vector& patterns);
+
+    void clear_variables (void);
+
+    std::string get_dispatch_class (void) const { return m_dispatch_class; }
+
+    void set_dispatch_class (const std::string& class_name)
+    {
+      m_dispatch_class = class_name;
+    }
+
+    void display_stopped_in_message (std::ostream& os) const;
+
+    virtual void mark_scope (const symbol_record&, scope_flags) = 0;
+
+    virtual void display (bool follow = true) const;
+
+    virtual void accept (stack_frame_walker& sfw) = 0;
+
+  protected:
+
+    // Reference to the call stack that contains this frame.  Global
+    // variables are stored in the call stack.  This link gives us
+    // immediate access to them.
+    tree_evaluator& m_evaluator;
+
+    // The line and column of the source file where this stack frame
+    // was created.  Used to print stack traces.
+    int m_line;
+    int m_column;
+
+    // Index in call stack.
+    size_t m_index;
+
+    // Pointer to the nearest parent frame that contains variable
+    // information (script, function, or scope).
+    stack_frame *m_static_link;
+
+    // Pointer to the nearest lexical parent frame.  Used to access
+    // non-local variables for nested and anonymous functions or as a
+    // link to the parent frame in which a script is executed.
+    stack_frame *m_access_link;
+
+    // Allow function handles to temporarily store their dispatch class
+    // in the call stack.
+    std::string m_dispatch_class;
+  };
+
+  class compiled_fcn_stack_frame : public stack_frame
+  {
+  public:
+
+    compiled_fcn_stack_frame (void) = delete;
+
+    compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn,
+                              size_t index, stack_frame *static_link)
+      : stack_frame (tw, index, static_link, static_link->access_link ()),
+        m_fcn (fcn)
+    { }
+
+    compiled_fcn_stack_frame (const compiled_fcn_stack_frame& elt) = default;
+
+    compiled_fcn_stack_frame&
+    operator = (const compiled_fcn_stack_frame& elt) = delete;
+
+    ~compiled_fcn_stack_frame (void) = default;
+
+    compiled_fcn_stack_frame * dup (void) const;
+
+    bool is_compiled_fcn_frame (void) const { return true; }
+
+    symbol_scope get_scope (void) const
+    {
+      return m_static_link->get_scope ();
+    }
+
+    octave_function * function (void) const { return m_fcn; }
+
+    symbol_record lookup_symbol (const std::string& name) const
+    {
+      return m_static_link->lookup_symbol (name);
+    }
+
+    symbol_record insert_symbol (const std::string& name)
+    {
+      return m_static_link->insert_symbol (name);
+    }
+
+    stack_frame::scope_flags scope_flag (const symbol_record& sym) const
+    {
+      // Look in closest stack frame that contains values (either the
+      // top scope, or a user-defined function or script).
+
+      return m_static_link->scope_flag (sym);
+    }
+
+    void set_auto_fcn_var (auto_var_type avt, const octave_value& val)
+    {
+      m_static_link->set_auto_fcn_var (avt, val);
+    }
+
+    octave_value get_auto_fcn_var (auto_var_type avt) const
+    {
+      return m_static_link->get_auto_fcn_var (avt);
+    }
+
+    // We only need to override one of each of these functions.  The
+    // using declaration will avoid warnings about partially-overloaded
+    // virtual functions.
+    using stack_frame::varval;
+    using stack_frame::varref;
+
+    octave_value varval (const symbol_record& sym) const
+    {
+      // Look in closest stack frame that contains values (either the
+      // top scope, or a user-defined function or script).
+
+      return m_static_link->varval (sym);
+    }
+
+    octave_value& varref (const symbol_record& sym)
+    {
+      // Look in closest stack frame that contains values (either the
+      // top scope, or a user-defined function or script).
+
+      return m_static_link->varref (sym);
+    }
+
+    void mark_scope (const symbol_record& sym,
+                                               scope_flags flag)
+    {
+      // Look in closest stack frame that contains values (either the
+      // top scope, or a user-defined function or script).
+
+      m_static_link->mark_scope (sym, flag);
+    }
+
+    void display (bool follow = true) const;
+
+    void accept (stack_frame_walker& sfw);
+
+  private:
+
+    // Compiled function object associated with this stack frame.
+    // Should always be a built-in, .oct or .mex file function and
+    // should always be valid.
+    octave_function *m_fcn;
+  };
+
+  // Scripts have a symbol_scope object to store the set of variables
+  // in the script, but values for those variables are stored in the
+  // stack frame corresponding to the nearest calling function or in
+  // the top-level scope (the evaluation stack frame).
+  //
+  // Accessing values in a scope requires a mapping from the index of
+  // the variable for the script scope to the list of values in the
+  // evaluation frame(s).  The frame offset tells us how many access
+  // links we must follow to find the stack frame that holds the
+  // value.  The value offset is the index into the vector of values
+  // in that stack frame that we should use to find the value.
+  //
+  // Frame and value offsets are set in this stack frame when it is
+  // created using information from the script and enclosing scopes.
+  //
+  // If a script is invoked in a nested function context, the frame
+  // offsets for individual values may be different.  Some may be
+  // accessed from the invoking function and some may come from a
+  // parent function.
+
+  class script_stack_frame : public stack_frame
+  {
+  public:
+
+    script_stack_frame (void) = delete;
+
+    script_stack_frame (tree_evaluator& tw, octave_user_script *script,
+                        unwind_protect *up_frame, size_t index,
+                        stack_frame *static_link);
+
+    script_stack_frame (const script_stack_frame& elt) = default;
+
+    script_stack_frame& operator = (const script_stack_frame& elt) = delete;
+
+    ~script_stack_frame (void) = default;
+
+    script_stack_frame * dup (void) const;
+
+    bool is_user_script_frame (void) const { return true; }
+
+    static stack_frame * get_access_link (stack_frame *static_link);
+
+    static size_t get_num_symbols (octave_user_script *script);
+
+    void set_script_offsets (void);
+
+    void set_script_offsets_internal (const std::map<std::string, symbol_record>& symbols);
+
+    void resize_and_update_script_offsets (const symbol_record& sym);
+
+    symbol_scope get_scope (void) const { return m_script->scope (); }
+
+    octave_function * function (void) const { return m_script; }
+
+    unwind_protect *
+    unwind_protect_frame (void) const { return m_unwind_protect_frame; }
+
+    symbol_record lookup_symbol (const std::string& name) const;
+
+    symbol_record insert_symbol (const std::string&);
+
+    size_t size (void) const { return m_lexical_frame_offsets.size (); }
+
+    void resize (size_t size)
+    {
+      m_lexical_frame_offsets.resize (size, 0);
+      m_value_offsets.resize (size, 0);
+    }
+
+    void get_val_offsets_with_insert (const symbol_record& sym,
+                                      size_t& frame_offset,
+                                      size_t& data_offset);
+
+    bool get_val_offsets_internal (const symbol_record& sym,
+                                   size_t& frame_offset,
+                                   size_t& data_offset) const;
+
+    bool get_val_offsets (const symbol_record& sym, size_t& frame_offset,
+                          size_t& data_offset) const;
+
+    scope_flags scope_flag (const symbol_record& sym) const;
+
+    void set_auto_fcn_var (auto_var_type avt, const octave_value& val)
+    {
+      m_access_link->set_auto_fcn_var (avt, val);
+    }
+
+    octave_value get_auto_fcn_var (auto_var_type avt) const
+    {
+      return m_access_link->get_auto_fcn_var (avt);
+    }
+
+    // We only need to override one of each of these functions.  The
+    // using declaration will avoid warnings about partially-overloaded
+    // virtual functions.
+    using stack_frame::varval;
+    using stack_frame::varref;
+
+    octave_value varval (const symbol_record& sym) const;
+
+    octave_value& varref (const symbol_record& sym);
+
+    void mark_scope (const symbol_record& sym, scope_flags flag);
+
+    void display (bool follow = true) const;
+
+    void accept (stack_frame_walker& sfw);
+
+  private:
+
+    // Script object associated with this stack frame.  Should always
+    // be valid.
+    octave_user_script *m_script;
+
+    // The nearest unwind protect frame that was active when this
+    // stack frame was created.  Should always be valid.
+    unwind_protect *m_unwind_protect_frame;
+
+    // Mapping between the symbols in the symbol_scope object of the
+    // script to the stack frame in which the script is executed.  The
+    // frame offsets may be greater than one if the script is executed
+    // in a nested function context.
+
+    std::vector<size_t> m_lexical_frame_offsets;
+    std::vector<size_t> m_value_offsets;
+  };
+
+  // Base class for values and offsets shared by user_fcn and scope
+  // frames.
+
+  class base_value_stack_frame : public stack_frame
+  {
+  public:
+
+    base_value_stack_frame (void) = delete;
+
+    base_value_stack_frame (tree_evaluator& tw, size_t num_symbols,
+                            size_t index, stack_frame *static_link,
+                            stack_frame *access_link)
+      : stack_frame (tw, index, static_link, access_link),
+        m_values (num_symbols, octave_value ()),
+        m_flags (num_symbols, LOCAL),
+        m_auto_vars (NUM_AUTO_VARS, octave_value ())
+    { }
+
+    base_value_stack_frame (const base_value_stack_frame& elt) = default;
+
+    base_value_stack_frame&
+    operator = (const base_value_stack_frame& elt) = delete;
+
+    ~base_value_stack_frame (void) = default;
+
+    size_t size (void) const
+    {
+      return m_values.size ();
+    }
+
+    void resize (size_t size)
+    {
+      m_values.resize (size, octave_value ());
+      m_flags.resize (size, LOCAL);
+    }
+
+    stack_frame::scope_flags get_scope_flag (size_t data_offset) const
+    {
+      return m_flags.at (data_offset);
+    }
+
+    void set_scope_flag (size_t data_offset, scope_flags flag)
+    {
+      m_flags.at (data_offset) = flag;
+    }
+
+    octave_value get_auto_fcn_var (auto_var_type avt) const
+    {
+      return m_auto_vars.at (avt);
+    }
+
+    void set_auto_fcn_var (auto_var_type avt, const octave_value& val)
+    {
+      m_auto_vars.at (avt) = val;
+    }
+
+    // We only need to override one of each of these functions.  The
+    // using declaration will avoid warnings about partially-overloaded
+    // virtual functions.
+    using stack_frame::varval;
+    using stack_frame::varref;
+
+    octave_value varval (size_t data_offset) const
+    {
+      return m_values.at (data_offset);
+    }
+
+    octave_value& varref (size_t data_offset)
+    {
+      return m_values.at (data_offset);
+    }
+
+    void display (bool follow = true) const;
+
+  protected:
+
+    // Variable values.  This array is indexed by the data_offset
+    // value stored in the symbol_record objects of the scope
+    // associated with this stack frame.
+    std::vector<octave_value> m_values;
+
+    // The type of each variable (local, global, persistent) of each
+    // value.  This array is indexed by the data_offset value stored
+    // in the symbol_record objects of the scope associated with this
+    // stack frame.  Local values are found in the M_VALUES array.
+    // Global values are stored in the tree_evaluator object that contains
+    // the stack frame.  Persistent values are stored in the function
+    // scope corresponding to the stack frame.
+    std::vector<scope_flags> m_flags;
+
+    // A fixed list of Automatic variables created for this function.
+    // The elements of this vector correspond to the auto_var_type
+    // enum.
+    std::vector<octave_value> m_auto_vars;
+  };
+
+  // User-defined functions have a symbol_scope object to store the set
+  // of variables in the function and values are stored in the stack
+  // frame corresponding to the invocation of the function or one of
+  // its parents.  The frame offset tells us how many access links we
+  // must follow to find the stack frame that holds the value.  The
+  // value offset is the index into the vector of values in that stack
+  // frame that we should use to find the value.
+  //
+  // Frame and value offsets are determined when the corresponding
+  // function is parsed.
+
+  class user_fcn_stack_frame : public base_value_stack_frame
+  {
+  public:
+
+    user_fcn_stack_frame (void) = delete;
+
+    user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn,
+                          unwind_protect *up_frame, size_t index,
+                          stack_frame *static_link,
+                          stack_frame *access_link = nullptr)
+      : base_value_stack_frame (tw, get_num_symbols (fcn), index, static_link,
+                                (access_link
+                                 ? access_link
+                                 : get_access_link (fcn, static_link))),
+        m_fcn (fcn), m_unwind_protect_frame (up_frame)
+    { }
+
+    user_fcn_stack_frame (const user_fcn_stack_frame& elt) = default;
+
+    user_fcn_stack_frame&
+    operator = (const user_fcn_stack_frame& elt) = delete;
+
+    ~user_fcn_stack_frame (void) = default;
+
+    user_fcn_stack_frame * dup (void) const;
+
+    bool is_user_fcn_frame (void) const { return true; }
+
+    static stack_frame *
+    get_access_link (octave_user_function *fcn, stack_frame *static_link);
+
+    static size_t get_num_symbols (octave_user_function *fcn)
+    {
+      symbol_scope fcn_scope = fcn->scope ();
+
+      return fcn_scope.num_symbols ();
+    }
+
+    void clear_values (void);
+
+    symbol_scope get_scope (void) const { return m_fcn->scope (); }
+
+    octave_function * function (void) const { return m_fcn; }
+
+    unwind_protect *
+    unwind_protect_frame (void) const { return m_unwind_protect_frame; }
+
+    symbol_record lookup_symbol (const std::string& name) const;
+
+    symbol_record insert_symbol (const std::string&);
+
+    scope_flags scope_flag (const symbol_record& sym) const;
+
+    // We only need to override one of each of these functions.  The
+    // using declaration will avoid warnings about partially-overloaded
+    // virtual functions.
+    using base_value_stack_frame::varval;
+    using base_value_stack_frame::varref;
+
+    octave_value varval (const symbol_record& sym) const;
+
+    octave_value& varref (const symbol_record& sym);
+
+    void mark_scope (const symbol_record& sym, scope_flags flag);
+
+    void display (bool follow = true) const;
+
+    void accept (stack_frame_walker& sfw);
+
+  private:
+
+    // User-defined object associated with this stack frame.  Should
+    // always be valid.
+    octave_user_function *m_fcn;
+
+    // The nearest unwind protect frame that was active when this
+    // stack frame was created.  Should always be valid.
+    unwind_protect *m_unwind_protect_frame;
+  };
+
+  // Pure scope stack frames (primarily the top-level workspace) have
+  // a set of variables and values are stored in the stack frame.  All
+  // variable accesses are direct as there are no parent stack frames.
+  //
+  // Value offsets are determined when the corresponding variable is
+  // entered into the symbol_scope object corresponding to the frame.
+
+  class scope_stack_frame : public base_value_stack_frame
+  {
+  public:
+
+    scope_stack_frame (void) = delete;
+
+    scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope,
+                       size_t index, stack_frame *static_link)
+      : base_value_stack_frame (tw, scope.num_symbols (), index,
+                                static_link, nullptr),
+        m_scope (scope)
+    { }
+
+    scope_stack_frame (const scope_stack_frame& elt) = default;
+
+    scope_stack_frame& operator = (const scope_stack_frame& elt) = delete;
+
+    ~scope_stack_frame (void) = default;
+
+    scope_stack_frame * dup (void) const;
+
+    bool is_scope_frame (void) const { return true; }
+
+    symbol_scope get_scope (void) const { return m_scope; }
+
+    symbol_record lookup_symbol (const std::string& name) const
+    {
+      return m_scope.lookup_symbol (name);
+    }
+
+    symbol_record insert_symbol (const std::string&);
+
+    scope_flags scope_flag (const symbol_record& sym) const;
+
+    // We only need to override one of each of these functions.  The
+    // using declaration will avoid warnings about partially-overloaded
+    // virtual functions.
+    using base_value_stack_frame::varval;
+    using base_value_stack_frame::varref;
+
+    octave_value varval (const symbol_record& sym) const;
+
+    octave_value& varref (const symbol_record& sym);
+
+    void mark_scope (const symbol_record& sym, scope_flags flag);
+
+    void display (bool follow = true) const;
+
+    void accept (stack_frame_walker& sfw);
+
+  private:
+
+    // The scope object associated with this stack frame.
+    symbol_scope m_scope;
+  };
+}
+
+#endif
--- a/libinterp/corefcn/strfind.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/strfind.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -36,6 +36,7 @@
 #include "builtin-defun-decls.h"
 #include "defun.h"
 #include "errwarn.h"
+#include "error.h"
 #include "ov.h"
 #include "unwind-prot.h"
 #include "utils.h"
--- a/libinterp/corefcn/strfns.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/strfns.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1030,6 +1030,42 @@
 %!assert (unicode_idx (["aäou"; "Ä∞"]), [1 2 2 3 4; 5 5 6 6 6]);
 */
 
+DEFUN (newline, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {} newline
+Return the character corresponding to a newline.
+
+This is equivalent to @qcode{"@xbackslashchar{}n"}.
+
+Example Code
+
+@example
+@group
+joined_string = [newline "line1" newline "line2"]
+@result{}
+line1
+line2
+@end group
+@end example
+
+@seealso{strcat, strjoin, strsplit}
+@end deftypefn */)
+{
+  if (args.length () != 0)
+  print_usage ();
+ 
+  static octave_value_list retval = ovl ("\n");
+ 
+  return retval;
+}
+
+/*
+%!assert (newline (), "\n")
+
+%!error newline (1)
+%!error [a, b] = newline ();
+*/
+
 DEFUN (list_in_columns, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} list_in_columns (@var{arg}, @var{width}, @var{prefix})
--- a/libinterp/corefcn/svd.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/svd.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -372,6 +372,8 @@
 %! [~,~,v] = svd ([1, 1, 1], "econ");
 %! assert (size (v), [3 1]);
 
+%!assert <*55710> (1 / svd (-0), Inf)
+
 %!error svd ()
 %!error svd ([1, 2; 4, 5], 2, 3)
 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/syminfo-accumulator.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,304 @@
+/*
+
+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_syminfo_accumulator_h)
+#define octave_syminfo_accumulator_h 1
+
+#include "octave-config.h"
+
+#include <string>
+
+#include "oct-map.h"
+#include "ov.h"
+#include "stack-frame.h"
+#include "syminfo.h"
+#include "symrec.h"
+
+namespace octave
+{
+  class symbol_info_accumulator : public stack_frame_walker
+  {
+  public:
+
+    symbol_info_accumulator (const std::string& pattern,
+                             bool have_regexp = false)
+      : stack_frame_walker (), m_patterns (pattern), m_match_all (false),
+        m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (),
+        m_found_names ()
+    { }
+
+    symbol_info_accumulator (const string_vector& patterns,
+                             bool have_regexp = false)
+      : stack_frame_walker (), m_patterns (patterns), m_match_all (false),
+        m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (),
+        m_found_names ()
+    { }
+
+    symbol_info_accumulator (bool match_all = true, bool first_only = true)
+      : stack_frame_walker (), m_patterns (), m_match_all (match_all),
+        m_first_only (first_only), m_have_regexp (false),
+        m_sym_inf_list (), m_found_names ()
+    { }
+
+    symbol_info_accumulator (const symbol_info_accumulator&) = delete;
+
+    symbol_info_accumulator& operator = (const symbol_info_accumulator&) = delete;
+
+    ~symbol_info_accumulator (void) = default;
+
+    bool is_empty  (void) const
+    {
+      for (const auto& nm_sil : m_sym_inf_list)
+        {
+          const symbol_info_list& lst = nm_sil.second;
+
+          if (! lst.empty ())
+            return false;
+        }
+
+      return true;
+    }
+
+    std::list<std::string> names (void) const
+    {
+      std::list<std::string> retval;
+
+      for (const auto& nm_sil : m_sym_inf_list)
+        {
+          const symbol_info_list& lst = nm_sil.second;
+
+          std::list<std::string> nm_list = lst.names ();
+
+          for (const auto& nm : nm_list)
+            retval.push_back (nm);
+        }
+
+      return retval;
+    }
+
+    symbol_info_list symbol_info (void) const
+    {
+      symbol_info_list retval;
+
+      for (const auto& nm_sil : m_sym_inf_list)
+        {
+          const symbol_info_list& lst = nm_sil.second;
+
+          for (const auto& syminf : lst)
+            retval.push_back (syminf);
+        }
+
+      return retval;
+    }
+
+    octave_map map_value (void) const
+    {
+      octave_map retval;
+
+      // FIXME: is there a better way to concatenate structures?
+
+      size_t n_frames = m_sym_inf_list.size ();
+
+      OCTAVE_LOCAL_BUFFER (octave_map, map_list, n_frames);
+
+      size_t j = 0;
+      for (const auto& nm_sil : m_sym_inf_list)
+        {
+          std::string scope_name = nm_sil.first;
+          const symbol_info_list& lst = nm_sil.second;
+
+          map_list[j] = lst.map_value (scope_name, n_frames-j);
+
+          j++;
+        }
+
+      return octave_map::cat (-1, n_frames, map_list);
+    }
+
+    void display (std::ostream& os, const std::string& format) const
+    {
+      for (const auto& nm_sil : m_sym_inf_list)
+        {
+          os << "\nvariables in scope: " << nm_sil.first << "\n\n";
+
+          const symbol_info_list& lst = nm_sil.second;
+
+          lst.display (os, format);
+        }
+    }
+
+    void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)
+    {
+      // This one follows static link always.  Hmm, should the access
+      // link for a compiled_fcn_stack_frame be the same as the static
+      // link?
+
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
+
+    void visit_script_stack_frame (script_stack_frame& frame)
+    {
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+    void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame)
+    {
+      append_list (frame);
+
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+    void visit_scope_stack_frame (scope_stack_frame& frame)
+    {
+      append_list (frame);
+
+      stack_frame *alink = frame.access_link ();
+
+      if (alink)
+        alink->accept (*this);
+    }
+
+  private:
+
+    typedef std::pair<std::string, symbol_info_list> syminf_list_elt;
+
+    // FIXME: the following is too complex and duplicates too much
+    // code.  Maybe it should be split up so we have separate classes
+    // that do each job that is needed?
+
+    std::list<symbol_record>
+    filter (stack_frame& frame, const std::list<symbol_record>& symbols)
+    {
+      std::list<symbol_record> new_symbols;
+
+      if (m_match_all)
+        {
+          for (const auto& sym : symbols)
+            {
+              if (frame.is_defined (sym))
+                {
+                  std::string name = sym.name ();
+
+                  if (m_first_only
+                      && m_found_names.find (name) != m_found_names.end ())
+                    continue;
+
+                  m_found_names.insert (name);
+
+                  new_symbols.push_back (sym);
+                }
+            }
+        }
+      else if (m_have_regexp)
+        {
+          octave_idx_type npatterns = m_patterns.numel ();
+
+          for (octave_idx_type j = 0; j < npatterns; j++)
+            {
+              std::string pattern = m_patterns[j];
+
+              regexp pat (pattern);
+
+              for (const auto& sym : symbols)
+                {
+                  std::string name = sym.name ();
+
+                  if (pat.is_match (name) && frame.is_defined (sym))
+                    {
+                      if (m_first_only
+                          && m_found_names.find (name) != m_found_names.end ())
+                        continue;
+
+                      m_found_names.insert (name);
+
+                      new_symbols.push_back (sym);
+                    }
+                }
+            }
+        }
+      else
+        {
+          octave_idx_type npatterns = m_patterns.numel ();
+
+          for (octave_idx_type j = 0; j < npatterns; j++)
+            {
+              std::string pattern = m_patterns[j];
+
+              glob_match pat (pattern);
+
+              for (const auto& sym : symbols)
+                {
+                  std::string name = sym.name ();
+
+                  if (pat.match (name) && frame.is_defined (sym))
+                    {
+                      if (m_first_only
+                          && m_found_names.find (name) == m_found_names.end ())
+                        continue;
+
+                      m_found_names.insert (name);
+
+                      new_symbols.push_back (sym);
+                    }
+                }
+            }
+        }
+
+      return new_symbols;
+    }
+
+    void append_list (stack_frame& frame)
+    {
+      symbol_scope scope = frame.get_scope ();
+
+      std::list<symbol_record> symbols = scope.symbol_list ();
+
+      if (m_match_all || ! m_patterns.empty ())
+        symbols = filter (frame, symbols);
+
+      symbol_info_list syminf_list = frame.make_symbol_info_list (symbols);
+
+      m_sym_inf_list.push_back (syminf_list_elt (scope.name (), syminf_list));
+    }
+
+    string_vector m_patterns;
+
+    bool m_match_all;
+    bool m_first_only;
+    bool m_have_regexp;
+
+    std::list<std::pair<std::string, symbol_info_list>> m_sym_inf_list;
+
+    std::set<std::string> m_found_names;
+  };
+}
+
+#endif
--- a/libinterp/corefcn/syminfo.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/syminfo.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -30,6 +30,7 @@
 #include <sstream>
 
 #include "Cell.h"
+#include "error.h"
 #include "octave-preserve-stream-state.h"
 #include "ov.h"
 #include "oct-map.h"
@@ -46,7 +47,7 @@
 
     auto i = params.begin ();
 
-    octave::preserve_stream_state stream_state (os);
+    preserve_stream_state stream_state (os);
 
     while (i != params.end ())
       {
@@ -105,14 +106,13 @@
               {
               case 'a':
                 {
-                  char tmp[6];
+                  char tmp[5];
 
-                  tmp[0] = (m_is_automatic ? 'a' : ' ');
-                  tmp[1] = (m_is_complex ? 'c' : ' ');
-                  tmp[2] = (m_is_formal ? 'f' : ' ');
-                  tmp[3] = (m_is_global ? 'g' : ' ');
-                  tmp[4] = (m_is_persistent ? 'p' : ' ');
-                  tmp[5] = 0;
+                  tmp[0] = (m_is_complex ? 'c' : ' ');
+                  tmp[1] = (m_is_formal ? 'f' : ' ');
+                  tmp[2] = (m_is_global ? 'g' : ' ');
+                  tmp[3] = (m_is_persistent ? 'p' : ' ');
+                  tmp[4] = 0;
 
                   os << tmp;
                 }
@@ -173,6 +173,16 @@
     return octave_value ();
   }
 
+  std::list<std::string> symbol_info_list::names (void) const
+  {
+    std::list<std::string> retval;
+
+    for (const auto& syminfo : m_lst)
+      retval.push_back (syminfo.name ());
+
+    return retval;
+  }
+
   octave_map
   symbol_info_list::map_value (const std::string& caller_function_name,
                                int nesting_level) const
@@ -235,7 +245,7 @@
   {
     std::ostringstream param_buf;
 
-    octave::preserve_stream_state stream_state (os);
+    preserve_stream_state stream_state (os);
 
     for (const auto& param : params)
       {
@@ -314,7 +324,8 @@
     os << param_buf.str ();
   }
 
-  void symbol_info_list::display (std::ostream& os, const std::string& format)
+  void symbol_info_list::display (std::ostream& os,
+                                  const std::string& format) const
   {
     if (! m_lst.empty ())
       {
@@ -345,7 +356,7 @@
   }
 
   std::list<whos_parameter>
-  symbol_info_list::parse_whos_line_format (const std::string& format)
+  symbol_info_list::parse_whos_line_format (const std::string& format) const
   {
     int idx;
     size_t format_len = format.length ();
--- a/libinterp/corefcn/syminfo.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/syminfo.h	Fri Jul 12 12:14:43 2019 -0400
@@ -52,19 +52,16 @@
   public:
 
     symbol_info (const std::string& name, const octave_value& value,
-                 bool is_automatic, bool is_complex, bool is_formal,
-                 bool is_global, bool is_persistent)
-      : m_name (name), m_value (value), m_is_automatic (is_automatic),
-        m_is_complex (is_complex), m_is_formal (is_formal),
-        m_is_global (is_global), m_is_persistent (is_persistent)
+                 bool is_formal, bool is_global, bool is_persistent)
+      : m_name (name), m_value (value), m_is_complex (value.iscomplex ()),
+        m_is_formal (is_formal), m_is_global (is_global),
+        m_is_persistent (is_persistent)
     { }
 
     std::string name (void) const { return m_name; }
 
     octave_value value (void) const { return m_value; }
 
-    bool is_automatic (void) const { return m_is_automatic; }
-
     bool is_complex (void) const { return m_is_complex; }
 
     bool is_formal (void) const { return m_is_formal; }
@@ -79,7 +76,6 @@
 
     std::string m_name;
     octave_value m_value;
-    bool m_is_automatic;
     bool m_is_complex;
     bool m_is_formal;
     bool m_is_global;
@@ -100,6 +96,8 @@
 
     octave_value varval (const std::string& name) const;
 
+    std::list<std::string> names (void) const;
+
     octave_map map_value (const std::string& caller_function_name,
                           int nesting_level) const;
 
@@ -107,13 +105,13 @@
     void print_descriptor (std::ostream& os,
                            const std::list<whos_parameter> params) const;
 
-    void display (std::ostream& os, const std::string& format);
+    void display (std::ostream& os, const std::string& format) const;
 
     // Parse FORMAT, and return a parameter list,
     // containing all information needed to print the given
     // attributes of the symbols.
     std::list<whos_parameter>
-    parse_whos_line_format (const std::string& format);
+    parse_whos_line_format (const std::string& format) const;
   };
 }
 
--- a/libinterp/corefcn/symrec.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symrec.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -36,86 +36,25 @@
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "symrec.h"
-#include "symscope.h"
-#include "symtab.h"
 
 namespace octave
 {
-  symbol_record::context_id
-  symbol_record::symbol_record_rep::get_fwd_scope_context (void) const
-  {
-    // This should NOT recurse.  We only want to know the current
-    // context of the immediately forwarded rep object.  This is used
-    // only in symbol_record::symbol_record_rep::varref and
-    // symbol_record::symbol_record_rep::varval.
-
-    auto t_fwd_scope = m_fwd_scope.lock ();
-    return t_fwd_scope ? t_fwd_scope->current_context () : 0;
-  }
-
-  void
-  symbol_record::symbol_record_rep::init_persistent (void)
+  std::shared_ptr<symbol_record::symbol_record_rep>
+  symbol_record::symbol_record_rep::dup (void) const
   {
-    if (auto t_fwd_rep = m_fwd_rep.lock ())
-      {
-        t_fwd_rep->init_persistent ();
-        return;
-      }
-
-    mark_persistent ();
-  }
-
-  std::shared_ptr<symbol_record::symbol_record_rep>
-  symbol_record::symbol_record_rep::dup (const std::shared_ptr<symbol_scope_rep>& new_scope) const
-  {
-    // FIXME: is this the right thing do to?
-    if (auto t_fwd_rep = m_fwd_rep.lock ())
-      return t_fwd_rep->dup (new_scope);
-
-    static const context_id FIXME_CONTEXT = 0;
-
-    return std::shared_ptr<symbol_record_rep>
-      (new symbol_record_rep (m_name, varval (FIXME_CONTEXT),
-                              m_storage_class));
+    return std::shared_ptr<symbol_record::symbol_record_rep> (new symbol_record_rep (*this));
   }
 
   octave_value
-  symbol_record::symbol_record_rep::dump (context_id context) const
+  symbol_record::symbol_record_rep::dump (void) const
   {
-    if (auto t_fwd_rep = m_fwd_rep.lock ())
-      return t_fwd_rep->dump (context);
-
     std::map<std::string, octave_value> m
-      = {{ "name", m_name },
+      = {{ "frame_offset", m_frame_offset },
+         { "data_offset", m_data_offset },
+         { "name", m_name },
          { "local", is_local () },
-         { "automatic", is_automatic () },
-         { "formal", is_formal () },
-         { "hidden", is_hidden () },
-         { "inherited", is_inherited () },
-         { "global", is_global () },
-         { "persistent", is_persistent () }};
-
-    octave_value val = varval (context);
-
-    if (val.is_defined ())
-      m["value"] = val;
+         { "formal", is_formal () }};
 
     return octave_value (m);
   }
-
-  octave_value
-  symbol_record::find_function (const std::string& name,
-                                const octave_value_list& args) const
-  {
-    // FIXME: it would be better if the symbol_record object did not
-    // look back to the symbol_table when the value is undefined.  More
-    // refactoring is needed...
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("symbol_record::find_function");
-
-    return symtab.find_function (name, args);
-  }
-
-  octave_value symbol_record::dummy_octave_value;
 }
--- a/libinterp/corefcn/symrec.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symrec.h	Fri Jul 12 12:14:43 2019 -0400
@@ -49,28 +49,12 @@
     // generic variable
     static const unsigned int local = 1;
 
-    // varargin, argn, .nargin., .nargout.
-    // (FIXME: is this really used now?)
-    static const unsigned int automatic = 2;
-
     // formal parameter
-    static const unsigned int formal = 4;
-
-    // not listed or cleared (.nargin., .nargout.)
-    static const unsigned int hidden = 8;
-
-    // inherited from parent scope; not cleared at function exit
-    static const unsigned int inherited = 16;
-
-    // global (redirects to global scope)
-    static const unsigned int global = 32;
-
-    // not cleared at function exit
-    static const unsigned int persistent = 64;
+    static const unsigned int formal = 2;
 
     // this symbol may NOT become a variable.
     // (symbol added to a static workspace)
-    static const unsigned int added_static = 128;
+    static const unsigned int added_static = 4;
 
   private:
 
@@ -78,470 +62,78 @@
     {
     public:
 
-      symbol_record_rep (const std::string& nm, const octave_value& v,
-                         unsigned int sc)
-        : m_storage_class (sc), m_name (nm), m_fwd_scope (),
-          m_fwd_rep (), m_value_stack ()
-      {
-        m_value_stack.push_back (v);
-      }
+      symbol_record_rep (const std::string& nm, unsigned int sc)
+        : m_frame_offset (0), m_data_offset (0), m_storage_class (sc),
+          m_name (nm)
+      { }
 
-      // No copying!
+      symbol_record_rep (const symbol_record_rep&) = default;
 
-      symbol_record_rep (const symbol_record_rep& ov) = delete;
-
-      symbol_record_rep& operator = (const symbol_record_rep&) = delete;
+      symbol_record_rep& operator = (const symbol_record_rep&) = default;
 
       ~symbol_record_rep (void) = default;
 
-      void assign (const octave_value& value, context_id context)
-      {
-        varref(context) = value;
-      }
-
-      void assign (octave_value::assign_op op,
-                   const std::string& type,
-                   const std::list<octave_value_list>& idx,
-                   const octave_value& value, context_id context)
-      {
-        varref(context).assign (op, type, idx, value);
-      }
-
-      void assign (octave_value::assign_op op, const octave_value& value,
-                   context_id context)
-      {
-        varref(context).assign (op, value);
-      }
-
-      void do_non_const_unary_op (octave_value::unary_op op,
-                                  context_id context)
-      {
-        varref(context).do_non_const_unary_op (op);
-      }
+      // FIXME: use special storage class instead?
+      bool is_valid (void) const { return ! m_name.empty (); }
 
-      void do_non_const_unary_op (octave_value::unary_op op,
-                                  const std::string& type,
-                                  const std::list<octave_value_list>& idx,
-                                  context_id context)
-      {
-        varref(context).do_non_const_unary_op (op, type, idx);
-      }
-
-      context_id get_fwd_scope_context (void) const;
-
-      octave_value& varref (context_id context)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->varref (get_fwd_scope_context ());
-
-        if (is_persistent ())
-          context = 0;
-
-        context_id n = m_value_stack.size ();
-        while (n++ <= context)
-          m_value_stack.push_back (octave_value ());
-
-        return m_value_stack[context];
-      }
-
-      octave_value varval (context_id context) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->varval (get_fwd_scope_context ());
-
-        if (is_persistent ())
-          context = 0;
-
-        if (context < m_value_stack.size ())
-          return m_value_stack[context];
-        else
-          return octave_value ();
-      }
+      void set_frame_offset (size_t offset) { m_frame_offset = offset; }
 
-      void push_context (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return;
-
-        if (! (is_persistent () || is_global ()))
-          m_value_stack.push_back (octave_value ());
-      }
-
-      // If pop_context returns 0, we are out of values and this element
-      // of the symbol table should be deleted.  This can happen for
-      // functions like
-      //
-      //   function foo (n)
-      //     if (n > 0)
-      //       foo (n-1);
-      //     else
-      //       eval ("x = 1");
-      //     endif
-      //   endfunction
-      //
-      // Here, X should only exist in the final stack frame.
-
-      context_id pop_context (void)
-      {
-        context_id retval = 1;
-
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return retval;
-
-        if (! (is_persistent () || is_global ()))
-          {
-            m_value_stack.pop_back ();
-            retval = m_value_stack.size ();
-          }
+      size_t frame_offset (void) const { return m_frame_offset; }
 
-        return retval;
-      }
-
-      void clear (context_id context)
-      {
-        // For globals, break the link to the global value first, then
-        // clear the local value.
-
-        if (is_global ())
-          unbind_global_rep ();
-
-        if (! (is_hidden () || is_inherited ()))
-          {
-            assign (octave_value (), context);
-
-            // For persistent values, we clear the value then unmark so
-            // that we clear the first element of the value stack.
+      void set_data_offset (size_t offset) { m_data_offset = offset; }
 
-            if (is_persistent ())
-              unmark_persistent ();
-          }
-      }
-
-      bool is_defined (context_id context) const
-      {
-        return varval (context).is_defined ();
-      }
-
-      bool is_variable (context_id context) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_variable (context);
-
-        return (! is_local () || is_defined (context));
-      }
+      size_t data_offset (void) const { return m_data_offset; }
 
       bool is_local (void) const
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_local ();
-
         return m_storage_class & local;
       }
 
-      bool is_automatic (void) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_automatic ();
-
-        return m_storage_class & automatic;
-      }
-
       bool is_formal (void) const
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_formal ();
-
         return m_storage_class & formal;
       }
 
-      bool is_hidden (void) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_hidden ();
-
-        return m_storage_class & hidden;
-      }
-
-      bool is_inherited (void) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_inherited ();
-
-        return m_storage_class & inherited;
-      }
-
-      bool is_forwarded (void) const
-      {
-        return ! m_fwd_rep.expired ();
-      }
-
-      bool is_global (void) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_global ();
-
-        return is_marked_global ();
-      }
-
-      bool is_persistent (void) const
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_persistent ();
-
-        return m_storage_class & persistent;
-      }
-
       bool is_added_static (void) const
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          return t_fwd_rep->is_added_static ();
-
         return m_storage_class & added_static;
       }
 
       void mark_local (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_local ();
-            return;
-          }
-
         m_storage_class |= local;
       }
 
-      void mark_automatic (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_automatic ();
-            return;
-          }
-
-        m_storage_class |= automatic;
-      }
-
       void mark_formal (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_formal ();
-            return;
-          }
-
         m_storage_class |= formal;
       }
 
-      void mark_hidden (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_hidden ();
-            return;
-          }
-
-        m_storage_class |= hidden;
-      }
-
-      void mark_inherited (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_inherited ();
-            return;
-          }
-
-        m_storage_class |= inherited;
-      }
-
-      // This flag should only be set for a symbol record that is
-      // actually in the global symbol_scope, and that should only
-      // happen when it is added to the global symbol_scope.
-
-      void mark_global (void)
-      {
-        m_storage_class |= global;
-      }
-
-      bool is_marked_global (void) const
-      {
-        return m_storage_class & global;
-      }
-
-      void mark_persistent (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_persistent ();
-            return;
-          }
-
-        if (is_global ())
-          error ("can't make global variable %s persistent", m_name.c_str ());
-
-        if (is_formal ())
-          error ("can't make function parameter %s persistent", m_name.c_str ());
-        m_storage_class |= persistent;
-      }
-
       void mark_added_static (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->mark_added_static ();
-            return;
-          }
-
         m_storage_class |= added_static;
       }
 
       void unmark_local (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_local ();
-            return;
-          }
-
         m_storage_class &= ~local;
       }
 
-      void unmark_automatic (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_automatic ();
-            return;
-          }
-
-        m_storage_class &= ~automatic;
-      }
-
       void unmark_formal (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_formal ();
-            return;
-          }
-
         m_storage_class &= ~formal;
       }
 
-      void unmark_hidden (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_hidden ();
-            return;
-          }
-
-        m_storage_class &= ~hidden;
-      }
-
-      void unmark_inherited (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_inherited ();
-            return;
-          }
-
-        m_storage_class &= ~inherited;
-      }
-
-      void unmark_persistent (void)
-      {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_persistent ();
-            return;
-          }
-
-        m_storage_class &= ~persistent;
-      }
-
       void unmark_added_static (void)
       {
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            t_fwd_rep->unmark_added_static ();
-            return;
-          }
-
         m_storage_class &= ~added_static;
       }
 
       unsigned int storage_class (void) const { return m_storage_class; }
 
-      void init_persistent (void);
-
-      void bind_fwd_rep (const std::shared_ptr<symbol_scope_rep>& fwd_scope,
-                         const std::shared_ptr<symbol_record_rep>& fwd_rep)
-      {
-        // If this object is already bound to another scope (for
-        // example, a variable in a script or nested function is bound
-        // to the enclosing scope), then bind that object to the next
-        // scope.  FIXME: can this happen for any other reason than we
-        // are making a variable in a script global?
-
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            // If this is the symbol in the global scope, then don't
-            // forward again!
-
-            if (t_fwd_rep->is_marked_global ())
-              return;
-
-            t_fwd_rep->bind_fwd_rep (fwd_scope, fwd_rep);
-          }
-
-        // Don't bind forward rep to this!  Avoids crash reported in
-        // bug #55728.
-
-        if (this == fwd_rep.get ())
-          return;
-
-        m_fwd_scope = fwd_scope;
-        m_fwd_rep = fwd_rep;
-      }
+      std::shared_ptr<symbol_record_rep> dup (void) const;
 
-      void unbind_fwd_rep (void)
-      {
-        // When unbinding variables in a script scope, we only break
-        // the immediate link.  By doing that, we ensure that any
-        // variables that are made global in a script remain linked as
-        // globals in the enclosing scope.
-
-        m_fwd_scope = std::weak_ptr<symbol_scope_rep> ();
-        m_fwd_rep.reset ();
-      }
-
-      void unbind_global_rep (void)
-      {
-        // Break the link to the global symbol_record_rep.  These must
-        // forwarded, so we don't do anything unless the forward rep
-        // points to something.
-
-        if (auto t_fwd_rep = m_fwd_rep.lock ())
-          {
-            if (t_fwd_rep->is_marked_global ())
-              {
-                // The rep this object points to is in the global
-                // scope, so delete the link to it.
-
-                m_fwd_scope = std::weak_ptr<symbol_scope_rep> ();
-                m_fwd_rep.reset ();
-              }
-            else
-              t_fwd_rep->unbind_global_rep ();
-          }
-      }
-
-      std::shared_ptr<symbol_record_rep>
-      dup (const std::shared_ptr<symbol_scope_rep>& new_scope) const;
-
-      octave_value dump (context_id context) const;
+      octave_value dump (void) const;
 
       std::string name (void) const { return m_name; }
 
@@ -549,23 +141,23 @@
 
     private:
 
+      size_t m_frame_offset;
+      size_t m_data_offset;
+
       unsigned int m_storage_class;
 
       std::string m_name;
-
-      std::weak_ptr<symbol_scope_rep> m_fwd_scope;
-
-      std::weak_ptr<symbol_record_rep> m_fwd_rep;
-
-      std::deque<octave_value> m_value_stack;
     };
 
   public:
 
-    symbol_record (const std::string& nm = "",
-                   const octave_value& v = octave_value (),
+    symbol_record (const std::string& nm = "", unsigned int sc = local)
+      : m_rep (new symbol_record_rep (nm, sc))
+    { }
+
+    symbol_record (const std::string& nm, const octave_value&,
                    unsigned int sc = local)
-      : m_rep (new symbol_record_rep (nm, v, sc))
+      : m_rep (new symbol_record_rep (nm, sc))
     { }
 
     symbol_record (const symbol_record&) = default;
@@ -574,132 +166,39 @@
 
     ~symbol_record (void) = default;
 
-    symbol_record dup (const std::shared_ptr<symbol_scope_rep>& sid) const
-    {
-      return symbol_record (m_rep->dup (sid));
-    }
+    bool is_valid (void) const { return m_rep->is_valid (); }
+
+    explicit operator bool () const { return is_valid (); }
+
+    void set_frame_offset (size_t offset) { m_rep->set_frame_offset (offset); }
+
+    size_t frame_offset (void) const { return m_rep->frame_offset (); }
+
+    void set_data_offset (size_t offset) { m_rep->set_data_offset (offset); }
+
+    size_t data_offset (void) const { return m_rep->data_offset (); }
+
+    symbol_record dup (void) const { return symbol_record (m_rep->dup ()); }
 
     std::string name (void) const { return m_rep->name (); }
 
     void rename (const std::string& new_name) { m_rep->rename (new_name); }
 
-    octave_value
-    find (context_id context,
-          const octave_value_list& args = octave_value_list ()) const
-    {
-      octave_value retval = varval (context);
-
-      if (retval.is_undefined ())
-        return find_function (name (), args);
-
-      return retval;
-    }
-
-    void assign (const octave_value& value, context_id context)
-    {
-      m_rep->assign (value, context);
-    }
-
-    void assign (octave_value::assign_op op,
-                 const std::string& type,
-                 const std::list<octave_value_list>& idx,
-                 const octave_value& value, context_id context)
-    {
-      m_rep->assign (op, type, idx, value, context);
-    }
-
-    void assign (octave_value::assign_op op, const octave_value& value,
-                 context_id context)
-    {
-      m_rep->assign (op, value, context);
-    }
-
-    void do_non_const_unary_op (octave_value::unary_op op, context_id context)
-    {
-      m_rep->do_non_const_unary_op (op, context);
-    }
-
-    void do_non_const_unary_op (octave_value::unary_op op,
-                                const std::string& type,
-                                const std::list<octave_value_list>& idx,
-                                context_id context)
-    {
-      m_rep->do_non_const_unary_op (op, type, idx, context);
-    }
-
-    octave_value varval (context_id context) const
-    {
-      return m_rep->varval (context);
-    }
-
-    void push_context (void) { m_rep->push_context (); }
-
-    context_id pop_context (void) { return m_rep->pop_context (); }
-
-    void clear (context_id context) { m_rep->clear (context); }
-
-    bool is_defined (context_id context) const
-    {
-      return m_rep->is_defined (context);
-    }
-
-    bool is_undefined (context_id context) const
-    {
-      return ! m_rep->is_defined (context);
-    }
-
-    bool is_variable (context_id context) const
-    {
-      return m_rep->is_variable (context);
-    }
-
     bool is_local (void) const { return m_rep->is_local (); }
-    bool is_automatic (void) const { return m_rep->is_automatic (); }
     bool is_formal (void) const { return m_rep->is_formal (); }
-    bool is_global (void) const { return m_rep->is_global (); }
-    bool is_hidden (void) const { return m_rep->is_hidden (); }
-    bool is_inherited (void) const { return m_rep->is_inherited (); }
-    bool is_forwarded (void) const { return m_rep->is_forwarded (); }
-    bool is_persistent (void) const { return m_rep->is_persistent (); }
     bool is_added_static (void) const { return m_rep->is_added_static (); }
 
     void mark_local (void) { m_rep->mark_local (); }
-    void mark_automatic (void) { m_rep->mark_automatic (); }
     void mark_formal (void) { m_rep->mark_formal (); }
-    void mark_hidden (void) { m_rep->mark_hidden (); }
-    void mark_inherited (void) { m_rep->mark_inherited (); }
-    void mark_persistent (void) { m_rep->mark_persistent (); }
     void mark_added_static (void) { m_rep->mark_added_static (); }
 
     void unmark_local (void) { m_rep->unmark_local (); }
-    void unmark_automatic (void) { m_rep->unmark_automatic (); }
     void unmark_formal (void) { m_rep->unmark_formal (); }
-    void unmark_hidden (void) { m_rep->unmark_hidden (); }
-    void unmark_inherited (void) { m_rep->unmark_inherited (); }
-    void unmark_persistent (void) { m_rep->unmark_persistent (); }
     void unmark_added_static (void) { m_rep->unmark_added_static (); }
 
-    bool is_marked_global (void) const { return m_rep->is_marked_global (); }
-    void mark_global (void) { m_rep->mark_global (); }
-
-    void init_persistent (void) { m_rep->init_persistent (); }
-
     unsigned int storage_class (void) const { return m_rep->storage_class (); }
 
-    void bind_fwd_rep (const std::shared_ptr<symbol_scope_rep>& fwd_scope,
-                       const symbol_record& sr)
-    {
-      m_rep->bind_fwd_rep (fwd_scope, sr.m_rep);
-    }
-
-    void unbind_global_rep (void) { m_rep->unbind_global_rep (); }
-
-    void unbind_fwd_rep (void) { m_rep->unbind_fwd_rep (); }
-
-    octave_value dump (context_id context) const
-    {
-      return m_rep->dump (context);
-    }
+    octave_value dump (void) const { return m_rep->dump (); }
 
   private:
 
@@ -709,11 +208,6 @@
     symbol_record (const std::shared_ptr<symbol_record_rep>& new_rep)
       : m_rep (new_rep)
     { }
-
-    octave_value find_function (const std::string& name,
-                                const octave_value_list& args) const;
-
-    static octave_value dummy_octave_value;
   };
 }
 
--- a/libinterp/corefcn/symscope.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symscope.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -34,66 +34,30 @@
 #include "ov-usr-fcn.h"
 #include "symrec.h"
 #include "symscope.h"
-#include "symtab.h"
 #include "utils.h"
 
 namespace octave
 {
-  void symbol_scope_rep::install_auto_fcn_vars (void)
+  symbol_record symbol_scope_rep::insert_local (const std::string& name)
   {
-    install_auto_fcn_var (".argn.");
-    install_auto_fcn_var (".ignored.");
-    install_auto_fcn_var (".nargin.");
-    install_auto_fcn_var (".nargout.");
-    install_auto_fcn_var (".saved_warning_states.");
-  }
+    symbol_record sym (name);
 
-  void symbol_scope_rep::install_auto_fcn_var (const std::string& name)
-  {
-    insert (name, true);
-    mark_hidden (name);
-    mark_automatic (name);
+    insert_symbol_record (sym);
+
+    return sym;
   }
 
-  octave_value
-  symbol_scope_rep::find (const std::string& name)
+  void symbol_scope_rep::insert_symbol_record (symbol_record& sr)
   {
-    symbol_table& symtab
-      = __get_symbol_table__ ("symbol_scope_rep::find");
-
-    // Variable.
-
-    table_iterator p = m_symbols.find (name);
-
-    if (p != m_symbols.end ())
-      {
-        symbol_record sr = p->second;
+    size_t data_offset = num_symbols ();
+    std::string name = sr.name ();
 
-        if (sr.is_global ())
-          return symtab.global_varval (name);
-        else
-          {
-            octave_value val = sr.varval (m_context);
-
-            if (val.is_defined ())
-              return val;
-          }
-      }
+    sr.set_data_offset (data_offset);
 
-    // Subfunction.  I think it only makes sense to check for
-    // subfunctions if we are currently executing a function defined
-    // from a .m file.
-
-    octave_value fcn = find_subfunction (name);
-
-    if (fcn.is_defined ())
-      return fcn;
-
-    return symtab.fcn_table_find (name, ovl ());
+    m_symbols[name] = sr;
   }
 
-  symbol_record&
-  symbol_scope_rep::insert (const std::string& name, bool force_add)
+  symbol_record symbol_scope_rep::insert (const std::string& name)
   {
     table_iterator p = m_symbols.find (name);
 
@@ -101,13 +65,20 @@
       {
         symbol_record ret (name);
 
+        size_t data_offset = num_symbols ();
+
+        ret.set_data_offset (data_offset);
+
         auto t_parent = m_parent.lock ();
 
-        if (is_nested () && t_parent && t_parent->look_nonlocal (name, ret))
+        size_t offset = 0;
+
+        if (is_nested () && t_parent
+            && t_parent->look_nonlocal (name, offset, ret))
           return m_symbols[name] = ret;
         else
           {
-            if (m_is_static && ! force_add)
+            if (m_is_static)
               ret.mark_added_static ();
 
             return m_symbols[name] = ret;
@@ -139,13 +110,23 @@
     for (const auto& nm_sr : m_symbols)
       {
         std::string nm = nm_sr.first;
-        const symbol_record& sr = nm_sr.second;
-        info_map[nm] = sr.dump (m_context);
+        symbol_record sr = nm_sr.second;
+        info_map[nm] = sr.dump ();
       }
 
     return octave_value (info_map);
   }
 
+  std::list<symbol_record> symbol_scope_rep::symbol_list (void) const
+  {
+    std::list<symbol_record> retval;
+
+    for (const auto& nm_sr : m_symbols)
+      retval.push_back (nm_sr.second);
+
+    return retval;
+  }
+
   octave_value
   symbol_scope_rep::find_subfunction (const std::string& name) const
   {
@@ -194,18 +175,30 @@
         // Since is_nested is true, the following should always return a
         // valid scope.
 
+        auto t_parent = m_parent.lock ();
+
+        if (t_parent)
+          {
+            // SCOPE is the parent of this scope: this scope is a child
+            // of SCOPE.
+
+            if (t_parent == scope)
+              return true;
+          }
+
         auto t_primary_parent = m_primary_parent.lock ();
 
         if (t_primary_parent)
           {
             // SCOPE is the primary parent of this scope: this scope is a
-            // child of SCOPE.
+            // child (or grandchild) of SCOPE.
             if (t_primary_parent == scope)
               return true;
 
             // SCOPE and this scope share the same primary parent: they are
-            // siblings.
-            if (t_primary_parent == scope->primary_parent_scope_rep ())
+            // siblings (or cousins)
+            auto scope_primary_parent = scope->primary_parent_scope_rep ();
+            if (t_primary_parent == scope_primary_parent)
               return true;
           }
       }
@@ -213,8 +206,7 @@
     return false;
   }
 
-  void
-  symbol_scope_rep::update_nest (void)
+  void symbol_scope_rep::update_nest (void)
   {
     auto t_parent = m_parent.lock ();
 
@@ -225,12 +217,10 @@
           {
             symbol_record& ours = nm_sr.second;
 
-            if (! ours.is_formal ()
-                && is_nested () && t_parent->look_nonlocal (nm_sr.first, ours))
-              {
-                if (ours.is_global () || ours.is_persistent ())
-                  error ("global and persistent may only be used in the topmost level in which a nested variable is used");
-              }
+            size_t offset = 0;
+
+            if (! ours.is_formal () && is_nested ())
+              t_parent->look_nonlocal (nm_sr.first, offset, ours);
           }
 
         // The scopes of nested functions are static.
@@ -247,40 +237,37 @@
       scope_obj.update_nest ();
   }
 
-  bool
-  symbol_scope_rep::look_nonlocal (const std::string& name,
-                                   symbol_record& result)
+  bool symbol_scope_rep::look_nonlocal (const std::string& name,
+                                        size_t offset, symbol_record& result)
   {
+    offset++;
+
     table_iterator p = m_symbols.find (name);
+
     if (p == m_symbols.end ())
       {
         auto t_parent = m_parent.lock ();
 
         if (is_nested () && t_parent)
-          return t_parent->look_nonlocal (name, result);
+          return t_parent->look_nonlocal (name, offset, result);
       }
-    else if (! p->second.is_automatic ())
+    else
       {
-        result.bind_fwd_rep (shared_from_this (), p->second);
+        // Add scope offsets because the one we found may be used in
+        // this scope but initially from another parent scope beyond
+        // that.  The parent offset will already point to the first
+        // occurrence because we do the overall nesting update from the
+        // parent function down through the lists of all children.
+
+        size_t t_frame_offset = offset + p->second.frame_offset ();
+        size_t t_data_offset = p->second.data_offset ();
+
+        result.set_frame_offset (t_frame_offset);
+        result.set_data_offset (t_data_offset);
+
         return true;
       }
 
     return false;
   }
-
-  void
-  symbol_scope_rep::bind_script_symbols
-    (const std::shared_ptr<symbol_scope_rep>& curr_scope)
-  {
-    for (auto& nm_sr : m_symbols)
-      nm_sr.second.bind_fwd_rep (curr_scope,
-                                 curr_scope->find_symbol (nm_sr.first));
-  }
-
-  void
-  symbol_scope_rep::unbind_script_symbols (void)
-  {
-    for (auto& nm_sr : m_symbols)
-      nm_sr.second.unbind_fwd_rep ();
-  }
 }
--- a/libinterp/corefcn/symscope.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symscope.h	Fri Jul 12 12:14:43 2019 -0400
@@ -64,10 +64,15 @@
     subfunctions_iterator;
 
     symbol_scope_rep (const std::string& name = "")
-      : m_name (name), m_symbols (), m_subfunctions (), m_fcn (nullptr),
-        m_parent (), m_primary_parent (), m_children (),
-        m_nesting_depth (0), m_is_static (false), m_context (0)
-    { }
+      : m_name (name), m_symbols (), m_subfunctions (),
+        m_persistent_values (), m_fcn (nullptr), m_parent (),
+        m_primary_parent (), m_children (), m_nesting_depth (0),
+        m_is_static (false)
+    {
+      // All scopes have ans as the first symbol, initially undefined.
+
+      insert_local ("ans");
+    }
 
     // No copying!
 
@@ -77,14 +82,13 @@
 
     ~symbol_scope_rep (void) = default;
 
-    void insert_symbol_record (const symbol_record& sr)
-    {
-      m_symbols[sr.name ()] = sr;
-    }
+    size_t num_symbols (void) const { return m_symbols.size (); }
+
+    // Simply inserts symbol.  No non-local searching.
 
-    void install_auto_fcn_vars (void);
+    symbol_record insert_local (const std::string& name);
 
-    void install_auto_fcn_var (const std::string& name);
+    void insert_symbol_record (symbol_record& sr);
 
     bool is_nested (void) const { return m_nesting_depth > 0; }
 
@@ -92,6 +96,8 @@
 
     void set_nesting_depth (size_t depth) { m_nesting_depth = depth; }
 
+    bool is_parent (void) const { return ! m_children.empty (); }
+
     bool is_static (void) const { return m_is_static; }
 
     void mark_static (void) { m_is_static = true; }
@@ -112,22 +118,31 @@
         = std::shared_ptr<symbol_scope_rep> (new symbol_scope_rep (m_name));
 
       for (const auto& nm_sr : m_symbols)
-        new_sid->insert_symbol_record (nm_sr.second.dup (new_sid));
+        new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();
 
+      new_sid->m_subfunctions = m_subfunctions;
+      new_sid->m_persistent_values = m_persistent_values;
+      new_sid->m_subfunction_names = m_subfunction_names;
+      new_sid->m_fcn = m_fcn;
       new_sid->m_parent = m_parent;
       new_sid->m_primary_parent = m_primary_parent;
+      new_sid->m_children = m_children;
+      new_sid->m_nesting_depth = m_nesting_depth;
+      new_sid->m_is_static = m_is_static;
 
       return new_sid;
     }
 
-    void set_context (symbol_record::context_id context)
+    octave_value& persistent_varref (size_t data_offset)
     {
-      m_context = context;
+      return m_persistent_values[data_offset];
     }
 
-    symbol_record::context_id current_context (void) const
+    octave_value persistent_varval (size_t data_offset) const
     {
-      return m_context;
+      auto p = m_persistent_values.find (data_offset);
+
+      return p == m_persistent_values.end () ? octave_value () : p->second;
     }
 
     symbol_record find_symbol (const std::string& name)
@@ -140,51 +155,14 @@
         return p->second;
     }
 
-    void inherit_internal
-      (const std::shared_ptr<symbol_scope_rep>& donor_scope_rep)
+    symbol_record lookup_symbol (const std::string& name) const
     {
-      for (auto& nm_sr : m_symbols)
-        {
-          symbol_record& sr = nm_sr.second;
-
-          if (! (sr.is_automatic () || sr.is_formal ()))
-            {
-              std::string nm = sr.name ();
+      auto p = m_symbols.find (name);
 
-              if (nm != "__retval__")
-                {
-                  octave_value val = donor_scope_rep->varval (nm);
-
-                  if (val.is_defined ())
-                    {
-                      sr.assign (val, m_context);
-
-                      sr.mark_inherited ();
-                    }
-                }
-            }
-        }
+      return p == m_symbols.end () ? symbol_record () : p->second;
     }
 
-    void inherit (const std::shared_ptr<symbol_scope_rep>& donor_scope_rep)
-    {
-      std::shared_ptr<symbol_scope_rep> dsr = donor_scope_rep;
-
-      while (dsr)
-        {
-          inherit_internal (dsr);
-
-          if (dsr->is_nested ())
-            dsr = parent_scope_rep ();
-          else
-            break;
-        }
-    }
-
-    octave_value find (const std::string& name);
-
-    symbol_record&
-    insert (const std::string& name, bool force_add = false);
+    symbol_record insert (const std::string& name);
 
     void rename (const std::string& old_name, const std::string& new_name)
     {
@@ -202,289 +180,6 @@
         }
     }
 
-    void assign (const std::string& name, const octave_value& value,
-                 bool force_add)
-    {
-      auto p = m_symbols.find (name);
-
-      if (p == m_symbols.end ())
-        {
-          symbol_record& sr = insert (name, force_add);
-
-          sr.assign (value, m_context);
-        }
-      else
-        p->second.assign (value, m_context);
-    }
-
-    void assign (const std::string& name,
-                 const octave_value& value = octave_value ())
-    {
-      assign (name, value, false);
-    }
-
-    void force_assign (const std::string& name, const octave_value& value)
-    {
-      auto p = m_symbols.find (name);
-
-      if (p == m_symbols.end ())
-        {
-          symbol_record& sr = insert (name, true);
-
-          sr.assign (value, m_context);
-        }
-      else
-        p->second.assign (value, m_context);
-    }
-
-    octave_value varval (const std::string& name) const
-    {
-      table_const_iterator p = m_symbols.find (name);
-
-      return (p != m_symbols.end ()
-              ? p->second.varval (m_context) : octave_value ());
-    }
-
-    bool is_variable (const std::string& name) const
-    {
-      bool retval = false;
-
-      table_const_iterator p = m_symbols.find (name);
-
-      if (p != m_symbols.end ())
-        {
-          const symbol_record& sr = p->second;
-
-          retval = sr.is_variable (m_context);
-        }
-
-      return retval;
-    }
-
-    void push_context (void)
-    {
-      for (auto& nm_sr : m_symbols)
-        nm_sr.second.push_context ();
-    }
-
-    void pop_context (void)
-    {
-      auto tbl_it = m_symbols.begin ();
-
-      while (tbl_it != m_symbols.end ())
-        {
-          if (tbl_it->second.pop_context () == 0)
-            m_symbols.erase (tbl_it++);
-          else
-            tbl_it++;
-        }
-    }
-
-    void refresh (void)
-    {
-      for (auto& nm_sr : m_symbols)
-        {
-          symbol_record& sr = nm_sr.second;
-
-          if (sr.is_global ())
-            sr.unbind_global_rep ();
-          else if (! (sr.is_persistent () || sr.is_forwarded ()))
-            sr.clear (m_context);
-        }
-    }
-
-    void clear_variables (void)
-    {
-      for (auto& nm_sr : m_symbols)
-        nm_sr.second.clear (m_context);
-    }
-
-    void clear_objects (void)
-    {
-      for (auto& nm_sr : m_symbols)
-        {
-          symbol_record& sr = nm_sr.second;
-          octave_value val = sr.varval (m_context);
-          if (val.isobject ())
-            nm_sr.second.clear (m_context);
-        }
-    }
-
-    void clear_variable (const std::string& name)
-    {
-      auto p = m_symbols.find (name);
-
-      if (p != m_symbols.end ())
-        p->second.clear (m_context);
-      else if (is_nested ())
-        {
-          std::shared_ptr<symbol_scope_rep> psr = parent_scope_rep ();
-
-          if (psr)
-            psr->clear_variable (name);
-        }
-    }
-
-    void clear_variable_pattern (const std::string& pat)
-    {
-      glob_match pattern (pat);
-
-      for (auto& nm_sr : m_symbols)
-        {
-          symbol_record& sr = nm_sr.second;
-
-          if (sr.is_defined (m_context) || sr.is_global ())
-            {
-              if (pattern.match (sr.name ()))
-                sr.clear (m_context);
-            }
-        }
-
-      if (is_nested ())
-        {
-          std::shared_ptr<symbol_scope_rep> psr = parent_scope_rep ();
-
-          if (psr)
-            psr->clear_variable_pattern (pat);
-        }
-    }
-
-    void clear_variable_regexp (const std::string& pat)
-    {
-      octave::regexp pattern (pat);
-
-      for (auto& nm_sr : m_symbols)
-        {
-          symbol_record& sr = nm_sr.second;
-
-          if (sr.is_defined (m_context) || sr.is_global ())
-            {
-              if (pattern.is_match (sr.name ()))
-                sr.clear (m_context);
-            }
-        }
-
-      if (is_nested ())
-        {
-          std::shared_ptr<symbol_scope_rep> psr = parent_scope_rep ();
-
-          if (psr)
-            psr->clear_variable_regexp (pat);
-        }
-    }
-
-    void mark_automatic (const std::string& name)
-    {
-      insert (name).mark_automatic ();
-    }
-
-    void mark_hidden (const std::string& name)
-    {
-      insert (name).mark_hidden ();
-    }
-
-    void mark_global (const std::string& name)
-    {
-      insert (name).mark_global ();
-    }
-
-    std::list<symbol_record>
-    all_variables (bool defined_only = true,
-                   unsigned int exclude = symbol_record::hidden) const
-    {
-      std::list<symbol_record> retval;
-
-      for (const auto& nm_sr : m_symbols)
-        {
-          const symbol_record& sr = nm_sr.second;
-
-          if ((defined_only && ! sr.is_defined (m_context))
-              || (sr.storage_class () & exclude))
-            continue;
-
-          retval.push_back (sr);
-        }
-
-      return retval;
-    }
-
-    std::list<symbol_record>
-    glob (const std::string& pattern, bool vars_only = false) const
-    {
-      std::list<symbol_record> retval;
-
-      glob_match pat (pattern);
-
-      for (const auto& nm_sr : m_symbols)
-        {
-          if (pat.match (nm_sr.first))
-            {
-              const symbol_record& sr = nm_sr.second;
-
-              if (vars_only && ! sr.is_variable (m_context))
-                continue;
-
-              retval.push_back (sr);
-            }
-        }
-
-      return retval;
-    }
-
-    std::list<symbol_record>
-    regexp (const std::string& pattern, bool vars_only = false) const
-    {
-      std::list<symbol_record> retval;
-
-      octave::regexp pat (pattern);
-
-      for (const auto& nm_sr : m_symbols)
-        {
-          if (pat.is_match (nm_sr.first))
-            {
-              const symbol_record& sr = nm_sr.second;
-
-              if (vars_only && ! sr.is_variable (m_context))
-                continue;
-
-              retval.push_back (sr);
-            }
-        }
-
-      return retval;
-    }
-
-    std::list<std::string> variable_names (void)
-    {
-      std::list<std::string> retval;
-
-      for (const auto& nm_sr : m_symbols)
-        {
-          if (nm_sr.second.is_variable (m_context))
-            retval.push_back (nm_sr.first);
-        }
-
-      retval.sort ();
-
-      return retval;
-    }
-
-    bool is_local_variable (const std::string& name) const
-    {
-      table_const_iterator p = m_symbols.find (name);
-
-      return (p != m_symbols.end ()
-              && ! p->second.is_global ()
-              && p->second.is_defined (m_context));
-    }
-
-    bool is_global (const std::string& name) const
-    {
-      table_const_iterator p = m_symbols.find (name);
-
-      return p != m_symbols.end () && p->second.is_global ();
-    }
-
     void install_subfunction (const std::string& name,
                               const octave_value& fval)
     {
@@ -547,7 +242,7 @@
 
     void cache_name (const std::string& name) { m_name = name; }
 
-    octave_user_function *function (void) { return m_fcn; }
+    octave_user_function *function (void) const { return m_fcn; }
 
     void set_function (octave_user_function *fcn) { m_fcn = fcn; }
 
@@ -559,14 +254,23 @@
 
     void update_nest (void);
 
-    bool look_nonlocal (const std::string& name, symbol_record& result);
-
-    void bind_script_symbols (const std::shared_ptr<symbol_scope_rep>& curr_scope);
-
-    void unbind_script_symbols (void);
+    bool look_nonlocal (const std::string& name, size_t offset,
+                        symbol_record& result);
 
     octave_value dump_symbols_map (void) const;
 
+    const std::map<std::string, symbol_record>& symbols (void) const
+    {
+      return m_symbols;
+    }
+
+    std::map<std::string, symbol_record>& symbols (void)
+    {
+      return m_symbols;
+    }
+
+    std::list<symbol_record> symbol_list (void) const;
+
   private:
 
     //! Name for this scope (usually the corresponding filename of the
@@ -582,6 +286,9 @@
 
     std::map<std::string, octave_value> m_subfunctions;
 
+    //! Map from data offset to persistent values in this scope.
+    std::map<size_t, octave_value> m_persistent_values;
+
     //! The list of subfunctions (if any) in the order they appear in
     //! the function file.
 
@@ -611,8 +318,6 @@
     //! If true then no variables can be added.
 
     bool m_is_static;
-
-    symbol_record::context_id m_context;
   };
 
   class symbol_scope
@@ -640,23 +345,32 @@
 
     explicit operator bool () const { return bool (m_rep); }
 
-    void insert_symbol_record (const symbol_record& sr)
+    size_t num_symbols (void) const
+    {
+      return m_rep ? m_rep->num_symbols () : 0;
+    }
+
+    symbol_record insert_local (const std::string& name)
+    {
+      return m_rep ? m_rep->insert_local (name) : symbol_record ();
+    }
+
+    void insert_symbol_record (symbol_record& sr)
     {
       if (m_rep)
         m_rep->insert_symbol_record (sr);
     }
 
-    void install_auto_fcn_vars (void)
-    {
-      if (m_rep)
-        m_rep->install_auto_fcn_vars ();
-    }
-
     bool is_nested (void) const
     {
       return m_rep ? m_rep->is_nested () : false;
     }
 
+    bool is_parent (void) const
+    {
+      return m_rep ? m_rep->is_parent () : false;
+    }
+
     void set_nesting_depth (size_t depth)
     {
       if (m_rep)
@@ -694,15 +408,16 @@
       return symbol_scope (m_rep ? m_rep->dup () : nullptr);
     }
 
-    void set_context (symbol_record::context_id context)
+    octave_value& persistent_varref (size_t data_offset)
     {
-      if (m_rep)
-        m_rep->set_context (context);
+      static octave_value dummy_value;
+
+      return m_rep ? m_rep->persistent_varref (data_offset) : dummy_value;
     }
 
-    symbol_record::context_id current_context (void) const
+    octave_value persistent_varval (size_t data_offset) const
     {
-      return m_rep ? m_rep->current_context () : 0;
+      return m_rep ? m_rep->persistent_varval (data_offset) : octave_value ();
     }
 
     symbol_record find_symbol (const std::string& name)
@@ -710,22 +425,15 @@
       return m_rep ? m_rep->find_symbol (name) : symbol_record ();
     }
 
-    void inherit (const symbol_scope& donor_scope)
+    // Like find_symbol, but does not insert.
+    symbol_record lookup_symbol (const std::string& name) const
     {
-      if (m_rep)
-        m_rep->inherit (donor_scope.get_rep ());
+      return m_rep ? m_rep->lookup_symbol (name) : symbol_record ();
     }
 
-    octave_value find (const std::string& name)
+    symbol_record insert (const std::string& name)
     {
-      return m_rep ? m_rep->find (name) : octave_value ();
-    }
-
-    symbol_record&
-    insert (const std::string& name, bool force_add = false)
-    {
-      static symbol_record dummy_symrec;
-      return m_rep ? m_rep->insert (name, force_add) : dummy_symrec;
+      return m_rep ? m_rep->insert (name) : symbol_record ();
     }
 
     void rename (const std::string& old_name, const std::string& new_name)
@@ -734,146 +442,6 @@
         m_rep->rename (old_name, new_name);
     }
 
-    void assign (const std::string& name, const octave_value& value,
-                 bool force_add)
-    {
-      if (m_rep)
-        m_rep->assign (name, value, force_add);
-    }
-
-    void assign (const std::string& name,
-                 const octave_value& value = octave_value ())
-    {
-      if (m_rep)
-        m_rep->assign (name, value);
-    }
-
-    void force_assign (const std::string& name, const octave_value& value)
-    {
-      if (m_rep)
-        m_rep->force_assign (name, value);
-    }
-
-    octave_value varval (const std::string& name) const
-    {
-      return m_rep ? m_rep->varval (name) : octave_value ();
-    }
-
-    bool is_variable (const std::string& name) const
-    {
-      return m_rep ? m_rep->is_variable (name) : false;
-    }
-
-    void push_context (void)
-    {
-      if (m_rep)
-        m_rep->push_context ();
-    }
-
-    void pop_context (void)
-    {
-      if (m_rep)
-        m_rep->pop_context ();
-    }
-
-    void refresh (void)
-    {
-      if (m_rep)
-        m_rep->refresh ();
-    }
-
-    void clear_variables (void)
-    {
-      if (m_rep)
-        m_rep->clear_variables ();
-    }
-
-    void clear_objects (void)
-    {
-      if (m_rep)
-        m_rep->clear_objects ();
-    }
-
-    void clear_variable (const std::string& name)
-    {
-      if (m_rep)
-        m_rep->clear_variable (name);
-    }
-
-    void clear_variable_pattern (const std::string& pat)
-    {
-      if (m_rep)
-        m_rep->clear_variable_pattern (pat);
-    }
-
-    void clear_variable_regexp (const std::string& pat)
-    {
-      if (m_rep)
-        m_rep->clear_variable_regexp (pat);
-    }
-
-    void mark_automatic (const std::string& name)
-    {
-      if (m_rep)
-        m_rep->mark_automatic (name);
-    }
-
-    void mark_hidden (const std::string& name)
-    {
-      if (m_rep)
-        m_rep->mark_hidden (name);
-    }
-
-    // This function should only be called for the global
-    // symbol_scope, and that should only happen when it is added to
-    // the global symbol_scope.
-
-    void mark_global (const std::string& name)
-    {
-      if (m_rep)
-        m_rep->mark_global (name);
-    }
-
-    std::list<symbol_record>
-    all_variables (bool defined_only = true,
-                   unsigned int exclude = symbol_record::hidden) const
-    {
-      return (m_rep
-              ? m_rep->all_variables (defined_only, exclude)
-              : std::list<symbol_record> ());
-    }
-
-    std::list<symbol_record>
-    glob (const std::string& pattern, bool vars_only = false) const
-    {
-      return (m_rep
-              ? m_rep->glob (pattern, vars_only)
-              : std::list<symbol_record> ());
-    }
-
-    std::list<symbol_record>
-    regexp (const std::string& pattern, bool vars_only = false) const
-    {
-      return (m_rep
-              ? m_rep->regexp (pattern, vars_only)
-              : std::list<symbol_record> ());
-    }
-
-    std::list<std::string> variable_names (void)
-    {
-      return m_rep ? m_rep->variable_names () : std::list<std::string> ();
-    }
-
-    bool is_local_variable (const std::string& name) const
-    {
-      return m_rep ? m_rep->is_local_variable (name) : false;
-    }
-
-    bool is_global (const std::string& name) const
-    {
-      return m_rep ? m_rep->is_global (name) : false;
-    }
-
     void install_subfunction (const std::string& name,
                               const octave_value& fval)
     {
@@ -957,7 +525,7 @@
         m_rep->cache_name (name);
     }
 
-    octave_user_function * function (void)
+    octave_user_function * function (void) const
     {
       return m_rep ? m_rep->function () : nullptr;
     }
@@ -991,21 +559,10 @@
         m_rep->update_nest ();
     }
 
-    bool look_nonlocal (const std::string& name, symbol_record& result)
-    {
-      return m_rep ? m_rep->look_nonlocal (name, result) : false;
-    }
-
-    void bind_script_symbols (const symbol_scope& curr_scope)
+    bool look_nonlocal (const std::string& name, size_t offset,
+                        symbol_record& result)
     {
-      if (m_rep)
-        m_rep->bind_script_symbols (curr_scope.get_rep ());
-    }
-
-    void unbind_script_symbols (void)
-    {
-      if (m_rep)
-        m_rep->unbind_script_symbols ();
+      return m_rep ? m_rep->look_nonlocal (name, offset, result) : false;
     }
 
     std::shared_ptr<symbol_scope_rep> get_rep (void) const
@@ -1023,14 +580,30 @@
       return a.m_rep != b.m_rep;
     }
 
+    const std::map<std::string, symbol_record>& symbols (void) const
+    {
+      static const std::map<std::string, symbol_record> empty_map;
+
+      return m_rep ? m_rep->symbols () : empty_map;
+    }
+
+    std::map<std::string, symbol_record>& symbols (void)
+    {
+      static std::map<std::string, symbol_record> empty_map;
+
+      return m_rep ? m_rep->symbols () : empty_map;
+    }
+
+    std::list<symbol_record> symbol_list (void) const
+    {
+      static const std::list<symbol_record> empty_list;
+
+      return m_rep ? m_rep->symbol_list () : empty_list;
+    }
+
   private:
 
     std::shared_ptr<symbol_scope_rep> m_rep;
-
-    octave_value dump_symbols_map (void) const
-    {
-      return m_rep ? m_rep->dump_symbols_map () : octave_value ();
-    }
   };
 }
 
--- a/libinterp/corefcn/symtab.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symtab.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,16 +25,14 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include <sstream>
 
-#include "file-ops.h"
-#include "file-stat.h"
-#include "oct-env.h"
 #include "oct-time.h"
 
 #include "bp-table.h"
 #include "defun.h"
-#include "dirfns.h"
 #include "fcn-info.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
@@ -45,279 +43,378 @@
 #include "pager.h"
 #include "parse.h"
 #include "pt-pr-code.h"
-#include "symrec.h"
 #include "symscope.h"
 #include "symtab.h"
-#include "unwind-prot.h"
-#include "utils.h"
-
-// Should Octave always check to see if function files have changed
-// since they were last compiled?
-static int Vignore_function_time_stamp = 1;
 
 namespace octave
 {
-  static void
-  split_name_with_package (const std::string& name, std::string& fname,
-                           std::string& pname)
+  symbol_table::symbol_table (interpreter& interp)
+    : m_interpreter (interp), m_fcn_table (), m_class_precedence_table (),
+      m_parent_map ()
+  {
+    install_builtins ();
+  }
+
+  symbol_scope symbol_table::current_scope (void) const
+  {
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+    return tw.get_current_scope ();
+  }
+
+  bool symbol_table::is_built_in_function_name (const std::string& name)
   {
-    size_t pos = name.rfind ('.');
+    octave_value val = find_built_in_function (name);
+
+    return val.is_defined ();
+  }
+
+  // FIXME: this function only finds legacy class methods, not
+  // classdef methods.
+
+  octave_value symbol_table::find_method (const std::string& name,
+                                          const std::string& dispatch_type)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    fcn_table_const_iterator p = m_fcn_table.find (name);
 
-    fname.clear ();
-    pname.clear ();
-
-    if (pos != std::string::npos)
+    if (p != m_fcn_table.end ())
+      return p->second.find_method (dispatch_type);
+    else
       {
-        fname = name.substr (pos + 1);
-        pname = name.substr (0, pos);
+        fcn_info finfo (name);
+
+        octave_value fcn = finfo.find_method (dispatch_type);
+
+        if (fcn.is_defined ())
+          m_fcn_table[name] = finfo;
+
+        return fcn;
       }
-    else
-      fname = name;
+  }
+
+  octave_value symbol_table::find_built_in_function (const std::string& name)
+  {
+    fcn_table_const_iterator p = m_fcn_table.find (name);
+
+    return (p != m_fcn_table.end ()
+            ? p->second.find_built_in_function () : octave_value ());
+  }
+
+  octave_value symbol_table::find_autoload (const std::string& name)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    auto p = m_fcn_table.find (name);
+
+    return (p != m_fcn_table.end ()
+            ? p->second.find_autoload () : octave_value ());
   }
 
-  // Check the load path to see if file that defined this is still
-  // visible.  If the file is no longer visible, then erase the
-  // definition and move on.  If the file is visible, then we also
-  // need to check to see whether the file has changed since the
-  // function was loaded/parsed.  However, this check should only
-  // happen once per prompt (for files found from relative path
-  // elements, we also check if the working directory has changed
-  // since the last time the function was loaded/parsed).
-  //
-  // FIXME: perhaps this should be done for all loaded functions when
-  // the prompt is printed or the directory has changed, and then we
-  // would not check for it when finding symbol definitions.
+  octave_value
+  symbol_table::builtin_find (const std::string& name,
+                              const symbol_scope& search_scope_arg)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    fcn_table_iterator p = m_fcn_table.find (name);
+
+    symbol_scope search_scope
+      = (search_scope_arg ? search_scope_arg : current_scope ());
+
+    if (p != m_fcn_table.end ())
+      return p->second.builtin_find (search_scope);
+    else
+      {
+        fcn_info finfo (name);
+
+        octave_value fcn = finfo.builtin_find (search_scope);
+
+        if (fcn.is_defined ())
+          m_fcn_table[name] = finfo;
+
+        return fcn;
+      }
+
+    return octave_value ();
+  }
+
+  octave_value
+  symbol_table::fcn_table_find (const std::string& name,
+                                const octave_value_list& args,
+                                const symbol_scope& search_scope_arg)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    fcn_table_iterator p = m_fcn_table.find (name);
 
-  static inline bool
-  load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
-                        octave_value& function,
-                        const std::string& dispatch_type = "",
-                        const std::string& package_name = "")
-  {
-    bool retval = false;
+    symbol_scope search_scope
+      = (search_scope_arg ? search_scope_arg : current_scope ());
+
+    if (p != m_fcn_table.end ())
+      return p->second.find (search_scope, args);
+    else
+      {
+        fcn_info finfo (name);
+
+        octave_value fcn = finfo.find (search_scope, args);
+
+        if (fcn.is_defined ())
+          m_fcn_table[name] = finfo;
+
+        return fcn;
+      }
 
-    octave_value ov_fcn
-      = load_fcn_from_file (ff, dir_name, dispatch_type,
-                                    package_name);
+    return octave_value ();
+  }
+
+  octave_value
+  symbol_table::find_function (const std::string& name,
+                               const symbol_scope& search_scope_arg)
+  {
+    if (name.empty ())
+      return octave_value ();
 
-    if (ov_fcn.is_defined ())
+    if (name[0] == '@')
       {
-        retval = true;
+        size_t pos = name.find_first_of ('/');
+
+        if (pos == std::string::npos)
+          return octave_value ();
 
-        function = ov_fcn;
+        std::string method = name.substr (pos+1);
+        std::string dispatch_type = name.substr (1, pos-1);
+
+        return find_method (method, dispatch_type);
       }
     else
-      function = octave_value ();
+      {
+        symbol_scope search_scope
+          = (search_scope_arg ? search_scope_arg : current_scope ());
+
+        return find_function (name, ovl (), search_scope);
+      }
+  }
 
-    return retval;
+  octave_value
+  symbol_table::find_function (const std::string& name,
+                               const octave_value_list& args,
+                               const symbol_scope& search_scope)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    return fcn_table_find (name, args, search_scope);
+  }
+
+  octave_value
+  symbol_table::find_user_function (const std::string& name)
+  {
+    if (name.empty ())
+      return octave_value ();
+
+    auto p = m_fcn_table.find (name);
+
+    return (p != m_fcn_table.end ()
+            ? p->second.find_user_function () : octave_value ());
   }
 
-  bool
-  out_of_date_check (octave_value& function,
-                     const std::string& dispatch_type,
-                     bool check_relative)
+  octave_value symbol_table::find_cmdline_function (const std::string& name)
   {
-    bool retval = false;
+    if (name.empty ())
+      return octave_value ();
 
-    octave_function *fcn = function.function_value (true);
-
-    if (fcn)
-      {
-        // FIXME: we need to handle subfunctions properly here.
-
-        if (! fcn->is_subfunction ())
-          {
-            std::string ff = fcn->fcn_file_name ();
+    auto p = m_fcn_table.find (name);
 
-            if (! ff.empty ())
-              {
-                sys::time tc = fcn->time_checked ();
-
-                bool relative = check_relative && fcn->is_relative ();
+    return (p != m_fcn_table.end ()
+            ? p->second.find_cmdline_function () : octave_value ());
+  }
 
-                if (tc <= Vlast_prompt_time
-                    || (relative && tc < Vlast_chdir_time))
-                  {
-                    bool clear_breakpoints = false;
-                    std::string nm = fcn->name ();
-                    std::string pack = fcn->package_name ();
-                    std::string canonical_nm = fcn->canonical_name ();
-
-                    bool is_same_file = false;
-
-                    std::string file;
-                    std::string dir_name;
-
-                    if (check_relative)
-                      {
-                        int nm_len = nm.length ();
+  void symbol_table::install_cmdline_function (const std::string& name,
+                                               const octave_value& fcn)
+  {
+    auto p = m_fcn_table.find (name);
 
-                        if (sys::env::absolute_pathname (nm)
-                            && ((nm_len > 4
-                                 && (nm.substr (nm_len-4) == ".oct"
-                                     || nm.substr (nm_len-4) == ".mex"))
-                                || (nm_len > 2
-                                    && nm.substr (nm_len-2) == ".m")))
-                          file = nm;
-                        else
-                          {
-                            // We don't want to make this an absolute name,
-                            // because load_fcn_file looks at the name to
-                            // decide whether it came from a relative lookup.
-
-                            if (! dispatch_type.empty ())
-                              {
-                                load_path& lp
-                                  = __get_load_path__ ("out_of_date_check");
-
-                                file = lp.find_method (dispatch_type, nm,
-                                                       dir_name, pack);
-
-                                if (file.empty ())
-                                  {
-                                    std::string s_name;
-                                    std::string s_pack;
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
 
-                                    symbol_table& symtab
-                                      = __get_symbol_table__ ("out_of_date_check");
-
-                                    const std::list<std::string>& plist
-                                      = symtab.parent_classes (dispatch_type);
-
-                                    std::list<std::string>::const_iterator it
-                                      = plist.begin ();
+        finfo.install_cmdline_function (fcn);
+      }
+    else
+      {
+        fcn_info finfo (name);
 
-                                    while (it != plist.end ())
-                                      {
-                                        split_name_with_package (*it, s_name,
-                                                                 s_pack);
+        finfo.install_cmdline_function (fcn);
 
-                                        file = lp.find_method (*it, nm, dir_name,
-                                                               s_pack);
-                                        if (! file.empty ())
-                                          {
-                                            pack = s_pack;
-                                            break;
-                                          }
+        m_fcn_table[name] = finfo;
+      }
+  }
 
-                                        it++;
-                                      }
-                                  }
-                              }
+  // Install local function FCN named NAME.  FILE_NAME is the name of
+  // the file containing the local function.
 
-                            // Maybe it's an autoload?
-                            if (file.empty ())
-                              file = lookup_autoload (nm);
-
-                            if (file.empty ())
-                              {
-                                load_path& lp
-                                  = __get_load_path__ ("out_of_date_check");
-                                file = lp.find_fcn (nm, dir_name, pack);
-                              }
-                          }
-
-                        if (! file.empty ())
-                          is_same_file = same_file (file, ff);
-                      }
-                    else
-                      {
-                        is_same_file = true;
-                        file = ff;
-                      }
+  void symbol_table::install_local_function (const std::string& name,
+                                             const octave_value& fcn,
+                                             const std::string& file_name)
+  {
+    auto p = m_fcn_table.find (name);
 
-                    if (file.empty ())
-                      {
-                        // Can't see this function from current
-                        // directory, so we should clear it.
-
-                        function = octave_value ();
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
 
-                        clear_breakpoints = true;
-                      }
-                    else if (is_same_file)
-                      {
-                        // Same file.  If it is out of date, then reload it.
+        finfo.install_local_function (fcn, file_name);
+      }
+    else
+      {
+        fcn_info finfo (name);
 
-                        sys::time ottp = fcn->time_parsed ();
-                        time_t tp = ottp.unix_time ();
-
-                        fcn->mark_fcn_file_up_to_date (sys::time ());
-
-                        if (! (Vignore_function_time_stamp == 2
-                               || (Vignore_function_time_stamp
-                                   && fcn->is_system_fcn_file ())))
-                          {
-                            sys::file_stat fs (ff);
+        finfo.install_local_function (fcn, file_name);
 
-                            if (fs)
-                              {
-                                if (fs.is_newer (tp))
-                                  {
-                                    retval = load_out_of_date_fcn (ff, dir_name,
-                                                                   function,
-                                                                   dispatch_type,
-                                                                   pack);
+        m_fcn_table[name] = finfo;
+      }
+  }
 
-                                    clear_breakpoints = true;
-                                  }
-                              }
-                            else
-                              {
-                                function = octave_value ();
+  void symbol_table::install_user_function (const std::string& name,
+                                            const octave_value& fcn)
+  {
+    auto p = m_fcn_table.find (name);
 
-                                clear_breakpoints = true;
-                              }
-                          }
-                      }
-                    else
-                      {
-                        // Not the same file, so load the new file in
-                        // place of the old.
-
-                        retval = load_out_of_date_fcn (file, dir_name, function,
-                                                       dispatch_type, pack);
-
-                        clear_breakpoints = true;
-                      }
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
 
-                    // If the function has been replaced then clear any
-                    // breakpoints associated with it
-                    if (clear_breakpoints)
-                      {
-                        bp_table& bptab
-                          = __get_bp_table__ ("out_of_date_check");
+        finfo.install_user_function (fcn);
+      }
+    else
+      {
+        fcn_info finfo (name);
 
-                        bptab.remove_all_breakpoints_in_file (canonical_nm,
-                                                              true);
-                      }
-                  }
-              }
-          }
+        finfo.install_user_function (fcn);
+
+        m_fcn_table[name] = finfo;
       }
-
-    return retval;
   }
 
-  void
-  symbol_table::clear_global (const std::string& name)
+  // FIXME: should we ensure that FCN really is a built-in function
+  // object?
+  void symbol_table::install_built_in_function (const std::string& name,
+                                                const octave_value& fcn)
   {
-    m_global_scope.clear_variable (name);
+    auto p = m_fcn_table.find (name);
+
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
+
+        finfo.install_built_in_function (fcn);
+      }
+    else
+      {
+        fcn_info finfo (name);
+
+        finfo.install_built_in_function (fcn);
+
+        m_fcn_table[name] = finfo;
+      }
+  }
+
+  // This is written as two separate functions instead of a single
+  // function with default values so that it will work properly with
+  // unwind_protect.
+
+  void symbol_table::clear_functions (bool force)
+  {
+    auto p = m_fcn_table.begin ();
+
+    while (p != m_fcn_table.end ())
+      (p++)->second.clear (force);
+  }
+
+  void symbol_table::clear_function (const std::string& name)
+  {
+    clear_user_function (name);
   }
 
-  void
-  symbol_table::clear_global_pattern (const std::string& pattern)
+  void symbol_table::clear_function_pattern (const std::string& pat)
+  {
+    glob_match pattern (pat);
+
+    auto p = m_fcn_table.begin ();
+
+    while (p != m_fcn_table.end ())
+      {
+        if (pattern.match (p->first))
+          (p++)->second.clear_user_function ();
+        else
+          p++;
+      }
+  }
+
+  void symbol_table::clear_function_regexp (const std::string& pat)
+  {
+    regexp pattern (pat);
+
+    auto p = m_fcn_table.begin ();
+
+    while (p != m_fcn_table.end ())
+      {
+        if (pattern.is_match (p->first))
+          (p++)->second.clear_user_function ();
+        else
+          p++;
+      }
+  }
+
+  void symbol_table::clear_user_function (const std::string& name)
   {
-    m_global_scope.clear_variable_pattern (pattern);
+    auto p = m_fcn_table.find (name);
+
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
+
+        finfo.clear_user_function ();
+      }
+    // FIXME: is this necessary, or even useful?
+    // else
+    //   error ("clear: no such function '%s'", name.c_str ());
+  }
+
+  // This clears oct and mex files, including autoloads.
+  void symbol_table::clear_dld_function (const std::string& name)
+  {
+    auto p = m_fcn_table.find (name);
+
+    if (p != m_fcn_table.end ())
+      {
+        fcn_info& finfo = p->second;
+
+        finfo.clear_autoload_function ();
+        finfo.clear_user_function ();
+      }
+  }
+
+  void symbol_table::clear_mex_functions (void)
+  {
+    auto p = m_fcn_table.begin ();
+
+    while (p != m_fcn_table.end ())
+      (p++)->second.clear_mex_function ();
   }
 
   // Insert INF_CLASS in the set of class names that are considered
   // inferior to SUP_CLASS.  Return FALSE if INF_CLASS is currently
   // marked as superior to SUP_CLASS.
 
-  bool
-  symbol_table::set_class_relationship (const std::string& sup_class,
-                                        const std::string& inf_class)
+  bool symbol_table::set_class_relationship (const std::string& sup_class,
+                                             const std::string& inf_class)
   {
     if (is_superiorto (inf_class, sup_class))
       return false;
@@ -343,8 +440,7 @@
   //  else
   //    // No relation.
 
-  bool
-  symbol_table::is_superiorto (const std::string& a, const std::string& b)
+  bool symbol_table::is_superiorto (const std::string& a, const std::string& b)
   {
     class_precedence_table_const_iterator p = m_class_precedence_table.find (a);
     // If a has no entry in the precedence table, return false
@@ -356,111 +452,88 @@
     return (q != inferior_classes.end ());
   }
 
-  octave_value
-  symbol_table::builtin_find (const std::string& name)
+  void symbol_table::alias_built_in_function (const std::string& alias,
+                                              const std::string& name)
   {
-    fcn_table_iterator p = m_fcn_table.find (name);
+    octave_value fcn = find_built_in_function (name);
 
-    if (p != m_fcn_table.end ())
-      return p->second.builtin_find ();
-    else
+    if (fcn.is_defined ())
       {
-        fcn_info finfo (name);
+        fcn_info finfo (alias);
 
-        octave_value fcn = finfo.builtin_find ();
+        finfo.install_built_in_function (fcn);
 
-        if (fcn.is_defined ())
-          m_fcn_table[name] = finfo;
-
-        return fcn;
+        m_fcn_table[alias] = finfo;
       }
-
-    return octave_value ();
+    else
+      panic ("alias: '%s' is undefined", name.c_str ());
   }
 
-  octave_value
-  symbol_table::fcn_table_find (const std::string& name,
-                                const octave_value_list& args)
+  void symbol_table::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 ())
-      return p->second.find (args);
-    else
       {
-        fcn_info finfo (name);
-
-        octave_value fcn = finfo.find (args);
+        fcn_info& finfo = p->second;
 
-        if (fcn.is_defined ())
-          m_fcn_table[name] = finfo;
-
-        return fcn;
+        finfo.install_built_in_dispatch (klass);
       }
-
-    return octave_value ();
+    else
+      error ("install_built_in_dispatch: '%s' is undefined", name.c_str ());
   }
 
-  octave_value symbol_table::find_function (const std::string& name)
+  std::list<std::string> symbol_table::user_function_names (void)
   {
-    if (name.empty ())
-      return octave_value ();
-
-    if (name[0] == '@')
-      {
-        size_t pos = name.find_first_of ('/');
+    std::list<std::string> retval;
 
-        if (pos == std::string::npos)
-          return octave_value ();
+    for (const auto& nm_finfo : m_fcn_table)
+      {
+        if (nm_finfo.second.is_user_function_defined ())
+          retval.push_back (nm_finfo.first);
+      }
 
-        std::string method = name.substr (pos+1);
-        std::string dispatch_type = name.substr (1, pos-1);
+    if (! retval.empty ())
+      retval.sort ();
 
-        return find_method (method, dispatch_type);
-      }
-    else
-      return find_function (name, ovl ());
+    return retval;
   }
 
-  octave_value
-  symbol_table::find_function (const std::string& name,
-                               const octave_value_list& args)
+  std::list<std::string> symbol_table::built_in_function_names (void)
   {
-    octave_value fcn;
+    std::list<std::string> retval;
 
-    if (m_current_scope)
+    for (const auto& nm_finfo : m_fcn_table)
       {
-        fcn = m_current_scope.find_subfunction (name);
+        octave_value fcn = nm_finfo.second.find_built_in_function ();
 
         if (fcn.is_defined ())
-          return fcn;
+          retval.push_back (nm_finfo.first);
       }
 
-    return fcn_table_find (name, args);
+    if (! retval.empty ())
+      retval.sort ();
+
+    return retval;
   }
 
-  // FIXME: this function only finds legacy class methods, not
-  // classdef methods.
-
-  octave_value
-  symbol_table::find_method (const std::string& name,
-                             const std::string& dispatch_type)
+  std::list<std::string> symbol_table::cmdline_function_names (void)
   {
-    fcn_table_const_iterator p = m_fcn_table.find (name);
+    std::list<std::string> retval;
 
-    if (p != m_fcn_table.end ())
-      return p->second.find_method (dispatch_type);
-    else
+    for (const auto& nm_finfo : m_fcn_table)
       {
-        fcn_info finfo (name);
-
-        octave_value fcn = finfo.find_method (dispatch_type);
+        octave_value fcn = nm_finfo.second.find_cmdline_function ();
 
         if (fcn.is_defined ())
-          m_fcn_table[name] = finfo;
+          retval.push_back (nm_finfo.first);
+      }
 
-        return fcn;
-      }
+    if (! retval.empty ())
+      retval.sort ();
+
+    return retval;
   }
 
   template <template <typename, typename...> class C, typename V,
@@ -483,8 +556,7 @@
     return octave_value (info_map);
   }
 
-  octave_value
-  symbol_table::dump (void) const
+  octave_value symbol_table::dump (void) const
   {
     std::map<std::string, octave_value> m
       = {{ "function_info", dump_fcn_table_map () },
@@ -494,18 +566,59 @@
     return octave_value (m);
   }
 
-  void
-  symbol_table::cleanup (void)
+  void symbol_table::add_to_parent_map (const std::string& classname,
+                          const std::list<std::string>& parent_list)
+  {
+    m_parent_map[classname] = parent_list;
+  }
+
+  std::list<std::string> symbol_table::parent_classes (const std::string& dispatch_type)
   {
-    clear_all (true);
+    std::list<std::string> retval;
+
+    const_parent_map_iterator it = m_parent_map.find (dispatch_type);
+
+    if (it != m_parent_map.end ())
+      retval = it->second;
+
+    for (const auto& nm : retval)
+      {
+        // Search for parents of parents and append them to the list.
+
+        // FIXME: should we worry about a circular inheritance graph?
+
+        std::list<std::string> parents = parent_classes (nm);
+
+        if (! parents.empty ())
+          retval.insert (retval.end (), parents.begin (), parents.end ());
+      }
+
+    return retval;
+  }
+
+  octave_user_function * symbol_table::get_curr_fcn (void)
+  {
+    symbol_scope curr_scope = current_scope ();
+
+    return curr_scope ? curr_scope.function () : nullptr;
+  }
+
+  void symbol_table::cleanup (void)
+  {
+    clear_functions ();
 
     m_fcn_table.clear ();
     m_class_precedence_table.clear ();
     m_parent_map.clear ();
   }
 
-  octave_value
-  symbol_table::dump_fcn_table_map (void) const
+  fcn_info * symbol_table::get_fcn_info (const std::string& name)
+  {
+    auto p = m_fcn_table.find (name);
+    return p != m_fcn_table.end () ? &p->second : nullptr;
+  }
+
+  octave_value symbol_table::dump_fcn_table_map (void) const
   {
     if (m_fcn_table.empty ())
       return octave_value (Matrix ());
@@ -523,107 +636,11 @@
   }
 }
 
-DEFUN (ignore_function_time_stamp, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{val} =} ignore_function_time_stamp ()
-@deftypefnx {} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})
-Query or set the internal variable that controls whether Octave checks
-the time stamp on files each time it looks up functions defined in
-function files.
-
-If the internal variable is set to @qcode{"system"}, Octave will not
-automatically recompile function files in subdirectories of
-@file{@var{octave-home}/lib/@var{version}} if they have changed since they were last compiled, but will recompile other function files in the search path if they change.
-
-If set to @qcode{"all"}, Octave will not recompile any function files
-unless their definitions are removed with @code{clear}.
-
-If set to @qcode{"none"}, Octave will always check time stamps on files to
-determine whether functions defined in function files need to recompiled.
-@end deftypefn */)
-{
-  int nargin = args.length ();
-
-  if (nargin > 1)
-    print_usage ();
-
-  octave_value retval;
-
-  if (nargout > 0 || nargin == 0)
-    {
-      switch (Vignore_function_time_stamp)
-        {
-        case 1:
-          retval = "system";
-          break;
-
-        case 2:
-          retval = "all";
-          break;
-
-        default:
-          retval = "none";
-          break;
-        }
-    }
-
-  if (nargin == 1)
-    {
-      std::string sval = args(0).xstring_value ("ignore_function_time_stamp: first argument must be a string");
-
-      if (sval == "all")
-        Vignore_function_time_stamp = 2;
-      else if (sval == "system")
-        Vignore_function_time_stamp = 1;
-      else if (sval == "none")
-        Vignore_function_time_stamp = 0;
-      else
-        error (R"(ignore_function_time_stamp: argument must be one of "all", "system", or "none")");
-    }
-
-  return retval;
-}
-
-/*
-%!shared old_state
-%! old_state = ignore_function_time_stamp ();
-%!test
-%! state = ignore_function_time_stamp ("all");
-%! assert (state, old_state);
-%! assert (ignore_function_time_stamp (), "all");
-%! state = ignore_function_time_stamp ("system");
-%! assert (state, "all");
-%! assert (ignore_function_time_stamp (), "system");
-%! ignore_function_time_stamp (old_state);
-
-## Test input validation
-%!error (ignore_function_time_stamp ("all", "all"))
-%!error (ignore_function_time_stamp ("UNKNOWN_VALUE"))
-%!error (ignore_function_time_stamp (42))
-*/
-
-DEFMETHOD (__current_scope__, interp, , ,
-           doc: /* -*- texinfo -*-
-@deftypefn {} {[@var{scope}, @var{context}] =} __current_scope__ ()
-Return the current scope and context as integers.
-@seealso{__dump_symtab_info__}
-@end deftypefn */)
-{
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  std::string nm = scope ? scope.name () : "<unknown>";
-
-  return ovl (nm, symtab.current_context ());
-}
-
 DEFMETHOD (__dump_symtab_info__, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} __dump_symtab_info__ ()
 @deftypefnx {} {} __dump_symtab_info__ (@var{function})
 Undocumented internal function.
-@seealso{__current_scope__}
 @end deftypefn */)
 {
   int nargin = args.length ();
--- a/libinterp/corefcn/symtab.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/symtab.h	Fri Jul 12 12:14:43 2019 -0400
@@ -50,17 +50,11 @@
   {
   public:
 
-    typedef octave::symbol_record symbol_record;
+    // Make symbol_table::scope and symbol_table::fcn_info valid type names.
     typedef octave::symbol_scope scope;
     typedef octave::fcn_info fcn_info;
 
-    symbol_table (void)
-      : m_fcn_table (), m_class_precedence_table (),
-        m_parent_map (), m_global_scope ("global scope"),
-        m_top_scope ("top scope"), m_current_scope (m_top_scope)
-    {
-      install_builtins ();
-    }
+    symbol_table (interpreter& interp);
 
     // No copying!
 
@@ -70,147 +64,27 @@
 
     ~symbol_table (void) = default;
 
-    symbol_scope global_scope (void) { return m_global_scope; }
-    symbol_scope top_scope (void) { return m_top_scope; }
-
-    symbol_scope current_scope (void) { return m_current_scope; }
-
-    symbol_scope require_current_scope (const std::string& who)
-    {
-      if (! m_current_scope)
-        error ("%s: missing scope", who.c_str ());
-
-      return m_current_scope;
-    }
-
-    symbol_record::context_id current_context (void) const
-    {
-      return m_current_scope ? m_current_scope.current_context () : 0;
-    }
-
-    void set_scope (const symbol_scope& sid)
-    {
-      set_scope_and_context (sid, 0);
-    }
-
-    void set_scope_and_context (const symbol_scope& sid,
-                                symbol_record::context_id context)
-    {
-      if (sid == m_global_scope)
-        error ("can't set scope to global");
-
-      m_current_scope = sid;
-
-      if (m_current_scope)
-        m_current_scope.set_context (context);
-    }
-
-    symbol_record find_symbol (const std::string& name)
-    {
-      return m_current_scope.find_symbol (name);
-    }
-
-    symbol_record find_global_symbol (const std::string& name)
-    {
-      symbol_record sym = m_global_scope.find_symbol (name);
-
-      sym.mark_global ();
-
-      return sym;
-    }
-
-    void
-    inherit (symbol_scope& recipient_scope, const symbol_scope& donor_scope)
-    {
-      if (recipient_scope)
-        recipient_scope.inherit (donor_scope);
-    }
+    symbol_scope current_scope (void) const;
 
-    void inherit (symbol_scope& recipient_scope)
-    {
-      inherit (recipient_scope, m_current_scope);
-    }
-
-    bool at_top_level (void) { return m_current_scope == m_top_scope; }
-
-    void assign (const std::string& name, const octave_value& value, bool force_add)
-    {
-      if (m_current_scope)
-        m_current_scope.assign (name, value, force_add);
-    }
-
-    void assign (const std::string& name,
-                 const octave_value& value = octave_value ())
-    {
-      if (m_current_scope)
-        m_current_scope.assign (name, value);
-    }
-
-    octave_value varval (const std::string& name) const
-    {
-      return (m_current_scope
-              ? m_current_scope.varval (name) : octave_value ());
-    }
-
-    void global_assign (const std::string& name,
-                        const octave_value& value = octave_value ())
-    {
-      m_global_scope.assign (name, value);
-    }
-
-    octave_value global_varval (const std::string& name) const
-    {
-      return m_global_scope.varval (name);
-    }
-
-    void
-    top_level_assign (const std::string& name,
-                      const octave_value& value = octave_value ())
-    {
-      m_top_scope.assign (name, value);
-    }
-
-    octave_value top_level_varval (const std::string& name) const
-    {
-      return m_top_scope.varval (name);
-    }
-
-    bool
-    is_built_in_function_name (const std::string& name)
-    {
-      octave_value val = find_built_in_function (name);
-
-      return val.is_defined ();
-    }
+    bool is_built_in_function_name (const std::string& name);
 
     // FIXME: this function only finds legacy class methods, not
     // classdef methods.
-    octave_value
-    find_method (const std::string& name, const std::string& dispatch_type);
+    octave_value find_method (const std::string& name,
+                              const std::string& dispatch_type);
+
+    octave_value find_built_in_function (const std::string& name);
+
+    octave_value find_autoload (const std::string& name);
 
     octave_value
-    find_built_in_function (const std::string& name)
-    {
-      fcn_table_const_iterator p = m_fcn_table.find (name);
-
-      return (p != m_fcn_table.end ()
-              ? p->second.find_built_in_function () : octave_value ());
-    }
-
-    octave_value
-    find_autoload (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
-
-      return (p != m_fcn_table.end ()
-              ? p->second.find_autoload () : octave_value ());
-    }
-
-    octave_value builtin_find (const std::string& name);
+    builtin_find (const std::string& name,
+                  const symbol_scope& search_scope = symbol_scope ());
 
     octave_value
     fcn_table_find (const std::string& name,
-                    const octave_value_list& args = octave_value_list ());
+                    const octave_value_list& args = ovl (),
+                    const symbol_scope& search_scope = symbol_scope ());
 
     // If NAME is of the form @CLASS/FUNCTION, call
     //
@@ -218,222 +92,60 @@
     //
     // otherwise call
     //
-    //   function_function (NAME, ovl ())
+    //   find_function (NAME, ovl ())
 
-    octave_value find_function (const std::string& name);
+    octave_value
+    find_function (const std::string& name,
+                   const symbol_scope& search_scope = symbol_scope ());
 
     // NAME should just be function name; dispatch type determined
     // from types of ARGS.
 
     octave_value
-    find_function (const std::string& name, const octave_value_list& args);
-
-    octave_value find_user_function (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
+    find_function (const std::string& name,
+                   const octave_value_list& args,
+                   const symbol_scope& search_scope = symbol_scope ());
 
-      return (p != m_fcn_table.end ()
-              ? p->second.find_user_function () : octave_value ());
-    }
+    octave_value find_user_function (const std::string& name);
 
-    octave_value find_cmdline_function (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
-
-      return (p != m_fcn_table.end ()
-              ? p->second.find_cmdline_function () : octave_value ());
-    }
+    octave_value find_cmdline_function (const std::string& name);
 
     void install_cmdline_function (const std::string& name,
-                                   const octave_value& fcn)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.install_cmdline_function (fcn);
-        }
-      else
-        {
-          fcn_info finfo (name);
-
-          finfo.install_cmdline_function (fcn);
-
-          m_fcn_table[name] = finfo;
-        }
-    }
+                                   const octave_value& fcn);
 
     // Install local function FCN named NAME.  FILE_NAME is the name of
     // the file containing the local function.
 
     void install_local_function (const std::string& name,
                                  const octave_value& fcn,
-                                 const std::string& file_name)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.install_local_function (fcn, file_name);
-        }
-      else
-        {
-          fcn_info finfo (name);
-
-          finfo.install_local_function (fcn, file_name);
-
-          m_fcn_table[name] = finfo;
-        }
-    }
+                                 const std::string& file_name);
 
     void install_user_function (const std::string& name,
-                                const octave_value& fcn)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.install_user_function (fcn);
-        }
-      else
-        {
-          fcn_info finfo (name);
-
-          finfo.install_user_function (fcn);
-
-          m_fcn_table[name] = finfo;
-        }
-    }
+                                const octave_value& fcn);
 
     // FIXME: should we ensure that FCN really is a built-in function
     // object?
     void install_built_in_function (const std::string& name,
-                                    const octave_value& fcn)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.install_built_in_function (fcn);
-        }
-      else
-        {
-          fcn_info finfo (name);
-
-          finfo.install_built_in_function (fcn);
-
-          m_fcn_table[name] = finfo;
-        }
-    }
-
-    void clear_all (bool force = false)
-    {
-      m_current_scope.clear_variables ();
-      m_global_scope.clear_variables ();
-
-      clear_functions (force);
-    }
-
-    void clear_global (const std::string& name);
-
-    void clear_global_pattern (const std::string& pattern);
+                                    const octave_value& fcn);
 
     // This is written as two separate functions instead of a single
     // function with default values so that it will work properly with
     // unwind_protect.
 
-    void clear_functions (bool force = false)
-    {
-      auto p = m_fcn_table.begin ();
-
-      while (p != m_fcn_table.end ())
-        (p++)->second.clear (force);
-    }
-
-    void clear_function (const std::string& name)
-    {
-      clear_user_function (name);
-    }
+    void clear_functions (bool force = false);
 
-    void clear_symbol (const std::string& name)
-    {
-      // FIXME: are we supposed to do both here?
-
-      if (m_current_scope)
-        m_current_scope.clear_variable (name);
-
-      clear_function (name);
-    }
-
-    void clear_function_pattern (const std::string& pat)
-    {
-      glob_match pattern (pat);
-
-      auto p = m_fcn_table.begin ();
+    void clear_function (const std::string& name);
 
-      while (p != m_fcn_table.end ())
-        {
-          if (pattern.match (p->first))
-            (p++)->second.clear_user_function ();
-          else
-            p++;
-        }
-    }
-
-    void clear_symbol_pattern (const std::string& pat)
-    {
-      // FIXME: are we supposed to do both here?
-
-      if (m_current_scope)
-        m_current_scope.clear_variable_pattern (pat);
+    void clear_function_pattern (const std::string& pat);
 
-      clear_function_pattern (pat);
-    }
-
-    void clear_user_function (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
+    void clear_function_regexp (const std::string& pat);
 
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.clear_user_function ();
-        }
-      // FIXME: is this necessary, or even useful?
-      // else
-      //   error ("clear: no such function '%s'", name.c_str ());
-    }
+    void clear_user_function (const std::string& name);
 
     // This clears oct and mex files, including autoloads.
-    void clear_dld_function (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
+    void clear_dld_function (const std::string& name);
 
-          finfo.clear_autoload_function ();
-          finfo.clear_user_function ();
-        }
-    }
-
-    void clear_mex_functions (void)
-    {
-      auto p = m_fcn_table.begin ();
-
-      while (p != m_fcn_table.end ())
-        (p++)->second.clear_mex_function ();
-    }
+    void clear_mex_functions (void);
 
     bool set_class_relationship (const std::string& sup_class,
                                  const std::string& inf_class);
@@ -441,209 +153,34 @@
     bool is_superiorto (const std::string& a, const std::string& b);
 
     void alias_built_in_function (const std::string& alias,
-                                  const std::string& name)
-    {
-      octave_value fcn = find_built_in_function (name);
-
-      if (fcn.is_defined ())
-        {
-          fcn_info finfo (alias);
-
-          finfo.install_built_in_function (fcn);
-
-          m_fcn_table[alias] = finfo;
-        }
-      else
-        panic ("alias: '%s' is undefined", name.c_str ());
-    }
+                                  const std::string& name);
 
     void install_built_in_dispatch (const std::string& name,
-                                    const std::string& klass)
-    {
-      auto p = m_fcn_table.find (name);
-
-      if (p != m_fcn_table.end ())
-        {
-          fcn_info& finfo = p->second;
-
-          finfo.install_built_in_dispatch (klass);
-        }
-      else
-        error ("install_built_in_dispatch: '%s' is undefined", name.c_str ());
-    }
-
-    std::list<symbol_record> glob (const std::string& pattern)
-    {
-      return (m_current_scope
-              ? m_current_scope.glob (pattern) : std::list<symbol_record> ());
-    }
-
-    std::list<symbol_record> glob_global_variables (const std::string& pattern)
-    {
-      return m_global_scope.glob (pattern);
-    }
-
-    std::list<symbol_record>
-    regexp_global_variables (const std::string& pattern)
-    {
-      return m_global_scope.regexp (pattern);
-    }
+                                    const std::string& klass);
 
-    std::list<symbol_record> glob_variables (const string_vector& patterns)
-    {
-      std::list<symbol_record> retval;
-
-      if (! m_current_scope)
-        return retval;
-
-      size_t len = patterns.numel ();
-
-      for (size_t i = 0; i < len; i++)
-        {
-          std::list<symbol_record> tmp = m_current_scope.glob (patterns[i]);
-
-          retval.insert (retval.begin (), tmp.begin (), tmp.end ());
-        }
-
-      return retval;
-    }
-
-    std::list<symbol_record> regexp_variables (const string_vector& patterns)
-    {
-      std::list<symbol_record> retval;
-
-      if (! m_current_scope)
-        return retval;
-
-      size_t len = patterns.numel ();
-
-      for (size_t i = 0; i < len; i++)
-        {
-          std::list<symbol_record> tmp = m_current_scope.regexp (patterns[i]);
-
-          retval.insert (retval.begin (), tmp.begin (), tmp.end ());
-        }
-
-      return retval;
-    }
+    std::list<std::string> user_function_names (void);
 
-    std::list<std::string> user_function_names (void)
-    {
-      std::list<std::string> retval;
-
-      for (const auto& nm_finfo : m_fcn_table)
-        {
-          if (nm_finfo.second.is_user_function_defined ())
-            retval.push_back (nm_finfo.first);
-        }
-
-      if (! retval.empty ())
-        retval.sort ();
-
-      return retval;
-    }
-
-    std::list<std::string> global_variable_names (void)
-    {
-      return m_global_scope.variable_names ();
-    }
-
-    std::list<std::string> top_level_variable_names (void)
-    {
-      return (m_top_scope
-              ? m_top_scope.variable_names () : std::list<std::string> ());
-    }
-
-    std::list<std::string> variable_names (void)
-    {
-      return (m_current_scope
-              ? m_current_scope.variable_names () : std::list<std::string> ());
-    }
+    std::list<std::string> built_in_function_names (void);
 
-    std::list<std::string> built_in_function_names (void)
-    {
-      std::list<std::string> retval;
-
-      for (const auto& nm_finfo : m_fcn_table)
-        {
-          octave_value fcn = nm_finfo.second.find_built_in_function ();
-
-          if (fcn.is_defined ())
-            retval.push_back (nm_finfo.first);
-        }
-
-      if (! retval.empty ())
-        retval.sort ();
-
-      return retval;
-    }
-
-    std::list<std::string> cmdline_function_names (void)
-    {
-      std::list<std::string> retval;
-
-      for (const auto& nm_finfo : m_fcn_table)
-        {
-          octave_value fcn = nm_finfo.second.find_cmdline_function ();
-
-          if (fcn.is_defined ())
-            retval.push_back (nm_finfo.first);
-        }
-
-      if (! retval.empty ())
-        retval.sort ();
-
-      return retval;
-    }
+    std::list<std::string> cmdline_function_names (void);
 
     octave_value dump (void) const;
 
     void add_to_parent_map (const std::string& classname,
-                            const std::list<std::string>& parent_list)
-    {
-      m_parent_map[classname] = parent_list;
-    }
-
-    std::list<std::string>
-    parent_classes (const std::string& dispatch_type)
-    {
-      std::list<std::string> retval;
-
-      const_parent_map_iterator it = m_parent_map.find (dispatch_type);
-
-      if (it != m_parent_map.end ())
-        retval = it->second;
+                            const std::list<std::string>& parent_list);
 
-      for (const auto& nm : retval)
-        {
-          // Search for parents of parents and append them to the list.
-
-          // FIXME: should we worry about a circular inheritance graph?
-
-          std::list<std::string> parents = parent_classes (nm);
+    std::list<std::string> parent_classes (const std::string& dispatch_type);
 
-          if (! parents.empty ())
-            retval.insert (retval.end (), parents.begin (), parents.end ());
-        }
-
-      return retval;
-    }
-
-    octave_user_function * get_curr_fcn (void)
-    {
-      return m_current_scope ? m_current_scope.function () : nullptr;
-    }
+    octave_user_function * get_curr_fcn (void);
 
     void cleanup (void);
 
-    fcn_info * get_fcn_info (const std::string& name)
-    {
-      auto p = m_fcn_table.find (name);
-      return p != m_fcn_table.end () ? &p->second : nullptr;
-    }
+    fcn_info * get_fcn_info (const std::string& name);
 
   private:
 
+    interpreter& m_interpreter;
+
     typedef std::map<std::string, octave_value>::const_iterator
       global_symbols_const_iterator;
     typedef std::map<std::string, octave_value>::iterator
@@ -677,20 +214,11 @@
     typedef std::map<std::string, std::list<std::string>>::iterator
       parent_map_iterator;
 
-    symbol_scope m_global_scope;
-    symbol_scope m_top_scope;
-
-    symbol_scope m_current_scope;
-
     octave_value dump_fcn_table_map (void) const;
 
     // This function is generated automatically by mk-builtins.pl.
     void install_builtins (void);
   };
-
-  extern bool out_of_date_check (octave_value& function,
-                                 const std::string& dispatch_type = "",
-                                 bool check_relative = true);
 }
 
 #endif
--- a/libinterp/corefcn/syscalls.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/syscalls.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -484,9 +484,7 @@
   if (args.length () != 0)
     print_usage ();
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
-  if (symtab.at_top_level ())
+  if (interp.at_top_level ())
     error ("fork: cannot be called from command line");
 
   std::string msg;
@@ -1064,7 +1062,7 @@
 }
 
 /*
-%!test <51869>
+%!test <*51869>
 %! [info, status, msg] = uname ();
 %! if (status == 0)
 %!   assert (isstruct (info))
--- a/libinterp/corefcn/sysdep.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/sysdep.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -88,20 +88,6 @@
 #  define STDIN_FILENO 1
 #endif
 
-#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
-static void
-BSD_init (void)
-{
-#  if defined (HAVE_FLOATINGPOINT_H)
-  // Disable trapping on common exceptions.
-#    if ! defined (FP_X_DNML)
-#      define FP_X_DNML 0
-#    endif
-  fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
-#  endif
-}
-#endif
-
 #if defined (__MINGW32__) || defined (_MSC_VER)
 
 #define WIN32_LEAN_AND_MEAN
@@ -109,65 +95,85 @@
 #include <tlhelp32.h>
 #include <shellapi.h>
 
-static void
-w32_set_octave_home (void)
-{
-  std::string bin_dir;
-
-  HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE
-#if defined (TH32CS_SNAPMODULE32)
-                                       | TH32CS_SNAPMODULE32
-#endif
-                                       , 0);
-
-  if (h != INVALID_HANDLE_VALUE)
-    {
-      MODULEENTRY32W mod_info;
-
-      ZeroMemory (&mod_info, sizeof (mod_info));
-      mod_info.dwSize = sizeof (mod_info);
-
-      if (Module32FirstW (h, &mod_info))
-        {
-          do
-            {
-              std::string mod_name (octave::sys::u8_from_wstring (mod_info.szModule));
-
-              if (mod_name.find ("octinterp") != std::string::npos)
-                {
-                  bin_dir = octave::sys::u8_from_wstring (mod_info.szExePath);
-                  if (! bin_dir.empty () && bin_dir.back () != '\\')
-                    bin_dir.push_back ('\\');
-                  break;
-                }
-            }
-          while (Module32NextW (h, &mod_info));
-        }
-
-      CloseHandle (h);
-    }
-
-  if (! bin_dir.empty ())
-    {
-      size_t pos = bin_dir.rfind (R"(\bin\)");
-
-      if (pos != std::string::npos)
-        octave::sys::env::putenv ("OCTAVE_HOME", bin_dir.substr (0, pos));
-    }
-}
-
-static void
-w32_init (void)
-{
-  w32_set_octave_home ();
-
-  octave::command_editor::prefer_env_winsize (true);
-}
-
 #endif
 
 namespace octave
 {
+#if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
+
+  static void
+  BSD_init (void)
+  {
+#  if defined (HAVE_FLOATINGPOINT_H)
+    // Disable trapping on common exceptions.
+#    if ! defined (FP_X_DNML)
+#      define FP_X_DNML 0
+#    endif
+    fpsetmask (~(FP_X_OFL|FP_X_INV|FP_X_DZ|FP_X_DNML|FP_X_UFL|FP_X_IMP));
+#  endif
+  }
+
+#endif
+
+#if defined (__MINGW32__) || defined (_MSC_VER)
+
+  static void
+  w32_set_octave_home (void)
+  {
+    std::string bin_dir;
+
+    HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE
+#if defined (TH32CS_SNAPMODULE32)
+                                         | TH32CS_SNAPMODULE32
+#endif
+                                         , 0);
+
+    if (h != INVALID_HANDLE_VALUE)
+      {
+        MODULEENTRY32W mod_info;
+
+        ZeroMemory (&mod_info, sizeof (mod_info));
+        mod_info.dwSize = sizeof (mod_info);
+
+        if (Module32FirstW (h, &mod_info))
+          {
+            do
+              {
+                std::string mod_name (sys::u8_from_wstring (mod_info.szModule));
+
+                if (mod_name.find ("octinterp") != std::string::npos)
+                  {
+                    bin_dir = sys::u8_from_wstring (mod_info.szExePath);
+                    if (! bin_dir.empty () && bin_dir.back () != '\\')
+                      bin_dir.push_back ('\\');
+                    break;
+                  }
+              }
+            while (Module32NextW (h, &mod_info));
+          }
+
+        CloseHandle (h);
+      }
+
+    if (! bin_dir.empty ())
+      {
+        size_t pos = bin_dir.rfind (R"(\bin\)");
+
+        if (pos != std::string::npos)
+          sys::env::putenv ("OCTAVE_HOME", bin_dir.substr (0, pos));
+      }
+  }
+
+  static void
+  w32_init (void)
+  {
+    w32_set_octave_home ();
+
+    command_editor::prefer_env_winsize (true);
+  }
+
+#endif
+
   // Set app id if we have the SetCurrentProcessExplicitAppUserModelID
   // available (>= Win7).  FIXME: Could we check for existence of this
   // function in the configure script instead of dynamically loading
@@ -200,7 +206,7 @@
 DEFUN (__open_with_system_app__, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} __open_with_system_app__ (@var{file})
-Undocumented internal function.
+Internal function.  Returns 1 on successful system call and 0 otherwise.
 @end deftypefn */)
 {
   if (args.length () != 1)
@@ -208,52 +214,53 @@
 
   std::string file = args(0).xstring_value ("__open_with_system_app__: argument must be a filename");
 
-  octave_value retval;
-
 #if defined (OCTAVE_USE_WINDOWS_API)
-  HINSTANCE status = ShellExecuteW (0, 0,
-                                    octave::sys::u8_to_wstring (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);
-#elif defined (__APPLE__)
+  return octave_value (reinterpret_cast<ptrdiff_t> (status) > 32);
+#else
+#  if defined (__APPLE__)
+#    define FSYSTEM_OPEN_STR "open "
+#  else
+#    define FSYSTEM_OPEN_STR "xdg-open "
+#  endif
   octave_value_list tmp
-    = Fsystem (ovl ("open " + file + " 2> /dev/null",
+    = Fsystem (ovl (FSYSTEM_OPEN_STR + file + " 2> /dev/null",
                     false, "async"),
                1);
+#  undef FSYSTEM_OPEN_STR
 
-  retval = (tmp(0).double_value () == 0);
-#else
-  octave_value_list tmp
-    = Fsystem (ovl ("xdg-open " + file + " 2> /dev/null",
-                    false, "async"),
-               1);
-
-  retval = (tmp(0).double_value () == 0);
+  // Asynchronous Fsystem calls return the new child process identifier,
+  // which must be greater than 1 if successful.
+  return octave_value (tmp(0).double_value () > 1);
 #endif
-
-  return retval;
 }
 
+namespace octave
+{
 #if defined (__MINGW32__)
-static void
-MINGW_init (void)
-{
-  w32_init ();
-}
+
+  static void
+  MINGW_init (void)
+  {
+    w32_init ();
+  }
+
 #endif
 
 #if defined (_MSC_VER)
-static void
-MSVC_init (void)
-{
-  w32_init ();
-}
+
+  static void
+  MSVC_init (void)
+  {
+    w32_init ();
+  }
+
 #endif
 
-namespace octave
-{
   // Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
 
   bool same_file_internal (const std::string& file1, const std::string& file2)
@@ -262,8 +269,8 @@
 
     bool retval = false;
 
-    std::wstring file1w = octave::sys::u8_to_wstring (file1);
-    std::wstring file2w = octave::sys::u8_to_wstring (file2);
+    std::wstring file1w = sys::u8_to_wstring (file1);
+    std::wstring file2w = sys::u8_to_wstring (file2);
     const wchar_t *f1 = file1w.c_str ();
     const wchar_t *f2 = file2w.c_str ();
 
@@ -310,8 +317,8 @@
 
     // POSIX Code
 
-    octave::sys::file_stat fs_file1 (file1);
-    octave::sys::file_stat fs_file2 (file2);
+    sys::file_stat fs_file1 (file1);
+    sys::file_stat fs_file2 (file2);
 
     return (fs_file1 && fs_file2
             && fs_file1.ino () == fs_file2.ino ()
@@ -320,6 +327,57 @@
 #endif
   }
 
+  // Return TRUE if NAME refers to an existing drive letter or UNC share
+
+  bool drive_or_unc_share (const std::string& name)
+  {
+#if defined (OCTAVE_USE_WINDOWS_API)
+    size_t len = name.length ();
+    bool candidate = false;
+    if (len > 1 && isalpha(name[0]) && name[1]==':'
+         && (len == 2 || (len == 3 && name[2] == '\\')))
+      candidate = true;
+    if (len > 4 && name[0] == '\\' && name[1] == '\\')
+      {
+        // It starts with two slashes.  Find the next slash.
+        size_t next_slash = name.find ("\\", 3);
+        if (next_slash != -1 && len > next_slash+1)
+          {
+            // Check if it ends with the share
+            size_t last_slash = name.find ("\\", next_slash+1);
+            if (last_slash == -1 ||
+                (len > next_slash+2 && last_slash == len-1))
+              candidate = true;
+          }
+      }
+
+    if (candidate)
+      {
+        // Open a handle to the file.
+        std::wstring wname = sys::u8_to_wstring (name);
+        HANDLE h =
+          CreateFileW (wname.c_str (), FILE_READ_ATTRIBUTES,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                       nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
+                       nullptr);
+        if (h != INVALID_HANDLE_VALUE)
+          {
+            CloseHandle (h);
+            return true;
+          }
+      }
+
+    return false;
+
+#else
+
+    octave_unused_parameter (name);
+
+    return false;
+
+#endif
+  }
+
   void sysdep_init (void)
   {
     // Use a function from libgomp to force loading of OpenMP library.
@@ -365,8 +423,8 @@
     int tty_fd = STDIN_FILENO;
     if (! octave_isatty_wrapper (tty_fd))
       {
-        if (octave::application::interactive ()
-            && ! octave::application::forced_interactive ())
+        if (application::interactive ()
+            && ! application::forced_interactive ())
           error ("stdin is not a tty!");
       }
 
@@ -511,7 +569,7 @@
     wchar_t *wcommand = u8_to_wchar (command);
     wchar_t *wmode = u8_to_wchar (mode);
 
-    octave::unwind_protect frame;
+    unwind_protect frame;
     frame.add_fcn (::free, static_cast<void *> (wcommand));
     frame.add_fcn (::free, static_cast<void *> (wmode));
 
@@ -559,13 +617,13 @@
     raw_mode (true, wait);
 
     // Get current handler.
-    octave::interrupt_handler saved_interrupt_handler
-      = octave::ignore_interrupts ();
+    interrupt_handler saved_interrupt_handler
+      = ignore_interrupts ();
 
     // Restore it, disabling system call restarts (if possible) so the
     // read can be interrupted.
 
-    octave::set_interrupt_handler (saved_interrupt_handler, false);
+    set_interrupt_handler (saved_interrupt_handler, false);
 
     int c = std::cin.get ();
 
@@ -576,7 +634,7 @@
       }
 
     // Restore it, enabling system call restarts (if possible).
-    octave::set_interrupt_handler (saved_interrupt_handler, true);
+    set_interrupt_handler (saved_interrupt_handler, true);
 
     raw_mode (false, true);
 #endif
@@ -600,10 +658,10 @@
 
     if (retval.empty () || retval == R"(\)")
       {
-        retval = octave::sys::env::getenv ("TEMP");
+        retval = sys::env::getenv ("TEMP");
 
         if (retval.empty ())
-          retval = octave::sys::env::getenv ("TMP");
+          retval = sys::env::getenv ("TMP");
 
         if (retval.empty ())
           retval = R"(c:\temp)";
@@ -729,91 +787,98 @@
 
 #if defined (OCTAVE_USE_WINDOWS_API)
 
-static void
-reg_close_key_wrapper (HKEY key)
+namespace octave
 {
-  RegCloseKey (key);
+  static void
+  reg_close_key_wrapper (HKEY key)
+  {
+    RegCloseKey (key);
+  }
+
+  // This function is also used in ov-java.cc, so don't declare static.
+  // Maybe the functions that use it should be here instead?
+
+  LONG
+  get_regkey_value (HKEY h_rootkey, const std::string subkey,
+                    const std::string name, octave_value& value)
+  {
+    LONG result;
+    HKEY h_subkey;
+
+    result = RegOpenKeyExW (h_rootkey,
+                            sys::u8_to_wstring (subkey).c_str (), 0,
+                            KEY_READ, &h_subkey);
+    if (result != ERROR_SUCCESS)
+      return result;
+
+    unwind_protect frame;
+
+    frame.add_fcn (reg_close_key_wrapper, h_subkey);
+
+    DWORD length = 0;
+    result = RegQueryValueExW (h_subkey,
+                               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 = RegQueryValueExW (h_subkey,
+                               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 (sys::u8_from_wstring (
+                                                           reinterpret_cast<wchar_t *> (data)));
+
+    return result;
+  }
+
+  static LONG
+  get_regkey_names (HKEY h_rootkey, const std::string subkey,
+                    std::list<std::string> &fields)
+  {
+    LONG retval;
+    HKEY h_subkey;
+
+    fields.clear ();
+
+    retval = RegOpenKeyExW (h_rootkey,
+                            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;
+    wchar_t value_name[MAX_VALUE_NAME_SIZE+1];
+    DWORD value_name_size = MAX_VALUE_NAME_SIZE;
+
+    while (true)
+      {
+        retval = RegEnumValueW (h_subkey, idx, value_name, &value_name_size,
+                                nullptr, nullptr, nullptr, nullptr);
+        if (retval != ERROR_SUCCESS)
+          break;
+        fields.push_back (sys::u8_from_wstring (value_name));
+        value_name_size = MAX_VALUE_NAME_SIZE;
+        idx++;
+      }
+
+    if (retval == ERROR_NO_MORE_ITEMS)
+      retval = ERROR_SUCCESS;
+
+    RegCloseKey (h_subkey);
+
+    return retval;
+  }
 }
 
-LONG
-get_regkey_value (HKEY h_rootkey, const std::string subkey,
-                  const std::string name, octave_value& value)
-{
-  LONG result;
-  HKEY 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;
-
-  octave::unwind_protect frame;
-
-  frame.add_fcn (reg_close_key_wrapper, h_subkey);
-
-  DWORD length = 0;
-  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 = 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 (octave::sys::u8_from_wstring (
-                                        reinterpret_cast<wchar_t *> (data)));
-
-  return result;
-}
-
-static LONG
-get_regkey_names (HKEY h_rootkey, const std::string subkey,
-                  std::list<std::string> &fields)
-{
-  LONG retval;
-  HKEY h_subkey;
-
-  fields.clear ();
-
-  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;
-  wchar_t value_name[MAX_VALUE_NAME_SIZE+1];
-  DWORD value_name_size = MAX_VALUE_NAME_SIZE;
-
-  while (true)
-    {
-      retval = RegEnumValueW (h_subkey, idx, value_name, &value_name_size,
-                              nullptr, nullptr, nullptr, nullptr);
-      if (retval != ERROR_SUCCESS)
-        break;
-      fields.push_back (octave::sys::u8_from_wstring (value_name));
-      value_name_size = MAX_VALUE_NAME_SIZE;
-      idx++;
-    }
-
-  if (retval == ERROR_NO_MORE_ITEMS)
-    retval = ERROR_SUCCESS;
-
-  RegCloseKey (h_subkey);
-
-  return retval;
-}
 #endif
 
 DEFUN (winqueryreg, args, ,
@@ -938,7 +1003,7 @@
     {
       std::list<std::string> fields;
 
-      LONG retval = get_regkey_names (h_rootkey, subkey_name, fields);
+      LONG retval = octave::get_regkey_names (h_rootkey, subkey_name, fields);
       if (retval != ERROR_SUCCESS)
         error ("winqueryreg: error %ld reading names from registry", retval);
 
@@ -953,8 +1018,8 @@
   else
     {
       octave_value key_val;
-      LONG retval = get_regkey_value (h_rootkey, subkey_name, value_name,
-                                      key_val);
+      LONG retval = octave::get_regkey_value (h_rootkey, subkey_name,
+                                              value_name, key_val);
       if (retval == ERROR_FILE_NOT_FOUND)
         error ("winqueryreg: no value found for '%s' at %s\\%s.",
                value_name.c_str (), rootkey_name.c_str (),
--- a/libinterp/corefcn/sysdep.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/sysdep.h	Fri Jul 12 12:14:43 2019 -0400
@@ -52,6 +52,8 @@
 
   extern OCTINTERP_API bool same_file_internal (const std::string&,
                                                 const std::string&);
+
+  extern OCTINTERP_API bool drive_or_unc_share (const std::string&);
 }
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
--- a/libinterp/corefcn/text-renderer.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/text-renderer.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -30,17 +30,17 @@
 #include "ft-text-renderer.h"
 #include "text-renderer.h"
 
-static octave::base_text_renderer *
-make_text_renderer (void)
-{
-  // Allow the possibility of choosing different text rendering
-  // implementations.
-
-  return octave::make_ft_text_renderer ();
-}
-
 namespace octave
 {
+  static base_text_renderer *
+  make_text_renderer (void)
+  {
+    // Allow the possibility of choosing different text rendering
+    // implementations.
+
+    return make_ft_text_renderer ();
+  }
+
   text_renderer::text_renderer (void)
     : rep (make_text_renderer ())
   { }
@@ -87,6 +87,13 @@
   }
 
   void
+  text_renderer::set_anti_aliasing (bool val)
+  {
+    if (ok ())
+      rep->set_anti_aliasing (val);
+  }
+
+  void
   text_renderer::set_font (const std::string& name, const std::string& weight,
                            const std::string& angle, double size)
   {
--- a/libinterp/corefcn/text-renderer.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/text-renderer.h	Fri Jul 12 12:14:43 2019 -0400
@@ -62,6 +62,8 @@
     Matrix get_extent (const std::string& txt, double rotation = 0.0,
                        const caseless_str& interpreter = "tex");
 
+    void set_anti_aliasing (bool val);
+
     void set_font (const std::string& name, const std::string& weight,
                    const std::string& angle, double size);
 
--- a/libinterp/corefcn/time.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/time.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -156,7 +156,7 @@
 @seealso{strftime, strptime, localtime, mktime, time, now, date, clock, datenum, datestr, datevec, calendar, weekday}
 @end deftypefn */)
 {
-  if (args.length () != 1)
+  if (args.length () != 1 || args(0).numel () != 1)
     print_usage ();
 
   double tmp = args(0).double_value ();
@@ -211,7 +211,7 @@
 @seealso{strftime, strptime, gmtime, mktime, time, now, date, clock, datenum, datestr, datevec, calendar, weekday}
 @end deftypefn */)
 {
-  if (args.length () != 1)
+  if (args.length () != 1 || args(0).numel () != 1)
     print_usage ();
 
   double tmp = args(0).double_value ();
--- a/libinterp/corefcn/toplev.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/toplev.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -48,7 +48,6 @@
 
 #include "build-env.h"
 #include "liboctinterp-build-info.h"
-#include "call-stack.h"
 #include "defaults.h"
 #include "defun.h"
 #include "error.h"
@@ -285,6 +284,7 @@
   frame.add_fcn (restore_signal_mask, get_signal_mask ());
 
   octave_unblock_async_signals ();
+  octave_unblock_signal_by_name ("SIGTSTP");
 
   if (type == et_async)
     retval(0) = octave_async_system_wrapper (cmd_str.c_str ());
--- a/libinterp/corefcn/url-handle-manager.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/url-handle-manager.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -30,16 +30,16 @@
 
 #include "url-handle-manager.h"
 
-static double
-make_handle_fraction (void)
-{
-  static double maxrand = RAND_MAX + 2.0;
-
-  return (rand () + 1.0) / maxrand;
-}
-
 namespace octave
 {
+  static double
+  make_handle_fraction (void)
+  {
+    static double maxrand = RAND_MAX + 2.0;
+
+    return (rand () + 1.0) / maxrand;
+  }
+
   url_handle url_handle_manager::get_handle (void)
   {
     url_handle retval;
--- a/libinterp/corefcn/urlwrite.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/urlwrite.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -47,6 +47,7 @@
 #include "oct-map.h"
 #include "oct-refcount.h"
 #include "ov-cell.h"
+#include "ov-classdef.h"
 #include "ovl.h"
 #include "pager.h"
 #include "unwind-prot.h"
@@ -680,7 +681,8 @@
   std::string target;
 
   if (nargin == 3 && ! args(2).isempty ())
-    target = args(2).xstring_value ("__ftp_mget__: TARGET must be a string") + octave::sys::file_ops::dir_sep_str ();
+    target = args(2).xstring_value ("__ftp_mget__: TARGET must be a string")
+                        + octave::sys::file_ops::dir_sep_str ();
 
   octave::url_handle_manager& uhm = interp.get_url_handle_manager ();
 
@@ -738,3 +740,93 @@
 
   return ovl ();
 }
+
+DEFUN (__restful_service__, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{response} =} __restful_service__ (@var{url}, @var{param}, @var{weboptions})
+Undocumented internal function.
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin < 1)
+    print_usage ();
+
+  std::string url = args(0).xstring_value ("__restful_service__: URL must be a string");
+
+  std::ostringstream content;
+
+  octave::url_transfer url_xfer (url, content);
+
+  if (! url_xfer.is_valid ())
+    error ("support for URL transfers was disabled when Octave was built");
+
+  Array<std::string> param = args(1).cellstr_value ();
+
+  std::string data, method;
+
+  struct octave::weboptions options;
+
+  octave::cdef_object object = args (nargin - 1).classdef_object_value ()
+                                                         -> get_object ();
+
+  // We could've used object.map_value () instead to return a map but that
+  // shows a warning about about overriding access restrictions.
+  // Nevertheless, we are keeping checking that here if the keys are not
+  // equal to "delete" and "display", getting away with the warning.
+  string_vector keys = object.map_keys ();
+
+  for (int i = 0; i < keys.numel (); i++)
+  {
+    if (keys(i) == "Timeout")
+    {
+      float timeout = object.get (keys(i)).float_value ();
+      options.Timeout = static_cast<long>(timeout * 1000);
+    }
+
+    if (keys(i) == "HeaderFields")
+    {
+      options.HeaderFields = object.get (keys(i)).cellstr_value ();
+    }
+
+    // FIXME: 'delete' and 'display', auto-generated, probably by cdef_object
+    // class?  Remaining fields have already been adjusted elsewhere in the
+    // m-script.  Set 'value' as the Value of the Key wherever it's a string.
+    if (keys(i) != "Timeout" && keys(i) != "HeaderFields"
+        && keys(i) != "delete" && keys(i) != "display")
+    {
+      std::string value = object.get (keys(i)).string_value ();
+
+      if (keys(i) == "UserAgent")
+        options.UserAgent = value;
+
+      if (keys(i) == "Username")
+        options.Username = value;
+
+      if (keys(i) == "Password")
+        options.Password = value;
+
+      if (keys(i) == "ContentReader")
+        // Unimplemented. Only for MATLAB compatibility.
+        options.ContentReader = "";
+
+      if (keys(i) == "RequestMethod")
+        method = value;
+
+      if (keys(i) == "ArrayFormat")
+        options.ArrayFormat = value;
+
+      if (keys(i) == "CertificateFilename")
+        options.CertificateFilename = "";
+    }
+  }
+
+  url_xfer.set_weboptions (options);
+
+  url_xfer.http_action (param, method);
+
+  if (nargout < 2 && ! url_xfer.good ())
+    error ("__restful_service__: %s", url_xfer.lasterror ().c_str ());
+
+  return ovl (content.str ());
+}
--- a/libinterp/corefcn/utils.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/utils.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1106,7 +1106,7 @@
       for (octave_idx_type i = 0; i < n; i++)
         dim(i) = v(i);
 
-    octave::check_dimensions (dim, warn_for);
+    check_dimensions (dim, warn_for);
   }
 
   void get_dimensions (const octave_value& a, const char *warn_for,
@@ -1129,7 +1129,7 @@
         nc = v(1);
       }
 
-    octave::check_dimensions (nr, nc, warn_for);
+    check_dimensions (nr, nc, warn_for);
   }
 
   void get_dimensions (const octave_value& a, const octave_value& b,
@@ -1139,7 +1139,7 @@
     nr = (a.isempty () ? 0 : a.idx_type_value (true));
     nc = (b.isempty () ? 0 : b.idx_type_value (true));
 
-    octave::check_dimensions (nr, nc, warn_for);
+    check_dimensions (nr, nc, warn_for);
   }
 
   octave_idx_type dims_to_numel (const dim_vector& dims,
@@ -1284,11 +1284,11 @@
     if (do_graphics_events)
       gh_manager::unlock ();
 
-    if (octave::math::isinf (seconds))
+    if (math::isinf (seconds))
       {
         // Wait for kbhit
         int c = -1;
-        octave::flush_stdout ();
+        flush_stdout ();
 
         struct timespec one_tenth = { 0, 100000000 };
 
@@ -1301,69 +1301,51 @@
             if (do_graphics_events)
               gh_manager::process_events ();
 
-            c = octave::kbhit (false);
+            c = kbhit (false);
           }
       }
     else
       {
-        // Split delay into whole seconds and the remainder as a decimal
-        // fraction.
-
-        double fraction = std::modf (seconds, &seconds);
-
-        // Further split the fractional seconds into whole tenths and the
-        // nearest number of nanoseconds remaining.
-
-        double tenths = 0;
-        fraction = std::modf (fraction * 10, &tenths) / 10;
-        fraction = std::round (fraction * 1000000000);
-
-        // Sleep for the hundredths portion.
+        sys::time now;
+        double end_time = now.double_value () + seconds;
+        double remaining_time = seconds;
 
-        struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
-
-        octave_nanosleep_wrapper (&hundredths_delay, nullptr);
-
-        // Sleep for the whole tenths portion, allowing interrupts every
-        // tenth.
+        // Split pause into 100 ms time steps to allow the execution of
+        // graphics events and interrupts.
+        struct timespec nano_laps = { 0, 100000000 };
 
-        struct timespec one_tenth = { 0, 100000000 };
-
-        for (int i = 0; i < static_cast<int> (tenths); i++)
+        while (remaining_time > 0.1)
           {
-            octave_nanosleep_wrapper (&one_tenth, nullptr);
-
             octave_quit ();
 
             if (do_graphics_events)
-              gh_manager::process_events ();
+              {
+                gh_manager::process_events ();
+
+                now.stamp ();
+                remaining_time = end_time - now.double_value ();
+
+                if (remaining_time < 0.1)
+                  break;
+              }
+
+            octave_nanosleep_wrapper (&nano_laps, nullptr);
+
+            now.stamp ();
+            remaining_time = end_time - now.double_value ();
           }
 
-        // Sleep for the whole seconds portion, allowing interrupts every
-        // tenth.
-
-        time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
-                      ? std::numeric_limits<time_t>::max ()
-                      : static_cast<time_t> (seconds));
-
-        for (time_t s = 0; s < sec; s++)
+        if (remaining_time > 0.0)
           {
-            for (int i = 0; i < 10; i++)
-              {
-                octave_nanosleep_wrapper (&one_tenth, nullptr);
-
-                octave_quit ();
-
-                if (do_graphics_events)
-                  gh_manager::process_events ();
-              }
+            nano_laps = { 0, static_cast<int> (remaining_time * 1e9) };
+            octave_nanosleep_wrapper (&nano_laps, nullptr);
           }
       }
   }
 }
 
-DEFUN (isindex, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (isindex, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} isindex (@var{ind})
 @deftypefnx {} {} isindex (@var{ind}, @var{n})
 Return true if @var{ind} is a valid index.
@@ -1391,10 +1373,13 @@
 
   octave_value retval;
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave::unwind_protect frame;
 
-  frame.protect_var (discard_error_messages);
-  discard_error_messages = true;
+  frame.add_method (es, &octave::error_system::set_discard_error_messages,
+                    es.discard_error_messages ());
+  es.discard_error_messages (true);
 
   try
     {
@@ -1501,7 +1486,7 @@
   {
     octave_value retval;
 
-    const octave_value_list tmp = octave::do_simple_cellfun (fun, fun_name, args, 1);
+    const octave_value_list tmp = do_simple_cellfun (fun, fun_name, args, 1);
 
     if (tmp.length () > 0)
       retval = tmp(0);
--- a/libinterp/corefcn/variables.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/variables.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,6 +29,7 @@
 #include <cstring>
 
 #include <iomanip>
+#include <list>
 #include <set>
 #include <string>
 
@@ -39,7 +40,6 @@
 #include "lo-regexp.h"
 #include "str-vec.h"
 
-#include "call-stack.h"
 #include "Cell.h"
 #include "defun.h"
 #include "dirfns.h"
@@ -60,8 +60,10 @@
 #include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
+#include "pt-eval.h"
 #include "syminfo.h"
 #include "symtab.h"
+#include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -157,22 +159,6 @@
   return retval;
 }
 
-static octave_value
-do_isglobal (octave::symbol_table& symtab, const octave_value_list& args)
-{
-  if (args.length () != 1)
-    print_usage ();
-
-  if (! args(0).is_string ())
-    error ("isglobal: NAME must be a string");
-
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  std::string name = args(0).string_value ();
-
-  return scope && scope.is_global (name);
-}
-
 DEFMETHOD (isglobal, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {} isglobal (@var{name})
@@ -190,9 +176,12 @@
 @seealso{isvarname, exist}
 @end deftypefn */)
 {
-  octave::symbol_table& symtab = interp.get_symbol_table ();
+  if (args.length () != 1)
+    print_usage ();
 
-  return do_isglobal (symtab, args);
+  std::string name = args(0).xstring_value ("isglobal: NAME must be a string");
+
+  return ovl (interp.isglobal (name));
 }
 
 /*
@@ -228,9 +217,7 @@
 
   if (search_any || search_var)
     {
-      octave::symbol_scope scope = symtab.current_scope ();
-
-      octave_value val = scope ? scope.varval (name) : octave_value ();
+      octave_value val = interp.varval (name);
 
       if (val.is_constant () || val.isobject ()
           || val.is_function_handle ()
@@ -256,7 +243,9 @@
 
   if (search_any || search_file || search_dir)
     {
-      std::string file_name = octave::lookup_autoload (name);
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
+      std::string file_name = tw.lookup_autoload (name);
 
       if (file_name.empty ())
         {
@@ -284,6 +273,10 @@
       if (file_name.empty ())
         file_name = name;
 
+      // "stat" doesn't work on UNC shares and drive letters.
+      if ((search_any || search_file) && octave::drive_or_unc_share (file_name))
+        return 7;
+
       octave::sys::file_stat fs (file_name);
 
       if (fs)
@@ -486,13 +479,13 @@
 
 ## Don't search path for absolute filenames
 %!test
-%! tname = tempname (pwd ());
+%! tname = tempname ();
 %! unwind_protect
 %!   ## open/close file to create it, equivalent of touch
 %!   fid = fopen (tname, "w");
 %!   fclose (fid);
 %!   [~, fname] = fileparts (tname);
-%!   assert (exist (fullfile (pwd (), fname), "file"), 2);
+%!   assert (exist (fullfile (tempdir (), fname), "file"), 2);
 %! unwind_protect_cleanup
 %!   unlink (tname);
 %! end_unwind_protect
@@ -543,10 +536,10 @@
 static octave::unwind_protect *
 curr_fcn_unwind_protect_frame (void)
 {
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("curr_fcn_unwind_protect_frame");
+  octave::tree_evaluator& tw
+    = octave::__get_evaluator__ ("curr_fcn_unwind_protect_frame");
 
-  return cs.curr_fcn_unwind_protect_frame ();
+  return tw.curr_fcn_unwind_protect_frame ();
 }
 
 template <typename T>
@@ -841,9 +834,9 @@
   if (args.length () != 0)
     print_usage ();
 
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave_function *fcn = cs.caller ();
+  octave_function *fcn = tw.caller_function ();
 
   if (! fcn)
     error ("mlock: invalid use outside a function");
@@ -877,9 +870,9 @@
     }
   else
     {
-      octave::call_stack& cs = interp.get_call_stack ();
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave_function *fcn = cs.caller ();
+      octave_function *fcn = tw.caller_function ();
 
       if (! fcn)
         error ("munlock: invalid use outside a function");
@@ -915,9 +908,9 @@
     }
   else
     {
-      octave::call_stack& cs = interp.get_call_stack ();
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave_function *fcn = cs.caller ();
+      octave_function *fcn = tw.caller_function ();
 
       if (! fcn)
         error ("mislocked: invalid use outside a function");
@@ -973,76 +966,59 @@
 }
 
 static void
-do_clear_functions (octave::symbol_table& symtab,
+do_clear_functions (octave::interpreter& interp,
                     const string_vector& argv, int argc, int idx,
                     bool exclusive = false)
 {
   if (idx == argc)
-    symtab.clear_functions ();
+    interp.clear_functions ();
   else
     {
       if (exclusive)
         {
-          string_vector fcns = symtab.user_function_names ();
-
-          int fcount = fcns.numel ();
+          std::list<std::string> fcns = interp.user_function_names ();
 
-          for (int i = 0; i < fcount; i++)
+          for (const auto& name : fcns)
             {
-              std::string nm = fcns[i];
-
-              if (! name_matches_any_pattern (nm, argv, argc, idx))
-                symtab.clear_function (nm);
+              if (! name_matches_any_pattern (name, argv, argc, idx))
+                interp.clear_function (name);
             }
         }
       else
         {
           while (idx < argc)
-            symtab.clear_function_pattern (argv[idx++]);
+            interp.clear_function_pattern (argv[idx++]);
         }
     }
 }
 
 static void
-do_clear_globals (octave::symbol_table& symtab,
+do_clear_globals (octave::interpreter& interp,
                   const string_vector& argv, int argc, int idx,
                   bool exclusive = false)
 {
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  if (! scope)
-    return;
-
   if (idx == argc)
     {
-      string_vector gvars = symtab.global_variable_names ();
-
-      int gcount = gvars.numel ();
+      std::list<std::string> gvars = interp.global_variable_names ();
 
-      for (int i = 0; i < gcount; i++)
+      for (const auto& name : gvars)
         {
-          std::string name = gvars[i];
-
-          scope.clear_variable (name);
-          symtab.clear_global (name);
+          interp.clear_variable (name);
+          interp.clear_global_variable (name);
         }
     }
   else
     {
       if (exclusive)
         {
-          string_vector gvars = symtab.global_variable_names ();
-
-          int gcount = gvars.numel ();
+          std::list<std::string> gvars = interp.global_variable_names ();
 
-          for (int i = 0; i < gcount; i++)
+          for (const auto& name : gvars)
             {
-              std::string name = gvars[i];
-
               if (! name_matches_any_pattern (name, argv, argc, idx))
                 {
-                  scope.clear_variable (name);
-                  symtab.clear_global (name);
+                  interp.clear_variable (name);
+                  interp.clear_global_variable (name);
                 }
             }
         }
@@ -1052,64 +1028,53 @@
             {
               std::string pattern = argv[idx++];
 
-              scope.clear_variable_pattern (pattern);
-              symtab.clear_global_pattern (pattern);
+              interp.clear_variable_pattern (pattern);
+              interp.clear_global_variable_pattern (pattern);
             }
         }
     }
 }
 
 static void
-do_clear_variables (octave::symbol_table& symtab,
+do_clear_variables (octave::interpreter& interp,
                     const string_vector& argv, int argc, int idx,
                     bool exclusive = false, bool have_regexp = false)
 {
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  if (! scope)
-    return;
-
   if (idx == argc)
-    scope.clear_variables ();
+    interp.clear_variables ();
   else
     {
       if (exclusive)
         {
-          string_vector lvars = scope.variable_names ();
-
-          int lcount = lvars.numel ();
+          std::list<std::string> lvars = interp.variable_names ();
 
-          for (int i = 0; i < lcount; i++)
+          for (const auto& name : lvars)
             {
-              std::string nm = lvars[i];
-
-              if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
-                scope.clear_variable (nm);
+              if (! name_matches_any_pattern (name, argv, argc, idx,
+                                              have_regexp))
+                interp.clear_variable (name);
             }
         }
       else
         {
           if (have_regexp)
             while (idx < argc)
-              scope.clear_variable_regexp (argv[idx++]);
+              interp.clear_variable_regexp (argv[idx++]);
           else
             while (idx < argc)
-              scope.clear_variable_pattern (argv[idx++]);
+              interp.clear_variable_pattern (argv[idx++]);
         }
     }
 }
 
 static void
-do_clear_symbols (octave::symbol_table& symtab,
+do_clear_symbols (octave::interpreter& interp,
                   const string_vector& argv, int argc, int idx,
                   bool exclusive = false)
 {
   if (idx == argc)
     {
-      octave::symbol_scope scope = symtab.current_scope ();
-
-      if (scope)
-        scope.clear_variables ();
+      interp.clear_variables ();
     }
   else
     {
@@ -1120,60 +1085,54 @@
           // shadowed by local variables?  It seems that would be a
           // bit harder to do.
 
-          do_clear_variables (symtab, argv, argc, idx, exclusive);
-          do_clear_functions (symtab, argv, argc, idx, exclusive);
+          do_clear_variables (interp, argv, argc, idx, exclusive);
+          do_clear_functions (interp, argv, argc, idx, exclusive);
         }
       else
         {
           while (idx < argc)
-            symtab.clear_symbol_pattern (argv[idx++]);
+            interp.clear_symbol_pattern (argv[idx++]);
         }
     }
 }
 
 static void
-do_matlab_compatible_clear (octave::symbol_table& symtab,
+do_matlab_compatible_clear (octave::interpreter& interp,
                             const string_vector& argv, int argc, int idx)
 {
   // This is supposed to be mostly Matlab compatible.
 
-  octave::symbol_scope scope = symtab.current_scope ();
-
-  if (! scope)
-    return;
-
   for (; idx < argc; idx++)
     {
-      if (argv[idx] == "all"
-          && ! scope.is_local_variable ("all"))
+      if (argv[idx] == "all" && ! interp.is_local_variable ("all"))
         {
-          symtab.clear_all ();
+          interp.clear_all ();
         }
       else if (argv[idx] == "functions"
-               && ! scope.is_local_variable ("functions"))
+               && ! interp.is_local_variable ("functions"))
         {
-          do_clear_functions (symtab, argv, argc, ++idx);
+          do_clear_functions (interp, argv, argc, ++idx);
         }
       else if (argv[idx] == "global"
-               && ! scope.is_local_variable ("global"))
+               && ! interp.is_local_variable ("global"))
         {
-          do_clear_globals (symtab, argv, argc, ++idx);
+          do_clear_globals (interp, argv, argc, ++idx);
         }
       else if (argv[idx] == "variables"
-               && ! scope.is_local_variable ("variables"))
+               && ! interp.is_local_variable ("variables"))
         {
-          scope.clear_variables ();
+          interp.clear_variables ();
         }
       else if (argv[idx] == "classes"
-               && ! scope.is_local_variable ("classes"))
+               && ! interp.is_local_variable ("classes"))
         {
-          scope.clear_objects ();
+          interp.clear_objects ();
           octave_class::clear_exemplar_map ();
-          symtab.clear_all ();
+          interp.clear_all ();
         }
       else
         {
-          symtab.clear_symbol_pattern (argv[idx]);
+          interp.clear_symbol_pattern (argv[idx]);
         }
     }
 }
@@ -1262,15 +1221,13 @@
 @seealso{who, whos, exist, mlock}
 @end deftypefn */)
 {
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
   int argc = args.length () + 1;
 
   string_vector argv = args.make_argv ("clear");
 
   if (argc == 1)
     {
-      do_clear_variables (symtab, argv, argc, argc);
+      do_clear_variables (interp, argv, argc, true);
 
       octave_link::clear_workspace ();
     }
@@ -1287,8 +1244,6 @@
       bool have_regexp = false;
       bool have_dash_option = false;
 
-      octave::symbol_scope scope = symtab.current_scope ();
-
       while (++idx < argc)
         {
           if (argv[idx] == "-all" || argv[idx] == "-a")
@@ -1350,7 +1305,7 @@
       if (idx <= argc)
         {
           if (! have_dash_option && ! exclusive)
-            do_matlab_compatible_clear (symtab, argv, argc, idx);
+            do_matlab_compatible_clear (interp, argv, argc, idx);
           else
             {
               if (clear_all)
@@ -1360,34 +1315,33 @@
                   if (++idx < argc)
                     warning ("clear: ignoring extra arguments after -all");
 
-                  symtab.clear_all ();
+                  interp.clear_all ();
                 }
               else if (have_regexp)
                 {
-                  do_clear_variables (symtab, argv, argc, idx, exclusive, true);
+                  do_clear_variables (interp, argv, argc, idx, exclusive, true);
                 }
               else if (clear_functions)
                 {
-                  do_clear_functions (symtab, argv, argc, idx, exclusive);
+                  do_clear_functions (interp, argv, argc, idx, exclusive);
                 }
               else if (clear_globals)
                 {
-                  do_clear_globals (symtab, argv, argc, idx, exclusive);
+                  do_clear_globals (interp, argv, argc, idx, exclusive);
                 }
               else if (clear_variables)
                 {
-                  do_clear_variables (symtab, argv, argc, idx, exclusive);
+                  do_clear_variables (interp, argv, argc, idx, exclusive);
                 }
               else if (clear_objects)
                 {
-                  if (scope)
-                    scope.clear_objects ();
+                  interp.clear_objects ();
                   octave_class::clear_exemplar_map ();
-                  symtab.clear_all ();
+                  interp.clear_all ();
                 }
               else
                 {
-                  do_clear_symbols (symtab, argv, argc, idx, exclusive);
+                  do_clear_symbols (interp, argv, argc, idx, exclusive);
                 }
             }
         }
@@ -1441,27 +1395,31 @@
 void
 maybe_missing_function_hook (const std::string& name)
 {
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("maybe_missing_function_hook");
+
+  octave::error_system& es = interp.get_error_system ();
+
   // Don't do this if we're handling errors.
-  if (buffer_error_messages == 0 && ! Vmissing_function_hook.empty ())
-    {
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("maybe_missing_function_hook");
+  if (es.buffer_error_messages () || Vmissing_function_hook.empty ())
+    return;
 
-      octave_value val = symtab.find_function (Vmissing_function_hook);
+  octave::symbol_table& symtab = interp.get_symbol_table ();
+
+  octave_value val = symtab.find_function (Vmissing_function_hook);
 
-      if (val.is_defined ())
-        {
-          // Ensure auto-restoration.
-          octave::unwind_protect frame;
-          frame.protect_var (Vmissing_function_hook);
+  if (val.is_defined ())
+    {
+      // Ensure auto-restoration.
+      octave::unwind_protect frame;
+      frame.protect_var (Vmissing_function_hook);
 
-          // Clear the variable prior to calling the function.
-          const std::string func_name = Vmissing_function_hook;
-          Vmissing_function_hook.clear ();
+      // Clear the variable prior to calling the function.
+      const std::string func_name = Vmissing_function_hook;
+      Vmissing_function_hook.clear ();
 
-          // Call.
-          octave::feval (func_name, octave_value (name));
-        }
+      // Call.
+      octave::feval (func_name, octave_value (name));
     }
 }
 
@@ -1476,9 +1434,18 @@
 
   std::string name = args(0).xstring_value ("__varval__: first argument must be a variable name");
 
-  octave::symbol_scope scope = interp.get_current_scope ();
+  std::string nm = args(0).string_value ();
+
+  // FIXME: we need this kluge to implement inputname in a .m file.
 
-  return scope ? scope.varval (args(0).string_value ()) : octave_value ();
+  if (nm == ".argn.")
+    {
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
+      return tw.get_auto_fcn_var (octave::stack_frame::ARG_NAMES);
+    }
+
+  return interp.varval (nm);
 }
 
 static std::string Vmissing_component_hook;
@@ -1514,131 +1481,7 @@
   return SET_INTERNAL_VARIABLE (missing_component_hook);
 }
 
-// The following functions are deprecated.
-
-void
-mlock (void)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("mlock");
-
-  interp.mlock ();
-}
-
-void
-munlock (const std::string& nm)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("mlock");
-
-  return interp.munlock (nm);
-}
-
-bool
-mislocked (const std::string& nm)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("mlock");
-
-  return interp.mislocked (nm);
-}
-
-void
-bind_ans (const octave_value& val, bool print)
-{
-  octave::tree_evaluator& tw = octave::__get_evaluator__ ("bind_ans");
-
-  tw.bind_ans (val, print);
-}
-
-void
-clear_mex_functions (void)
-{
-  octave::symbol_table& symtab =
-    octave::__get_symbol_table__ ("clear_mex_functions");
-
-  symtab.clear_mex_functions ();
-}
-
-void
-clear_function (const std::string& nm)
-{
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ("clear_function");
-
-  symtab.clear_function (nm);
-}
-
-void
-clear_variable (const std::string& nm)
-{
-  octave::symbol_scope scope
-    = octave::__get_current_scope__ ("clear_variable");
-
-  if (scope)
-    scope.clear_variable (nm);
-}
-
-void
-clear_symbol (const std::string& nm)
-{
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ("clear_symbol");
-
-  symtab.clear_symbol (nm);
-}
-
-octave_value
-lookup_function_handle (const std::string& nm)
-{
-  octave::symbol_scope scope
-    = octave::__get_current_scope__ ("lookup_function_handle");
-
-  octave_value val = scope ? scope.varval (nm) : octave_value ();
-
-  return val.is_function_handle () ? val : octave_value ();
-}
-
-octave_value
-get_global_value (const std::string& nm, bool silent)
-{
-  octave::symbol_table& symtab =
-    octave::__get_symbol_table__ ("get_global_value");
-
-  octave_value val = symtab.global_varval (nm);
-
-  if (val.is_undefined () && ! silent)
-    error ("get_global_value: undefined symbol '%s'", nm.c_str ());
-
-  return val;
-}
-
-void
-set_global_value (const std::string& nm, const octave_value& val)
-{
-  octave::symbol_table& symtab =
-    octave::__get_symbol_table__ ("set_global_value");
-
-  symtab.global_assign (nm, val);
-}
-
-octave_value
-get_top_level_value (const std::string& nm, bool silent)
-{
-  octave::symbol_table& symtab =
-    octave::__get_symbol_table__ ("get_top_level_value");
-
-  octave_value val = symtab.top_level_varval (nm);
-
-  if (val.is_undefined () && ! silent)
-    error ("get_top_level_value: undefined symbol '%s'", nm.c_str ());
-
-  return val;
-}
-
-void
-set_top_level_value (const std::string& nm, const octave_value& val)
-{
-  octave::symbol_table& symtab =
-    octave::__get_symbol_table__ ("set_top_level_value");
-
-  symtab.top_level_assign (nm, val);
-}
+// The following function is deprecated.
 
 string_vector
 get_struct_elts (const std::string& text)
--- a/libinterp/corefcn/variables.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/corefcn/variables.h	Fri Jul 12 12:14:43 2019 -0400
@@ -53,6 +53,7 @@
 is_valid_function (const std::string&, const std::string& = "",
                    bool warn = false);
 
+OCTAVE_DEPRECATED (6, "use 'octave::get_function_handle' instead")
 extern OCTINTERP_API octave_function *
 extract_function (const octave_value& arg, const std::string& warn_for,
                   const std::string& fname, const std::string& header,
@@ -111,50 +112,6 @@
 
 extern OCTINTERP_API void maybe_missing_function_hook (const std::string& name);
 
-OCTAVE_DEPRECATED (4.4, "use 'interpreter::mlock' instead")
-extern OCTINTERP_API void mlock (void);
-
-OCTAVE_DEPRECATED (4.4, "use 'interpreter::munlock' instead")
-extern OCTINTERP_API void munlock (const std::string&);
-
-OCTAVE_DEPRECATED (4.4, "use 'interpreter::mislocked' instead")
-extern OCTINTERP_API bool mislocked (const std::string&);
-
-OCTAVE_DEPRECATED (4.4, "use 'tree_evaluator::bind_ans' instead")
-extern OCTINTERP_API void bind_ans (const octave_value& val, bool print);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::clear_mex_functions' instead")
-extern OCTINTERP_API void clear_mex_functions (void);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::clear_function' instead")
-extern OCTINTERP_API void clear_function (const std::string& nm);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::clear_variable' instead")
-extern OCTINTERP_API void clear_variable (const std::string& nm);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::clear_symbol' instead")
-extern OCTINTERP_API void clear_symbol (const std::string& nm);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::varval' instead")
-extern OCTINTERP_API octave_value
-lookup_function_handle (const std::string& nm);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::global_varval' instead")
-extern OCTINTERP_API octave_value
-get_global_value (const std::string& nm, bool silent = false);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::global_assign' instead")
-extern OCTINTERP_API void
-set_global_value (const std::string& nm, const octave_value& val);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::top_level_varval' instead")
-extern OCTINTERP_API octave_value
-get_top_level_value (const std::string& nm, bool silent = false);
-
-OCTAVE_DEPRECATED (4.4, "use 'symbol_table::top_level_assign' instead")
-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);
--- a/libinterp/dldfcn/__eigs__.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/dldfcn/__eigs__.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -34,6 +34,7 @@
 #include "defun-dld.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "oct-map.h"
 #include "ov.h"
 #include "ovl.h"
@@ -44,7 +45,7 @@
 #if defined (HAVE_ARPACK)
 
 // Global pointer for user defined function.
-static octave_function *eigs_fcn = nullptr;
+static octave_value eigs_fcn;
 
 // Have we warned about imaginary values returned from user function?
 static bool warned_imaginary = false;
@@ -59,7 +60,7 @@
   octave_value_list args;
   args(0) = x;
 
-  if (eigs_fcn)
+  if (eigs_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -99,7 +100,7 @@
   octave_value_list args;
   args(0) = x;
 
-  if (eigs_fcn)
+  if (eigs_fcn.is_defined ())
     {
       octave_value_list tmp;
 
@@ -206,20 +207,9 @@
   if (args(0).is_function_handle () || args(0).is_inline_function ()
       || args(0).is_string ())
     {
-      if (args(0).is_string ())
-        {
-          std::string name = args(0).string_value ();
-          std::string fname = "function y = ";
-          fcn_name = unique_symbol_name ("__eigs_fcn__");
-          fname.append (fcn_name);
-          fname.append ("(x) y = ");
-          eigs_fcn = extract_function (args(0), "eigs", fcn_name, fname,
-                                       "; endfunction");
-        }
-      else
-        eigs_fcn = args(0).function_value ();
+      eigs_fcn = octave::get_function_handle (interp, args(0), "x");
 
-      if (! eigs_fcn)
+      if (eigs_fcn.is_undefined ())
         error ("eigs: unknown function");
 
       if (nargin < 2)
--- a/libinterp/dldfcn/__init_fltk__.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/dldfcn/__init_fltk__.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1852,9 +1852,6 @@
     if (! instance)
       instance = new figure_manager ();
 
-    if (! instance)
-      error ("unable to create figure_manager object!");
-
     return retval;
   }
 
--- a/libinterp/dldfcn/__ode15__.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/dldfcn/__ode15__.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1,6 +1,7 @@
 /*
 
 Copyright (C) 2016-2019 Francesco Faccio <francesco.faccio@mail.polimi.it>
+Copyright (C) 2019 William Greene <w.h.greene@gmail.com>
 
 This file is part of Octave.
 
@@ -40,44 +41,96 @@
 
 #if defined (HAVE_SUNDIALS)
 
-#  if defined (HAVE_IDA_IDA_H)
-#    include <ida/ida.h>
-#  endif
-
-#  if defined (HAVE_IDA_IDA_DENSE_H)
-#    include <ida/ida_dense.h>
-#  endif
-
-#  if defined (HAVE_IDA_IDA_KLU_H)
-#    include <ida/ida_klu.h>
-#    include <sundials/sundials_sparse.h>
-#  endif
-
 #  if defined (HAVE_NVECTOR_NVECTOR_SERIAL_H)
 #    include <nvector/nvector_serial.h>
 #  endif
 
-static inline realtype *
-nv_data_s (N_Vector& v)
+#  if defined (HAVE_IDA_IDA_H)
+#    include <ida/ida.h>
+#  elif defined (HAVE_IDA_H)
+#    include <ida.h>
+#  endif
+#  if defined (HAVE_IDA_IDA_DIRECT_H)
+#    include <ida/ida_direct.h>
+#  elif defined (HAVE_IDA_DIRECT_H)
+#    include <ida_direct.h>
+#  endif
+
+#  if defined (HAVE_SUNLINSOL_SUNLINSOL_DENSE_H)
+#    include <sunlinsol/sunlinsol_dense.h>
+#  endif
+
+#  if defined (HAVE_SUNLINSOL_SUNLINSOL_KLU_H)
+#    if defined (HAVE_KLU_H)
+#      include <klu.h>
+#    endif
+#    if defined (HAVE_KLU_KLU_H)
+#      include <klu/klu.h>
+#    endif
+#    if defined (HAVE_SUITESPARSE_KLU_H)
+#      include <suitesparse/klu.h>
+#    endif
+#    if defined (HAVE_UFPARSE_KLU_H)
+#      include <ufsparse/klu.h>
+#    endif
+#    include <sunlinsol/sunlinsol_klu.h>
+#  endif
+
+namespace octave
 {
+#  if ! defined (HAVE_IDASETJACFN) && defined (HAVE_IDADLSSETJACFN)
+  static inline int
+  IDASetJacFn (void *ida_mem, IDADlsJacFn jac)
+  {
+    return IDADlsSetJacFn (ida_mem, jac);
+  }
+#  endif
+
+#  if ! defined (HAVE_IDASETLINEARSOLVER) && defined (HAVE_IDADLSSETLINEARSOLVER)
+  static inline int
+  IDASetLinearSolver (void *ida_mem, SUNLinearSolver LS, SUNMatrix A)
+  {
+    return IDADlsSetLinearSolver (ida_mem, LS, A);
+  }
+#  endif
+
+#  if ! defined (HAVE_SUNLINSOL_DENSE) && defined (HAVE_SUNDENSELINEARSOLVER)
+  static inline SUNLinearSolver
+  SUNLinSol_Dense (N_Vector y, SUNMatrix A)
+  {
+    return SUNDenseLinearSolver (y, A);
+  }
+#  endif
+
+#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
+#    if ! defined (HAVE_SUNLINSOL_KLU) && defined (HAVE_SUNKLU)
+  static inline SUNLinearSolver
+  SUNLinSol_KLU (N_Vector y, SUNMatrix A)
+  {
+    return SUNKLU (y, A);
+  }
+#    endif
+#  endif
+
+  static inline realtype *
+  nv_data_s (N_Vector& v)
+  {
 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Disable warning from GCC about old-style casts in Sundials
-   // macro expansions.  Do this in a function so that this
-   // diagnostic may still be enabled for the rest of the file.
+    // Disable warning from GCC about old-style casts in Sundials
+    // macro expansions.  Do this in a function so that this
+    // diagnostic may still be enabled for the rest of the file.
 #  pragma GCC diagnostic push
 #  pragma GCC diagnostic ignored "-Wold-style-cast"
 #endif
 
-  return NV_DATA_S (v);
+    return NV_DATA_S (v);
 
 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Restore prevailing warning state for remainder of the file.
+    // Restore prevailing warning state for remainder of the file.
 #  pragma GCC diagnostic pop
 #endif
-}
+  }
 
-namespace octave
-{
   class IDA
   {
   public:
@@ -85,18 +138,18 @@
     typedef
     ColumnVector (*DAERHSFuncIDA) (const ColumnVector& x,
                                    const ColumnVector& xdot,
-                                   realtype t, octave_function *idaf);
+                                   realtype t, const octave_value& idaf);
 
     typedef
     Matrix (*DAEJacFuncDense) (const ColumnVector& x,
                                const ColumnVector& xdot, realtype t,
-                               realtype cj, octave_function *idaj);
+                               realtype cj, const octave_value& idaj);
 
     typedef
     SparseMatrix (*DAEJacFuncSparse) (const ColumnVector& x,
                                       const ColumnVector& xdot,
                                       realtype t, realtype cj,
-                                      octave_function *idaj);
+                                      const octave_value& idaj);
 
     typedef
     Matrix (*DAEJacCellDense) (Matrix *dfdy, Matrix *dfdyp,
@@ -108,57 +161,67 @@
 
     //Default
     IDA (void)
-      : t0 (0.0), y0 (), yp0 (), havejac (false), havejacfun (false),
-        havejacsparse (false), mem (nullptr), num (), ida_fun (nullptr),
-        ida_jac (nullptr), dfdy (nullptr), dfdyp (nullptr), spdfdy (nullptr),
-        spdfdyp (nullptr), fun (nullptr), jacfun (nullptr), jacspfun (nullptr),
-        jacdcell (nullptr), jacspcell (nullptr)
+      : m_t0 (0.0), m_y0 (), m_yp0 (), m_havejac (false), m_havejacfun (false),
+        m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fun (),
+        m_ida_jac (), m_dfdy (nullptr), m_dfdyp (nullptr), m_spdfdy (nullptr),
+        m_spdfdyp (nullptr), m_fun (nullptr), m_jacfun (nullptr), m_jacspfun (nullptr),
+        m_jacdcell (nullptr), m_jacspcell (nullptr),
+        m_sunJacMatrix (nullptr), m_sunLinearSolver (nullptr)
     { }
 
 
     IDA (realtype t, ColumnVector y, ColumnVector yp,
-         octave_function *ida_fcn, DAERHSFuncIDA daefun)
-      : t0 (t), y0 (y), yp0 (yp), havejac (false), havejacfun (false),
-        havejacsparse (false), mem (nullptr), num (), ida_fun (ida_fcn),
-        ida_jac (nullptr), dfdy (nullptr), dfdyp (nullptr), spdfdy (nullptr),
-        spdfdyp (nullptr), fun (daefun), jacfun (nullptr), jacspfun (nullptr),
-        jacdcell (nullptr), jacspcell (nullptr)
+         const octave_value& ida_fcn, DAERHSFuncIDA daefun)
+      : m_t0 (t), m_y0 (y), m_yp0 (yp), m_havejac (false), m_havejacfun (false),
+        m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fun (ida_fcn),
+        m_ida_jac (), m_dfdy (nullptr), m_dfdyp (nullptr), m_spdfdy (nullptr),
+        m_spdfdyp (nullptr), m_fun (daefun), m_jacfun (nullptr), m_jacspfun (nullptr),
+        m_jacdcell (nullptr), m_jacspcell (nullptr),
+        m_sunJacMatrix (nullptr), m_sunLinearSolver (nullptr)
     { }
 
 
-    ~IDA (void) { IDAFree (&mem); }
+    ~IDA (void)
+    {
+      IDAFree (&m_mem);
+      SUNLinSolFree (m_sunLinearSolver);
+      SUNMatDestroy (m_sunJacMatrix);
+    }
 
     IDA&
-    set_jacobian (octave_function *jac, DAEJacFuncDense j)
+    set_jacobian (const octave_value& jac, DAEJacFuncDense j)
     {
-      jacfun = j;
-      ida_jac = jac;
-      havejac = true;
-      havejacfun = true;
-      havejacsparse = false;
+      m_jacfun = j;
+      m_ida_jac = jac;
+      m_havejac = true;
+      m_havejacfun = true;
+      m_havejacsparse = false;
+
       return *this;
     }
 
     IDA&
-    set_jacobian (octave_function *jac, DAEJacFuncSparse j)
+    set_jacobian (const octave_value& jac, DAEJacFuncSparse j)
     {
-      jacspfun = j;
-      ida_jac = jac;
-      havejac = true;
-      havejacfun = true;
-      havejacsparse = true;
+      m_jacspfun = j;
+      m_ida_jac = jac;
+      m_havejac = true;
+      m_havejacfun = true;
+      m_havejacsparse = true;
+
       return *this;
     }
 
     IDA&
     set_jacobian (Matrix *dy, Matrix *dyp, DAEJacCellDense j)
     {
-      jacdcell = j;
-      dfdy = dy;
-      dfdyp = dyp;
-      havejac = true;
-      havejacfun = false;
-      havejacsparse = false;
+      m_jacdcell = j;
+      m_dfdy = dy;
+      m_dfdyp = dyp;
+      m_havejac = true;
+      m_havejacfun = false;
+      m_havejacsparse = false;
+
       return *this;
     }
 
@@ -166,12 +229,13 @@
     set_jacobian (SparseMatrix *dy, SparseMatrix *dyp,
                   DAEJacCellSparse j)
     {
-      jacspcell = j;
-      spdfdy = dy;
-      spdfdyp = dyp;
-      havejac = true;
-      havejacfun = false;
-      havejacsparse = true;
+      m_jacspcell = j;
+      m_spdfdy = dy;
+      m_spdfdyp = dyp;
+      m_havejac = true;
+      m_havejacfun = false;
+      m_havejacsparse = true;
+
       return *this;
     }
 
@@ -184,7 +248,7 @@
     static N_Vector ColToNVec (const ColumnVector& data, long int n);
 
     void
-    set_up (void);
+    set_up (const ColumnVector& y);
 
     void
     set_tolerance (ColumnVector& abstol, realtype reltol);
@@ -199,25 +263,24 @@
     void
     resfun_impl (realtype t, N_Vector& yy,
                  N_Vector& yyp, N_Vector& rr);
-
     static int
-    jacdense (long int Neq, realtype t,  realtype cj, N_Vector yy,
-              N_Vector yyp, N_Vector, DlsMat JJ, void *user_data,
+    jacdense (realtype t, realtype cj, N_Vector yy,
+              N_Vector yyp, N_Vector, SUNMatrix JJ, void *user_data,
               N_Vector, N_Vector, N_Vector)
     {
       IDA *self = static_cast <IDA *> (user_data);
-      self->jacdense_impl (Neq, t, cj, yy, yyp, JJ);
+      self->jacdense_impl (t, cj, yy, yyp, JJ);
       return 0;
     }
 
     void
-    jacdense_impl (long int Neq, realtype t, realtype cj,
-                   N_Vector& yy, N_Vector& yyp, DlsMat& JJ);
+    jacdense_impl (realtype t, realtype cj,
+                   N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ);
 
-#  if defined (HAVE_SUNDIALS_IDAKLU)
+#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
     static int
     jacsparse (realtype t, realtype cj, N_Vector yy, N_Vector yyp,
-               N_Vector, SlsMat Jac, void *user_data, N_Vector,
+               N_Vector, SUNMatrix Jac, void *user_data, N_Vector,
                N_Vector, N_Vector)
     {
       IDA *self = static_cast <IDA *> (user_data);
@@ -227,8 +290,8 @@
 
     void
     jacsparse_impl (realtype t, realtype cj, N_Vector& yy,
-                    N_Vector& yyp, SlsMat& Jac);
-#endif
+                    N_Vector& yyp, SUNMatrix& Jac);
+#  endif
 
     void set_maxstep (realtype maxstep);
 
@@ -237,21 +300,21 @@
     bool
     interpolate (int& cont, Matrix& output, ColumnVector& tout,
                  int refine, realtype tend, bool haveoutputfcn,
-                 bool haveoutputsel, octave_function *output_fcn,
+                 bool haveoutputsel, const octave_value& output_fcn,
                  ColumnVector& outputsel, bool haveeventfunction,
-                 octave_function *event_fcn, ColumnVector& te,
+                 const octave_value& event_fcn, ColumnVector& te,
                  Matrix& ye, ColumnVector& ie, ColumnVector& oldval,
                  ColumnVector& oldisterminal, ColumnVector& olddir,
                  int& temp, ColumnVector& yold);
 
     bool
-    outputfun (octave_function *output_fcn, bool haveoutputsel,
+    outputfun (const octave_value& output_fcn, bool haveoutputsel,
                const ColumnVector& output, realtype tout, realtype tend,
                ColumnVector& outputsel, const std::string& flag);
 
 
     bool
-    event (octave_function *event_fcn,
+    event (const octave_value& event_fcn,
            ColumnVector& te, Matrix& ye, ColumnVector& ie,
            realtype tsol, const ColumnVector& y, const std::string& flag,
            const ColumnVector& yp, ColumnVector& oldval,
@@ -264,33 +327,35 @@
     integrate (const int numt, const ColumnVector& tt,
                const ColumnVector& y0, const ColumnVector& yp0,
                const int refine, bool haverefine, bool haveoutputfcn,
-               octave_function *output_fcn, bool haveoutputsel,
+               const octave_value& output_fcn, bool haveoutputsel,
                ColumnVector& outputsel, bool haveeventfunction,
-               octave_function *event_fcn);
+               const octave_value& event_fcn);
 
     void print_stat (void);
 
   private:
 
-    realtype t0;
-    ColumnVector y0;
-    ColumnVector yp0;
-    bool havejac;
-    bool havejacfun;
-    bool havejacsparse;
-    void *mem;
-    int num;
-    octave_function *ida_fun;
-    octave_function *ida_jac;
-    Matrix *dfdy;
-    Matrix *dfdyp;
-    SparseMatrix *spdfdy;
-    SparseMatrix *spdfdyp;
-    DAERHSFuncIDA fun;
-    DAEJacFuncDense jacfun;
-    DAEJacFuncSparse jacspfun;
-    DAEJacCellDense jacdcell;
-    DAEJacCellSparse jacspcell;
+    realtype m_t0;
+    ColumnVector m_y0;
+    ColumnVector m_yp0;
+    bool m_havejac;
+    bool m_havejacfun;
+    bool m_havejacsparse;
+    void *m_mem;
+    int m_num;
+    octave_value m_ida_fun;
+    octave_value m_ida_jac;
+    Matrix *m_dfdy;
+    Matrix *m_dfdyp;
+    SparseMatrix *m_spdfdy;
+    SparseMatrix *m_spdfdyp;
+    DAERHSFuncIDA m_fun;
+    DAEJacFuncDense m_jacfun;
+    DAEJacFuncSparse m_jacspfun;
+    DAEJacCellDense m_jacdcell;
+    DAEJacCellSparse m_jacspcell;
+    SUNMatrix m_sunJacMatrix;
+    SUNLinearSolver m_sunLinearSolver;
   };
 
   int
@@ -306,52 +371,73 @@
   IDA::resfun_impl (realtype t, N_Vector& yy,
                     N_Vector& yyp, N_Vector& rr)
   {
-    BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
-    ColumnVector y = IDA::NVecToCol (yy, num);
+    ColumnVector y = IDA::NVecToCol (yy, m_num);
 
-    ColumnVector yp = IDA::NVecToCol (yyp, num);
+    ColumnVector yp = IDA::NVecToCol (yyp, m_num);
 
-    ColumnVector res = (*fun) (y, yp, t, ida_fun);
+    ColumnVector res = (*m_fun) (y, yp, t, m_ida_fun);
 
     realtype *puntrr = nv_data_s (rr);
 
-    for (octave_idx_type i = 0; i < num; i++)
+    for (octave_idx_type i = 0; i < m_num; i++)
       puntrr[i] = res(i);
-
-    END_INTERRUPT_WITH_EXCEPTIONS;
   }
 
   void
-  IDA::set_up (void)
+  IDA::set_up (const ColumnVector& y)
   {
-    if (havejacsparse)
+    N_Vector yy = ColToNVec(y, m_num);
+
+    if (m_havejacsparse)
       {
-#  if defined (HAVE_SUNDIALS_IDAKLU)
-        if (IDAKLU (mem, num, num*num, CSC_MAT) != 0)
-          error ("IDAKLU solver not initialized");
+#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
+        // FIXME : one should not allocate space for a full Jacobian
+        // when using a sparse format. Consider allocating less space
+        // then possibly using SUNSparseMatrixReallocate to increase it.
+        m_sunJacMatrix = SUNSparseMatrix (m_num, m_num, m_num*m_num, CSC_MAT);
+        if (! m_sunJacMatrix)
+          error ("Unable to create sparse Jacobian for Sundials");
 
-        IDASlsSetSparseJacFn (mem, IDA::jacsparse);
+        m_sunLinearSolver = SUNLinSol_KLU (yy, m_sunJacMatrix);
+        if (! m_sunLinearSolver)
+          error ("Unable to create KLU sparse solver");
+
+        if (IDASetLinearSolver (m_mem, m_sunLinearSolver, m_sunJacMatrix))
+          error ("Unable to set sparse linear solver");
+
+        IDASetJacFn (m_mem, IDA::jacsparse);
+
 #  else
-        error ("IDAKLU is not available in this version of Octave");
+        error ("SUNDIALS SUNLINSOL KLU is not available in this version of Octave");
 #  endif
+
       }
     else
       {
-        if (IDADense (mem, num) != 0)
-          error ("IDADense solver not initialized");
+
+        m_sunJacMatrix = SUNDenseMatrix (m_num, m_num);
+        if (! m_sunJacMatrix)
+          error ("Unable to create dense Jacobian for Sundials");
 
-        if (havejac && IDADlsSetDenseJacFn (mem, IDA::jacdense) != 0)
-          error ("Dense Jacobian not set");
+        m_sunLinearSolver = SUNLinSol_Dense (yy, m_sunJacMatrix);
+        if (! m_sunLinearSolver)
+          error ("Unable to create dense linear solver");
+
+        if (IDASetLinearSolver (m_mem, m_sunLinearSolver, m_sunJacMatrix))
+          error ("Unable to set dense linear solver");
+
+        if (m_havejac && IDASetJacFn (m_mem, IDA::jacdense) != 0)
+          error ("Unable to set dense Jacobian function");
+
       }
   }
 
   void
-  IDA::jacdense_impl (long int Neq, realtype t, realtype cj,
-                      N_Vector& yy, N_Vector& yyp, DlsMat& JJ)
+  IDA::jacdense_impl (realtype t, realtype cj,
+                      N_Vector& yy, N_Vector& yyp, SUNMatrix& JJ)
 
   {
-    BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+    long int Neq = NV_LENGTH_S(yy);
 
     ColumnVector y = NVecToCol (yy, Neq);
 
@@ -359,53 +445,48 @@
 
     Matrix jac;
 
-    if (havejacfun)
-      jac = (*jacfun) (y, yp, t, cj, ida_jac);
+    if (m_havejacfun)
+      jac = (*m_jacfun) (y, yp, t, cj, m_ida_jac);
     else
-      jac = (*jacdcell) (dfdy, dfdyp, cj);
+      jac = (*m_jacdcell) (m_dfdy, m_dfdyp, cj);
 
     std::copy (jac.fortran_vec (),
                jac.fortran_vec () + jac.numel (),
-               JJ->data);
-
-    END_INTERRUPT_WITH_EXCEPTIONS;
+               SUNDenseMatrix_Data (JJ));
   }
 
-#  if defined (HAVE_SUNDIALS_IDAKLU)
+#  if defined (HAVE_SUNDIALS_SUNLINSOL_KLU)
   void
   IDA::jacsparse_impl (realtype t, realtype cj, N_Vector& yy, N_Vector& yyp,
-                       SlsMat& Jac)
+                       SUNMatrix& Jac)
 
   {
-    BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+    ColumnVector y = NVecToCol (yy, m_num);
 
-    ColumnVector y = NVecToCol (yy, num);
-
-    ColumnVector yp = NVecToCol (yyp, num);
+    ColumnVector yp = NVecToCol (yyp, m_num);
 
     SparseMatrix jac;
 
-    if (havejacfun)
-      jac = (*jacspfun) (y, yp, t, cj, ida_jac);
+    if (m_havejacfun)
+      jac = (*m_jacspfun) (y, yp, t, cj, m_ida_jac);
     else
-      jac = (*jacspcell) (spdfdy, spdfdyp, cj);
+      jac = (*m_jacspcell) (m_spdfdy, m_spdfdyp, cj);
 
-    SparseSetMatToZero (Jac);
-    int *colptrs = *(Jac->colptrs);
-    int *rowvals = *(Jac->rowvals);
+    SUNMatZero_Sparse (Jac);
+    sunindextype *colptrs = SUNSparseMatrix_IndexPointers (Jac);
+    sunindextype *rowvals = SUNSparseMatrix_IndexValues (Jac);
 
-    for (int i = 0; i < num + 1; i++)
+    for (int i = 0; i < m_num + 1; i++)
       colptrs[i] = jac.cidx(i);
 
+    double *d = SUNSparseMatrix_Data (Jac);
     for (int i = 0; i < jac.nnz (); i++)
       {
         rowvals[i] = jac.ridx(i);
-        Jac->data[i] = jac.data(i);
+        d[i] = jac.data(i);
       }
-
-    END_INTERRUPT_WITH_EXCEPTIONS;
   }
-#endif
+#  endif
 
   ColumnVector
   IDA::NVecToCol (N_Vector& v, long int n)
@@ -437,32 +518,32 @@
   {
     void *userdata = this;
 
-    if (IDASetUserData (mem, userdata) != 0)
+    if (IDASetUserData (m_mem, userdata) != 0)
       error ("User data not set");
   }
 
   void
   IDA::initialize (void)
   {
-    num = y0.numel ();
-    mem = IDACreate ();
+    m_num = m_y0.numel ();
+    m_mem = IDACreate ();
 
-    N_Vector yy = ColToNVec (y0, num);
+    N_Vector yy = ColToNVec (m_y0, m_num);
 
-    N_Vector yyp = ColToNVec (yp0, num);
+    N_Vector yyp = ColToNVec (m_yp0, m_num);
 
     IDA::set_userdata ();
 
-    if (IDAInit (mem, IDA::resfun, t0, yy, yyp) != 0)
+    if (IDAInit (m_mem, IDA::resfun, m_t0, yy, yyp) != 0)
       error ("IDA not initialized");
   }
 
   void
   IDA::set_tolerance (ColumnVector& abstol, realtype reltol)
   {
-    N_Vector abs_tol = ColToNVec (abstol, num);
+    N_Vector abs_tol = ColToNVec (abstol, m_num);
 
-    if (IDASVtolerances (mem, reltol, abs_tol) != 0)
+    if (IDASVtolerances (m_mem, reltol, abs_tol) != 0)
       error ("IDA: Tolerance not set");
 
     N_VDestroy_Serial (abs_tol);
@@ -471,7 +552,7 @@
   void
   IDA::set_tolerance (realtype abstol, realtype reltol)
   {
-    if (IDASStolerances (mem, reltol, abstol) != 0)
+    if (IDASStolerances (m_mem, reltol, abstol) != 0)
       error ("IDA: Tolerance not set");
   }
 
@@ -479,12 +560,12 @@
   IDA::integrate (const int numt, const ColumnVector& tspan,
                   const ColumnVector& y, const ColumnVector& yp,
                   const int refine, bool haverefine, bool haveoutputfcn,
-                  octave_function *output_fcn, bool haveoutputsel,
+                  const octave_value& output_fcn, bool haveoutputsel,
                   ColumnVector& outputsel, bool haveeventfunction,
-                  octave_function *event_fcn)
+                  const octave_value& event_fcn)
   {
     // Set up output
-    ColumnVector tout, yout (num), ypout (num), ysel (outputsel.numel ());
+    ColumnVector tout, yout (m_num), ypout (m_num), ysel (outputsel.numel ());
     ColumnVector ie, te, oldval, oldisterminal, olddir;
     Matrix output, ye;
     int cont = 0, temp = 0;
@@ -495,9 +576,9 @@
     realtype tsol = tspan(0);
     realtype tend = tspan(numt-1);
 
-    N_Vector yyp = ColToNVec (yp, num);
+    N_Vector yyp = ColToNVec (yp, m_num);
 
-    N_Vector yy = ColToNVec (y, num);
+    N_Vector yy = ColToNVec (y, m_num);
 
     // Initialize OutputFcn
     if (haveoutputfcn)
@@ -515,9 +596,9 @@
         // First output value
         tout.resize (numt);
         tout(0) = tsol;
-        output.resize (numt, num);
+        output.resize (numt, m_num);
 
-        for (octave_idx_type i = 0; i < num; i++)
+        for (octave_idx_type i = 0; i < m_num; i++)
           output.elem (0, i) = y.elem (i);
 
         //Main loop
@@ -525,14 +606,14 @@
           {
             // IDANORMAL already interpolates tspan(j)
 
-            if (IDASolve (mem, tspan (j), &tsol, yy, yyp, IDA_NORMAL) != 0)
+            if (IDASolve (m_mem, tspan (j), &tsol, yy, yyp, IDA_NORMAL) != 0)
               error ("IDASolve failed");
 
-            yout = NVecToCol (yy, num);
-            ypout = NVecToCol (yyp, num);
+            yout = NVecToCol (yy, m_num);
+            ypout = NVecToCol (yyp, m_num);
             tout(j) = tsol;
 
-            for (octave_idx_type i = 0; i < num; i++)
+            for (octave_idx_type i = 0; i < m_num; i++)
               output.elem (j, i) = yout.elem (i);
 
             if (haveoutputfcn)
@@ -547,7 +628,7 @@
             // If integration is stopped, return only the reached steps
             if (status == 1)
               {
-                output.resize (j + 1, num);
+                output.resize (j + 1, m_num);
                 tout.resize (j + 1);
               }
 
@@ -558,19 +639,19 @@
         // First output value
         tout.resize (1);
         tout(0) = tsol;
-        output.resize (1, num);
+        output.resize (1, m_num);
 
-        for (octave_idx_type i = 0; i < num; i++)
+        for (octave_idx_type i = 0; i < m_num; i++)
           output.elem (0, i) = y.elem (i);
 
         bool posdirection = (tend > tsol);
 
         //main loop
         while (((posdirection == 1 && tsol < tend)
-                || (posdirection == 0 && tsol > tend))
+               || (posdirection == 0 && tsol > tend))
                && status == 0)
           {
-            if (IDASolve (mem, tend, &tsol, yy, yyp, IDA_ONE_STEP) != 0)
+            if (IDASolve (m_mem, tend, &tsol, yy, yyp, IDA_ONE_STEP) != 0)
               error ("IDASolve failed");
 
             if (haverefine)
@@ -581,14 +662,14 @@
                                          ye, ie, oldval, oldisterminal,
                                          olddir, temp, yold);
 
-            ypout = NVecToCol (yyp, num);
+            ypout = NVecToCol (yyp, m_num);
             cont += 1;
-            output.resize (cont + 1, num); // This may be not efficient
+            output.resize (cont + 1, m_num); // This may be not efficient
             tout.resize (cont + 1);
             tout(cont) = tsol;
-            yout = NVecToCol (yy, num);
+            yout = NVecToCol (yy, m_num);
 
-            for (octave_idx_type i = 0; i < num; i++)
+            for (octave_idx_type i = 0; i < m_num; i++)
               output.elem (cont, i) = yout.elem (i);
 
             if (haveoutputfcn && ! haverefine && tout(cont) < tend)
@@ -604,15 +685,15 @@
         if (status == 0)
           {
             // Interpolate in tend
-            N_Vector dky = N_VNew_Serial (num);
+            N_Vector dky = N_VNew_Serial (m_num);
 
-            if (IDAGetDky (mem, tend, 0, dky) != 0)
+            if (IDAGetDky (m_mem, tend, 0, dky) != 0)
               error ("IDA failed to interpolate y");
 
             tout(cont) = tend;
-            yout = NVecToCol (dky, num);
+            yout = NVecToCol (dky, m_num);
 
-            for (octave_idx_type i = 0; i < num; i++)
+            for (octave_idx_type i = 0; i < m_num; i++)
               output.elem (cont, i) = yout.elem (i);
 
             // Plot final value
@@ -642,7 +723,7 @@
   }
 
   bool
-  IDA::event (octave_function *event_fcn,
+  IDA::event (const octave_value& event_fcn,
               ColumnVector& te, Matrix& ye, ColumnVector& ie,
               realtype tsol, const ColumnVector& y, const std::string& flag,
               const ColumnVector& yp, ColumnVector& oldval,
@@ -686,18 +767,18 @@
           {
             temp = 1; // register only the first event
             te.resize (1);
-            ye.resize (1, num);
+            ye.resize (1, m_num);
             ie.resize (1);
 
             // Linear interpolation
             ie(0) = index(0);
             te(0) = tsol - val (index(0)) * (tsol - told)
-                    / (val (index(0)) - oldval (index(0)));
+              / (val (index(0)) - oldval (index(0)));
 
             ColumnVector ytemp
               = y - ((tsol - te(0)) * (y - yold) / (tsol - told));
 
-            for (octave_idx_type i = 0; i < num; i++)
+            for (octave_idx_type i = 0; i < m_num; i++)
               ye.elem (0, i) = ytemp.elem (i);
 
           }
@@ -705,7 +786,7 @@
           // Not first step: register all events and test if stop integration or not
           {
             te.resize (temp + index.numel ());
-            ye.resize (temp + index.numel (), num);
+            ye.resize (temp + index.numel (), m_num);
             ie.resize (temp + index.numel ());
 
             for (octave_idx_type i = 0; i < index.numel (); i++)
@@ -717,12 +798,12 @@
                 // Linear interpolation
                 ie(temp+i) = index(i);
                 te(temp+i) = tsol - val(index(i)) * (tsol - told)
-                             / (val(index(i)) - oldval(index(i)));
+                  / (val(index(i)) - oldval(index(i)));
 
                 ColumnVector ytemp
                   = y - (tsol - te (temp + i)) * (y - yold) / (tsol - told);
 
-                for (octave_idx_type j = 0; j < num; j++)
+                for (octave_idx_type j = 0; j < m_num; j++)
                   ye.elem (temp + i, j) = ytemp.elem (j);
 
               }
@@ -744,9 +825,9 @@
   bool
   IDA::interpolate (int& cont, Matrix& output, ColumnVector& tout,
                     int refine, realtype tend, bool haveoutputfcn,
-                    bool haveoutputsel, octave_function *output_fcn,
+                    bool haveoutputsel, const octave_value& output_fcn,
                     ColumnVector& outputsel, bool haveeventfunction,
-                    octave_function *event_fcn, ColumnVector& te,
+                    const octave_value& event_fcn, ColumnVector& te,
                     Matrix& ye, ColumnVector& ie, ColumnVector& oldval,
                     ColumnVector& oldisterminal, ColumnVector& olddir,
                     int& temp, ColumnVector& yold)
@@ -754,18 +835,18 @@
     realtype h = 0, tcur = 0;
     bool status = 0;
 
-    N_Vector dky = N_VNew_Serial (num);
+    N_Vector dky = N_VNew_Serial (m_num);
 
-    N_Vector dkyp = N_VNew_Serial (num);
+    N_Vector dkyp = N_VNew_Serial (m_num);
 
-    ColumnVector yout (num);
-    ColumnVector ypout (num);
+    ColumnVector yout (m_num);
+    ColumnVector ypout (m_num);
     std::string string = "";
 
-    if (IDAGetLastStep (mem, &h) != 0)
+    if (IDAGetLastStep (m_mem, &h) != 0)
       error ("IDA failed to return last step");
 
-    if (IDAGetCurrentTime (mem, &tcur) != 0)
+    if (IDAGetCurrentTime (m_mem, &tcur) != 0)
       error ("IDA failed to return the current time");
 
     realtype tin = tcur - h;
@@ -776,21 +857,21 @@
          i < refine && tin + step * i < tend && status == 0;
          i++)
       {
-        if (IDAGetDky (mem, tin + step*i, 0, dky) != 0)
+        if (IDAGetDky (m_mem, tin + step*i, 0, dky) != 0)
           error ("IDA failed to interpolate y");
 
-        if (IDAGetDky (mem, tin + step*i, 1, dkyp) != 0)
+        if (IDAGetDky (m_mem, tin + step*i, 1, dkyp) != 0)
           error ("IDA failed to interpolate yp");
 
         cont += 1;
-        output.resize (cont + 1, num);
+        output.resize (cont + 1, m_num);
         tout.resize (cont + 1);
 
         tout(cont) = tin + step * i;
-        yout = NVecToCol (dky, num);
-        ypout = NVecToCol (dkyp, num);
+        yout = NVecToCol (dky, m_num);
+        ypout = NVecToCol (dkyp, m_num);
 
-        for (octave_idx_type j = 0; j < num; j++)
+        for (octave_idx_type j = 0; j < m_num; j++)
           output.elem (cont, j) = yout.elem (j);
 
         if (haveoutputfcn)
@@ -810,7 +891,7 @@
   }
 
   bool
-  IDA::outputfun (octave_function *output_fcn, bool haveoutputsel,
+  IDA::outputfun (const octave_value& output_fcn, bool haveoutputsel,
                   const ColumnVector& yout, realtype tsol,
                   realtype tend, ColumnVector& outputsel,
                   const std::string& flag)
@@ -859,21 +940,21 @@
   void
   IDA::set_maxstep (realtype maxstep)
   {
-    if (IDASetMaxStep (mem, maxstep) != 0)
+    if (IDASetMaxStep (m_mem, maxstep) != 0)
       error ("IDA: Max Step not set");
   }
 
   void
   IDA::set_initialstep (realtype initialstep)
   {
-    if (IDASetInitStep (mem, initialstep) != 0)
+    if (IDASetInitStep (m_mem, initialstep) != 0)
       error ("IDA: Initial Step not set");
   }
 
   void
   IDA::set_maxorder (int maxorder)
   {
-    if (IDASetMaxOrd (mem, maxorder) != 0)
+    if (IDASetMaxOrd (m_mem, maxorder) != 0)
       error ("IDA: Max Order not set");
   }
 
@@ -882,13 +963,13 @@
   {
     long int nsteps = 0, netfails = 0, nrevals = 0;
 
-    if (IDAGetNumSteps (mem, &nsteps) != 0)
+    if (IDAGetNumSteps (m_mem, &nsteps) != 0)
       error ("IDA failed to return the number of internal steps");
 
-    if (IDAGetNumErrTestFails (mem, &netfails) != 0)
+    if (IDAGetNumErrTestFails (m_mem, &netfails) != 0)
       error ("IDA failed to return the number of internal errors");
 
-    if (IDAGetNumResEvals (mem, &nrevals) != 0)
+    if (IDAGetNumResEvals (m_mem, &nrevals) != 0)
       error ("IDA failed to return the number of residual evaluations");
 
     octave_stdout << nsteps << " successful steps\n";
@@ -901,7 +982,7 @@
 
   ColumnVector
   ida_user_function (const ColumnVector& x, const ColumnVector& xdot,
-                     double t, octave_function *ida_fc)
+                     double t, const octave_value& ida_fc)
   {
     octave_value_list tmp;
 
@@ -919,7 +1000,7 @@
 
   Matrix
   ida_dense_jac (const ColumnVector& x, const ColumnVector& xdot,
-                 double t, double cj, octave_function *ida_jc)
+                 double t, double cj, const octave_value& ida_jc)
   {
     octave_value_list tmp;
 
@@ -937,7 +1018,7 @@
 
   SparseMatrix
   ida_sparse_jac (const ColumnVector& x, const ColumnVector& xdot,
-                  double t, double cj, octave_function *ida_jc)
+                  double t, double cj, const octave_value& ida_jc)
   {
     octave_value_list tmp;
 
@@ -967,7 +1048,7 @@
   }
 
   octave_value_list
-  do_ode15 (octave_function *ida_fcn,
+  do_ode15 (const octave_value& ida_fcn,
             const ColumnVector& tspan,
             const int numt,
             const realtype t0,
@@ -987,16 +1068,14 @@
 
     bool havejacfun = options.getfield ("havejacfun").bool_value ();
 
-    Matrix ida_dfdy, ida_dfdyp, *dfdy, *dfdyp;
-    SparseMatrix ida_spdfdy, ida_spdfdyp, *spdfdy, *spdfdyp;
-    octave_function *ida_jac;
-    Cell jaccell;
+    Matrix ida_dfdy, ida_dfdyp;
+    SparseMatrix ida_spdfdy, ida_spdfdyp;
 
     if (havejac)
       {
         if (havejacfun)
           {
-            ida_jac = options.getfield ("Jacobian").function_value ();
+            octave_value ida_jac = options.getfield ("Jacobian");
 
             if (havejacsparse)
               dae.set_jacobian (ida_jac, ida_sparse_jac);
@@ -1005,23 +1084,22 @@
           }
         else
           {
-            jaccell = options.getfield ("Jacobian").cell_value ();
+            Cell jaccell = options.getfield ("Jacobian").cell_value ();
 
             if (havejacsparse)
               {
                 ida_spdfdy = jaccell(0).sparse_matrix_value ();
                 ida_spdfdyp = jaccell(1).sparse_matrix_value ();
-                spdfdy = &ida_spdfdy;
-                spdfdyp = &ida_spdfdyp;
-                dae.set_jacobian (spdfdy, spdfdyp, ida_sparse_cell_jac);
+
+                dae.set_jacobian (&ida_spdfdy, &ida_spdfdyp,
+                                  ida_sparse_cell_jac);
               }
             else
               {
                 ida_dfdy = jaccell(0).matrix_value ();
                 ida_dfdyp = jaccell(1).matrix_value ();
-                dfdy = &ida_dfdy;
-                dfdyp = &ida_dfdyp;
-                dae.set_jacobian (dfdy, dfdyp, ida_dense_cell_jac);
+
+                dae.set_jacobian (&ida_dfdy, &ida_dfdyp, ida_dense_cell_jac);
               }
           }
       }
@@ -1070,7 +1148,7 @@
 
     bool haverefine = (refine > 1);
 
-    octave_function *output_fcn = nullptr;
+    octave_value output_fcn;
     ColumnVector outputsel;
 
     // OutputFcn
@@ -1078,7 +1156,7 @@
       = options.getfield("haveoutputfunction").bool_value ();
 
     if (haveoutputfunction)
-      output_fcn = options.getfield("OutputFcn").function_value ();
+      output_fcn = options.getfield("OutputFcn");
 
     // OutputSel
     bool haveoutputsel = options.getfield("haveoutputselection").bool_value ();
@@ -1086,17 +1164,17 @@
     if (haveoutputsel)
       outputsel = options.getfield("OutputSel").vector_value ();
 
-    octave_function *event_fcn = nullptr;
+    octave_value event_fcn;
 
     // Events
     bool haveeventfunction
       = options.getfield("haveeventfunction").bool_value ();
 
     if (haveeventfunction)
-      event_fcn = options.getfield("Events").function_value ();
+      event_fcn = options.getfield("Events");
 
     // Set up linear solver
-    dae.set_up ();
+    dae.set_up (y0);
 
     // Integrate
     retval = dae.integrate (numt, tspan, y0, yp0, refine,
@@ -1132,13 +1210,11 @@
     print_usage ();
 
   // Check odefun
-  octave_value f_arg = args(0);
+  octave_value ida_fcn = args(0);
 
-  if (! f_arg.is_function_handle ())
+  if (! ida_fcn.is_function_handle ())
     error ("__ode15__: odefun must be a function handle");
 
-  octave_function *ida_fcn = f_arg.function_value ();
-
   // Check input tspan
   ColumnVector tspan
     = args(1).xvector_value ("__ode15__: TRANGE must be a vector of numbers");
@@ -1184,3 +1260,8 @@
 
 #endif
 }
+
+/*
+## No test needed for internal helper function.
+%!assert (1)
+*/
--- a/libinterp/dldfcn/audiodevinfo.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/dldfcn/audiodevinfo.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -2255,9 +2255,6 @@
 
   audioplayer *recorder = new audioplayer ();
 
-  if (! recorder)
-    error ("__player_audioplayer__: Couldn't instantiate new audioplayer");
-
   bool is_function = (args(0).is_string () || args(0).is_function_handle ()
                       || args(0).is_inline_function ());
 
--- a/libinterp/dldfcn/gzip.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/dldfcn/gzip.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -98,7 +98,7 @@
     CFile (void) = delete;
 
     CFile (const std::string& path, const std::string& mode)
-      : m_fp (octave::sys::fopen (path, mode))
+      : m_fp (sys::fopen (path, mode))
     {
       if (! m_fp)
         throw std::runtime_error ("unable to open file");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-class.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,1162 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <algorithm>
+#include <iomanip>
+
+#include "cdef-class.h"
+#include "cdef-manager.h"
+#include "cdef-method.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
+#include "cdef-utils.h"
+#include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "parse.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-eval.h"
+#include "pt-idx.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+#include "unwind-prot.h"
+
+// Define to 1 to enable debugging statements.
+#define DEBUG_TRACE 0
+#if DEBUG_TRACE
+#  include <iostream>
+#endif
+
+namespace octave
+{
+  static octave_value
+  make_fcn_handle (interpreter& interp, const octave_value& fcn,
+                   const std::string& nm)
+  {
+    octave_value retval;
+
+    if (fcn.is_defined ())
+      {
+        tree_evaluator& tw = interp.get_evaluator ();
+
+        symbol_scope curr_scope = tw.get_current_scope ();
+
+        retval = octave_value (new octave_fcn_handle (curr_scope, fcn, nm));
+      }
+
+    return retval;
+  }
+
+  cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
+    : cdef_meta_object_rep (), member_count (0), handle_class (false),
+      object_count (0), meta (false)
+  {
+    put ("SuperClasses", to_ov (superclasses));
+    implicit_ctor_list = superclasses;
+  }
+
+  cdef_method
+  cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
+  {
+    auto it = method_map.find (nm);
+
+    if (it == method_map.end ())
+      {
+        // FIXME: look into class directory
+      }
+    else
+      {
+        cdef_method& meth = it->second;
+
+        // FIXME: check if method reload needed
+
+        if (meth.ok ())
+          return meth;
+      }
+
+    if (! local)
+      {
+        // Look into superclasses
+
+        Cell super_classes = get ("SuperClasses").cell_value ();
+
+        for (int i = 0; i < super_classes.numel (); i++)
+          {
+            cdef_class cls = lookup_class (super_classes(i));
+
+            cdef_method meth = cls.find_method (nm);
+
+            if (meth.ok ())
+              return meth;
+          }
+      }
+
+    return cdef_method ();
+  }
+
+  class ctor_analyzer : public tree_walker
+  {
+  public:
+
+    ctor_analyzer (void) = delete;
+
+    ctor_analyzer (const std::string& ctor, const std::string& obj)
+      : 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 (tree_statement_list& t)
+    {
+      for (const auto& stmt_p : t)
+        stmt_p->accept (*this);
+    }
+
+    void visit_statement (tree_statement& t)
+    {
+      if (t.is_expression ())
+        t.expression ()->accept (*this);
+    }
+
+    void visit_simple_assignment (tree_simple_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+    void visit_multi_assignment (tree_multi_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+    void visit_index_expression (tree_index_expression& t)
+    {
+      t.expression ()->accept (*this);
+    }
+
+    std::list<cdef_class> get_constructor_list (void) const
+    { return ctor_list; }
+
+    // NO-OP
+
+    void visit_anon_fcn_handle (tree_anon_fcn_handle&) { }
+    void visit_argument_list (tree_argument_list&) { }
+    void visit_binary_expression (tree_binary_expression&) { }
+    void visit_break_command (tree_break_command&) { }
+    void visit_colon_expression (tree_colon_expression&) { }
+    void visit_continue_command (tree_continue_command&) { }
+    void visit_decl_command (tree_decl_command&) { }
+    void visit_decl_init_list (tree_decl_init_list&) { }
+    void visit_decl_elt (tree_decl_elt&) { }
+    void visit_simple_for_command (tree_simple_for_command&) { }
+    void visit_complex_for_command (tree_complex_for_command&) { }
+    void visit_octave_user_script (octave_user_script&) { }
+    void visit_octave_user_function (octave_user_function&) { }
+    void visit_function_def (tree_function_def&) { }
+    void visit_identifier (tree_identifier&) { }
+    void visit_if_clause (tree_if_clause&) { }
+    void visit_if_command (tree_if_command&) { }
+    void visit_if_command_list (tree_if_command_list&) { }
+    void visit_switch_case (tree_switch_case&) { }
+    void visit_switch_case_list (tree_switch_case_list&) { }
+    void visit_switch_command (tree_switch_command&) { }
+    void visit_matrix (tree_matrix&) { }
+    void visit_cell (tree_cell&) { }
+    void visit_no_op_command (tree_no_op_command&) { }
+    void visit_constant (tree_constant&) { }
+    void visit_fcn_handle (tree_fcn_handle&) { }
+    void visit_parameter_list (tree_parameter_list&) { }
+    void visit_postfix_expression (tree_postfix_expression&) { }
+    void visit_prefix_expression (tree_prefix_expression&) { }
+    void visit_return_command (tree_return_command&) { }
+    void visit_return_list (tree_return_list&) { }
+    void visit_try_catch_command (tree_try_catch_command&) { }
+    void visit_unwind_protect_command (tree_unwind_protect_command&) { }
+    void visit_while_command (tree_while_command&) { }
+    void visit_do_until_command (tree_do_until_command&) { }
+
+    void visit_superclass_ref (tree_superclass_ref& t)
+    {
+      if (t.method_name () == obj_name)
+        {
+          std::string class_name = t.class_name ();
+
+          cdef_class cls = lookup_class (class_name, false);
+
+          if (cls.ok ())
+            ctor_list.push_back (cls);
+        }
+    }
+
+  private:
+
+    // The name of the constructor being analyzed.
+    std::string who;
+
+    // The name of the first output argument of the constructor.
+    std::string obj_name;
+
+    // The list of superclass constructors that are explicitly called.
+    std::list<cdef_class> ctor_list;
+  };
+
+  void
+  cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
+  {
+    method_map[meth.get_name ()] = meth;
+
+    member_count++;
+
+    if (meth.is_constructor ())
+      {
+        // Analyze the constructor code to determine what superclass
+        // constructors are called explicitly.
+
+        octave_function *of = meth.get_function ().function_value (true);
+
+        if (of)
+          {
+            octave_user_function *uf = of->user_function_value (true);
+
+            if (uf)
+              {
+                tree_parameter_list *ret_list = uf->return_list ();
+                tree_statement_list *body = uf->body ();
+
+                if (! ret_list || ret_list->size () != 1)
+                  error ("%s: invalid constructor output arguments",
+                         meth.get_name ().c_str ());
+
+                std::string obj_name = ret_list->front ()->name ();
+                ctor_analyzer a (meth.get_name (), obj_name);
+
+                body->accept (a);
+
+                std::list<cdef_class> explicit_ctor_list
+                  = a.get_constructor_list ();
+
+                for (const auto& cdef_cls : explicit_ctor_list)
+                  {
+#if DEBUG_TRACE
+                    std::cerr << "explicit superclass constructor: "
+                              << cdef_cls.get_name () << std::endl;
+#endif
+
+                    implicit_ctor_list.remove (cdef_cls);
+                  }
+              }
+          }
+      }
+  }
+
+  void
+  cdef_class::cdef_class_rep::load_all_methods (void)
+  {
+    // FIXME: re-scan class directory
+  }
+
+  Cell
+  cdef_class::cdef_class_rep::get_methods (bool include_ctor)
+  {
+    std::map<std::string,cdef_method> meths;
+
+    find_methods (meths, false, include_ctor);
+
+    Cell c (meths.size (), 1);
+
+    int idx = 0;
+
+    for (const auto& nm_mthd : meths)
+      c(idx++, 0) = to_ov (nm_mthd.second);
+
+    return c;
+  }
+
+  std::map<std::string, cdef_method>
+  cdef_class::cdef_class_rep::get_method_map (bool only_inherited,
+                                              bool include_ctor)
+  {
+    std::map<std::string, cdef_method> methods;
+
+    find_methods (methods, only_inherited, include_ctor);
+
+    return methods;
+  }
+
+  void
+  cdef_class::cdef_class_rep::find_methods (std::map<std::string, cdef_method>& meths,
+                                            bool only_inherited, bool include_ctor)
+  {
+    load_all_methods ();
+
+    method_const_iterator it;
+
+    for (it = method_map.begin (); it != method_map.end (); ++it)
+      {
+        if (include_ctor || ! it->second.is_constructor ())
+          {
+            std::string nm = it->second.get_name ();
+
+            if (meths.find (nm) == meths.end ())
+              {
+                if (only_inherited)
+                  {
+                    octave_value acc = it->second.get ("Access");
+
+                    if (! acc.is_string ()
+                        || acc.string_value () == "private")
+                      continue;
+                  }
+
+                meths[nm] = it->second;
+              }
+          }
+      }
+
+    // Look into superclasses
+
+    Cell super_classes = get ("SuperClasses").cell_value ();
+
+    for (int i = 0; i < super_classes.numel (); i++)
+      {
+        cdef_class cls = lookup_class (super_classes(i));
+
+        cls.get_rep ()->find_methods (meths, true, false);
+      }
+  }
+
+  cdef_property
+  cdef_class::cdef_class_rep::find_property (const std::string& nm)
+  {
+    auto it = property_map.find (nm);
+
+    if (it != property_map.end ())
+      {
+        cdef_property& prop = it->second;
+
+        if (prop.ok ())
+          return prop;
+      }
+
+    // Look into superclasses
+
+    Cell super_classes = get ("SuperClasses").cell_value ();
+
+    for (int i = 0; i < super_classes.numel (); i++)
+      {
+        cdef_class cls = lookup_class (super_classes(i));
+
+        cdef_property prop = cls.find_property (nm);
+
+        if (prop.ok ())
+          return prop;
+      }
+
+    return cdef_property ();
+  }
+
+  void
+  cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
+  {
+    property_map[prop.get_name ()] = prop;
+
+    member_count++;
+  }
+
+  Cell
+  cdef_class::cdef_class_rep::get_properties (int mode)
+  {
+    std::map<std::string,cdef_property> props;
+
+    props = get_property_map (mode);
+
+    Cell c (props.size (), 1);
+
+    int idx = 0;
+
+    for (const auto& pname_prop : props)
+      c(idx++, 0) = to_ov (pname_prop.second);
+
+    return c;
+  }
+
+  std::map<std::string, cdef_property>
+  cdef_class::cdef_class_rep::get_property_map (int mode)
+  {
+    std::map<std::string,cdef_property> props;
+
+    find_properties (props, mode);
+
+    return props;
+  }
+
+  void
+  cdef_class::cdef_class_rep::find_properties (std::map<std::string,
+                                               cdef_property>& props,
+                                               int mode)
+  {
+    property_const_iterator it;
+
+    for (it = property_map.begin (); it != property_map.end (); ++it)
+      {
+        std::string nm = it->second.get_name ();
+
+        if (props.find (nm) == props.end ())
+          {
+            if (mode == property_inherited)
+              {
+                octave_value acc = it->second.get ("GetAccess");
+
+                if (! acc.is_string ()
+                    || acc.string_value () == "private")
+                  continue;
+              }
+
+            props[nm] = it->second;
+          }
+      }
+
+    // Look into superclasses
+
+    Cell super_classes = get ("SuperClasses").cell_value ();
+
+    for (int i = 0; i < super_classes.numel (); i++)
+      {
+        cdef_class cls = lookup_class (super_classes(i));
+
+        cls.get_rep ()->find_properties (props,
+                                         (mode == property_all
+                                          ? property_all
+                                          : property_inherited));
+      }
+  }
+
+  void
+  cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
+                                          bool all)
+  {
+    load_all_methods ();
+
+    for (const auto& cls_fnmap : method_map)
+      {
+        if (! cls_fnmap.second.is_constructor ())
+          {
+            std::string nm = cls_fnmap.second.get_name ();
+
+            if (! all)
+              {
+                octave_value acc = cls_fnmap.second.get ("Access");
+
+                if (! acc.is_string()
+                    || acc.string_value () != "public")
+                  continue;
+              }
+
+            names.insert (nm);
+          }
+      }
+
+    for (const auto& pname_prop : property_map)
+      {
+        std::string nm = pname_prop.second.get_name ();
+
+        if (! all)
+          {
+            octave_value acc = pname_prop.second.get ("GetAccess");
+
+            if (! acc.is_string()
+                || acc.string_value () != "public")
+              continue;
+          }
+
+        names.insert (nm);
+      }
+
+    // Look into superclasses
+
+    Cell super_classes = get ("SuperClasses").cell_value ();
+
+    for (int i = 0; i < super_classes.numel (); i++)
+      {
+        cdef_class cls = lookup_class (super_classes(i));
+
+        cls.get_rep ()->find_names (names, all);
+      }
+  }
+
+  string_vector
+  cdef_class::cdef_class_rep::get_names (void)
+  {
+    std::set<std::string> names;
+
+    find_names (names, false);
+
+    string_vector v (names);
+
+    return v.sort (true);
+  }
+
+  void
+  cdef_class::cdef_class_rep::delete_object (const cdef_object& obj)
+  {
+    cdef_method dtor = find_method ("delete");
+
+    // FIXME: would it be better to tell find_method above to not find
+    // overloaded functions?
+
+    if (dtor.ok () && dtor.is_defined_in_class (get_name ()))
+      dtor.execute (obj, octave_value_list (), 0, true, "destructor");
+
+    // FIXME: should we destroy corresponding properties here?
+
+    // Call "delete" in super classes
+
+    Cell super_classes = get ("SuperClasses").cell_value ();
+
+    for (int i = 0; i < super_classes.numel (); i++)
+      {
+        cdef_class cls = lookup_class (super_classes(i));
+
+        if (cls.get_name () != "handle")
+          cls.delete_object (obj);
+      }
+  }
+
+  octave_value_list
+  cdef_class::cdef_class_rep::meta_subsref (const std::string& type,
+                                            const std::list<octave_value_list>& idx,
+                                            int nargout)
+  {
+    size_t skip = 1;
+
+    octave_value_list retval;
+
+    switch (type[0])
+      {
+      case '(':
+        // Constructor call
+
+#if DEBUG_TRACE
+        std::cerr << "constructor" << std::endl;
+#endif
+
+        retval(0) = construct (idx.front ());
+        break;
+
+      case '.':
+        {
+          // Static method, constant (or property?)
+
+#if DEBUG_TRACE
+          std::cerr << "static method/property" << std::endl;
+#endif
+
+          if (idx.front ().length () != 1)
+            error ("invalid meta.class indexing");
+
+          std::string nm = idx.front ()(0).xstring_value ("invalid meta.class indexing, expected a method or property name");
+
+          cdef_method meth = find_method (nm);
+
+          if (meth.ok ())
+            {
+              if (! meth.is_static ())
+                error ("method '%s' is not static", nm.c_str ());
+
+              octave_value_list args;
+
+              if (type.length () > 1 && idx.size () > 1 && type[1] == '(')
+                {
+                  args = *(++(idx.begin ()));
+                  skip++;
+                }
+
+              retval = meth.execute (args, (type.length () > skip
+                                            ? 1 : nargout), true,
+                                     "meta.class");
+            }
+          else
+            {
+              cdef_property prop = find_property (nm);
+
+              if (! prop.ok ())
+                error ("no such method or property '%s'", nm.c_str ());
+
+              if (! prop.is_constant ())
+                error ("property '%s' is not constant", nm.c_str ());
+
+              retval(0) = prop.get_value (true, "meta.class");
+            }
+        }
+        break;
+
+      default:
+        error ("invalid meta.class indexing");
+        break;
+      }
+
+    if (type.length () > skip && idx.size () > skip && ! retval.empty ())
+      retval = retval(0).next_subsref (nargout, type, idx, skip);
+
+    return retval;
+  }
+
+  void
+  cdef_class::cdef_class_rep::meta_release (void)
+  {
+    cdef_manager& cdm
+      = __get_cdef_manager__ ("cdef_class::cdef_class_rep::meta_release");
+
+    cdm.unregister_class (wrap ());
+  }
+
+  void
+  cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
+  {
+    // Populate the object with default property values
+
+    std::list<cdef_class> super_classes = lookup_classes (
+                                                          get ("SuperClasses").cell_value ());
+
+    for (auto& cls : super_classes)
+      cls.initialize_object (obj);
+
+    for (const auto& pname_prop : property_map)
+      {
+        if (! pname_prop.second.get ("Dependent").bool_value ())
+          {
+            octave_value pvalue = pname_prop.second.get ("DefaultValue");
+
+            if (pvalue.is_defined ())
+              obj.put (pname_prop.first, pvalue);
+            else
+              obj.put (pname_prop.first, octave_value (Matrix ()));
+          }
+      }
+
+    m_count++;
+    obj.mark_for_construction (cdef_class (this));
+  }
+
+  void
+  cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
+                                               const octave_value_list& args)
+  {
+    octave_value_list empty_args;
+
+    for (const auto& cls : implicit_ctor_list)
+      {
+        cdef_class supcls = lookup_class (cls);
+
+        supcls.run_constructor (obj, empty_args);
+      }
+
+    std::string cls_name = get_name ();
+    std::string ctor_name = get_base_name (cls_name);
+
+    cdef_method ctor = find_method (ctor_name);
+
+    if (ctor.ok ())
+      {
+        octave_value_list ctor_args (args);
+        octave_value_list ctor_retval;
+
+        ctor_args.prepend (to_ov (obj));
+        ctor_retval = ctor.execute (ctor_args, 1, true, "constructor");
+
+        if (ctor_retval.length () != 1)
+          error ("%s: invalid number of output arguments for classdef constructor",
+                 ctor_name.c_str ());
+
+        obj = to_cdef (ctor_retval(0));
+      }
+
+    obj.mark_as_constructed (wrap ());
+  }
+
+  octave_value
+  cdef_class::cdef_class_rep::get_method (const std::string& name) const
+  {
+    auto p = method_map.find (name);
+
+    if (p == method_map.end ())
+      return octave_value ();
+
+    return p->second.get_function ();
+  }
+
+
+  octave_value
+  cdef_class::cdef_class_rep::construct (const octave_value_list& args)
+  {
+    cdef_object obj = construct_object (args);
+
+    if (obj.ok ())
+      return to_ov (obj);
+
+    return octave_value ();
+  }
+
+  cdef_object
+  cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
+  {
+    if (is_abstract ())
+      error ("cannot instantiate object for abstract class '%s'",
+             get_name ().c_str ());
+
+    cdef_object obj;
+
+    if (is_meta_class ())
+      {
+        // This code path is only used to create empty meta objects
+        // as filler for the empty values within a meta object array.
+
+        cdef_class this_cls = wrap ();
+
+        static cdef_object empty_class;
+
+        cdef_manager& cdm
+          = __get_cdef_manager__ ("cdef_class::cdef_class_rep::construct_object");
+
+        if (this_cls == cdm.meta_class ())
+          {
+            if (! empty_class.ok ())
+              empty_class = cdm.make_class ("", std::list<cdef_class> ());
+            obj = empty_class;
+          }
+        else if (this_cls == cdm.meta_property ())
+          {
+            static cdef_property empty_property;
+
+            if (! empty_class.ok ())
+              empty_class = cdm.make_class ("", std::list<cdef_class> ());
+            if (! empty_property.ok ())
+              empty_property = cdm.make_property (empty_class, "");
+            obj = empty_property;
+          }
+        else if (this_cls == cdm.meta_method ())
+          {
+            static cdef_method empty_method;
+
+            if (! empty_class.ok ())
+              empty_class = cdm.make_class ("", std::list<cdef_class> ());
+            if (! empty_method.ok ())
+              empty_method = cdm.make_method (empty_class, "", octave_value ());
+            obj = empty_method;
+          }
+        else if (this_cls == cdm.meta_package ())
+          {
+            static cdef_package empty_package;
+
+            if (! empty_package.ok ())
+              empty_package = cdm.make_package ("");
+            obj = empty_package;
+          }
+        else
+          panic_impossible ();
+
+        return obj;
+      }
+    else
+      {
+        if (is_handle_class ())
+          obj = cdef_object (new handle_cdef_object ());
+        else
+          obj = cdef_object (new value_cdef_object ());
+        obj.set_class (wrap ());
+
+        initialize_object (obj);
+
+        run_constructor (obj, args);
+
+        return obj;
+      }
+
+    return cdef_object ();
+  }
+
+  static octave_value
+  compute_attribute_value (tree_evaluator& tw,
+                           tree_classdef_attribute *t)
+  {
+    tree_expression *expr = t->expression ();
+
+    if (expr)
+      {
+        if (expr->is_identifier ())
+          {
+            std::string s = expr->name ();
+
+            if (s == "public")
+              return std::string ("public");
+            else if (s == "protected")
+              return std::string ("protected");
+            else if (s == "private")
+              return std::string ("private");
+          }
+
+        return tw.evaluate (expr);
+      }
+    else
+      return octave_value (true);
+  }
+
+  template <typename T>
+  static std::string
+  attribute_value_to_string (T *t, octave_value v)
+  {
+    if (v.is_string ())
+      return v.string_value ();
+    else if (t->expression ())
+      return t->expression ()->original_text ();
+    else
+      return "true";
+  }
+
+  cdef_class
+  cdef_class::make_meta_class (interpreter& interp,
+                               tree_classdef *t, bool is_at_folder)
+  {
+    cdef_class retval;
+    std::string class_name, full_class_name;
+
+    // Class creation
+
+    class_name = full_class_name = t->ident ()->name ();
+    if (! t->package_name ().empty ())
+      full_class_name = t->package_name () + '.' + full_class_name;
+
+#if DEBUG_TRACE
+    std::cerr << "class: " << full_class_name << std::endl;
+#endif
+
+    // Push a dummy scope frame on the call stack that corresponds to
+    // the scope that was used when parsing classdef object.  Without
+    // this, we may pick up stray values from the current scope when
+    // evaluating expressions found in things like attribute lists.
+
+    unwind_protect frame;
+
+    tree_evaluator& tw = interp.get_evaluator ();
+
+    tw.push_dummy_scope (full_class_name);
+    frame.add_method (tw, &octave::tree_evaluator::pop_scope);
+
+    std::list<cdef_class> slist;
+
+    if (t->superclass_list ())
+      {
+        for (auto& scls : (*t->superclass_list ()))
+          {
+            std::string sclass_name = (scls)->class_name ();
+
+#if DEBUG_TRACE
+            std::cerr << "superclass: " << sclass_name << std::endl;
+#endif
+
+            cdef_class sclass = lookup_class (sclass_name);
+
+            if (sclass.get ("Sealed").bool_value ())
+              error ("'%s' cannot inherit from '%s', because it is sealed",
+                     full_class_name.c_str (), sclass_name.c_str ());
+
+            slist.push_back (sclass);
+          }
+      }
+
+    cdef_manager& cdm = __get_cdef_manager__ ("cdef_class::make_meta_class");
+
+    retval = cdm.make_class (full_class_name, slist);
+
+    // Package owning this class
+
+    if (! t->package_name ().empty ())
+      {
+        cdef_package pack = cdm.find_package (t->package_name ());
+
+        if (pack.ok ())
+          retval.put ("ContainingPackage", to_ov (pack));
+      }
+
+    // Class attributes
+
+    if (t->attribute_list ())
+      {
+        for (const auto& attr : (*t->attribute_list ()))
+          {
+            std::string aname = attr->ident ()->name ();
+            octave_value avalue = compute_attribute_value (tw, attr);
+
+#if DEBUG_TRACE
+            std::cerr << "class attribute: " << aname << " = "
+                      << attribute_value_to_string (attr, avalue) << std::endl;
+#endif
+
+            retval.put (aname, avalue);
+          }
+      }
+
+    tree_classdef_body *b = t->body ();
+
+    if (b)
+      {
+        // Keep track of the get/set accessor methods.  They will be used
+        // later on when creating properties.
+
+        std::map<std::string, octave_value> get_methods;
+        std::map<std::string, octave_value> set_methods;
+
+        // Method blocks
+
+        std::list<tree_classdef_methods_block *> mb_list = b->methods_list ();
+
+        load_path& lp = interp.get_load_path ();
+
+        for (auto& mb_p : mb_list)
+          {
+            std::map<std::string, octave_value> amap;
+
+#if DEBUG_TRACE
+            std::cerr << "method block" << std::endl;
+#endif
+
+            // Method attributes
+
+            if (mb_p->attribute_list ())
+              {
+                for (auto& attr_p : *mb_p->attribute_list ())
+                  {
+                    std::string aname = attr_p->ident ()->name ();
+                    octave_value avalue = compute_attribute_value (tw, attr_p);
+
+#if DEBUG_TRACE
+                    std::cerr << "method attribute: " << aname << " = "
+                              << attribute_value_to_string (attr_p, avalue)
+                              << std::endl;
+#endif
+
+                    amap[aname] = avalue;
+                  }
+              }
+
+            // Methods
+
+            if (mb_p->element_list ())
+              {
+                for (auto& mtd : *mb_p->element_list ())
+                  {
+                    std::string mname = mtd.function_value ()->name ();
+                    std::string mprefix = mname.substr (0, 4);
+
+                    if (mprefix == "get.")
+                      get_methods[mname.substr (4)] =
+                        make_fcn_handle (interp, mtd,
+                                         full_class_name + '>' + mname);
+                    else if (mprefix == "set.")
+                      set_methods[mname.substr (4)] =
+                        make_fcn_handle (interp, mtd,
+                                         full_class_name + '>' + mname);
+                    else
+                      {
+                        cdef_method meth = cdm.make_method (retval, mname, mtd);
+
+#if DEBUG_TRACE
+                        std::cerr << (mname == class_name ? "constructor"
+                                      : "method")
+                                  << ": " << mname << std::endl;
+#endif
+
+                        for (auto& attrnm_val : amap)
+                          meth.put (attrnm_val.first, attrnm_val.second);
+
+                        retval.install_method (meth);
+                      }
+                  }
+              }
+          }
+
+        if (is_at_folder)
+          {
+            // Look for all external methods visible on octave path at the
+            // time of loading of the class.
+            //
+            // FIXME: This is an "extension" to Matlab behavior, which only looks
+            // in the @-folder containing the original classdef file.  However,
+            // this is easier to implement it that way at the moment.
+
+            std::list<std::string> external_methods
+              = lp.methods (full_class_name);
+
+            for (const auto& mtdnm : external_methods)
+              {
+                // FIXME: should we issue a warning if the method is already
+                // defined in the classdef file?
+
+                if (mtdnm != class_name
+                    && ! retval.find_method (mtdnm, true).ok ())
+                  {
+                    // Create a dummy method that is used until the actual
+                    // method is loaded.
+                    octave_user_function *fcn = new octave_user_function ();
+
+                    fcn->stash_function_name (mtdnm);
+
+                    cdef_method meth
+                      = cdm.make_method (retval, mtdnm, octave_value (fcn));
+
+                    retval.install_method (meth);
+                  }
+              }
+          }
+
+        // Property blocks
+
+        // FIXME: default property expression should be able to call static
+        //        methods of the class being constructed.  A restricted CLASSNAME
+        //        symbol should be added to the scope before evaluating default
+        //        value expressions.
+
+        std::list<tree_classdef_properties_block *> pb_list
+          = b->properties_list ();
+
+        for (auto& pb_p : pb_list)
+          {
+            std::map<std::string, octave_value> amap;
+
+#if DEBUG_TRACE
+            std::cerr << "property block" << std::endl;
+#endif
+
+            // Property attributes
+
+            if (pb_p->attribute_list ())
+              {
+                for (auto& attr_p : *pb_p->attribute_list ())
+                  {
+                    std::string aname = attr_p->ident ()->name ();
+                    octave_value avalue = compute_attribute_value (tw, attr_p);
+
+#if DEBUG_TRACE
+                    std::cerr << "property attribute: " << aname << " = "
+                              << attribute_value_to_string (attr_p, avalue)
+                              << std::endl;
+#endif
+
+                    if (aname == "Access")
+                      {
+                        amap["GetAccess"] = avalue;
+                        amap["SetAccess"] = avalue;
+                      }
+                    else
+                      amap[aname] = avalue;
+                  }
+              }
+
+            // Properties
+
+            if (pb_p->element_list ())
+              {
+                for (auto& prop_p : *pb_p->element_list ())
+                  {
+                    std::string prop_name = prop_p->ident ()->name ();
+
+                    cdef_property prop = cdm.make_property (retval, prop_name);
+
+#if DEBUG_TRACE
+                    std::cerr << "property: " << prop_p->ident ()->name ()
+                              << std::endl;
+#endif
+
+                    tree_expression *expr = prop_p->expression ();
+                    if (expr)
+                      {
+                        octave_value pvalue = tw.evaluate (expr);
+
+#if DEBUG_TRACE
+                        std::cerr << "property default: "
+                                  << attribute_value_to_string (prop_p, pvalue)
+                                  << std::endl;
+#endif
+
+                        prop.put ("DefaultValue", pvalue);
+                      }
+
+                    // Install property attributes.  This is done before assigning
+                    // the property accessors so we can do validation by using
+                    // cdef_property methods.
+
+                    for (auto& attrnm_val : amap)
+                      prop.put (attrnm_val.first, attrnm_val.second);
+
+                    // Install property access methods, if any.  Remove the
+                    // accessor methods from the temporary storage map, so we can
+                    // detect which ones are invalid and do not correspond to a
+                    // defined property.
+
+                    auto git = get_methods.find (prop_name);
+
+                    if (git != get_methods.end ())
+                      {
+                        make_function_of_class (retval, git->second);
+                        prop.put ("GetMethod", git->second);
+                        get_methods.erase (git);
+                      }
+
+                    auto sit = set_methods.find (prop_name);
+
+                    if (sit != set_methods.end ())
+                      {
+                        make_function_of_class (retval, sit->second);
+                        prop.put ("SetMethod", sit->second);
+                        set_methods.erase (sit);
+                      }
+
+                    retval.install_property (prop);
+                  }
+              }
+          }
+      }
+
+    return retval;
+  }
+
+  octave_function*
+  cdef_class::get_method_function (const std::string& /* nm */)
+  {
+    octave_classdef_meta *p = new octave_classdef_meta (*this);
+
+    return p;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-class.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,454 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_class_h)
+#define octave_cdef_class_h 1
+
+#include "octave-config.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-refcount.h"
+
+#include "cdef-method.h"
+#include "cdef-object.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
+#include "error.h"
+#include "ov.h"
+#include "ovl.h"
+
+namespace octave
+{
+  class interpreter;
+  class tree_classdef;
+
+  class
+  cdef_class : public cdef_meta_object
+  {
+  private:
+
+    class
+    cdef_class_rep : public cdef_meta_object_rep
+    {
+    public:
+      cdef_class_rep (void)
+        : cdef_meta_object_rep (), member_count (0), handle_class (false),
+          object_count (0), meta (false)
+      { }
+
+      cdef_class_rep (const std::list<cdef_class>& superclasses);
+
+      cdef_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; }
+
+      std::string get_name (void) const
+      { return get ("Name").string_value (); }
+
+      void set_name (const std::string& nm) { put ("Name", nm); }
+
+      bool is_abstract (void) const { return get ("Abstract").bool_value (); }
+
+      bool is_sealed (void) const { return get ("Sealed").bool_value (); }
+
+      cdef_method find_method (const std::string& nm, bool local = false);
+
+      void install_method (const cdef_method& meth);
+
+      Cell get_methods (bool include_ctor);
+
+      std::map<std::string, cdef_method>
+      get_method_map (bool only_inherited, bool include_ctor);
+
+      cdef_property find_property (const std::string& nm);
+
+      void install_property (const cdef_property& prop);
+
+      Cell get_properties (int mode);
+
+      std::map<std::string, cdef_property> get_property_map (int mode);
+
+      string_vector get_names (void);
+
+      void set_directory (const std::string& dir) { directory = dir; }
+
+      std::string get_directory (void) const { return directory; }
+
+      void delete_object (const cdef_object& obj);
+
+      octave_value_list
+      meta_subsref (const std::string& type,
+                    const std::list<octave_value_list>& idx, int nargout);
+
+      void meta_release (void);
+
+      bool meta_accepts_postfix_index (char type) const
+      {
+        return (type == '(' || type == '.');
+      }
+
+      octave_value get_method (const std::string& name) const;
+
+      octave_value construct (const octave_value_list& args);
+
+      cdef_object construct_object (const octave_value_list& args);
+
+      void initialize_object (cdef_object& obj);
+
+      void run_constructor (cdef_object& obj, const octave_value_list& args);
+
+      void mark_as_handle_class (void) { handle_class = true; }
+
+      bool is_handle_class (void) const { return handle_class; }
+
+      void register_object (void) { object_count++; }
+
+      void unregister_object (void) { object_count--; }
+
+      octave_idx_type static_count (void) const { return member_count; }
+
+      void destroy (void)
+      {
+        if (member_count)
+          {
+            m_count++;
+            cdef_class lock (this);
+
+            member_count = 0;
+            method_map.clear ();
+            property_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+      void mark_as_meta_class (void) { meta = true; }
+
+      bool is_meta_class (void) const { return meta; }
+
+    private:
+
+      void load_all_methods (void);
+
+      void find_names (std::set<std::string>& names, bool all);
+
+      void find_properties (std::map<std::string,cdef_property>& props,
+                            int mode = 0);
+
+      void find_methods (std::map<std::string, cdef_method>& meths,
+                         bool only_inherited, bool include_ctor = false);
+
+      cdef_class wrap (void)
+      {
+        m_count++;
+        return cdef_class (this);
+      }
+
+      // The @-directory were this class is loaded from.
+      // (not used yet)
+
+      std::string directory;
+
+      // The methods defined by this class.
+
+      std::map<std::string,cdef_method> method_map;
+
+      // The properties defined by this class.
+
+      std::map<std::string,cdef_property> property_map;
+
+      // The number of members in this class (methods, properties...)
+
+      octave_idx_type member_count;
+
+      // TRUE if this class is a handle class.  A class is a handle
+      // class when the abstract "handle" class is one of its superclasses.
+
+      bool handle_class;
+
+      // The list of super-class constructors that are called implicitly by the
+      // the classdef engine when creating an object.  These constructors are not
+      // called explicitly by the class constructor.
+
+      std::list<cdef_class> implicit_ctor_list;
+
+      // The number of objects of this class.
+
+      refcount<octave_idx_type> object_count;
+
+      // TRUE if this class is a built-in meta class.
+
+      bool meta;
+
+      // Utility iterator typedefs.
+
+      typedef std::map<std::string,cdef_method>::iterator method_iterator;
+      typedef std::map<std::string,cdef_method>::const_iterator method_const_iterator;
+      typedef std::map<std::string,cdef_property>::iterator property_iterator;
+      typedef std::map<std::string,cdef_property>::const_iterator property_const_iterator;
+
+      cdef_class_rep (const cdef_class_rep& c)
+        : cdef_meta_object_rep (c), directory (c.directory),
+          method_map (c.method_map), property_map (c.property_map),
+          member_count (c.member_count), handle_class (c.handle_class),
+          implicit_ctor_list (c.implicit_ctor_list),
+          object_count (c.object_count), meta (c.meta) { }
+    };
+
+  public:
+
+    // Create an invalid class object.
+
+    cdef_class (void) : cdef_meta_object () { }
+
+    cdef_class (const std::string& nm, const std::list<cdef_class>& superclasses)
+      : cdef_meta_object (new cdef_class_rep (superclasses))
+    {
+      get_rep ()->set_name (nm);
+    }
+
+    cdef_class (const cdef_class& cls) : cdef_meta_object (cls) { }
+
+    cdef_class (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_class ())
+        error ("internal error: invalid assignment from %s to meta.class object",
+               class_name ().c_str ());
+    }
+
+    cdef_class& operator = (const cdef_class& cls)
+    {
+      cdef_object::operator = (cls);
+
+      return *this;
+    }
+
+    ~cdef_class (void) = default;
+
+    cdef_method find_method (const std::string& nm, bool local = false);
+
+    void install_method (const cdef_method& meth)
+    {
+      get_rep ()->install_method (meth);
+    }
+
+    Cell get_methods (bool include_ctor = false)
+    {
+      return get_rep ()->get_methods (include_ctor);
+    }
+
+    std::map<std::string, cdef_method>
+    get_method_map (bool only_inherited = false, bool include_ctor = false)
+    {
+      return get_rep ()->get_method_map (only_inherited, include_ctor);
+    }
+
+    cdef_property find_property (const std::string& nm);
+
+    void install_property (const cdef_property& prop)
+    {
+      get_rep ()->install_property (prop);
+    }
+
+    Cell get_properties (int mode = property_normal)
+    {
+      return get_rep ()->get_properties (mode);
+    }
+
+    std::map<std::string, cdef_property>
+    get_property_map (int mode = property_normal)
+    {
+      return get_rep ()->get_property_map (mode);
+    }
+
+    string_vector get_names (void) { return get_rep ()->get_names (); }
+
+    bool is_abstract (void) const { return get_rep ()->is_abstract (); }
+
+    bool is_sealed (void) const { return get_rep ()->is_sealed (); }
+
+    void set_directory (const std::string& dir)
+    {
+      get_rep ()->set_directory (dir);
+    }
+
+    std::string get_directory (void) const
+    {
+      return get_rep ()->get_directory ();
+    }
+
+    std::string get_name (void) const { return get_rep ()->get_name (); }
+
+    bool is_builtin (void) const { return get_directory ().empty (); }
+
+    void delete_object (const cdef_object& obj)
+    {
+      get_rep ()->delete_object (obj);
+    }
+
+    //! Analyze the tree_classdef tree and transform it to a cdef_class
+    //!
+    //! <b>All attribute validation should occur here.</b>
+    //!
+    //! Classdef attribute values can be given in the form of
+    //! expressions.  These expressions must be evaluated before
+    //! assigning them as attribute values.  Evaluating them as they are
+    //! parsed causes trouble with possible recusion in the parser so we
+    //! do it here.  For example
+    //!
+    //! @code
+    //! classdef recursion_class
+    //!   methods (Access = ?recursion_class)
+    //!   endmethods
+    //! endclassdef
+    //! @endcode
+    //!
+    //! will fail because each attempt to compute the metaclass of
+    //! recursion_class will cause recursion_class to be parsed again.
+
+    static cdef_class
+    make_meta_class (interpreter& interp, tree_classdef *t,
+                     bool is_at_folder = false);
+
+    octave_value get_method (const std::string& nm) const
+    {
+      return get_rep ()->get_method (nm);
+    }
+
+    octave_function * get_method_function (const std::string& nm);
+
+    octave_function * get_constructor_function (void)
+    {
+      return get_method_function (get_name ());
+    }
+
+    octave_value construct (const octave_value_list& args)
+    {
+      return get_rep ()->construct (args);
+    }
+
+    cdef_object construct_object (const octave_value_list& args)
+    {
+      return get_rep ()->construct_object (args);
+    }
+
+    void initialize_object (cdef_object& obj)
+    {
+      get_rep ()->initialize_object (obj);
+    }
+
+    void run_constructor (cdef_object& obj, const octave_value_list& args)
+    {
+      get_rep ()->run_constructor (obj, args);
+    }
+
+    void mark_as_handle_class (void)
+    {
+      get_rep ()->mark_as_handle_class ();
+    }
+
+    bool is_handle_class (void) const
+    {
+      return get_rep ()->is_handle_class ();
+    }
+
+    void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); }
+
+    bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
+
+    void register_object (void) { get_rep ()->register_object (); }
+
+    void unregister_object (void) { get_rep ()->unregister_object (); }
+
+  public:
+
+    enum
+      {
+       property_normal,
+       property_inherited,
+       property_all
+      };
+
+  private:
+
+    cdef_class_rep * get_rep (void)
+    {
+      return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ());
+    }
+
+    const cdef_class_rep * get_rep (void) const
+    {
+      return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ());
+    }
+
+    friend bool operator == (const cdef_class&, const cdef_class&);
+    friend bool operator != (const cdef_class&, const cdef_class&);
+    friend bool operator < (const cdef_class&, const cdef_class&);
+
+    friend void install_classdef (interpreter& interp);
+  };
+
+  inline bool
+  operator == (const cdef_class& clsa, const cdef_class& clsb)
+  {
+    // FIXME: is this really the right way to check class equality?
+
+    return (clsa.get_rep () == clsb.get_rep ());
+  }
+
+  inline bool
+  operator != (const cdef_class& clsa, const cdef_class& clsb)
+  {
+    return ! (clsa == clsb);
+  }
+
+  // This is only to be able to use cdef_class as map keys.
+
+  inline bool
+  operator < (const cdef_class& clsa, const cdef_class& clsb)
+  {
+    return clsa.get_rep () < clsb.get_rep ();
+  }
+
+  inline cdef_method
+  cdef_class::find_method (const std::string& nm, bool local)
+  {
+    return get_rep ()->find_method (nm, local);
+  }
+
+  inline cdef_property
+  cdef_class::find_property (const std::string& nm)
+  {
+    return get_rep ()->find_property (nm);
+  }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-manager.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,948 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "cdef-manager.h"
+#include "cdef-utils.h"
+#include "interpreter.h"
+#include "interpreter-private.h"
+#include "ov-classdef.h"
+
+namespace octave
+{
+  static octave_value
+  make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
+  {
+    octave_value fcn (new octave_builtin (ff, nm));
+
+    octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
+
+    return fcn_handle;
+  }
+
+  static octave_value_list
+  class_get_properties (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () == 1 && args(0).type_name () == "object")
+      {
+        cdef_class cls (to_cdef (args(0)));
+
+        retval(0) = cls.get_properties ();
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  class_get_methods (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () == 1 && args(0).type_name () == "object")
+      {
+        cdef_class cls (to_cdef (args(0)));
+
+        retval(0) = cls.get_methods ();
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  class_get_superclasses (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () == 1 && args(0).type_name () == "object"
+        && args(0).class_name () == "meta.class")
+      {
+        cdef_class cls (to_cdef (args(0)));
+
+        Cell classes = cls.get ("SuperClasses").cell_value ();
+
+        retval(0) = to_ov (lookup_classes (classes));
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () == 1 && args(0).type_name () == "object"
+        && args(0).class_name () == "meta.class")
+      {
+        cdef_class cls (to_cdef (args(0)));
+
+        Cell classes = cls.get ("InferiorClasses").cell_value ();
+
+        retval(0) = to_ov (lookup_classes (classes));
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  class_fromName (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () != 1)
+      error ("fromName: invalid number of parameters");
+
+    std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string");
+
+    retval(0) = to_ov (lookup_class (name, false));
+
+    return retval;
+  }
+
+  static octave_value_list
+  class_fevalStatic (const octave_value_list& args, int nargout)
+  {
+    if (args.length () <= 1 || args(0).type_name () != "object")
+      error ("fevalStatic: first argument must be a meta.class object");
+
+    cdef_class cls (to_cdef (args(0)));
+
+    std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string");
+
+    cdef_method meth = cls.find_method (meth_name);
+
+    if (! meth.ok ())
+      error ("fevalStatic: method not found: %s", meth_name.c_str ());
+
+    if (! meth.is_static ())
+      error ("fevalStatic: method '%s' is not static", meth_name.c_str ());
+
+    return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic");
+  }
+
+  static octave_value_list
+  class_getConstant (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () != 2 || args(0).type_name () != "object"
+        || args(0).class_name () != "meta.class")
+      error ("getConstant: first argument must be a meta.class object");
+
+    cdef_class cls = to_cdef (args(0));
+
+    std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string");
+
+    cdef_property prop = cls.find_property (prop_name);
+
+    if (! prop.ok ())
+      error ("getConstant: property not found: %s",
+             prop_name.c_str ());
+
+    if (! prop.is_constant ())
+      error ("getConstant: property '%s' is not constant",
+             prop_name.c_str ());
+
+    retval(0) = prop.get_value (true, "getConstant");
+
+    return retval;
+  }
+
+#define META_CLASS_CMP(OP, CLSA, CLSB, FUN)                             \
+  static octave_value_list                                              \
+  class_ ## OP (const octave_value_list& args, int /* nargout */)       \
+  {                                                                     \
+    octave_value_list retval;                                           \
+                                                                        \
+    if (args.length () != 2                                             \
+        || args(0).type_name () != "object"                             \
+        || args(1).type_name () != "object"                             \
+        || args(0).class_name () != "meta.class"                        \
+        || args(1).class_name () != "meta.class")                       \
+      error (#OP ": invalid arguments");                                \
+                                                                        \
+    cdef_class clsa = to_cdef (args(0));                                \
+                                                                        \
+    cdef_class clsb = to_cdef (args(1));                                \
+                                                                        \
+    retval(0) = FUN (CLSA, CLSB);                                       \
+                                                                        \
+    return retval;                                                      \
+  }
+
+  META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
+  META_CLASS_CMP (le, clsb, clsa, is_superclass)
+  META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
+  META_CLASS_CMP (ge, clsa, clsb, is_superclass)
+  META_CLASS_CMP (eq, clsa, clsb, operator==)
+  META_CLASS_CMP (ne, clsa, clsb, operator!=)
+
+  static octave_value_list
+  property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () == 1 && args(0).type_name () == "object")
+      {
+        cdef_property prop (to_cdef (args(0)));
+
+        retval(0) = prop.get ("DefaultValue");
+
+        if (! retval(0).is_defined ())
+          error_with_id ("Octave:class:NoDefaultDefined",
+                         "no default value for property '%s'",
+                         prop.get_name ().c_str ());
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  handle_delete (const octave_value_list& /* args */, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    // FIXME: implement this.  Wait, what is this supposed to do?
+
+    return retval;
+  }
+
+  static octave_value_list
+  package_get_classes (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval (1, Matrix ());
+
+    if (args.length () == 1 && args(0).type_name () == "object"
+        && args(0).class_name () == "meta.package")
+      {
+        cdef_package pack (to_cdef (args(0)));
+
+        retval(0) = pack.get_classes ();
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  package_get_functions (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval (1, Matrix ());
+
+    if (args.length () == 0 && args(0).type_name () == "object"
+        && args(0).class_name () == "meta.package")
+      {
+        cdef_package pack (to_cdef (args(0)));
+
+        retval(0) = pack.get_functions ();
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  package_get_packages (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval (1, Matrix ());
+
+    if (args.length () == 0 && args(0).type_name () == "object"
+        && args(0).class_name () == "meta.package")
+      {
+        cdef_package pack (to_cdef (args(0)));
+
+        retval(0) = pack.get_packages ();
+      }
+
+    return retval;
+  }
+
+  static octave_value_list
+  package_getAllPackages (interpreter& interp,
+                          const octave_value_list& /* args */, int /* nargout */)
+  {
+    std::map<std::string, cdef_package> toplevel_packages;
+
+    load_path& lp = interp.get_load_path ();
+
+    std::list<std::string> names = lp.get_all_package_names ();
+
+    cdef_manager& cdm = __get_cdef_manager__ ("package_getAllPackages");
+
+    toplevel_packages["meta"] = cdm.find_package ("meta", false, false);
+
+    for (const auto& nm : names)
+      toplevel_packages[nm] = cdm.find_package (nm, false, true);
+
+    Cell c (toplevel_packages.size (), 1);
+
+    int i = 0;
+
+    for (const auto& nm_pkg : toplevel_packages)
+      c(i++,0) = to_ov (nm_pkg.second);
+
+    return octave_value_list (octave_value (c));
+  }
+
+  static octave_value_list
+  package_fromName (const octave_value_list& args, int /* nargout */)
+  {
+    octave_value_list retval;
+
+    if (args.length () != 1)
+      error ("fromName: invalid number of parameters");
+
+    std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string");
+
+    retval(0) = to_ov (lookup_package (name, false));
+
+    return retval;
+  }
+
+  cdef_manager::cdef_manager (interpreter& interp)
+    : m_interpreter (interp), m_all_classes (), m_all_packages (),
+      m_meta_class (), m_meta_property (), m_meta_method (),
+      m_meta_package (), m_meta ()
+  {
+    type_info& ti = m_interpreter.get_type_info ();
+
+    octave_classdef::register_type (ti);
+
+    // bootstrap
+    cdef_class tmp_handle = make_class ("handle");
+
+    m_meta_class = make_meta_class ("meta.class", tmp_handle);
+
+    tmp_handle.set_class (m_meta_class);
+    m_meta_class.set_class (m_meta_class);
+
+    // meta classes
+    m_meta_property = make_meta_class ("meta.property", tmp_handle);
+
+    m_meta_method = make_meta_class ("meta.method", tmp_handle);
+
+    m_meta_package = make_meta_class ("meta.package", tmp_handle);
+
+    cdef_class tmp_meta_event
+      = make_meta_class ("meta.event", tmp_handle);
+
+    cdef_class tmp_meta_dynproperty
+      = make_meta_class ("meta.dynamicproperty", tmp_handle);
+
+    // meta.class properties
+    m_meta_class.install_property
+      (make_attribute (m_meta_class, "Abstract"));
+
+    m_meta_class.install_property
+      (make_attribute (m_meta_class, "ConstructOnLoad"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "ContainingPackage"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "Description"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "DetailedDescription"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "Events"));
+
+    m_meta_class.install_property
+      (make_attribute (m_meta_class, "HandleCompatible"));
+
+    m_meta_class.install_property
+      (make_attribute (m_meta_class, "Hidden"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "InferiorClasses",
+                      make_fcn_handle (class_get_inferiorclasses,
+                                       "meta.class>get.InferiorClasses"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "Methods",
+                      make_fcn_handle (class_get_methods,
+                                       "meta.class>get.Methods"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "MethodList",
+                      make_fcn_handle (class_get_methods,
+                                       "meta.class>get.MethodList"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property (make_attribute (m_meta_class, "Name"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "Properties",
+                      make_fcn_handle (class_get_properties,
+                                       "meta.class>get.Properties"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "PropertyList",
+                      make_fcn_handle (class_get_properties,
+                                       "meta.class>get.PropertyList"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property (make_attribute (m_meta_class, "Sealed"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "SuperClasses",
+                      make_fcn_handle (class_get_superclasses,
+                                       "meta.class>get.SuperClasses"),
+                      "public", Matrix (), "private"));
+
+    m_meta_class.install_property
+      (make_property (m_meta_class, "SuperClassList",
+                      make_fcn_handle (class_get_superclasses,
+                                       "meta.class>get.SuperClassList"),
+                      "public", Matrix (), "private"));
+
+    // meta.class methods
+    m_meta_class.install_method
+      (make_method (m_meta_class, "fromName", class_fromName, "public", true));
+
+    m_meta_class.install_method
+      (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public",
+                    false));
+
+    m_meta_class.install_method
+      (make_method (m_meta_class, "getConstant", class_getConstant, "public",
+                    false));
+
+    m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq));
+    m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne));
+    m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt));
+    m_meta_class.install_method (make_method (m_meta_class, "le", class_le));
+    m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt));
+    m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge));
+
+    // meta.method properties
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Abstract"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Access"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "DefiningClass"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Description"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "DetailedDescription"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Hidden"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Name"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Sealed"));
+
+    m_meta_method.install_property
+      (make_attribute (m_meta_method, "Static"));
+
+    // meta.property properties
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Name"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Description"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "DetailedDescription"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Abstract"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Constant"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "GetAccess"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "SetAccess"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Dependent"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Transient"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "Hidden"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "GetObservable"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "SetObservable"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "GetMethod"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "SetMethod"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "DefiningClass"));
+
+    m_meta_property.install_property
+      (make_property (m_meta_property, "DefaultValue",
+                      make_fcn_handle (property_get_defaultvalue,
+                                       "meta.property>get.DefaultValue"),
+                      "public", Matrix (), "private"));
+
+    m_meta_property.install_property
+      (make_attribute (m_meta_property, "HasDefault"));
+
+    // meta.property events
+    // FIXME: add events
+
+    // handle methods
+
+    tmp_handle.install_method
+      (make_method (tmp_handle, "delete", handle_delete));
+
+    // meta.package properties
+
+    m_meta_package.install_property
+      (make_attribute (m_meta_package, "Name"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "ContainingPackage"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "ClassList",
+                      make_fcn_handle (package_get_classes,
+                                       "meta.package>get.ClassList"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "Classes",
+                      make_fcn_handle (package_get_classes,
+                                       "meta.package>get.Classes"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "FunctionList",
+                      make_fcn_handle (package_get_functions,
+                                       "meta.package>get.FunctionList"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "Functions",
+                      make_fcn_handle (package_get_functions,
+                                       "meta.package>get.Functions"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "PackageList",
+                      make_fcn_handle (package_get_packages,
+                                       "meta.package>get.PackageList"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_property
+      (make_property (m_meta_package, "Packages",
+                      make_fcn_handle (package_get_packages,
+                                       "meta.package>get.Packages"),
+                      "public", Matrix (), "private"));
+
+    m_meta_package.install_method
+      (make_method (m_meta_package, "fromName", package_fromName,
+                    "public", true));
+
+    m_meta_package.install_method
+      (make_method (m_meta_package, "getAllPackages", package_getAllPackages,
+                    "public", true));
+
+    // create "meta" package
+    cdef_package package_meta
+      = m_meta
+      = make_package ("meta");
+
+    package_meta.install_class (m_meta_class, "class");
+    package_meta.install_class (m_meta_property, "property");
+    package_meta.install_class (m_meta_method, "method");
+    package_meta.install_class (m_meta_package, "package");
+    package_meta.install_class (tmp_meta_event, "event");
+    package_meta.install_class (tmp_meta_dynproperty, "dynproperty");
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    // install built-in classes into the symbol table
+    symtab.install_built_in_function
+      ("meta.class",
+       octave_value (m_meta_class.get_constructor_function ()));
+
+    symtab.install_built_in_function
+      ("meta.method",
+       octave_value (m_meta_method.get_constructor_function ()));
+
+    symtab.install_built_in_function
+      ("meta.property",
+       octave_value (m_meta_property.get_constructor_function ()));
+
+    symtab.install_built_in_function
+      ("meta.package",
+       octave_value (m_meta_package.get_constructor_function ()));
+
+    // FIXME: meta.event and meta.dynproperty are not implemented
+    //        and should not be installed into symbol table.
+
+    //  symtab.install_built_in_function
+    //    ("meta.event",
+    //     octave_value (tmp_meta_event.get_constructor_function ()));
+
+    //  symtab.install_built_in_function
+    //    ("meta.dynproperty",
+    //     octave_value (tmp_meta_dynproperty.get_constructor_function ()));
+  }
+
+  cdef_class
+  cdef_manager::find_class (const std::string& name, bool error_if_not_found,
+                            bool load_if_not_found)
+  {
+    auto it = m_all_classes.find (name);
+
+    if (it == m_all_classes.end ())
+      {
+        if (load_if_not_found)
+          {
+            octave_value ov_cls;
+
+            size_t pos = name.rfind ('.');
+
+            if (pos == std::string::npos)
+              ov_cls = m_interpreter.find (name);
+            else
+              {
+                std::string pack_name = name.substr (0, pos);
+
+                cdef_package pack = find_package (pack_name, false, true);
+
+                if (pack.ok ())
+                  ov_cls = pack.find (name.substr (pos+1));
+              }
+
+            if (ov_cls.is_defined ())
+              it = m_all_classes.find (name);
+          }
+      }
+
+    if (it == m_all_classes.end ())
+      {
+        if (error_if_not_found)
+          error ("class not found: %s", name.c_str ());
+      }
+    else
+      {
+        cdef_class cls = it->second;
+
+        if (! cls.is_builtin ())
+          cls = lookup_class (cls);
+
+        if (cls.ok ())
+          return cls;
+        else
+          m_all_classes.erase (it);
+      }
+
+    return cdef_class ();
+  }
+
+  octave_function *
+  cdef_manager::find_method_symbol (const std::string& method_name,
+                                    const std::string& class_name)
+  {
+    octave_function *retval = nullptr;
+
+    cdef_class cls = find_class (class_name, false, false);
+
+    if (cls.ok ())
+      {
+        cdef_method meth = cls.find_method (method_name);
+
+        if (meth.ok ())
+          retval = new octave_classdef_meta (meth);
+      }
+
+    return retval;
+  }
+
+  cdef_package
+  cdef_manager::find_package (const std::string& name, bool error_if_not_found,
+                              bool load_if_not_found)
+  {
+    cdef_package retval;
+
+    std::map<std::string, cdef_package>::const_iterator it
+      = m_all_packages.find (name);
+
+    if (it != m_all_packages.end ())
+      {
+        retval = it->second;
+
+        if (! retval.ok ())
+          error ("invalid package '%s'", name.c_str ());
+      }
+    else
+      {
+        load_path& lp = m_interpreter.get_load_path ();
+
+        if (load_if_not_found && lp.find_package (name))
+          {
+            size_t pos = name.rfind ('.');
+
+            if (pos == std::string::npos)
+              retval = make_package (name, "");
+            else
+              {
+                std::string parent_name = name.substr (0, pos);
+
+                retval = make_package (name, parent_name);
+              }
+          }
+        else if (error_if_not_found)
+          error ("unknown package '%s'", name.c_str ());
+      }
+
+    return retval;
+  }
+
+  octave_function *
+  cdef_manager::find_package_symbol (const std::string& pack_name)
+  {
+    octave_function *retval = nullptr;
+
+    cdef_package pack = find_package (pack_name, false);
+
+    if (pack.ok ())
+      retval = new octave_classdef_meta (pack);
+
+    return retval;
+  }
+
+  cdef_class
+  cdef_manager::make_class (const std::string& name,
+                            const std::list<cdef_class>& super_list)
+  {
+    cdef_class cls (name, super_list);
+
+    cls.set_class (meta_class ());
+
+    cls.put ("Abstract", false);
+    cls.put ("ConstructOnLoad", false);
+    cls.put ("ContainingPackage", Matrix ());
+    cls.put ("Description", "");
+    cls.put ("DetailedDescription", "");
+    cls.put ("Events", Cell ());
+    cls.put ("Hidden", false);
+    cls.put ("InferiorClasses", Cell ());
+    cls.put ("Methods", Cell ());
+    cls.put ("Properties", Cell ());
+    cls.put ("Sealed", false);
+
+    if (name == "handle")
+      {
+        cls.put ("HandleCompatible", true);
+        cls.mark_as_handle_class ();
+      }
+    else if (super_list.empty ())
+      {
+        cls.put ("HandleCompatible", false);
+      }
+    else
+      {
+        bool all_handle_compatible = true;
+        bool has_handle_class = false;
+
+        for (const auto& cl : super_list)
+          {
+            all_handle_compatible = all_handle_compatible
+              && cl.get ("HandleCompatible").bool_value ();
+            has_handle_class = has_handle_class || cl.is_handle_class ();
+          }
+
+        if (has_handle_class && ! all_handle_compatible)
+          error ("%s: cannot mix handle and non-HandleCompatible classes",
+                 name.c_str ());
+
+        cls.put ("HandleCompatible", all_handle_compatible);
+        if (has_handle_class)
+          cls.mark_as_handle_class ();
+      }
+
+    if (! name.empty ())
+      register_class (cls);
+
+    return cls;
+  }
+
+  cdef_class
+  cdef_manager::make_class (const std::string& name,
+                            const cdef_class& super)
+  {
+    return make_class (name, std::list<cdef_class> (1, super));
+  }
+
+  cdef_class
+  cdef_manager::make_meta_class (const std::string& name,
+                                 const cdef_class& super)
+  {
+    cdef_class cls = make_class (name, super);
+
+    cls.put ("Sealed", true);
+    cls.mark_as_meta_class ();
+
+    return cls;
+  }
+
+  cdef_property
+  cdef_manager::make_property (const cdef_class& cls, const std::string& name,
+                               const octave_value& get_method,
+                               const std::string& get_access,
+                               const octave_value& set_method,
+                               const std::string& set_access)
+  {
+    cdef_property prop (name);
+
+    prop.set_class (meta_property ());
+
+    prop.put ("Description", "");
+    prop.put ("DetailedDescription", "");
+    prop.put ("Abstract", false);
+    prop.put ("Constant", false);
+    prop.put ("GetAccess", get_access);
+    prop.put ("SetAccess", set_access);
+    prop.put ("Dependent", false);
+    prop.put ("Transient", false);
+    prop.put ("Hidden", false);
+    prop.put ("GetObservable", false);
+    prop.put ("SetObservable", false);
+    prop.put ("GetMethod", get_method);
+    prop.put ("SetMethod", set_method);
+    prop.put ("DefiningClass", to_ov (cls));
+    prop.put ("DefaultValue", octave_value ());
+    prop.put ("HasDefault", false);
+
+    std::string class_name = cls.get_name ();
+
+    if (! get_method.isempty ())
+      make_function_of_class (class_name, get_method);
+    if (! set_method.isempty ())
+      make_function_of_class (class_name, set_method);
+
+    return prop;
+  }
+
+  cdef_property
+  cdef_manager::make_attribute (const cdef_class& cls, const std::string& name)
+  {
+    return make_property (cls, name, Matrix (), "public", Matrix (), "private");
+  }
+
+  cdef_method
+  cdef_manager::make_method (const cdef_class& cls, const std::string& name,
+                             const octave_value& fcn,
+                             const std::string& m_access, bool is_static)
+  {
+    cdef_method meth (name);
+
+    meth.set_class (meta_method ());
+
+    meth.put ("Abstract", false);
+    meth.put ("Access", m_access);
+    meth.put ("DefiningClass", to_ov (cls));
+    meth.put ("Description", "");
+    meth.put ("DetailedDescription", "");
+    meth.put ("Hidden", false);
+    meth.put ("Sealed", true);
+    meth.put ("Static", is_static);
+
+    if (fcn.is_defined ())
+      make_function_of_class (cls, fcn);
+
+    meth.set_function (fcn);
+
+    if (is_dummy_method (fcn))
+      meth.mark_as_external (cls.get_name ());
+
+    return meth;
+  }
+
+  cdef_method
+  cdef_manager::make_method (const cdef_class& cls, const std::string& name,
+                             octave_builtin::fcn ff,
+                             const std::string& m_access, bool is_static)
+  {
+    octave_value fcn (new octave_builtin (ff, name));
+
+    return make_method (cls, name, fcn, m_access, is_static);
+  }
+
+  cdef_method
+  cdef_manager::make_method (const cdef_class& cls, const std::string& name,
+                             octave_builtin::meth mm,
+                             const std::string& m_access, bool is_static)
+  {
+    octave_value fcn (new octave_builtin (mm, name));
+
+    return make_method (cls, name, fcn, m_access, is_static);
+  }
+
+  cdef_package
+  cdef_manager::make_package (const std::string& nm, const std::string& parent)
+  {
+    cdef_package pack (nm);
+
+    pack.set_class (meta_package ());
+
+    if (parent.empty ())
+      pack.put ("ContainingPackage", Matrix ());
+    else
+      pack.put ("ContainingPackage", to_ov (find_package (parent)));
+
+    if (! nm.empty ())
+      register_package (pack);
+
+    return pack;
+  }
+
+  octave_value
+  cdef_manager::find_method (const std::string& class_name,
+                             const std::string& name) const
+  {
+    cdef_class cls = lookup_class (class_name);
+
+    return cls.get_method (name);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-manager.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,155 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_manager_h)
+#define octave_cdef_manager_h 1
+
+#include "octave-config.h"
+
+#include "cdef-class.h"
+#include "cdef-method.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
+#include "ov-builtin.h"
+
+namespace octave
+{
+  class interpreter;
+
+  class
+    cdef_manager
+  {
+  public:
+
+    cdef_manager (interpreter& interp);
+
+    // No copying!
+
+    cdef_manager (const cdef_manager&) = delete;
+
+    cdef_manager& operator = (const cdef_manager&) = delete;
+
+    ~cdef_manager (void) = default;
+
+    cdef_class find_class (const std::string& name, bool error_if_not_found = true,
+                           bool load_if_not_found = true);
+
+    octave_function * find_method_symbol (const std::string& method_name,
+                                          const std::string& class_name);
+
+    cdef_package find_package (const std::string& name,
+                               bool error_if_not_found = true,
+                               bool load_if_not_found = true);
+
+    octave_function * find_package_symbol (const std::string& pack_name);
+
+    void register_class (const cdef_class& cls)
+    {
+      m_all_classes[cls.get_name ()] = cls;
+    }
+
+    void unregister_class (const cdef_class& cls)
+    {
+      m_all_classes.erase(cls.get_name ());
+    }
+
+    void register_package (const cdef_package& pkg)
+    {
+      m_all_packages[pkg.get_name ()] = pkg;
+    }
+
+    void unregister_package (const cdef_package& pkg)
+    {
+      m_all_packages.erase (pkg.get_name ());
+    }
+
+    const cdef_class& meta_class (void) const { return m_meta_class; }
+    const cdef_class& meta_property (void) const { return m_meta_property; }
+    const cdef_class& meta_method (void) const { return m_meta_method; }
+    const cdef_class& meta_package (void) const { return m_meta_package; }
+
+    const cdef_package& meta (void) const { return m_meta; }
+
+    cdef_class
+      make_class (const std::string& name,
+                  const std::list<cdef_class>& super_list = std::list<cdef_class> ());
+
+    cdef_class
+      make_class (const std::string& name, const cdef_class& super);
+
+    cdef_class
+      make_meta_class (const std::string& name, const cdef_class& super);
+
+    cdef_property
+      make_property (const cdef_class& cls, const std::string& name,
+                     const octave_value& get_method = Matrix (),
+                     const std::string& get_access = "public",
+                     const octave_value& set_method = Matrix (),
+                     const std::string& set_access = "public");
+
+    cdef_property
+      make_attribute (const cdef_class& cls, const std::string& name);
+
+    cdef_method
+      make_method (const cdef_class& cls, const std::string& name,
+                   const octave_value& fcn,
+                   const std::string& m_access = "public",
+                   bool is_static = false);
+
+    cdef_method
+      make_method (const cdef_class& cls, const std::string& name,
+                   octave_builtin::fcn ff,
+                   const std::string& m_access = "public",
+                   bool is_static = false);
+
+    cdef_method
+      make_method (const cdef_class& cls, const std::string& name,
+                   octave_builtin::meth mm,
+                   const std::string& m_access = "public",
+                   bool is_static = false);
+
+    cdef_package
+      make_package (const std::string& nm, const std::string& parent = "");
+
+    octave_value find_method (const std::string& class_name,
+                              const std::string& name) const;
+
+  private:
+
+    interpreter& m_interpreter;
+
+    // All registered/loaded classes
+    std::map<std::string, cdef_class> m_all_classes;
+
+    // All registered/loaded packages
+    std::map<std::string, cdef_package> m_all_packages;
+
+    cdef_class m_meta_class;
+    cdef_class m_meta_property;
+    cdef_class m_meta_method;
+    cdef_class m_meta_package;
+
+    cdef_package m_meta;
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-method.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,221 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <algorithm>
+#include <iomanip>
+
+#include "cdef-class.h"
+#include "cdef-manager.h"
+#include "cdef-utils.h"
+#include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "parse.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-idx.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+
+namespace octave
+{
+  OCTAVE_NORETURN static
+  void
+  err_method_access (const std::string& from, const cdef_method& meth)
+  {
+    octave_value acc = meth.get ("Access");
+    std::string acc_s;
+
+    if (acc.is_string ())
+      acc_s = acc.string_value ();
+    else
+      acc_s = "class-restricted";
+
+    error ("%s: method '%s' has %s access and cannot be run in this context",
+           from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
+  }
+
+  void
+  cdef_method::cdef_method_rep::check_method (void)
+  {
+    if (is_external ())
+      {
+        if (is_dummy_method (function))
+          {
+            load_path& lp
+              = __get_load_path__ ("cdef_method::cdef_method_rep::check_method");
+
+            std::string name = get_name ();
+            std::string cls_name = dispatch_type;
+            std::string pack_name;
+
+            size_t pos = cls_name.rfind ('.');
+
+            if (pos != std::string::npos)
+              {
+                pack_name = cls_name.substr (0, pos);
+                cls_name = cls_name.substr (pos + 1);
+              }
+
+            std::string dir_name;
+            std::string file_name = lp.find_method (cls_name, name,
+                                                    dir_name, pack_name);
+
+            if (! file_name.empty ())
+              {
+                octave_value ov_fcn
+                  = load_fcn_from_file (file_name, dir_name,
+                                                dispatch_type, pack_name);
+
+                if (ov_fcn.is_defined ())
+                  {
+                    function = ov_fcn;
+
+                    make_function_of_class (dispatch_type, function);
+                  }
+              }
+          }
+        else
+          {
+            // FIXME: check out-of-date status
+          }
+
+        if (is_dummy_method (function))
+          error ("no definition found for method '%s' of class '%s'",
+                 get_name ().c_str (), dispatch_type.c_str ());
+      }
+  }
+
+  octave_value_list
+  cdef_method::cdef_method_rep::execute (const octave_value_list& args,
+                                         int nargout, bool do_check_access,
+                                         const std::string& who)
+  {
+    octave_value_list retval;
+
+    if (do_check_access && ! check_access ())
+      err_method_access (who, wrap ());
+
+    if (get ("Abstract").bool_value ())
+      error ("%s: cannot execute abstract method",
+             get ("Name").string_value ().c_str ());
+
+    check_method ();
+
+    if (function.is_defined ())
+      retval = feval (function, args, nargout);
+
+    return retval;
+  }
+
+  octave_value_list
+  cdef_method::cdef_method_rep::execute (const cdef_object& obj,
+                                         const octave_value_list& args,
+                                         int nargout, bool do_check_access,
+                                         const std::string& who)
+  {
+    octave_value_list retval;
+
+    if (do_check_access && ! check_access ())
+      err_method_access (who, wrap ());
+
+    if (get ("Abstract").bool_value ())
+      error ("%s: cannot execute abstract method",
+             get ("Name").string_value ().c_str ());
+
+    check_method ();
+
+    if (function.is_defined ())
+      {
+        octave_value_list new_args;
+
+        new_args.resize (args.length () + 1);
+
+        new_args(0) = to_ov (obj);
+        for (int i = 0; i < args.length (); i++)
+          new_args(i+1) = args(i);
+
+        retval = feval (function, new_args, nargout);
+      }
+
+    return retval;
+  }
+
+  bool
+  cdef_method::cdef_method_rep::is_constructor (void) const
+  {
+    if (function.is_function())
+      return function.function_value ()->is_classdef_constructor ();
+
+    return false;
+  }
+
+  bool
+  cdef_method::cdef_method_rep::is_defined_in_class (const std::string &cname) const
+  {
+    return (function.is_function ()
+            ? function.function_value ()->dispatch_class () == cname
+            : false);
+  }
+
+  bool
+  cdef_method::cdef_method_rep::check_access (void) const
+  {
+    cdef_class cls (to_cdef (get ("DefiningClass")));
+
+    return octave::check_access (cls, get ("Access"), get_name ());
+  }
+
+  octave_value_list
+  cdef_method::cdef_method_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+  {
+    octave_value_list retval;
+
+    switch (type[0])
+      {
+      case '(':
+        retval = (execute (idx.front (), type.length () > 1 ? 1 : nargout, true));
+        break;
+
+      default:
+        error ("invalid meta.method indexing");
+        break;
+      }
+
+    if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
+      retval = retval(0).next_subsref (nargout, type, idx, 1);
+
+    return retval;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-method.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,221 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_method_h)
+#define octave_cdef_method_h 1
+
+#include "octave-config.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-refcount.h"
+
+#include "cdef-object.h"
+#include "ov.h"
+
+namespace octave
+{
+  class
+  cdef_method : public cdef_meta_object
+  {
+    friend class cdef_class;
+
+  private:
+
+    class
+    cdef_method_rep : public cdef_meta_object_rep
+    {
+    public:
+
+      cdef_method_rep (void)
+        : cdef_meta_object_rep (), function (), dispatch_type ()
+      { }
+
+      cdef_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; }
+
+      std::string get_name (void) const { return get("Name").string_value (); }
+
+      void set_name (const std::string& nm) { put ("Name", nm); }
+
+      bool is_static (void) const { return get("Static").bool_value (); }
+
+      octave_value get_function (void) const { return function; }
+
+      void set_function (const octave_value& fcn) { function = fcn; }
+
+      bool check_access (void) const;
+
+      bool is_external (void) const { return ! dispatch_type.empty (); }
+
+      void mark_as_external (const std::string& dtype)
+      {
+        dispatch_type = dtype;
+      }
+
+      octave_value_list execute (const octave_value_list& args, int nargout,
+                                 bool do_check_access = true,
+                                 const std::string& who = "");
+
+      octave_value_list execute (const cdef_object& obj,
+                                 const octave_value_list& args, int nargout,
+                                 bool do_check_access = true,
+                                 const std::string& who = "");
+
+      bool is_constructor (void) const;
+
+      bool is_defined_in_class (const std::string& cname) const;
+
+      octave_value_list
+      meta_subsref (const std::string& type,
+                    const std::list<octave_value_list>& idx, int nargout);
+
+      bool meta_accepts_postfix_index (char type) const
+      {
+        return (type == '(' || type == '.');
+      }
+
+    private:
+
+      cdef_method_rep (const cdef_method_rep& m)
+        : cdef_meta_object_rep (m), function (m.function),
+          dispatch_type (m.dispatch_type)
+      { }
+
+      void check_method (void);
+
+      cdef_method wrap (void)
+      {
+        m_count++;
+        return cdef_method (this);
+      }
+
+      octave_value function;
+
+      // When non-empty, the method is externally defined and this member
+      // is used to cache the dispatch type to look for the method.
+
+      std::string dispatch_type;
+    };
+
+  public:
+
+    cdef_method (void) : cdef_meta_object () { }
+
+    cdef_method (const std::string& nm)
+      : cdef_meta_object (new cdef_method_rep ())
+    {
+      get_rep ()->set_name (nm);
+    }
+
+    cdef_method (const cdef_method& meth) : cdef_meta_object (meth) { }
+
+    cdef_method (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_method ())
+        error ("internal error: invalid assignment from %s to meta.method object",
+               class_name ().c_str ());
+    }
+
+    cdef_method& operator = (const cdef_method& meth)
+    {
+      cdef_object::operator = (meth);
+
+      return *this;
+    }
+
+    ~cdef_method (void) = default;
+
+    // normal invocation
+    octave_value_list execute (const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = "")
+    {
+      return get_rep ()->execute (args, nargout, do_check_access, who);
+    }
+
+    // dot-invocation: object is pushed as 1st argument
+    octave_value_list execute (const cdef_object& obj,
+                               const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = "")
+    {
+      return get_rep ()->execute (obj, args, nargout, do_check_access, who);
+    }
+
+    bool check_access (void) const { return get_rep ()->check_access (); }
+
+    std::string get_name (void) const { return get_rep ()->get_name (); }
+
+    bool is_static (void) const { return get_rep ()->is_static (); }
+
+    void set_function (const octave_value& fcn)
+    {
+      get_rep ()->set_function (fcn);
+    }
+
+    octave_value get_function (void) const
+    {
+      return get_rep ()->get_function ();
+    }
+
+    bool is_constructor (void) const
+    {
+      return get_rep ()->is_constructor ();
+    }
+
+    bool is_defined_in_class (const std::string& cname) const
+    {
+      return get_rep ()->is_defined_in_class (cname);
+    }
+
+    bool is_external (void) const { return get_rep ()->is_external (); }
+
+    void mark_as_external (const std::string& dtype)
+    {
+      get_rep ()->mark_as_external (dtype);
+    }
+
+  private:
+
+    cdef_method_rep * get_rep (void)
+    {
+      return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ());
+    }
+
+    const cdef_method_rep * get_rep (void) const
+    {
+      return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ());
+    }
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-object.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,769 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "cdef-class.h"
+#include "cdef-object.h"
+#include "cdef-property.h"
+#include "cdef-utils.h"
+#include "interpreter.h"
+#include "interpreter-private.h"
+#include "ov-classdef.h"
+
+// Define to 1 to enable debugging statements.
+#define DEBUG_TRACE 0
+
+namespace octave
+{
+  void
+  cdef_object_rep::release (const cdef_object& obj)
+  {
+    // We need to be careful to keep a reference to the object if we are
+    // calling the delete method.  The object is passed to the delete
+    // method as an argument and if the count is already zero when we
+    // do that, then we will increment the count while creating the
+    // argument list for the delete method and then it will be decremented
+    // back to zero and we'll find ourselves in an infinite loop.
+
+    if (m_count - 1 > static_count ())
+      {
+        --m_count;
+        return;
+      }
+
+    if (is_handle_object () && ! is_meta_object ())
+      {
+        unwind_protect frame;
+
+        // Clear interrupts.
+        frame.protect_var (octave_interrupt_state);
+        octave_interrupt_state = 0;
+
+        // Disallow quit().
+        frame.protect_var (quit_allowed);
+        quit_allowed = false;
+
+        interpreter_try (frame);
+
+        try
+          {
+            // Call classdef "delete()" method on object
+            get_class ().delete_object (obj);
+          }
+        catch (const interrupt_exception&)
+          {
+            interpreter::recover_from_exception ();
+
+            warning ("interrupt occurred in handle class delete method");
+          }
+        catch (const execution_exception&)
+          {
+            octave::error_system& es
+              = octave::__get_error_system__ ("cdef_object::release");
+
+            std::string msg = es.last_error_message ();
+
+            warning ("error caught while executing handle class delete method:\n%s\n",
+                     msg.c_str ());
+
+          }
+        catch (const exit_exception&)
+          {
+            // This shouldn't happen since we disabled quit above.
+            warning ("exit disabled while executing handle class delete method");
+          }
+        catch (...) // Yes, the black hole.  We're in a d-tor.
+          {
+            // This shouldn't happen, in theory.
+            warning ("internal error: unhandled exception in handle class delete method");
+          }
+      }
+
+    // Now it is safe to set the count to zero.
+    m_count--;
+
+    destroy ();
+  }
+
+  cdef_class
+  cdef_object_rep::get_class (void) const
+  {
+    err_invalid_object ("get_class");
+  }
+
+  std::string
+  cdef_object_rep::class_name (void) const
+  {
+    return get_class ().get_name ();
+  }
+
+  string_vector
+  cdef_object_rep::map_keys (void) const
+  {
+    cdef_class cls = get_class ();
+
+    if (cls.ok ())
+      return cls.get_names ();
+
+    return string_vector ();
+  }
+
+  octave_map
+  cdef_object::map_value (void) const
+  {
+    octave_map retval;
+
+    warning_with_id ("Octave:classdef-to-struct",
+                     "struct: converting a classdef object into a struct "
+                     "overrides the access restrictions defined for properties. "
+                     "All properties are returned, including private and "
+                     "protected ones.");
+
+    cdef_class cls = get_class ();
+
+    if (cls.ok ())
+      {
+        std::map<std::string, cdef_property> props;
+
+        props = cls.get_property_map (cdef_class::property_all);
+
+        // FIXME: Why not const here?
+        for (auto& prop_val : props)
+          {
+            if (is_array ())
+              {
+                Array<cdef_object> a_obj = array_value ();
+
+                Cell cvalue (a_obj.dims ());
+
+                for (octave_idx_type i = 0; i < a_obj.numel (); i++)
+                  cvalue (i) = prop_val.second.get_value (a_obj(i), false);
+
+                retval.setfield (prop_val.first, cvalue);
+              }
+            else
+              {
+                Cell cvalue (dim_vector (1, 1),
+                             prop_val.second.get_value (*this, false));
+
+                retval.setfield (prop_val.first, cvalue);
+              }
+          }
+      }
+
+    return retval;
+  }
+
+  cdef_class
+  cdef_object::get_class (void) const
+  {
+    return rep->get_class ();
+  }
+
+  cdef_class
+  cdef_object_base::get_class (void) const
+  {
+    return cdef_class (klass);
+  }
+
+  void
+  cdef_object_base::set_class (const cdef_class& cls)
+  {
+    if ((klass.ok () && cls.ok () && cls != get_class ())
+        || (klass.ok () && ! cls.ok ())
+        || (! klass.ok () && cls.ok ()))
+      {
+        unregister_object ();
+        klass = cls;
+        register_object ();
+      }
+  }
+
+  void
+  cdef_object_base::register_object (void)
+  {
+    if (klass.ok ())
+      {
+        cdef_class cls (get_class ());
+
+        if (cls.ok ())
+          cls.register_object ();
+      }
+  }
+
+  void
+  cdef_object_base::unregister_object (void)
+  {
+    if (klass.ok ())
+      {
+        cdef_class cls (get_class ());
+
+        if (cls.ok ())
+          cls.unregister_object ();
+      }
+  }
+
+  cdef_object_rep*
+  cdef_object_base::make_array (void) const
+  {
+    cdef_object_rep *r = new cdef_object_array ();
+
+    r->set_class (get_class ());
+
+    return r;
+  }
+
+  octave_value_list
+  cdef_object_array::subsref (const std::string& type,
+                              const std::list<octave_value_list>& idx,
+                              int /* nargout */, size_t& skip,
+                              const cdef_class& /* context */, bool auto_add)
+  {
+    octave_value_list retval;
+
+    skip = 1;
+
+    switch (type[0])
+      {
+      case '(':
+        {
+          const octave_value_list& ival = idx.front ();
+
+          if (ival.empty ())
+            {
+              m_count++;
+              retval(0) = to_ov (cdef_object (this));
+              break;
+            }
+
+          bool is_scalar = true;
+          Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+          for (int i = 0; i < ival.length (); i++)
+            {
+              try
+                {
+                  iv(i) = ival(i).index_vector ();
+                }
+              catch (index_exception& e)
+                {
+                  // Rethrow to allow more info to be reported later.
+                  e.set_pos_if_unset (ival.length (), i+1);
+                  throw;
+                }
+
+              is_scalar = is_scalar && iv(i).is_scalar ();
+            }
+
+          Array<cdef_object> ires = array.index (iv, auto_add);
+
+          // If resizing is enabled (auto_add = true), it's possible
+          // indexing was out-of-bound and the result array contains
+          // invalid cdef_objects.
+
+          if (auto_add)
+            fill_empty_values (ires);
+
+          if (is_scalar)
+            retval(0) = to_ov (ires(0));
+          else
+            {
+              cdef_object array_obj (new cdef_object_array (ires));
+
+              array_obj.set_class (get_class ());
+
+              retval(0) = to_ov (array_obj);
+            }
+        }
+        break;
+
+      case '.':
+        if (type.size () == 1 && idx.size () == 1)
+          {
+            Cell c (dims ());
+
+            octave_idx_type n = array.numel ();
+
+            // dummy variables
+            size_t dummy_skip;
+            cdef_class dummy_cls;
+
+            for (octave_idx_type i = 0; i < n; i++)
+              {
+                octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip,
+                                                        dummy_cls);
+
+                if (r.length () > 0)
+                  c(i) = r(0);
+              }
+
+            retval(0) = octave_value (c, true);
+
+            break;
+          }
+        OCTAVE_FALLTHROUGH;
+
+      default:
+        error ("can't perform indexing operation on array of %s objects",
+               class_name ().c_str ());
+        break;
+      }
+
+    return retval;
+  }
+
+  octave_value
+  cdef_object_array::subsasgn (const std::string& type,
+                               const std::list<octave_value_list>& idx,
+                               const octave_value& rhs)
+  {
+    octave_value retval;
+
+    switch (type[0])
+      {
+      case '(':
+        if (type.length () == 1)
+          {
+            cdef_object rhs_obj = to_cdef (rhs);
+
+            if (rhs_obj.get_class () != get_class ())
+              error ("can't assign %s object into array of %s objects.",
+                     rhs_obj.class_name ().c_str (),
+                     class_name ().c_str ());
+
+            const octave_value_list& ival = idx.front ();
+            bool is_scalar = true;
+            Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+            for (int i = 0; i < ival.length (); i++)
+              {
+                try
+                  {
+                    iv(i) = ival(i).index_vector ();
+                  }
+                catch (index_exception& e)
+                  {
+                    e.set_pos_if_unset (ival.length (), i+1);
+                    throw;   // var name set in pt-idx.cc / pt-assign.cc
+                  }
+
+                is_scalar = is_scalar && iv(i).is_scalar ();
+              }
+
+            Array<cdef_object> rhs_mat;
+
+            if (! rhs_obj.is_array ())
+              {
+                rhs_mat = Array<cdef_object> (dim_vector (1, 1));
+                rhs_mat(0) = rhs_obj;
+              }
+            else
+              rhs_mat = rhs_obj.array_value ();
+
+            octave_idx_type n = array.numel ();
+
+            array.assign (iv, rhs_mat, cdef_object ());
+
+            if (array.numel () > n)
+              fill_empty_values ();
+
+            m_count++;
+            retval = to_ov (cdef_object (this));
+          }
+        else
+          {
+            const octave_value_list& ivl = idx.front ();
+
+            // Fill in trailing singleton dimensions so that
+            // array.index doesn't create a new blank entry (bug #46660).
+            const octave_idx_type one = static_cast<octave_idx_type> (1);
+            const octave_value_list& ival = ivl.length () >= 2
+              ? ivl : ((array.dims ()(0) == 1)
+                       ? ovl (one, ivl(0))
+                       : ovl (ivl(0), one));
+
+            bool is_scalar = true;
+
+            Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+            for (int i = 0; i < ival.length (); i++)
+              {
+                try
+                  {
+                    iv(i) = ival(i).index_vector ();
+                  }
+                catch (index_exception& e)
+                  {
+                    // Rethrow to allow more info to be reported later.
+                    e.set_pos_if_unset (ival.length (), i+1);
+                    throw;
+                  }
+
+                is_scalar = is_scalar && iv(i).is_scalar ();
+
+                if (! is_scalar)
+                  error ("subsasgn: invalid indexing for object array assignment"
+                         ", the index must reference a single object in the "
+                         "array.");
+              }
+
+            Array<cdef_object> a = array.index (iv, true);
+
+            if (a.numel () != 1)
+              error ("subsasgn: invalid indexing for object array assignment");
+
+            cdef_object obj = a(0);
+
+            int ignore_copies = 0;
+
+            // If the object in 'a' is not valid, this means the index
+            // was out-of-bound and we need to create a new object.
+
+            if (! obj.ok ())
+              obj = get_class ().construct_object (octave_value_list ());
+            else
+              // Optimize the subsasgn call to come.  There are 2 copies
+              // that we can safely ignore:
+              // - 1 in "array"
+              // - 1 in "a"
+              ignore_copies = 2;
+
+            std::list<octave_value_list> next_idx (idx);
+
+            next_idx.erase (next_idx.begin ());
+
+            octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
+                                             rhs, ignore_copies);
+
+            cdef_object robj = to_cdef (tmp);
+
+            if (! robj.ok ()
+                || robj.is_array ()
+                || robj.get_class () != get_class ())
+              error ("subsasgn: invalid assignment into array of %s objects",
+                     class_name ().c_str ());
+
+            // Small optimization, when dealing with handle
+            // objects, we don't need to re-assign the result
+            // of subsasgn back into the array.
+
+            if (! robj.is (a(0)))
+              {
+                Array<cdef_object> rhs_a (dim_vector (1, 1),
+                                          robj);
+
+                octave_idx_type n = array.numel ();
+
+                array.assign (iv, rhs_a);
+
+                if (array.numel () > n)
+                  fill_empty_values ();
+              }
+
+            m_count++;
+
+            retval = to_ov (cdef_object (this));
+          }
+        break;
+
+      default:
+        error ("can't perform indexing operation on array of %s objects",
+               class_name ().c_str ());
+        break;
+      }
+
+    return retval;
+  }
+
+  void
+  cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
+  {
+    cdef_class cls = get_class ();
+
+    cdef_object obj;
+
+    int n = arr.numel ();
+
+    for (int i = 0; i < n; i++)
+      {
+        if (! arr.xelem (i).ok ())
+          {
+            if (! obj.ok ())
+              {
+                obj = cls.construct_object (octave_value_list ());
+
+                arr.xelem (i) = obj;
+              }
+            else
+              arr.xelem (i) = obj.copy ();
+          }
+      }
+  }
+
+  octave_value_list
+  cdef_object_scalar::subsref (const std::string& type,
+                               const std::list<octave_value_list>& idx,
+                               int nargout, size_t& skip,
+                               const cdef_class& context, bool auto_add)
+  {
+    skip = 0;
+
+    cdef_class cls = (context.ok () ? context : get_class ());
+
+    octave_value_list retval;
+
+    if (! cls.ok ())
+      return retval;
+
+    switch (type[0])
+      {
+      case '.':
+        {
+          std::string name = (idx.front ())(0).string_value ();
+
+          cdef_method meth = cls.find_method (name);
+
+          if (meth.ok ())
+            {
+              int _nargout = (type.length () > 2 ? 1 : nargout);
+
+              octave_value_list args;
+
+              skip = 1;
+
+              if (type.length () > 1 && type[1] == '(')
+                {
+                  auto it = idx.begin ();
+
+                  args = *++it;
+
+                  skip++;
+                }
+
+              if (meth.is_static ())
+                retval = meth.execute (args, _nargout, true, "subsref");
+              else
+                {
+                  m_count++;
+                  retval = meth.execute (cdef_object (this), args, _nargout,
+                                         true, "subsref");
+                }
+            }
+
+          if (skip == 0)
+            {
+              cdef_property prop = cls.find_property (name);
+
+              if (! prop.ok ())
+                error ("subsref: unknown method or property: %s", name.c_str ());
+
+              if (prop.is_constant ())
+                retval(0) = prop.get_value (true, "subsref");
+              else
+                {
+                  m_count++;
+                  retval(0) = prop.get_value (cdef_object (this),
+                                              true, "subsref");
+                }
+
+              skip = 1;
+            }
+          break;
+        }
+
+      case '(':
+        {
+          const octave_value_list& ival = idx.front ();
+
+          m_count++;
+          cdef_object this_obj (this);
+
+          if (ival.empty ())
+            {
+              skip++;
+              retval(0) = to_ov (this_obj);
+            }
+          else
+            {
+              Array<cdef_object> arr (dim_vector (1, 1), this_obj);
+
+              cdef_object new_obj = cdef_object (new cdef_object_array (arr));
+
+              new_obj.set_class (get_class ());
+
+              retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
+            }
+        }
+        break;
+
+      default:
+        error ("object cannot be indexed with '%c'", type[0]);
+        break;
+      }
+
+    return retval;
+  }
+
+  octave_value
+  cdef_object_scalar::subsasgn (const std::string& type,
+                                const std::list<octave_value_list>& idx,
+                                const octave_value& rhs)
+  {
+    octave_value retval;
+
+    cdef_class cls = get_class ();
+
+    switch (type[0])
+      {
+      case '.':
+        {
+          std::string name = (idx.front ())(0).string_value ();
+
+          cdef_property prop = cls.find_property (name);
+
+          if (! prop.ok ())
+            error ("subsasgn: unknown property: %s", name.c_str ());
+
+          if (prop.is_constant ())
+            error ("subsasgn: cannot assign constant property: %s",
+                   name.c_str ());
+
+          m_count++;
+
+          cdef_object obj (this);
+
+          if (type.length () == 1)
+            {
+              prop.set_value (obj, rhs, true, "subsasgn");
+
+              retval = to_ov (obj);
+            }
+          else
+            {
+              octave_value val =
+                prop.get_value (obj, true, "subsasgn");
+
+              std::list<octave_value_list> args (idx);
+
+              args.erase (args.begin ());
+
+              val = val.assign (octave_value::op_asn_eq,
+                                type.substr (1), args, rhs);
+
+              if (val.class_name () != "object"
+                  || ! to_cdef (val).is_handle_object ())
+                prop.set_value (obj, val, true, "subsasgn");
+
+              retval = to_ov (obj);
+            }
+        }
+        break;
+
+      case '(':
+        {
+          m_count++;
+
+          cdef_object this_obj (this);
+
+          Array<cdef_object> arr (dim_vector (1, 1), this_obj);
+
+          cdef_object new_obj = cdef_object (new cdef_object_array (arr));
+
+          new_obj.set_class (get_class ());
+
+          octave_value tmp = new_obj.subsasgn (type, idx, rhs);
+
+          retval = tmp;
+        }
+        break;
+
+      default:
+        error ("subsasgn: object cannot be index with '%c'", type[0]);
+        break;
+      }
+
+    return retval;
+  }
+
+  void
+  cdef_object_scalar::mark_for_construction (const cdef_class& cls)
+  {
+    std::string cls_name = cls.get_name ();
+
+    Cell supcls = cls.get ("SuperClasses").cell_value ();
+
+    std::list<cdef_class> supcls_list = lookup_classes (supcls);
+
+    ctor_list[cls] = supcls_list;
+  }
+
+  bool
+  cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
+  {
+    return (is_constructed ()
+            || ctor_list.find (cls) == ctor_list.end ());
+  }
+
+  bool
+  cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
+  {
+    if (is_constructed ())
+      return true;
+
+    std::map<cdef_class, std::list<cdef_class>>::const_iterator it
+      = ctor_list.find (cls);
+
+    if (it == ctor_list.end () || it->second.empty ())
+      return true;
+
+    for (const auto& cdef_cls : it->second)
+      if (! is_partially_constructed_for (cdef_cls))
+        return false;
+
+    return true;
+  }
+
+  void
+  cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
+  {
+    ctor_list.erase (cls);
+  }
+
+  handle_cdef_object::~handle_cdef_object (void)
+  {
+#if DEBUG_TRACE
+    std::cerr << "deleting " << get_class ().get_name ()
+              << " object (handle)" << std::endl;
+#endif
+  }
+
+  value_cdef_object::~value_cdef_object (void)
+  {
+#if DEBUG_TRACE
+    std::cerr << "deleting " << get_class ().get_name ()
+              << " object (value)" << std::endl;
+#endif
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-object.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,699 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_object_h)
+#define octave_cdef_object_h 1
+
+#include "octave-config.h"
+
+#include <map>
+#include <string>
+
+#include "oct-refcount.h"
+
+#include "error.h"
+#include "oct-map.h"
+#include "ov.h"
+#include "ovl.h"
+
+namespace octave
+{
+  class cdef_object;
+  class cdef_class;
+
+  // This is mainly a boostrap class to declare the expected interface.
+  // The actual base class is cdef_class_base, which is declared after
+  // cdef_object, such that it can contain cdef_object objects.
+
+  class
+  cdef_object_rep
+  {
+  public:
+
+    friend class cdef_object;
+
+    cdef_object_rep (void) : m_count (1) { }
+
+    cdef_object_rep& operator = (const cdef_object_rep&) = delete;
+
+    virtual ~cdef_object_rep (void) = default;
+
+    virtual cdef_class get_class (void) const;
+
+    virtual void set_class (const cdef_class&)
+    {
+      err_invalid_object ("set_class");
+    }
+
+    virtual cdef_object_rep * clone (void) const
+    {
+      err_invalid_object ("clone");
+    }
+
+    virtual cdef_object_rep * empty_clone (void) const
+    {
+      err_invalid_object ("empty_clone");
+    }
+
+    virtual cdef_object_rep * copy (void) const
+    {
+      err_invalid_object ("copy");
+    }
+
+    virtual cdef_object_rep * make_array (void) const
+    {
+      err_invalid_object ("make_array");
+    }
+
+    virtual bool is_array (void) const { return false; }
+
+    virtual bool is_value_object (void) const { return false; }
+
+    virtual bool is_handle_object (void) const { return false; }
+
+    virtual bool is_meta_object (void) const { return false; }
+
+    virtual Array<cdef_object> array_value (void) const
+    {
+      err_invalid_object ("array_value");
+    }
+
+    virtual void put (const std::string&, const octave_value&)
+    { err_invalid_object ("put"); }
+
+    virtual octave_value get (const std::string&) const
+    {
+      err_invalid_object ("get");
+    }
+
+    virtual void set_property (octave_idx_type, const std::string&,
+                               const octave_value&)
+    {
+      err_invalid_object ("set_property");
+    }
+
+    virtual octave_value get_property (octave_idx_type, const std::string&) const
+    {
+      err_invalid_object ("get_property");
+    }
+
+    virtual octave_value_list
+    subsref (const std::string&, const std::list<octave_value_list>&,
+             int, size_t&, const cdef_class&, bool)
+    {
+      err_invalid_object ("subsref");
+    }
+
+    virtual octave_value
+    subsasgn (const std::string&, const std::list<octave_value_list>&,
+              const octave_value&)
+    {
+      err_invalid_object ("subsasgn");
+    }
+
+    virtual string_vector map_keys (void) const;
+
+    virtual bool is_valid (void) const { return false; }
+
+    std::string class_name (void) const;
+
+    virtual void mark_for_construction (const cdef_class&)
+    {
+      err_invalid_object ("mark_for_construction");
+    }
+
+    virtual bool is_constructed_for (const cdef_class&) const
+    {
+      err_invalid_object ("is_constructed_for");
+    }
+
+    virtual bool is_partially_constructed_for (const cdef_class&) const
+    {
+      err_invalid_object ("is_partially_constructed_for");
+    }
+
+    virtual void mark_as_constructed (void)
+    {
+      err_invalid_object ("mark_as_constructed");
+    }
+
+    virtual void mark_as_constructed (const cdef_class&)
+    {
+      err_invalid_object ("mark_as_constructed");
+    }
+
+    virtual bool is_constructed (void) const
+    {
+      err_invalid_object ("is_constructed");
+    }
+
+    virtual octave_idx_type static_count (void) const { return 0; }
+
+    virtual void destroy (void) { delete this; }
+
+    void release (const cdef_object& obj);
+
+    virtual dim_vector dims (void) const { return dim_vector (); }
+
+  protected:
+
+    // Reference count
+    refcount<octave_idx_type> m_count;
+
+    // Restricted copying.
+
+    cdef_object_rep (const cdef_object_rep&) : m_count (1) { }
+
+  private:
+
+    OCTAVE_NORETURN void err_invalid_object (const char *who) const
+    {
+      error ("%s: invalid object", who);
+    }
+  };
+
+  class
+  cdef_object
+  {
+  public:
+
+    // FIXME: use a null object?
+    cdef_object (void) : rep (new cdef_object_rep ()) { }
+
+    cdef_object (const cdef_object& obj) : rep (obj.rep) { rep->m_count++; }
+
+    cdef_object (cdef_object_rep *r) : rep (r) { }
+
+    virtual ~cdef_object (void) { rep->release (*this); }
+
+    cdef_object& operator = (const cdef_object& obj)
+    {
+      if (rep != obj.rep)
+        {
+          rep->release (*this);
+
+          rep = obj.rep;
+          rep->m_count++;
+        }
+
+      return *this;
+    }
+
+    cdef_class get_class (void) const;
+
+    void set_class (const cdef_class& cls) { rep->set_class (cls); }
+
+    std::string class_name (void) const { return rep->class_name (); }
+
+    cdef_object clone (void) const { return cdef_object (rep->clone ()); }
+
+    cdef_object empty_clone (void) const
+    {
+      return cdef_object (rep->empty_clone ());
+    }
+
+    dim_vector dims (void) const { return rep->dims (); }
+
+    cdef_object make_array (void) const
+    {
+      return cdef_object (rep->make_array ());
+    }
+
+    cdef_object copy (void) const { return cdef_object (rep->copy ()); }
+
+    bool is_array (void) const { return rep->is_array (); }
+
+    bool is_value_object (void) const { return rep->is_value_object (); }
+
+    bool is_handle_object (void) const { return rep->is_handle_object (); }
+
+    bool is_meta_object (void) const { return rep->is_meta_object (); }
+
+    Array<cdef_object> array_value (void) const { return rep->array_value (); }
+
+    void put (const std::string& pname, const octave_value& val)
+    {
+      rep->put (pname, val);
+    }
+
+    octave_value get (const std::string& pname) const
+    {
+      return rep->get (pname);
+    }
+
+    void set_property (octave_idx_type idx, const std::string& pname,
+                       const octave_value& pval)
+    {
+      return rep->set_property (idx, pname, pval);
+    }
+
+    octave_value
+    get_property (octave_idx_type idx, const std::string& pname) const
+    {
+      return rep->get_property (idx, pname);
+    }
+
+    octave_value_list
+    subsref (const std::string& type, const std::list<octave_value_list>& idx,
+             int nargout, size_t& skip, const cdef_class& context,
+             bool auto_add = false)
+    {
+      return rep->subsref (type, idx, nargout, skip, context, auto_add);
+    }
+
+    octave_value
+    subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+              const octave_value& rhs, int ignore_copies = 0)
+    {
+      make_unique (ignore_copies);
+      return rep->subsasgn (type, idx, rhs);
+    }
+
+    string_vector map_keys (void) const { return rep->map_keys (); }
+
+    octave_map map_value (void) const;
+
+    const cdef_object_rep * get_rep (void) const { return rep; }
+
+    bool ok (void) const { return rep->is_valid (); }
+
+    void mark_for_construction (const cdef_class& cls)
+    {
+      rep->mark_for_construction (cls);
+    }
+
+    bool is_constructed (void) const { return rep->is_constructed (); }
+
+    bool is_constructed_for (const cdef_class& cls) const
+    {
+      return rep->is_constructed_for (cls);
+    }
+
+    bool is_partially_constructed_for (const cdef_class& cls) const
+    {
+      return rep->is_partially_constructed_for (cls);
+    }
+
+    void mark_as_constructed (void) { rep->mark_as_constructed (); }
+
+    void mark_as_constructed (const cdef_class& cls)
+    { rep->mark_as_constructed (cls); }
+
+    bool is (const cdef_object& obj) const { return rep == obj.rep; }
+
+  protected:
+
+    cdef_object_rep * get_rep (void) { return rep; }
+
+    void make_unique (int ignore_copies)
+    {
+      if (rep->m_count > ignore_copies + 1)
+        *this = clone ();
+    }
+
+  private:
+
+    cdef_object_rep *rep;
+  };
+
+  class
+  cdef_object_base : public cdef_object_rep
+  {
+  public:
+
+    cdef_object_base (void)
+      : cdef_object_rep (), klass ()
+    {
+      register_object ();
+    }
+
+    cdef_object_base& operator = (const cdef_object_base&) = delete;
+
+    ~cdef_object_base (void) { unregister_object (); }
+
+    cdef_class get_class (void) const;
+
+    void set_class (const cdef_class& cls);
+
+    cdef_object_rep * empty_clone (void) const
+    {
+      return new cdef_object_base (*this);
+    }
+
+    cdef_object_rep * make_array (void) const;
+
+  protected:
+
+    // Restricted copying!
+    cdef_object_base (const cdef_object_base& obj)
+      : cdef_object_rep (obj), klass (obj.klass)
+    {
+      register_object ();
+    }
+
+  private:
+
+    void register_object (void);
+
+    void unregister_object (void);
+
+    // The class of the object
+    cdef_object klass;
+  };
+
+  class
+  cdef_object_array : public cdef_object_base
+  {
+  public:
+
+    cdef_object_array (void) : cdef_object_base () { }
+
+    cdef_object_array (const Array<cdef_object>& a)
+      : cdef_object_base (), array (a)
+    { }
+
+    cdef_object_array& operator = (const cdef_object_array&) = delete;
+
+    ~cdef_object_array (void) = default;
+
+    cdef_object_rep * clone (void) const
+    {
+      return new cdef_object_array (*this);
+    }
+
+    dim_vector dims (void) const { return array.dims (); }
+
+    bool is_valid (void) const { return true; }
+
+    bool is_array (void) const { return true; }
+
+    Array<cdef_object> array_value (void) const { return array; }
+
+    octave_value_list
+    subsref (const std::string& type, const std::list<octave_value_list>& idx,
+             int nargout, size_t& skip, const cdef_class& context,
+             bool auto_add);
+
+    octave_value
+    subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+              const octave_value& rhs);
+
+    void set_property (octave_idx_type idx, const std::string& pname,
+                       const octave_value& pval)
+    {
+      cdef_object& tmp = array.elem (idx);
+
+      return tmp.put (pname, pval);
+    }
+
+    octave_value
+    get_property (octave_idx_type idx, const std::string& pname) const
+    {
+      cdef_object tmp = array.elem (idx);
+
+      return tmp.get (pname);
+    }
+
+  private:
+
+    Array<cdef_object> array;
+
+    void fill_empty_values (void) { fill_empty_values (array); }
+
+    void fill_empty_values (Array<cdef_object>& arr);
+
+    // Private copying!
+    cdef_object_array (const cdef_object_array& obj)
+      : cdef_object_base (obj), array (obj.array)
+    { }
+  };
+
+  class
+  cdef_object_scalar : public cdef_object_base
+  {
+  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); }
+
+    void put (const std::string& pname, const octave_value& val)
+    {
+      map.assign (pname, val);
+    }
+
+    octave_value get (const std::string& pname) const
+    {
+      Cell val = map.contents (pname);
+
+      if (val.numel () < 1)
+        error ("get: unknown slot: %s", pname.c_str ());
+
+      return val(0, 0);
+    }
+
+    void set_property (octave_idx_type idx, const std::string& pname,
+                       const octave_value& pval)
+    {
+      if (idx != 0)
+        error ("invalid index");  // FIXME
+
+      put (pname, pval);
+    }
+
+    octave_value
+    get_property (octave_idx_type idx, const std::string& pname) const
+    {
+      if (idx != 0)
+        error ("invalid index");  // FIXME
+
+      return get (pname);
+    }
+
+    octave_value_list
+    subsref (const std::string& type, const std::list<octave_value_list>& idx,
+             int nargout, size_t& skip, const cdef_class& context,
+             bool auto_add);
+
+    octave_value
+    subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+              const octave_value& rhs);
+
+    void mark_for_construction (const cdef_class&);
+
+    bool is_constructed_for (const cdef_class& cls) const;
+
+    bool is_partially_constructed_for (const cdef_class& cls) const;
+
+    void mark_as_constructed (void) { ctor_list.clear (); }
+
+    void mark_as_constructed (const cdef_class& cls);
+
+    bool is_constructed (void) const { return ctor_list.empty (); }
+
+  protected:
+
+    // Object property values
+    octave_scalar_map map;
+
+    // Internal/temporary structure used during object construction
+    std::map< cdef_class, std::list<cdef_class>> ctor_list;
+
+  protected:
+
+    // Restricted object copying!
+    cdef_object_scalar (const cdef_object_scalar& obj)
+      : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list)
+    { }
+  };
+
+  class
+  handle_cdef_object : public cdef_object_scalar
+  {
+  public:
+
+    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
+    {
+      handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
+      obj->m_count++;
+      return obj;
+    }
+
+    cdef_object_rep * copy (void) const
+    {
+      return new handle_cdef_object (*this);
+    }
+
+    bool is_valid (void) const { return true; }
+
+    bool is_handle_object (void) const { return true; }
+
+  protected:
+
+    // Restricted copying!
+    handle_cdef_object (const handle_cdef_object& obj)
+      : cdef_object_scalar (obj)
+    { }
+  };
+
+  class
+  value_cdef_object : public cdef_object_scalar
+  {
+  public:
+
+    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
+    {
+      return new value_cdef_object (*this);
+    }
+
+    cdef_object_rep * copy (void) const { return clone (); }
+
+    bool is_valid (void) const { return true; }
+
+    bool is_value_object (void) const { return true; }
+
+  private:
+
+    // Private copying!
+    value_cdef_object (const value_cdef_object& obj)
+      : cdef_object_scalar (obj)
+    { }
+  };
+
+  class
+  cdef_meta_object_rep : public handle_cdef_object
+  {
+  public:
+
+    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
+    { return new cdef_meta_object_rep (*this); }
+
+    bool is_meta_object (void) const { return true; }
+
+    virtual bool is_class (void) const { return false; }
+
+    virtual bool is_property (void) const { return false; }
+
+    virtual bool is_method (void) const { return false; }
+
+    virtual bool is_package (void) const { return false; }
+
+    virtual octave_value_list
+    meta_subsref (const std::string& /* type */,
+                  const std::list<octave_value_list>& /* idx */,
+                  int /* nargout */)
+    {
+      error ("subsref: invalid meta object");
+    }
+
+    virtual void meta_release (void) { }
+
+    virtual bool meta_accepts_postfix_index (char /* type */) const
+    {
+      return false;
+    }
+
+  protected:
+
+    // Restricted copying!
+    cdef_meta_object_rep (const cdef_meta_object_rep& obj)
+      : handle_cdef_object (obj)
+    { }
+  };
+
+  class
+  cdef_meta_object : public cdef_object
+  {
+  public:
+
+    cdef_meta_object (void) : cdef_object () { }
+
+    // Object consistency is checked in sub-classes.
+    cdef_meta_object (const cdef_meta_object& obj) : cdef_object (obj) { }
+
+    cdef_meta_object (cdef_meta_object_rep *r) : cdef_object (r) { }
+
+    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 (); }
+
+    bool is_property (void) const { return get_rep ()->is_property (); }
+
+    bool is_method (void) const { return get_rep ()->is_method (); }
+
+    bool is_package (void) const { return get_rep ()->is_package (); }
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout)
+    {
+      return get_rep ()->meta_subsref (type, idx, nargout);
+    }
+
+    void meta_release (void) { get_rep ()->meta_release (); }
+
+    bool meta_accepts_postfix_index (char type) const
+    {
+      return get_rep ()->meta_accepts_postfix_index (type);
+    }
+
+  private:
+
+    cdef_meta_object_rep * get_rep (void)
+    {
+      return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ());
+    }
+
+    const cdef_meta_object_rep * get_rep (void) const
+    {
+      return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ());
+    }
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-package.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,201 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <algorithm>
+#include <iomanip>
+
+#include "cdef-class.h"
+#include "cdef-manager.h"
+#include "cdef-utils.h"
+#include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "parse.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-idx.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+
+// Define to 1 to enable debugging statements.
+#define DEBUG_TRACE 0
+
+namespace octave
+{
+  void
+  cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
+                                                 const std::string& nm)
+  {
+    class_map[nm] = cls;
+
+    member_count++;
+  }
+
+  void
+  cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
+                                                    const std::string& nm)
+  {
+    function_map[nm] = fcn;
+  }
+
+  void
+  cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
+                                                   const std::string& nm)
+  {
+    package_map[nm] = pack;
+
+    member_count++;
+  }
+
+  template <typename T1, typename T2>
+  Cell
+  map2Cell (const std::map<T1, T2>& m)
+  {
+    Cell retval (1, m.size ());
+    int i = 0;
+
+    for (auto it = m.begin (); it != m.end (); ++it, ++i)
+      retval(i) = to_ov (it->second);
+
+    return retval;
+  }
+
+  Cell
+  cdef_package::cdef_package_rep::get_classes (void) const
+  {
+    return map2Cell (class_map);
+  }
+
+  Cell
+  cdef_package::cdef_package_rep::get_functions (void) const
+  {
+    return map2Cell (function_map);
+  }
+
+  Cell
+  cdef_package::cdef_package_rep::get_packages (void) const
+  {
+    return map2Cell (package_map);
+  }
+
+  octave_value
+  cdef_package::cdef_package_rep::find (const std::string& nm)
+  {
+    std::string symbol_name = get_name () + '.' + nm;
+
+    interpreter& interp
+      = __get_interpreter__ ("cdef_package::cdef_package_rep::find");
+
+    return interp.find (symbol_name);
+  }
+
+  octave_value_list
+  cdef_package::cdef_package_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+  {
+    octave_value_list retval;
+
+    switch (type[0])
+      {
+      case '.':
+        {
+          if (idx.front ().length () != 1)
+            error ("invalid meta.package indexing");
+
+          std::string nm = idx.front ()(0).xstring_value ("invalid meta.package indexing, expected a symbol name");
+
+#if DEBUG_TRACE
+          std::cerr << "meta.package query: " << nm << std::endl;
+#endif
+
+          octave_value o = find (nm);
+
+          if (! o.is_defined ())
+            error ("member '%s' in package '%s' does not exist",
+                   nm.c_str (), get_name ().c_str ());
+
+          if (o.is_function ())
+            {
+              octave_function *fcn = o.function_value ();
+
+              // NOTE: the case where the package query is the last
+              // part of this subsref index is handled in the parse
+              // tree, because there is some logic to handle magic
+              // "end" that makes it impossible to execute the
+              // function call at this stage.
+
+              if (type.size () > 1
+                  && ! fcn->accepts_postfix_index (type[1]))
+                {
+                  octave_value_list tmp_args;
+
+                  retval = feval (o, tmp_args, nargout);
+                }
+              else
+                retval(0) = o;
+
+              if (type.size () > 1 && idx.size () > 1)
+                retval = retval(0).next_subsref (nargout, type,
+                                                 idx, 1);
+            }
+          else if (type.size () > 1 && idx.size () > 1)
+            retval = o.next_subsref (nargout, type, idx, 1);
+          else
+            retval(0) = o;
+        }
+        break;
+
+      default:
+        error ("invalid meta.package indexing");
+        break;
+      }
+
+    return retval;
+  }
+
+  void
+  cdef_package::cdef_package_rep::meta_release (void)
+  {
+    // FIXME: Do we really want to unregister the package, as it
+    //        could still be referenced by classes or sub-packages?
+    //        If the package object is recreated later on, it won't
+    //        match the one already referenced by those classes or
+    //        sub-packages.
+
+    cdef_manager& cdm
+      = __get_cdef_manager__ ("cdef_package::cdef_package_rep::meta_release");
+
+    // Don't delete the "meta" package.
+    if (this != cdm.meta ().get_rep ())
+      cdm.unregister_package (wrap ());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-package.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,223 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_package_h)
+#define octave_cdef_package_h 1
+
+#include "octave-config.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-refcount.h"
+
+#include "cdef-object.h"
+#include "ov.h"
+
+namespace octave
+{
+  class interpreter;
+
+  class
+  cdef_package : public cdef_meta_object
+  {
+    friend class cdef_class;
+
+  private:
+
+    class
+    cdef_package_rep : public cdef_meta_object_rep
+    {
+    public:
+
+      cdef_package_rep (void) : cdef_meta_object_rep (), member_count (0) { }
+
+      cdef_package_rep& operator = (const cdef_package_rep&) = delete;
+
+      ~cdef_package_rep (void) = default;
+
+      cdef_object_rep * copy (void) const { return new cdef_package_rep (*this); }
+
+      bool is_package (void) const { return true; }
+
+      std::string get_name (void) const { return get("Name").string_value (); }
+
+      void set_name (const std::string& nm) { put ("Name", nm); }
+
+      void install_class (const cdef_class& cls, const std::string& nm);
+
+      void install_function (const octave_value& fcn, const std::string& nm);
+
+      void install_package (const cdef_package& pack, const std::string& nm);
+
+      Cell get_classes (void) const;
+
+      Cell get_functions (void) const;
+
+      Cell get_packages (void) const;
+
+      octave_idx_type static_count (void) const { return member_count; }
+
+      void destroy (void)
+      {
+        if (member_count)
+          {
+            m_count++;
+            cdef_package lock (this);
+
+            member_count = 0;
+            class_map.clear ();
+            package_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+      octave_value_list
+      meta_subsref (const std::string& type,
+                    const std::list<octave_value_list>& idx, int nargout);
+
+      void meta_release (void);
+
+      bool meta_accepts_postfix_index (char type) const
+      {
+        return (type == '.');
+      }
+
+      octave_value find (const std::string& nm);
+
+    private:
+
+      std::string full_name;
+      std::map<std::string, cdef_class> class_map;
+      std::map<std::string, octave_value> function_map;
+      std::map<std::string, cdef_package> package_map;
+
+      // The number of registered members in this package (classes, packages).
+      // This only accounts for the members that back-reference to this package.
+      octave_idx_type member_count;
+
+      typedef std::map<std::string, cdef_class>::iterator class_iterator;
+      typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
+      typedef std::map<std::string, octave_value>::iterator function_iterator;
+      typedef std::map<std::string, octave_value>::const_iterator function_const_iterator;
+      typedef std::map<std::string, cdef_package>::iterator package_iterator;
+      typedef std::map<std::string, cdef_package>::const_iterator package_const_iterator;
+
+      cdef_package_rep (const cdef_package_rep& p)
+        : cdef_meta_object_rep (p), full_name (p.full_name),
+          class_map (p.class_map), function_map (p.function_map),
+          package_map (p.package_map), member_count (p.member_count)
+      { }
+
+      cdef_package wrap (void)
+      {
+        m_count++;
+        return cdef_package (this);
+      }
+    };
+
+  public:
+
+    cdef_package (void) : cdef_meta_object () { }
+
+    cdef_package (const std::string& nm)
+      : cdef_meta_object (new cdef_package_rep ())
+    {
+      get_rep ()->set_name (nm);
+    }
+
+    cdef_package (const cdef_package& pack) : cdef_meta_object (pack) { }
+
+    cdef_package (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_package ())
+        error ("internal error: invalid assignment from %s to meta.package object",
+               class_name ().c_str ());
+    }
+
+    cdef_package& operator = (const cdef_package& pack)
+    {
+      cdef_object::operator = (pack);
+
+      return *this;
+    }
+
+    ~cdef_package (void) = default;
+
+    void install_class (const cdef_class& cls, const std::string& nm)
+    {
+      get_rep ()->install_class (cls, nm);
+    }
+
+    void install_function (const octave_value& fcn, const std::string& nm)
+    {
+      get_rep ()->install_function (fcn, nm);
+    }
+
+    void install_package (const cdef_package& pack, const std::string& nm)
+    {
+      get_rep ()->install_package (pack, nm);
+    }
+
+    Cell get_classes (void) const
+    {
+      return get_rep ()->get_classes ();
+    }
+
+    Cell get_functions (void) const
+    {
+      return get_rep ()->get_functions ();
+    }
+
+    Cell get_packages (void) const
+    {
+      return get_rep ()->get_packages ();
+    }
+
+    std::string get_name (void) const { return get_rep ()->get_name (); }
+
+    octave_value find (const std::string& nm)
+    {
+      return get_rep ()->find (nm);
+    }
+
+  private:
+
+    cdef_package_rep * get_rep (void)
+    {
+      return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ());
+    }
+
+    const cdef_package_rep * get_rep (void) const
+    {
+      return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ());
+    }
+
+    friend void install_classdef (interpreter& interp);
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-property.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,242 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <algorithm>
+#include <iomanip>
+
+#include "cdef-class.h"
+#include "cdef-manager.h"
+#include "cdef-utils.h"
+#include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "parse.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-eval.h"
+#include "pt-idx.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+
+namespace octave
+{
+  static bool
+  is_method_executing (const octave_value& ov, const cdef_object& obj)
+  {
+    tree_evaluator& tw = __get_evaluator__ ("is_method_executing");
+
+    octave_function *stack_fcn = tw.current_function ();
+
+    octave_function *method_fcn = ov.function_value (true);
+
+    // Does the top of the call stack match our target function?
+
+    if (stack_fcn && stack_fcn == method_fcn)
+      {
+        octave_user_function *uf = method_fcn->user_function_value (true);
+
+        // We can only check the context object for user-function (not builtin),
+        // where we have access to the parameters (arguments and return values).
+        // That's ok as there's no need to call this function for builtin
+        // methods.
+
+        if (uf)
+          {
+            // At this point, the method is executing, but we still need to
+            // check the context object for which the method is executing.  For
+            // methods, it's the first argument of the function; for ctors, it
+            // is the first return value.
+
+            tree_parameter_list *pl = uf->is_classdef_constructor ()
+              ? uf->return_list () : uf->parameter_list ();
+
+            if (pl && pl->size () > 0)
+              {
+                tree_decl_elt *elt = pl->front ();
+
+                octave_value arg0 = tw.evaluate (elt);
+
+                if (arg0.is_defined () && arg0.type_name () == "object")
+                  {
+                    cdef_object arg0_obj = to_cdef (arg0);
+
+                    return obj.is (arg0_obj);
+                  }
+              }
+          }
+      }
+
+    return false;
+  }
+
+  octave_value
+  cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
+                                               bool do_check_access,
+                                               const std::string& who) const
+  {
+    octave_value retval;
+
+    if (do_check_access && ! check_get_access ())
+      err_property_access (who, false);
+
+    if (! obj.is_constructed ())
+      {
+        cdef_class cls (to_cdef (get ("DefiningClass")));
+
+        if (! obj.is_partially_constructed_for (cls))
+          error ("cannot reference properties of class '%s' for non-constructed object",
+                 cls.get_name ().c_str ());
+      }
+
+    octave_value get_fcn = get ("GetMethod");
+
+    // FIXME: should check whether we're already in get accessor method
+
+    if (get_fcn.isempty () || is_method_executing (get_fcn, obj))
+      retval = obj.get (get ("Name").string_value ());
+    else
+      {
+        octave_value_list args;
+
+        args(0) = to_ov (obj);
+
+        args = feval (get_fcn, args, 1);
+
+        retval = args(0);
+      }
+
+    return retval;
+  }
+
+  octave_value
+  cdef_property::cdef_property_rep::get_value (bool do_check_access,
+                                               const std::string& who) const
+  {
+    if (do_check_access && ! check_get_access ())
+      err_property_access (who, false);
+
+    return get ("DefaultValue");
+  }
+
+  bool
+  cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
+  {
+    // FIXME: implement
+    return false;
+  }
+
+  OCTAVE_NORETURN void
+  cdef_property::cdef_property_rep::err_property_access
+    (const std::string& from, bool is_set) const
+  {
+    octave_value acc = get (is_set ? "SetAccess" : "GetAccess");
+    std::string acc_s;
+
+    if (acc.is_string ())
+      acc_s = acc.string_value ();
+    else
+      acc_s = "class-restricted";
+
+    if (is_set)
+      error ("%s: property '%s' has %s access and cannot be set in this context",
+             from.c_str (), get_name ().c_str (), acc_s.c_str ());
+    else
+      error ("%s: property '%s' has %s access and cannot be obtained in this context",
+             from.c_str (), get_name ().c_str (), acc_s.c_str ());
+  }
+
+  void
+  cdef_property::cdef_property_rep::set_value (cdef_object& obj,
+                                               const octave_value& val,
+                                               bool do_check_access,
+                                               const std::string& who)
+  {
+    if (do_check_access && ! check_set_access ())
+      err_property_access (who, true);
+
+    if (! obj.is_constructed ())
+      {
+        cdef_class cls (to_cdef (get ("DefiningClass")));
+
+        if (! obj.is_partially_constructed_for (cls))
+          error ("cannot reference properties of class '%s' for non-constructed object",
+                 cls.get_name ().c_str ());
+      }
+
+    octave_value set_fcn = get ("SetMethod");
+
+    if (set_fcn.isempty () || is_method_executing (set_fcn, obj))
+      obj.put (get ("Name").string_value (), val);
+    else
+      {
+        octave_value_list args;
+
+        args(0) = to_ov (obj);
+        args(1) = val;
+
+        args = feval (set_fcn, args, 1);
+
+        if (args.length () > 0 && args(0).is_defined ())
+          {
+            if (args (0).is_classdef_object ())
+              {
+                cdef_object new_obj = to_cdef (args(0));
+
+                obj = new_obj;
+              }
+            else
+              ::warning ("set-method of property '%s' returned a non-classdef object",
+                         get_name ().c_str ());
+          }
+      }
+  }
+
+  bool
+  cdef_property::cdef_property_rep::check_get_access (void) const
+  {
+    cdef_class cls (to_cdef (get ("DefiningClass")));
+
+    return check_access (cls, get ("GetAccess"), "", get_name (), false);
+
+    return false;
+  }
+
+  bool
+  cdef_property::cdef_property_rep::check_set_access (void) const
+  {
+    cdef_class cls (to_cdef (get ("DefiningClass")));
+
+    return check_access (cls, get ("SetAccess"), "", get_name (), true);
+
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-property.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,181 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_property_h)
+#define octave_cdef_property_h 1
+
+#include "octave-config.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-refcount.h"
+
+#include "cdef-object.h"
+#include "error.h"
+#include "ov.h"
+
+namespace octave
+{
+  class
+  cdef_property : public cdef_meta_object
+  {
+    friend class cdef_class;
+
+  private:
+
+    class
+    cdef_property_rep : public cdef_meta_object_rep
+    {
+    public:
+
+      cdef_property_rep (void) : cdef_meta_object_rep () { }
+
+      cdef_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; }
+
+      std::string get_name (void) const { return get("Name").string_value (); }
+
+      void set_name (const std::string& nm) { put ("Name", nm); }
+
+      bool is_constant (void) const { return get("Constant").bool_value (); }
+
+      octave_value get_value (bool do_check_access = true,
+                              const std::string& who = "") const;
+
+      octave_value get_value (const cdef_object& obj,
+                              bool do_check_access = true,
+                              const std::string& who = "") const;
+
+      void set_value (cdef_object& obj, const octave_value& val,
+                      bool do_check_access = true,
+                      const std::string& who = "");
+
+      bool check_get_access (void) const;
+
+      bool check_set_access (void) const;
+
+    private:
+      cdef_property_rep (const cdef_property_rep& p)
+        : cdef_meta_object_rep (p)
+      { }
+
+      bool is_recursive_set (const cdef_object& obj) const;
+
+      cdef_property wrap (void)
+      {
+        m_count++;
+        return cdef_property (this);
+      }
+
+      OCTAVE_NORETURN
+      void err_property_access (const std::string& from,
+                                bool is_set = false) const;
+    };
+
+  public:
+
+    cdef_property (void) : cdef_meta_object () { }
+
+    cdef_property (const std::string& nm)
+      : cdef_meta_object (new cdef_property_rep ())
+    {
+      get_rep ()->set_name (nm);
+    }
+
+    cdef_property (const cdef_property& prop) : cdef_meta_object (prop) { }
+
+    cdef_property (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_property ())
+        error ("internal error: invalid assignment from %s to meta.property object",
+               class_name ().c_str ());
+    }
+
+    cdef_property& operator = (const cdef_property& prop)
+    {
+      cdef_object::operator = (prop);
+
+      return *this;
+    }
+
+    ~cdef_property (void) = default;
+
+    octave_value get_value (const cdef_object& obj, bool do_check_access = true,
+                            const std::string& who = "") const
+    {
+      return get_rep ()->get_value (obj, do_check_access, who);
+    }
+
+    octave_value get_value (bool do_check_access = true,
+                            const std::string& who = "") const
+    {
+      return get_rep ()->get_value (do_check_access, who);
+    }
+
+    void set_value (cdef_object& obj, const octave_value& val,
+                    bool do_check_access = true,
+                    const std::string& who = "")
+    {
+      get_rep ()->set_value (obj, val, do_check_access, who);
+    }
+
+    bool check_get_access (void) const
+    {
+      return get_rep ()->check_get_access ();
+    }
+
+    bool check_set_access (void) const
+    {
+      return get_rep ()->check_set_access ();
+    }
+
+    std::string get_name (void) const { return get_rep ()->get_name (); }
+
+    bool is_constant (void) const { return get_rep ()->is_constant (); }
+
+  private:
+
+    cdef_property_rep * get_rep (void)
+    {
+      return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ());
+    }
+
+    const cdef_property_rep * get_rep (void) const
+    {
+      return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ());
+    }
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-utils.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,399 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "cdef-class.h"
+#include "cdef-manager.h"
+#include "cdef-method.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
+#include "cdef-utils.h"
+#include "interpreter-private.h"
+#include "ov-classdef.h"
+#include "ov-usr-fcn.h"
+#include "pt-eval.h"
+
+namespace octave
+{
+  std::string
+  get_base_name (const std::string& nm)
+  {
+    std::string::size_type pos = nm.find_last_of ('.');
+
+    if (pos != std::string::npos)
+      return nm.substr (pos + 1);
+
+    return nm;
+  }
+
+  void
+  make_function_of_class (const std::string& class_name,
+                          const octave_value& fcn)
+  {
+    octave_function *of = fcn.function_value ();
+
+    of->stash_dispatch_class (class_name);
+
+    octave_user_function *uf = of->user_function_value (true);
+
+    if (uf)
+      {
+        if (get_base_name (class_name) == uf->name ())
+          uf->mark_as_classdef_constructor ();
+        else
+          uf->mark_as_classdef_method ();
+      }
+  }
+
+  void
+  make_function_of_class (const cdef_class& cls, const octave_value& fcn)
+  {
+    make_function_of_class (cls.get_name (), fcn);
+  }
+
+  cdef_class
+  lookup_class (const std::string& name, bool error_if_not_found,
+                bool load_if_not_found)
+  {
+    cdef_manager& cdm = __get_cdef_manager__ ("lookup_class");
+
+    return cdm.find_class (name, error_if_not_found, load_if_not_found);
+  }
+
+  cdef_class
+  lookup_class (const cdef_class& cls)
+  {
+    // FIXME: placeholder for the time being, the purpose
+    //        is to centralized any class update activity here.
+
+    return cls;
+  }
+
+  cdef_class
+  lookup_class (const octave_value& ov)
+  {
+    if (ov.is_string())
+      return lookup_class (ov.string_value ());
+    else
+      {
+        cdef_class cls (to_cdef (ov));
+
+        return lookup_class (cls);
+      }
+
+    return cdef_class ();
+  }
+
+  std::list<cdef_class>
+  lookup_classes (const Cell& cls_list)
+  {
+    std::list<cdef_class> retval;
+
+    for (int i = 0; i < cls_list.numel (); i++)
+      {
+        cdef_class c = lookup_class (cls_list(i));
+
+        retval.push_back (c);
+      }
+
+    return retval;
+  }
+
+  octave_value
+  to_ov (const cdef_object& obj)
+  {
+    if (obj.ok ())
+      return octave_value (new octave_classdef (obj));
+    else
+      return octave_value (Matrix ());
+  }
+
+  octave_value
+  to_ov (const octave_value& ov)
+  {
+    return ov;
+  }
+
+  cdef_object
+  to_cdef (const octave_value& val)
+  {
+    if (val.type_name () != "object")
+      error ("cannot convert '%s' into 'object'", val.type_name().c_str ());
+
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();
+  }
+
+  cdef_object&
+  to_cdef_ref (const octave_value& val)
+  {
+    if (val.type_name () != "object")
+      error ("cannot convert '%s' into 'object'", val.type_name().c_str ());
+
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
+  }
+
+  cdef_object
+  to_cdef (const cdef_object& obj)
+  {
+    return obj;
+  }
+
+  octave_value
+  to_ov (const std::list<cdef_class>& class_list)
+  {
+    Cell cls (class_list.size (), 1);
+    int i = 0;
+
+    for (const auto& cdef_cls : class_list)
+      cls(i++) = to_ov (cdef_cls);
+
+    return octave_value (cls);
+  }
+
+  bool
+  is_dummy_method (const octave_value& fcn)
+  {
+    bool retval = false;
+
+    if (fcn.is_defined ())
+      {
+        if (fcn.is_user_function ())
+          {
+            octave_user_function *uf = fcn.user_function_value (true);
+
+            if (! uf || ! uf->body ())
+              retval = true;
+          }
+      }
+    else
+      retval = true;
+
+    return retval;
+  }
+
+  bool
+  is_superclass (const cdef_class& clsa, const cdef_class& clsb,
+                 bool allow_equal, int max_depth)
+  {
+    bool retval = false;
+
+    if (allow_equal && clsa == clsb)
+      retval = true;
+    else if (max_depth != 0)
+      {
+        Cell c = clsb.get ("SuperClasses").cell_value ();
+
+        for (int i = 0; ! retval && i < c.numel (); i++)
+          {
+            cdef_class cls = lookup_class (c(i));
+
+            retval = is_superclass (clsa, cls, true,
+                                    max_depth < 0 ? max_depth : max_depth-1);
+          }
+      }
+
+    return retval;
+  }
+
+  bool
+  is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
+  {
+    return is_superclass (clsa, clsb, false);
+  }
+
+  bool
+  is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
+  {
+    return is_superclass (clsa, clsb, false, 1);
+  }
+
+  cdef_package
+  lookup_package (const std::string& name, bool error_if_not_found,
+                  bool load_if_not_found)
+  {
+    cdef_manager& cdm = __get_cdef_manager__ ("lookup_package");
+
+    return cdm.find_package (name, error_if_not_found, load_if_not_found);
+  }
+
+  cdef_class
+  get_class_context (std::string& name, bool& in_constructor)
+  {
+    name = "";
+    in_constructor = false;
+
+    cdef_class cls;
+
+    // If the dispatch class is set in the current stack frame it
+    // overrides whatever dispatch class there is for the currently
+    // executing function so that function handles returned from class
+    // methods will use the dispatch class of the class in which they
+    // are defined instead of the class in which they are executing.
+
+    tree_evaluator& tw = __get_evaluator__ ("get_class_context");
+
+    std::string dispatch_class = tw.get_dispatch_class ();
+
+    if (! dispatch_class.empty ())
+      return lookup_class (dispatch_class);
+
+    octave_function *fcn = tw.current_function ();
+
+    if (fcn && (fcn->is_class_method ()
+                || fcn->is_classdef_constructor ()
+                || fcn->is_anonymous_function_of_class ()
+                || (fcn->is_private_function ()
+                    && ! fcn->dispatch_class ().empty ())))
+      {
+        cls = lookup_class (fcn->dispatch_class ());
+
+        name = fcn->name ();
+        in_constructor = fcn->is_classdef_constructor ();
+      }
+
+    return cls;
+  }
+
+  cdef_class
+  get_class_context (void)
+  {
+    std::string dummy_string;
+    bool dummy_bool;
+
+    return get_class_context (dummy_string, dummy_bool);
+  }
+
+  bool
+  check_access (const cdef_class& cls, const octave_value& acc,
+                const std::string& meth_name, const std::string& prop_name,
+                bool is_prop_set)
+  {
+    if (acc.is_string ())
+      {
+        std::string acc_s = acc.string_value ();
+
+        if (acc_s == "public")
+          return true;
+
+        cdef_class ctx = get_class_context ();
+
+        // The access is private or protected, this requires a
+        // valid class context.
+
+        if (ctx.ok ())
+          {
+            if (acc_s == "private")
+              return (ctx == cls);
+            else if (acc_s == "protected")
+              {
+                if (is_superclass (cls, ctx))
+                  // Calling a protected method in a superclass.
+                  return true;
+                else if (is_strict_superclass (ctx, cls))
+                  {
+                    // Calling a protected method or property in a derived class.
+                    // This is only allowed if the context class knows about it
+                    // and has access to it.
+
+                    if (! meth_name.empty ())
+                      {
+                        cdef_method m = ctx.find_method (meth_name);
+
+                        if (m.ok ())
+                          return check_access (ctx, m.get ("Access"), meth_name);
+
+                        return false;
+                      }
+                    else if (! prop_name.empty ())
+                      {
+                        cdef_property p = ctx.find_property (prop_name);
+
+                        if (p.ok ())
+                          {
+                            octave_value p_access = p.get (is_prop_set ?
+                                                           "SetAccess" :
+                                                           "GetAccess");
+
+                            return check_access (ctx, p_access, meth_name,
+                                                 prop_name, is_prop_set);
+                          }
+
+                        return false;
+                      }
+                    else
+                      panic_impossible ();
+                  }
+
+                return false;
+              }
+            else
+              panic_impossible ();
+          }
+      }
+    else if (acc.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 ();
+
+        cdef_class ctx = get_class_context ();
+
+        // At this point, a class context is always required.
+
+        if (ctx.ok ())
+          {
+            if (ctx == cls)
+              return true;
+
+            for (int i = 0; i < acc.numel (); i++)
+              {
+                cdef_class acc_cls (to_cdef (acc_c(i)));
+
+                if (is_superclass (acc_cls, ctx))
+                  return true;
+              }
+          }
+      }
+    else
+      error ("invalid property/method access in class '%s'",
+             cls.get_name ().c_str ());
+
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-utils.h	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,109 @@
+/*
+
+Copyright (C) 2012-2019 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_cdef_utils_h)
+#define octave_cdef_utils_h 1
+
+#include "octave-config.h"
+
+#include <list>
+#include <string>
+
+class octave_value;
+class Cell;
+
+namespace octave
+{
+  class cdef_class;
+  class cdef_package;
+
+  extern std::string
+  get_base_name (const std::string& nm);
+
+  extern void
+  make_function_of_class (const std::string& class_name,
+                          const octave_value& fcn);
+
+  extern void
+  make_function_of_class (const cdef_class& cls, const octave_value& fcn);
+
+  extern cdef_class
+  lookup_class (const std::string& name, bool error_if_not_found = true,
+                bool load_if_not_found = true);
+
+  extern cdef_class
+  lookup_class (const cdef_class& cls);
+
+  extern cdef_class
+  lookup_class (const octave_value& ov);
+
+  extern std::list<cdef_class>
+  lookup_classes (const Cell& cls_list);
+
+  extern octave_value
+  to_ov (const cdef_object& obj);
+
+  extern octave_value
+  to_ov (const octave_value& ov);
+
+  extern cdef_object
+  to_cdef (const octave_value& val);
+
+  extern cdef_object&
+  to_cdef_ref (const octave_value& val);
+
+  extern cdef_object
+  to_cdef (const cdef_object& obj);
+
+  extern octave_value
+  to_ov (const std::list<cdef_class>& class_list);
+
+  extern bool
+  is_dummy_method (const octave_value& fcn);
+
+  extern bool
+  is_superclass (const cdef_class& clsa, const cdef_class& clsb,
+                 bool allow_equal = true, int max_depth = -1);
+  extern bool
+  is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb);
+
+  extern bool
+  is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb);
+
+  extern cdef_package
+  lookup_package (const std::string& name, bool error_if_not_found = true,
+                  bool load_if_not_found = true);
+
+  extern cdef_class
+  get_class_context (std::string& name, bool& in_constructor);
+
+  extern cdef_class
+  get_class_context (void);
+
+  extern bool
+  check_access (const cdef_class& cls, const octave_value& acc,
+                const std::string& meth_name = "",
+                const std::string& prop_name = "",
+                bool is_prop_set = false);
+}
+
+#endif
--- a/libinterp/octave-value/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -18,6 +18,13 @@
   %reldir%/ov-re-sparse.h
 
 OCTAVE_VALUE_INC = \
+  %reldir%/cdef-class.h \
+  %reldir%/cdef-manager.h \
+  %reldir%/cdef-method.h \
+  %reldir%/cdef-object.h \
+  %reldir%/cdef-package.h \
+  %reldir%/cdef-property.h \
+  %reldir%/cdef-utils.h \
   %reldir%/ov-base-diag.h \
   %reldir%/ov-base-mat.h \
   %reldir%/ov-base-scalar.h \
@@ -79,6 +86,13 @@
   %reldir%/ov-re-sparse.cc
 
 OCTAVE_VALUE_SRC = \
+  %reldir%/cdef-class.cc \
+  %reldir%/cdef-manager.cc \
+  %reldir%/cdef-method.cc \
+  %reldir%/cdef-object.cc \
+  %reldir%/cdef-package.cc \
+  %reldir%/cdef-property.cc \
+  %reldir%/cdef-utils.cc \
   %reldir%/ov-base.cc \
   %reldir%/ov-bool-mat.cc \
   %reldir%/ov-bool.cc \
--- a/libinterp/octave-value/ov-base-diag.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-diag.h	Fri Jul 12 12:14:43 2019 -0400
@@ -64,6 +64,11 @@
 
   octave_value full_value (void) const { return to_dense (); }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
@@ -104,6 +109,11 @@
   MatrixType matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::diag;
+
   octave_value diag (octave_idx_type k = 0) const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
--- a/libinterp/octave-value/ov-base-int.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-int.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -325,7 +325,7 @@
 
 template <typename T>
 bool
-octave_base_int_matrix<T>::save_binary (std::ostream& os, bool&)
+octave_base_int_matrix<T>::save_binary (std::ostream& os, bool)
 {
   dim_vector dv = this->dims ();
   if (dv.ndims () < 1)
@@ -691,7 +691,7 @@
 
 template <typename T>
 bool
-octave_base_int_scalar<T>::save_binary (std::ostream& os, bool&)
+octave_base_int_scalar<T>::save_binary (std::ostream& os, bool)
 {
   os.write (reinterpret_cast<char *> (&(this->scalar)), this->byte_size ());
   return true;
--- a/libinterp/octave-value/ov-base-int.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-int.h	Fri Jul 12 12:14:43 2019 -0400
@@ -91,7 +91,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool&);
+  bool save_binary (std::ostream& os, bool);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format);
@@ -156,7 +156,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool&);
+  bool save_binary (std::ostream& os, bool);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format);
--- a/libinterp/octave-value/ov-base-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -149,6 +149,7 @@
       switch (n_idx)
         {
         case 0:
+          warn_empty_index (type_name ());
           retval = matrix;
           break;
 
@@ -210,6 +211,13 @@
   return retval;
 }
 
+/*
+%% This behavior is required for Matlab compatibility.
+%!test
+%! a = [1, 2; 3, 4];
+%! assert (a(), a);
+*/
+
 template <typename MT>
 void
 octave_base_matrix<MT>::assign (const octave_value_list& idx, const MT& rhs)
--- a/libinterp/octave-value/ov-base-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -75,6 +75,11 @@
 
   void maybe_economize (void) { matrix.maybe_economize (); }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
--- a/libinterp/octave-value/ov-base-scalar.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-scalar.h	Fri Jul 12 12:14:43 2019 -0400
@@ -61,6 +61,11 @@
 
   octave_value full_value (void) const { return scalar; }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
--- a/libinterp/octave-value/ov-base-sparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base-sparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -84,6 +84,11 @@
 
   octave_value full_value (void) const { return matrix.matrix_value (); }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
@@ -122,6 +127,11 @@
   octave_value all (int dim = 0) const { return matrix.all (dim); }
   octave_value any (int dim = 0) const { return matrix.any (dim); }
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::diag;
+
   octave_value diag (octave_idx_type k = 0) const
   { return octave_value (matrix.diag (k)); }
 
@@ -150,9 +160,6 @@
 
   bool is_true (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'nzmax' instead")
-  octave_idx_type capacity (void) const { return nzmax (); }
-
   bool print_as_scalar (void) const;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false);
--- a/libinterp/octave-value/ov-base.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,6 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 
-#include "call-stack.h"
 #include "defun.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
@@ -191,7 +190,7 @@
 }
 
 octave_idx_type
-octave_base_value::numel (const octave_value_list& idx)
+octave_base_value::xnumel (const octave_value_list& idx)
 {
   return octave::dims_to_numel (dims (), idx);
 }
@@ -941,7 +940,7 @@
 }
 
 bool
-octave_base_value::save_binary (std::ostream&, bool&)
+octave_base_value::save_binary (std::ostream&, bool)
 {
   err_wrong_type_arg ("octave_base_value::save_binary()", type_name ());
 }
@@ -1464,9 +1463,10 @@
 bool
 called_from_builtin (void)
 {
-  octave::call_stack& cs = octave::__get_call_stack__ ("called_from_builtin");
+  octave::tree_evaluator& tw
+    = octave::__get_evaluator__ ("called_from_builtin");
 
-  octave_function *fcn = cs.caller ();
+  octave_function *fcn = tw.caller_function ();
 
   // FIXME: we probably need a better check here, or some other
   // mechanism to avoid overloaded functions when builtin is used.
--- a/libinterp/octave-value/ov-base.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-base.h	Fri Jul 12 12:14:43 2019 -0400
@@ -37,7 +37,6 @@
 #include "mx-base.h"
 #include "str-vec.h"
 
-#include "error.h"
 #include "oct-hdf5-types.h"
 #include "oct-stream.h"
 
@@ -278,7 +277,9 @@
 
   virtual Matrix size (void);
 
-  virtual octave_idx_type numel (const octave_value_list&);
+  virtual octave_idx_type xnumel (const octave_value_list&);
+
+  // FIXME: Do we really need all three of these versions of subsref?
 
   virtual octave_value
   subsref (const std::string& type,
@@ -332,10 +333,6 @@
 
   virtual octave_idx_type numel (void) const { return dims ().numel (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  virtual octave_idx_type capacity (void) const
-  { return numel (); }
-
   virtual size_t byte_size (void) const { return 0; }
 
   virtual octave_idx_type nnz (void) const;
@@ -676,7 +673,7 @@
 
   virtual bool load_ascii (std::istream& is);
 
-  virtual bool save_binary (std::ostream& os, bool& save_as_floats);
+  virtual bool save_binary (std::ostream& os, bool save_as_floats);
 
   virtual bool load_binary (std::istream& is, bool swap,
                             octave::mach_info::float_format fmt);
@@ -723,6 +720,8 @@
 
   virtual bool islocked (void) const { return false; }
 
+  virtual void call_object_destructor (void) { }
+
   virtual octave_value dump (void) const;
 
   // Standard mappers.  Register new ones here.
--- a/libinterp/octave-value/ov-bool-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -343,7 +343,7 @@
 }
 
 bool
-octave_bool_matrix::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_bool_matrix::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
 
   dim_vector dv = dims ();
--- a/libinterp/octave-value/ov-bool-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -213,7 +213,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-bool-sparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -202,7 +202,7 @@
 }
 
 bool
-octave_sparse_bool_matrix::save_binary (std::ostream& os, bool&)
+octave_sparse_bool_matrix::save_binary (std::ostream& os, bool)
 {
   dim_vector dv = this->dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-bool-sparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool-sparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -132,7 +132,7 @@
 
   octave_value as_double (void) const;
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-bool.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -203,7 +203,7 @@
 }
 
 bool
-octave_bool::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_bool::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = (scalar ? 1 : 0);
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-bool.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-bool.h	Fri Jul 12 12:14:43 2019 -0400
@@ -226,7 +226,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-builtin.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-builtin.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "call-stack.h"
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
@@ -51,11 +50,9 @@
 
   octave::unwind_protect frame;
 
-  octave::call_stack& cs = octave::__get_call_stack__ ("octave_builtin::call");
+  tw.push_stack_frame (this);
 
-  cs.push (this);
-
-  frame.add_method (cs, &octave::call_stack::pop);
+  frame.add_method (tw, &octave::tree_evaluator::pop_stack_frame);
 
   octave::profiler& profiler = tw.get_profiler ();
 
--- a/libinterp/octave-value/ov-builtin.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-builtin.h	Fri Jul 12 12:14:43 2019 -0400
@@ -93,6 +93,11 @@
 
   bool is_builtin_function (void) const { return true; }
 
+  // We don't need to override both forms of the call method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_function::call;
+
   octave_value_list
   call (octave::tree_evaluator& tw, int nargout = 0,
         const octave_value_list& args = octave_value_list ());
--- a/libinterp/octave-value/ov-cell.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cell.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -157,6 +157,9 @@
 
     case '{':
       {
+        if (idx.front ().empty ())
+          error ("invalid empty index expression");
+
         octave_value tmp = do_index_op (idx.front ());
 
         Cell tcell = tmp.cell_value ();
@@ -887,7 +890,7 @@
 }
 
 bool
-octave_cell::save_binary (std::ostream& os, bool& save_as_floats)
+octave_cell::save_binary (std::ostream& os, bool save_as_floats)
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-cell.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cell.h	Fri Jul 12 12:14:43 2019 -0400
@@ -90,6 +90,13 @@
                          const std::list<octave_value_list>& idx,
                          const octave_value& rhs);
 
+  // FIXME: should we import the functions from the base class and
+  // overload them here, or should we use a different name so we don't
+  // have to do this?  Without the using declaration or a name change,
+  // the base class functions will be hidden.  That may be OK, but it
+  // can also cause some confusion.
+  using octave_base_value::assign;
+
   void assign (const octave_value_list& idx, const Cell& rhs);
 
   void assign (const octave_value_list& idx, const octave_value& rhs);
@@ -152,7 +159,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-ch-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-ch-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -325,7 +325,7 @@
         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",                  \
+            warning_with_id ("Octave:multi_byte_char_length",                  \
                              "UMAP: Possible multi-byte error.");              \
             return octave_value (matrix.map<char, int (&) (int)> (STD_FCN));   \
           }                                                                    \
--- a/libinterp/octave-value/ov-class.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-class.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -34,7 +34,6 @@
 #include "lo-mappers.h"
 
 #include "Cell.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "error.h"
 #include "file-ops.h"
@@ -229,10 +228,10 @@
 
   if (nparents () > 0)
     {
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_class::get_current_method_class");
+      octave::tree_evaluator& tw
+        = octave::__get_evaluator__ ("octave_class::get_current_method_class");
 
-      octave_function *fcn = cs.current ();
+      octave_function *fcn = tw.current_function ();
 
       // Here we are just looking to see if FCN is a method or constructor
       // for any class, not specifically this one.
@@ -332,10 +331,10 @@
 }
 
 octave_idx_type
-octave_class::numel (const octave_value_list& idx)
+octave_class::xnumel (const octave_value_list& idx)
 {
   if (in_class_method () || called_from_builtin ())
-    return octave_base_value::numel (idx);
+    return octave_base_value::xnumel (idx);
 
   octave_idx_type retval = -1;
   const std::string cn = class_name ();
@@ -362,7 +361,7 @@
       retval = lv(0).idx_type_value (true);
     }
   else
-    retval = octave_base_value::numel (idx);
+    retval = octave_base_value::xnumel (idx);
 
   return retval;
 }
@@ -466,7 +465,7 @@
               // Set up a proper nargout for the subsref call by calling numel.
               octave_value_list tmp;
               if (type[0] != '.') tmp = idx.front ();
-              true_nargout = numel (tmp);
+              true_nargout = xnumel (tmp);
             }
 
           retval = octave::feval (meth.function_value (), args, true_nargout);
@@ -1023,19 +1022,6 @@
   newline (os);
 }
 
-bool
-octave_class::print_name_tag (std::ostream& os, const std::string& name) const
-{
-  return octave_base_value::print_name_tag (os, name);
-}
-
-void
-octave_class::print_with_name (std::ostream& os, const std::string& name,
-                               bool print_padding)
-{
-  octave_base_value::print_with_name (os, name, print_padding);
-}
-
 // Loading a class properly requires an exemplar map entry for success.
 // If we don't have one, we attempt to create one by calling the constructor
 // with no arguments.
@@ -1270,7 +1256,7 @@
 }
 
 bool
-octave_class::save_binary (std::ostream& os, bool& save_as_floats)
+octave_class::save_binary (std::ostream& os, bool save_as_floats)
 {
   int32_t classname_len = class_name ().length ();
 
@@ -1655,10 +1641,10 @@
 bool
 octave_class::in_class_method (void)
 {
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("octave_class::in_class_method");
+  octave::tree_evaluator& tw
+    = octave::__get_evaluator__ ("octave_class::in_class_method");
 
-  octave_function *fcn = cs.current ();
+  octave_function *fcn = tw.current_function ();
 
   return (fcn
           && (fcn->is_class_method ()
@@ -1750,9 +1736,9 @@
       // Called as class constructor
       std::string id = args(1).xstring_value ("class: ID (class name) must be a string");
 
-      octave::call_stack& cs = interp.get_call_stack ();
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave_function *fcn = cs.caller ();
+      octave_function *fcn = tw.caller_function ();
 
       if (! fcn)
         error ("class: invalid call from outside class constructor or method");
@@ -1937,66 +1923,6 @@
   return ovl (args(0).isobject ());
 }
 
-DEFMETHOD (ismethod, interp, args, ,
-           doc: /* -*- texinfo -*-
-@deftypefn  {} {} ismethod (@var{obj}, @var{method})
-@deftypefnx {} {} ismethod (@var{clsname}, @var{method})
-Return true if the string @var{method} is a valid method of the object
-@var{obj} or of the class @var{clsname}.
-@seealso{isprop, isobject}
-@end deftypefn */)
-{
-  if (args.length () != 2)
-    print_usage ();
-
-  octave_value arg = args(0);
-
-  std::string class_name;
-
-  if (arg.isobject ())
-    class_name = arg.class_name ();
-  else if (arg.is_string ())
-    class_name = arg.string_value ();
-  else
-    error ("ismethod: first argument must be object or class name");
-
-  std::string method = args(1).string_value ();
-
-  octave::load_path& lp = interp.get_load_path ();
-
-  if (lp.find_method (class_name, method) != "")
-    return ovl (true);
-  else
-    return ovl (false);
-}
-
-DEFMETHOD (__methods__, interp, args, ,
-           doc: /* -*- texinfo -*-
-@deftypefn  {} {} __methods__ (@var{x})
-@deftypefnx {} {} __methods__ ("classname")
-Internal function.
-
-Implements @code{methods} for Octave class objects and classnames.
-@seealso{methods}
-@end deftypefn */)
-{
-  // Input validation has already been done in methods.m.
-  octave_value arg = args(0);
-
-  std::string class_name;
-
-  if (arg.isobject ())
-    class_name = arg.class_name ();
-  else if (arg.is_string ())
-    class_name = arg.string_value ();
-
-  octave::load_path& lp = interp.get_load_path ();
-
-  string_vector sv = lp.methods (class_name);
-
-  return ovl (Cell (sv));
-}
-
 static bool
 is_built_in_class (const std::string& cn)
 {
@@ -2035,9 +1961,9 @@
 @seealso{inferiorto}
 @end deftypefn */)
 {
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave_function *fcn = cs.caller ();
+  octave_function *fcn = tw.caller_function ();
 
   if (! fcn || ! fcn->is_class_constructor ())
     error ("superiorto: invalid call from outside class constructor");
@@ -2073,9 +1999,9 @@
 @seealso{superiorto}
 @end deftypefn */)
 {
-  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave_function *fcn = cs.caller ();
+  octave_function *fcn = tw.caller_function ();
 
   if (! fcn || ! fcn->is_class_constructor ())
     error ("inferiorto: invalid call from outside class constructor");
--- a/libinterp/octave-value/ov-class.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-class.h	Fri Jul 12 12:14:43 2019 -0400
@@ -85,7 +85,12 @@
 
   Matrix size (void);
 
-  octave_idx_type numel (const octave_value_list&);
+  octave_idx_type xnumel (const octave_value_list&);
+
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
 
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx)
@@ -174,11 +179,6 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  bool print_name_tag (std::ostream& os, const std::string& name) const;
-
-  void print_with_name (std::ostream& os, const std::string& name,
-                        bool print_padding = true);
-
   bool reconstruct_exemplar (void);
 
   static void clear_exemplar_map (void);
@@ -189,7 +189,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-classdef.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-classdef.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,825 +25,34 @@
 #endif
 
 #include <algorithm>
+#include <iomanip>
 
-#include "call-stack.h"
+#include "cdef-class.h"
+#include "cdef-method.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
+#include "cdef-utils.h"
 #include "defun.h"
+#include "errwarn.h"
 #include "interpreter-private.h"
-#include "interpreter.h"
 #include "load-path.h"
-#include "ov-builtin.h"
 #include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-typeinfo.h"
 #include "ov-usr-fcn.h"
-#include "pt-assign.h"
-#include "pt-classdef.h"
+#include "parse.h"
+#include "pr-output.h"
 #include "pt-eval.h"
-#include "pt-funcall.h"
-#include "pt-idx.h"
 #include "pt-misc.h"
-#include "pt-stmt.h"
-#include "pt-walk.h"
-#include "symtab.h"
-
-// Define to 1 to enable debugging statements.
-#define DEBUG_TRACE 0
-
-OCTAVE_NORETURN static
-void
-err_method_access (const std::string& from, const cdef_method& meth)
-{
-  octave_value acc = meth.get ("Access");
-  std::string acc_s;
-
-  if (acc.is_string ())
-    acc_s = acc.string_value ();
-  else
-    acc_s = "class-restricted";
-
-  error ("%s: method `%s' has %s access and cannot be run in this context",
-         from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
-}
-
-OCTAVE_NORETURN static
-void
-err_property_access (const std::string& from, const cdef_property& prop,
-                     bool is_set = false)
-{
-  octave_value acc = (prop.get (is_set ? "SetAccess" : "GetAccess"));
-  std::string acc_s;
-
-  if (acc.is_string ())
-    acc_s = acc.string_value ();
-  else
-    acc_s = "class-restricted";
-
-  if (is_set)
-    error ("%s: property `%s' has %s access and cannot be set in this context",
-           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
-  else
-    error ("%s: property `%s' has %s access and cannot be obtained in this context",
-           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
-}
-
-static std::string
-get_base_name (const std::string& nm)
-{
-  std::string::size_type pos = nm.find_last_of ('.');
-
-  if (pos != std::string::npos)
-    return nm.substr (pos + 1);
-
-  return nm;
-}
-
-static void
-make_function_of_class (const std::string& class_name,
-                        const octave_value& fcn)
-{
-  octave_function *of = fcn.function_value ();
-
-  of->stash_dispatch_class (class_name);
-
-  octave_user_function *uf = of->user_function_value (true);
-
-  if (uf)
-    {
-      if (get_base_name (class_name) == uf->name ())
-        {
-          uf->mark_as_class_constructor ();
-          uf->mark_as_classdef_constructor ();
-        }
-      else
-        uf->mark_as_class_method ();
-    }
-}
-
-static void
-make_function_of_class (const cdef_class& cls, const octave_value& fcn)
-{
-  make_function_of_class (cls.get_name (), fcn);
-}
-
-static octave_value
-make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
-{
-  octave_value fcn (new octave_builtin (ff, nm));
-
-  octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
-
-  return fcn_handle;
-}
-
-static octave_value
-make_fcn_handle (const octave_value& fcn, const std::string& nm)
-{
-  octave_value retval;
-
-  if (fcn.is_defined ())
-    retval = octave_value (new octave_fcn_handle (fcn, nm));
-
-  return retval;
-}
-
-static cdef_class
-lookup_class (const std::string& name, bool error_if_not_found = true,
-              bool load_if_not_found = true)
-{
-  cdef_manager& cdm = octave::__get_cdef_manager__ ("lookup_class");
-
-  return cdm.find_class (name, error_if_not_found, load_if_not_found);
-}
-
-static cdef_class
-lookup_class (const cdef_class& cls)
-{
-  // FIXME: placeholder for the time being, the purpose
-  //        is to centralized any class update activity here.
-
-  return cls;
-}
-
-static cdef_class
-lookup_class (const octave_value& ov)
-{
-  if (ov.is_string())
-    return lookup_class (ov.string_value ());
-  else
-    {
-      cdef_class cls (to_cdef (ov));
-
-      return lookup_class (cls);
-    }
-
-  return cdef_class ();
-}
-
-static std::list<cdef_class>
-lookup_classes (const Cell& cls_list)
-{
-  std::list<cdef_class> retval;
-
-  for (int i = 0; i < cls_list.numel (); i++)
-    {
-      cdef_class c = lookup_class (cls_list(i));
-
-      retval.push_back (c);
-    }
-
-  return retval;
-}
-
-static octave_value
-to_ov (const std::list<cdef_class>& class_list)
-{
-  Cell cls (class_list.size (), 1);
-  int i = 0;
-
-  for (const auto& cdef_cls : class_list)
-    cls(i++) = to_ov (cdef_cls);
-
-  return octave_value (cls);
-}
-
-static bool
-is_superclass (const cdef_class& clsa, const cdef_class& clsb,
-               bool allow_equal = true, int max_depth = -1)
-{
-  bool retval = false;
-
-  if (allow_equal && clsa == clsb)
-    retval = true;
-  else if (max_depth != 0)
-    {
-      Cell c = clsb.get ("SuperClasses").cell_value ();
-
-      for (int i = 0; ! retval && i < c.numel (); i++)
-        {
-          cdef_class cls = lookup_class (c(i));
-
-          retval = is_superclass (clsa, cls, true,
-                                  max_depth < 0 ? max_depth : max_depth-1);
-        }
-    }
-
-  return retval;
-}
-
-inline bool
-is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
-{ return is_superclass (clsa, clsb, false); }
-
-inline bool
-is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
-{ return is_superclass (clsa, clsb, false, 1); }
-
-static octave_value_list
-class_get_properties (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () == 1 && args(0).type_name () == "object")
-    {
-      cdef_class cls (to_cdef (args(0)));
-
-      retval(0) = cls.get_properties ();
-    }
-
-  return retval;
-}
-
-static cdef_class
-get_class_context (std::string& name, bool& in_constructor)
-{
-  cdef_class cls;
-
-  octave::call_stack& cs = octave::__get_call_stack__ ("get_class_context");
-
-  octave_function *fcn = cs.current ();
-
-  in_constructor = false;
-
-  if (fcn && (fcn->is_class_method ()
-              || fcn->is_classdef_constructor ()
-              || fcn->is_anonymous_function_of_class ()
-              || (fcn->is_private_function ()
-                  && ! fcn->dispatch_class ().empty ())))
-    {
-      cls = lookup_class (fcn->dispatch_class ());
-
-      name = fcn->name ();
-      in_constructor = fcn->is_classdef_constructor ();
-    }
-
-  return cls;
-}
-
-inline cdef_class
-get_class_context (void)
-{
-  std::string dummy_string;
-  bool dummy_bool;
-
-  return get_class_context (dummy_string, dummy_bool);
-}
-
-static bool
-in_class_method (const cdef_class& cls)
-{
-  cdef_class ctx = get_class_context ();
-
-  return (ctx.ok () && is_superclass (ctx, cls));
-}
-
-static bool
-check_access (const cdef_class& cls, const octave_value& acc,
-              const std::string& meth_name = "",
-              const std::string& prop_name = "",
-              bool is_prop_set = false)
-{
-  if (acc.is_string ())
-    {
-      std::string acc_s = acc.string_value ();
-
-      if (acc_s == "public")
-        return true;
-
-      cdef_class ctx = get_class_context ();
-
-      // The access is private or protected, this requires a
-      // valid class context.
-
-      if (ctx.ok ())
-        {
-          if (acc_s == "private")
-            return (ctx == cls);
-          else if (acc_s == "protected")
-            {
-              if (is_superclass (cls, ctx))
-                // Calling a protected method in a superclass.
-                return true;
-              else if (is_strict_superclass (ctx, cls))
-                {
-                  // Calling a protected method or property in a derived class.
-                  // This is only allowed if the context class knows about it
-                  // and has access to it.
-
-                  if (! meth_name.empty ())
-                    {
-                      cdef_method m = ctx.find_method (meth_name);
-
-                      if (m.ok ())
-                        return check_access (ctx, m.get ("Access"), meth_name);
-
-                      return false;
-                    }
-                  else if (! prop_name.empty ())
-                    {
-                      cdef_property p = ctx.find_property (prop_name);
-
-                      if (p.ok ())
-                        {
-                          octave_value p_access = p.get (is_prop_set ?
-                                                         "SetAccess" :
-                                                         "GetAccess");
-
-                          return check_access (ctx, p_access, meth_name,
-                                               prop_name, is_prop_set);
-                        }
-
-                      return false;
-                    }
-                  else
-                    panic_impossible ();
-                }
-
-              return false;
-            }
-          else
-            panic_impossible ();
-        }
-    }
-  else if (acc.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 ();
-
-      cdef_class ctx = get_class_context ();
-
-      // At this point, a class context is always required.
-
-      if (ctx.ok ())
-        {
-          if (ctx == cls)
-            return true;
-
-          for (int i = 0; i < acc.numel (); i++)
-            {
-              cdef_class acc_cls (to_cdef (acc_c(i)));
-
-              if (is_superclass (acc_cls, ctx))
-                return true;
-            }
-        }
-    }
-  else
-    error ("invalid property/method access in class `%s'",
-           cls.get_name ().c_str ());
-
-  return false;
-}
-
-static bool
-is_dummy_method (const octave_value& fcn)
-{
-  bool retval = false;
-
-  if (fcn.is_defined ())
-    {
-      if (fcn.is_user_function ())
-        {
-          octave_user_function *uf = fcn.user_function_value (true);
-
-          if (! uf || ! uf->body ())
-            retval = true;
-        }
-    }
-  else
-    retval = true;
-
-  return retval;
-}
 
 static bool
-is_method_executing (const octave_value& ov, const cdef_object& obj)
-{
-  octave::tree_evaluator& tw
-    = octave::__get_evaluator__ ("is_method_executing");
-
-  octave::call_stack& cs = octave::__get_call_stack__ ("is_method_executing");
-
-  octave_function *stack_fcn = cs.current ();
-
-  octave_function *method_fcn = ov.function_value (true);
-
-  // Does the top of the call stack match our target function?
-
-  if (stack_fcn && stack_fcn == method_fcn)
-    {
-      octave_user_function *uf = method_fcn->user_function_value (true);
-
-      // We can only check the context object for user-function (not builtin),
-      // where we have access to the parameters (arguments and return values).
-      // That's ok as there's no need to call this function for builtin
-      // methods.
-
-      if (uf)
-        {
-          // At this point, the method is executing, but we still need to
-          // check the context object for which the method is executing.  For
-          // methods, it's the first argument of the function; for ctors, it
-          // is the first return value.
-
-          octave::tree_parameter_list *pl = uf->is_classdef_constructor ()
-            ? uf->return_list () : uf->parameter_list ();
-
-          if (pl && pl->size () > 0)
-            {
-              octave::tree_decl_elt *elt = pl->front ();
-
-              octave_value arg0 = tw.evaluate (elt);
-
-              if (arg0.is_defined () && arg0.type_name () == "object")
-                {
-                  cdef_object arg0_obj = to_cdef (arg0);
-
-                  return obj.is (arg0_obj);
-                }
-            }
-        }
-    }
-
-  return false;
-}
-
-static octave_value_list
-class_get_methods (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () == 1 && args(0).type_name () == "object")
-    {
-      cdef_class cls (to_cdef (args(0)));
-
-      retval(0) = cls.get_methods ();
-    }
-
-  return retval;
-}
-
-static octave_value_list
-class_get_superclasses (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () == 1 && args(0).type_name () == "object"
-      && args(0).class_name () == "meta.class")
-    {
-      cdef_class cls (to_cdef (args(0)));
-
-      Cell classes = cls.get ("SuperClasses").cell_value ();
-
-      retval(0) = to_ov (lookup_classes (classes));
-    }
-
-  return retval;
-}
-
-static octave_value_list
-class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
+in_class_method (const octave::cdef_class& cls)
 {
-  octave_value_list retval;
-
-  if (args.length () == 1 && args(0).type_name () == "object"
-      && args(0).class_name () == "meta.class")
-    {
-      cdef_class cls (to_cdef (args(0)));
-
-      Cell classes = cls.get ("InferiorClasses").cell_value ();
-
-      retval(0) = to_ov (lookup_classes (classes));
-    }
-
-  return retval;
-}
-
-static octave_value_list
-class_fromName (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () != 1)
-    error ("fromName: invalid number of parameters");
-
-  std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string");
-
-  retval(0) = to_ov (lookup_class (name, false));
-
-  return retval;
-}
-
-static octave_value_list
-class_fevalStatic (const octave_value_list& args, int nargout)
-{
-  if (args.length () <= 1 || args(0).type_name () != "object")
-    error ("fevalStatic: first argument must be a meta.class object");
-
-  cdef_class cls (to_cdef (args(0)));
-
-  std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string");
-
-  cdef_method meth = cls.find_method (meth_name);
-
-  if (! meth.ok ())
-    error ("fevalStatic: method not found: %s", meth_name.c_str ());
-
-  if (! meth.is_static ())
-    error ("fevalStatic: method `%s' is not static", meth_name.c_str ());
-
-  return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic");
-}
-
-static octave_value_list
-class_getConstant (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () != 2 || args(0).type_name () != "object"
-      || args(0).class_name () != "meta.class")
-    error ("getConstant: first argument must be a meta.class object");
-
-  cdef_class cls = to_cdef (args(0));
-
-  std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string");
-
-  cdef_property prop = cls.find_property (prop_name);
-
-  if (! prop.ok ())
-    error ("getConstant: property not found: %s",
-           prop_name.c_str ());
-
-  if (! prop.is_constant ())
-    error ("getConstant: property `%s' is not constant",
-           prop_name.c_str ());
-
-  retval(0) = prop.get_value (true, "getConstant");
-
-  return retval;
-}
-
-#define META_CLASS_CMP(OP, CLSA, CLSB, FUN)                             \
-  static octave_value_list                                              \
-  class_ ## OP (const octave_value_list& args, int /* nargout */)       \
-  {                                                                     \
-    octave_value_list retval;                                           \
-                                                                        \
-    if (args.length () != 2                                             \
-        || args(0).type_name () != "object"                             \
-        || args(1).type_name () != "object"                             \
-        || args(0).class_name () != "meta.class"                        \
-        || args(1).class_name () != "meta.class")                       \
-      error (#OP ": invalid arguments");                                \
-                                                                        \
-    cdef_class clsa = to_cdef (args(0));                                \
-                                                                        \
-    cdef_class clsb = to_cdef (args(1));                                \
-                                                                        \
-    retval(0) = FUN (CLSA, CLSB);                                       \
-                                                                        \
-    return retval;                                                      \
-  }
-
-META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
-META_CLASS_CMP (le, clsb, clsa, is_superclass)
-META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
-META_CLASS_CMP (ge, clsa, clsb, is_superclass)
-META_CLASS_CMP (eq, clsa, clsb, operator==)
-META_CLASS_CMP (ne, clsa, clsb, operator!=)
-
-octave_value_list
-property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () == 1 && args(0).type_name () == "object")
-    {
-      cdef_property prop (to_cdef (args(0)));
-
-      retval(0) = prop.get ("DefaultValue");
+  octave::cdef_class ctx = octave::get_class_context ();
 
-      if (! retval(0).is_defined ())
-        error_with_id ("Octave:class:NotDefaultDefined",
-                       "no default value for property `%s'",
-                       prop.get_name ().c_str ());
-    }
-
-  return retval;
-}
-
-static octave_value_list
-handle_delete (const octave_value_list& /* args */, int /* nargout */)
-{
-  octave_value_list retval;
-
-  // FIXME: implement this.  Wait, what is this supposed to do?
-
-  return retval;
-}
-
-cdef_class
-cdef_manager::make_class (const std::string& name,
-                          const std::list<cdef_class>& super_list)
-{
-  cdef_class cls (name, super_list);
-
-  cls.set_class (meta_class ());
-
-  cls.put ("Abstract", false);
-  cls.put ("ConstructOnLoad", false);
-  cls.put ("ContainingPackage", Matrix ());
-  cls.put ("Description", "");
-  cls.put ("DetailedDescription", "");
-  cls.put ("Events", Cell ());
-  cls.put ("Hidden", false);
-  cls.put ("InferiorClasses", Cell ());
-  cls.put ("Methods", Cell ());
-  cls.put ("Properties", Cell ());
-  cls.put ("Sealed", false);
-
-  if (name == "handle")
-    {
-      cls.put ("HandleCompatible", true);
-      cls.mark_as_handle_class ();
-    }
-  else if (super_list.empty ())
-    {
-      cls.put ("HandleCompatible", false);
-    }
-  else
-    {
-      bool all_handle_compatible = true;
-      bool has_handle_class = false;
-
-      for (const auto& cl : super_list)
-        {
-          all_handle_compatible = all_handle_compatible
-                                  && cl.get ("HandleCompatible").bool_value ();
-          has_handle_class = has_handle_class || cl.is_handle_class ();
-        }
-
-      if (has_handle_class && ! all_handle_compatible)
-        error ("%s: cannot mix handle and non-HandleCompatible classes",
-               name.c_str ());
-
-      cls.put ("HandleCompatible", all_handle_compatible);
-      if (has_handle_class)
-        cls.mark_as_handle_class ();
-    }
-
-  if (! name.empty ())
-    register_class (cls);
-
-  return cls;
-}
-
-cdef_class
-cdef_manager::make_class (const std::string& name,
-                          const cdef_class& super)
-{
-  return make_class (name, std::list<cdef_class> (1, super));
-}
-
-cdef_class
-cdef_manager::make_meta_class (const std::string& name,
-                               const cdef_class& super)
-{
-  cdef_class cls = make_class (name, super);
-
-  cls.put ("Sealed", true);
-  cls.mark_as_meta_class ();
-
-  return cls;
+  return (ctx.ok () && octave::is_superclass (ctx, cls));
 }
 
-cdef_property
-cdef_manager::make_property (const cdef_class& cls, const std::string& name,
-                             const octave_value& get_method,
-                             const std::string& get_access,
-                             const octave_value& set_method,
-                             const std::string& set_access)
-{
-  cdef_property prop (name);
-
-  prop.set_class (meta_property ());
-
-  prop.put ("Description", "");
-  prop.put ("DetailedDescription", "");
-  prop.put ("Abstract", false);
-  prop.put ("Constant", false);
-  prop.put ("GetAccess", get_access);
-  prop.put ("SetAccess", set_access);
-  prop.put ("Dependent", false);
-  prop.put ("Transient", false);
-  prop.put ("Hidden", false);
-  prop.put ("GetObservable", false);
-  prop.put ("SetObservable", false);
-  prop.put ("GetMethod", get_method);
-  prop.put ("SetMethod", set_method);
-  prop.put ("DefiningClass", to_ov (cls));
-  prop.put ("DefaultValue", octave_value ());
-  prop.put ("HasDefault", false);
-
-  std::string class_name = cls.get_name ();
-
-  if (! get_method.isempty ())
-    make_function_of_class (class_name, get_method);
-  if (! set_method.isempty ())
-    make_function_of_class (class_name, set_method);
-
-  return prop;
-}
-
-cdef_property
-cdef_manager::make_attribute (const cdef_class& cls, const std::string& name)
-{
-  return make_property (cls, name, Matrix (), "public", Matrix (), "private");
-}
-
-cdef_method
-cdef_manager::make_method (const cdef_class& cls, const std::string& name,
-                           const octave_value& fcn,
-                           const std::string& m_access, bool is_static)
-{
-  cdef_method meth (name);
-
-  meth.set_class (meta_method ());
-
-  meth.put ("Abstract", false);
-  meth.put ("Access", m_access);
-  meth.put ("DefiningClass", to_ov (cls));
-  meth.put ("Description", "");
-  meth.put ("DetailedDescription", "");
-  meth.put ("Hidden", false);
-  meth.put ("Sealed", true);
-  meth.put ("Static", is_static);
-
-  if (fcn.is_defined ())
-    make_function_of_class (cls, fcn);
-
-  meth.set_function (fcn);
-
-  if (is_dummy_method (fcn))
-    meth.mark_as_external (cls.get_name ());
-
-  return meth;
-}
-
-cdef_method
-cdef_manager::make_method (const cdef_class& cls, const std::string& name,
-                           octave_builtin::fcn ff,
-                           const std::string& m_access, bool is_static)
-{
-  octave_value fcn (new octave_builtin (ff, name));
-
-  return make_method (cls, name, fcn, m_access, is_static);
-}
-
-cdef_method
-cdef_manager::make_method (const cdef_class& cls, const std::string& name,
-                           octave_builtin::meth mm,
-                           const std::string& m_access, bool is_static)
-{
-  octave_value fcn (new octave_builtin (mm, name));
-
-  return make_method (cls, name, fcn, m_access, is_static);
-}
-
-cdef_package
-cdef_manager::make_package (const std::string& nm, const std::string& parent)
-{
-  cdef_package pack (nm);
-
-  pack.set_class (meta_package ());
-
-  if (parent.empty ())
-    pack.put ("ContainingPackage", Matrix ());
-  else
-    pack.put ("ContainingPackage", to_ov (find_package (parent)));
-
-  if (! nm.empty ())
-    register_package (pack);
-
-  return pack;
-}
-
-//----------------------------------------------------------------------------
-
 int octave_classdef::t_id (-1);
 
 const std::string octave_classdef::t_name ("object");
@@ -863,11 +72,11 @@
   size_t skip = 0;
   octave_value_list retval;
 
-  cdef_class cls = object.get_class ();
+  octave::cdef_class cls = object.get_class ();
 
   if (! in_class_method (cls) && ! called_from_builtin ())
     {
-      cdef_method meth = cls.find_method ("subsref");
+      octave::cdef_method meth = cls.find_method ("subsref");
 
       if (meth.ok ())
         {
@@ -886,7 +95,7 @@
 
   // At this point, the default subsref mechanism must be used.
 
-  retval = object.subsref (type, idx, nargout, skip, cdef_class ());
+  retval = object.subsref (type, idx, nargout, skip, octave::cdef_class ());
 
   if (type.length () > skip && idx.size () > skip)
     retval = retval(0).next_subsref (nargout, type, idx, skip);
@@ -906,11 +115,11 @@
   // assignment with multi-level indexing.  AFAIK this is only used for internal
   // purpose (not sure we should even implement this).
 
-  cdef_class cls = object.get_class ();
+  octave::cdef_class cls = object.get_class ();
 
   if (! in_class_method (cls))
     {
-      cdef_method meth = cls.find_method ("subsref");
+      octave::cdef_method meth = cls.find_method ("subsref");
 
       if (meth.ok ())
         {
@@ -927,7 +136,7 @@
         }
     }
 
-  retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add);
+  retval = object.subsref (type, idx, 1, skip, octave::cdef_class (), auto_add);
 
   if (type.length () > skip && idx.size () > skip)
     retval = retval(0).next_subsref (1, type, idx, skip);
@@ -942,11 +151,11 @@
 {
   octave_value retval;
 
-  cdef_class cls = object.get_class ();
+  octave::cdef_class cls = object.get_class ();
 
   if (! in_class_method (cls) && ! called_from_builtin ())
     {
-      cdef_method meth = cls.find_method ("subsasgn");
+      octave::cdef_method meth = cls.find_method ("subsasgn");
 
       if (meth.ok ())
         {
@@ -963,7 +172,7 @@
           retlist = meth.execute (args, 1, true, "subsasgn");
 
           if (retlist.empty ())
-            error ("overloaded method `subsasgn' did not return any value");
+            error ("overloaded method 'subsasgn' did not return any value");
 
           retval = retlist(0);
         }
@@ -993,15 +202,15 @@
 }
 
 octave_idx_type
-octave_classdef::numel (const octave_value_list& idx)
+octave_classdef::xnumel (const octave_value_list& idx)
 {
   octave_idx_type retval = -1;
 
-  cdef_class cls = object.get_class ();
+  octave::cdef_class cls = object.get_class ();
 
   if (! in_class_method (cls) && ! called_from_builtin ())
     {
-      cdef_method meth = cls.find_method ("numel");
+      octave::cdef_method meth = cls.find_method ("numel");
 
       if (meth.ok ())
         {
@@ -1023,7 +232,7 @@
         }
     }
 
-  retval = octave_base_value::numel (idx);
+  retval = octave_base_value::xnumel (idx);
 
   return retval;
 }
@@ -1037,32 +246,100 @@
 void
 octave_classdef::print_raw (std::ostream& os, bool) const
 {
-  indent (os);
-  os << "<object ";
-  if (object.is_array ())
-    os << "array ";
-  os << class_name () << '>';
-  newline (os);
-}
+  octave::cdef_class cls = object.get_class ();
+
+  if (cls.ok ())
+    {
+      bool is_array = object.is_array ();
+
+      increment_indent_level ();
+
+      indent (os);
+      os << class_name () << " object";
+      if (is_array)
+        os << " array";
+      os << " with properties:";
+      newline (os);
+      if (! Vcompact_format)
+        newline (os);
+
+      increment_indent_level ();
+
+      std::map<std::string, octave::cdef_property> property_map
+        = cls.get_property_map ();
+
+      size_t max_len = 0;
+      for (const auto& pname_prop : property_map)
+        {
+          // FIXME: this loop duplicates a significant portion of the
+          // loop below and the loop in Fproperties.
+
+          const octave::cdef_property& prop = pname_prop.second;
+
+          const std::string nm = prop.get_name ();
+
+          octave_value acc = prop.get ("GetAccess");
+
+          if (! acc.is_string () || acc.string_value () != "public")
+            continue;
+
+          octave_value hid = prop.get ("Hidden");
+
+          if (hid.bool_value ())
+            continue;
+
+          size_t sz = nm.size ();
 
-bool
-octave_classdef::print_name_tag (std::ostream& os,
-                                 const std::string& name) const
-{
-  return octave_base_value::print_name_tag (os, name);
-}
+          if (sz > max_len)
+            max_len = sz;
+        }
+
+      for (auto& pname_prop : property_map)
+        {
+          const octave::cdef_property& prop = pname_prop.second;
+
+          const std::string nm = prop.get_name ();
+
+          octave_value acc = prop.get ("GetAccess");
+
+          if (! acc.is_string () || acc.string_value () != "public")
+            continue;
+
+          octave_value hid = prop.get ("Hidden");
+
+          if (hid.bool_value ())
+            continue;
+
+          indent (os);
 
-void
-octave_classdef::print_with_name (std::ostream& os, const std::string& name,
-                                  bool print_padding)
-{
-  octave_base_value::print_with_name (os, name, print_padding);
+          if (is_array)
+            os << "  " << nm;
+          else
+            {
+              octave_value val = prop.get_value (object, false);
+              dim_vector dims = val.dims ();
+
+              os << std::setw (max_len+2) << nm << ": ";
+              if (val.is_string ())
+                os << val.string_value ();
+              else if (val.islogical ())
+                os << val.bool_value ();
+              else
+                os << "[" << dims.str () << " " << val.class_name () << "]";
+            }
+
+          newline (os);
+        }
+
+      decrement_indent_level ();
+      decrement_indent_level ();
+    }
 }
 
 bool
 octave_classdef::is_instance_of (const std::string& cls_name) const
 {
-  cdef_class cls = lookup_class (cls_name, false, false);
+  octave::cdef_class cls = octave::lookup_class (cls_name, false, false);
 
   if (cls.ok ())
     return is_superclass (cls, object.get_class ());
@@ -1070,2860 +347,166 @@
   return false;
 }
 
-//----------------------------------------------------------------------------
-
-class octave_classdef_meta : public octave_function
+octave_value
+octave_classdef::superclass_ref (const std::string& meth,
+                                 const std::string& cls)
 {
-public:
-  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 (); }
-
-  bool is_classdef_meta (void) const { return true; }
-
-  bool is_package (void) const { return object.is_package(); }
-
-  octave_function * function_value (bool = false) { return this; }
-
-  octave_value_list
-  subsref (const std::string& type,
-           const std::list<octave_value_list>& idx,
-           int nargout)
-  {
-    return object.meta_subsref (type, idx, nargout);
-  }
-
-  octave_value_list call (octave::tree_evaluator&, int nargout,
-                          const octave_value_list& args)
-  {
-    // Emulate ()-type meta subsref
-
-    std::list<octave_value_list> idx (1, args);
-    std::string type ("(");
-
-    return subsref (type, idx, nargout);
-  }
-
-  bool accepts_postfix_index (char type) const
-  { return object.meta_accepts_postfix_index (type); }
-
-  bool
-  is_classdef_constructor (const std::string& cname = "") const
-  {
-    bool retval = false;
-
-    if (object.is_class ())
-      {
-        if (cname.empty ())
-          retval = true;
-        else
-          {
-            cdef_class cls (object);
-
-            if (cls.get_name () == cname)
-              retval = true;
-          }
-      }
-
-    return retval;
-  }
-
-private:
-  cdef_meta_object object;
-};
-
-//----------------------------------------------------------------------------
-
-class octave_classdef_superclass_ref : public octave_function
-{
-public:
-  octave_classdef_superclass_ref (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; }
-
-  octave_function * function_value (bool = false) { return this; }
-
-  octave_value_list
-  call (octave::tree_evaluator& tw, int nargout, const octave_value_list& idx)
-  {
-    octave_value_list retval;
-
-    std::string meth_name;
-    bool in_constructor;
-    cdef_class ctx;
-
-    ctx = get_class_context (meth_name, in_constructor);
-
-    if (! ctx.ok ())
-      error ("superclass calls can only occur in methods or constructors");
-
-    std::string mname = args(0).string_value ();
-    std::string cname = args(1).string_value ();
-
-    cdef_class cls = lookup_class (cname);
-
-    if (in_constructor)
-      {
-        if (! is_direct_superclass (cls, ctx))
-          error ("`%s' is not a direct superclass of `%s'",
-                 cname.c_str (), ctx.get_name ().c_str ());
-
-        if (! is_constructed_object (tw, mname))
-          error ("cannot call superclass constructor with variable `%s'",
-                 mname.c_str ());
-
-        octave::symbol_scope scope = tw.get_current_scope ();
-
-        octave_value sym = scope.varval (mname);
-
-        cls.run_constructor (to_cdef_ref (sym), idx);
+  return octave_value (new octave_classdef_superclass_ref (meth, cls));
+}
 
-        retval(0) = sym;
-      }
-    else
-      {
-        if (mname != meth_name)
-          error ("method name mismatch (`%s' != `%s')",
-                 mname.c_str (), meth_name.c_str ());
-
-        if (! is_strict_superclass (cls, ctx))
-          error ("`%s' is not a superclass of `%s'",
-                 cname.c_str (), ctx.get_name ().c_str ());
-
-        // I see 2 possible implementations here:
-        // 1) use cdef_object::subsref with a different class
-        //    context; this avoids duplicating code, but
-        //    assumes the object is always the first argument
-        // 2) lookup the method manually and call
-        //    cdef_method::execute; this duplicates part of
-        //    logic in cdef_object::subsref, but avoid the
-        //    assumption of 1)
-        // Not being sure about the assumption of 1), I
-        // go with option 2) for the time being.
-
-        cdef_method meth = cls.find_method (meth_name, false);
-
-        if (! meth.ok ())
-          error ("no method `%s' found in superclass `%s'",
-                 meth_name.c_str (), cname.c_str ());
-
-        retval = meth.execute (idx, nargout, true,
-                               meth_name);
-      }
-
-    return retval;
-  }
-
-private:
-  bool is_constructed_object (octave::tree_evaluator& tw,
-                              const std::string& nm)
-  {
-    octave::call_stack& cs = tw.get_call_stack ();
-
-    octave_function *of = cs.current ();
-
-    if (of->is_classdef_constructor ())
-      {
-        octave_user_function *uf = of->user_function_value (true);
-
-        if (uf)
-          {
-            octave::tree_parameter_list *ret_list = uf->return_list ();
-
-            if (ret_list && ret_list->length () == 1)
-              return (ret_list->front ()->name () == nm);
-          }
-      }
-
-    return false;
-  }
-
-private:
-  octave_value_list args;
-};
-
-//----------------------------------------------------------------------------
-
-void
-cdef_object_rep::release (const cdef_object& obj)
+octave_value
+octave_classdef::metaclass_query (const std::string& cls)
 {
-  // We need to be careful to keep a reference to the object if we are
-  // calling the delete method.  The object is passed to the delete
-  // method as an argument and if the count is already zero when we
-  // do that, then we will increment the count while creating the
-  // argument list for the delete method and then it will be decremented
-  // back to zero and we'll find ourselves in an infinite loop.
-
-  if (refcount - 1 > static_count ())
-    {
-      --refcount;
-      return;
-    }
-
-  if (is_handle_object () && ! is_meta_object ())
-    {
-      octave::unwind_protect frame;
-
-      // Clear interrupts.
-      frame.protect_var (octave_interrupt_state);
-      octave_interrupt_state = 0;
-
-      // Disallow quit().
-      frame.protect_var (quit_allowed);
-      quit_allowed = false;
-
-      interpreter_try (frame);
-
-      try
-        {
-          // Call classdef "delete()" method on object
-          get_class ().delete_object (obj);
-        }
-      catch (const octave::interrupt_exception&)
-        {
-          octave::interpreter::recover_from_exception ();
-
-          warning ("interrupt occurred in handle class delete method");
-        }
-      catch (const octave::execution_exception&)
-        {
-          std::string msg = last_error_message ();
-          warning ("error caught while executing handle class delete method:\n%s\n",
-                   msg.c_str ());
-
-        }
-      catch (const octave::exit_exception&)
-        {
-          // This shouldn't happen since we disabled quit above.
-          warning ("exit disabled while executing handle class delete method");
-        }
-      catch (...) // Yes, the black hole.  We're in a d-tor.
-        {
-          // This shouldn't happen, in theory.
-          warning ("internal error: unhandled exception in handle class delete method");
-        }
-    }
-
-  // Now it is safe to set the count to zero.
-  refcount--;
-
-  destroy ();
+  return octave::to_ov (octave::lookup_class (cls));
 }
 
-octave_map
-cdef_object::map_value (void) const
+bool octave_classdef_meta::is_classdef_constructor (const std::string& cname) const
 {
-  octave_map retval;
-
-  warning_with_id ("Octave:classdef-to-struct",
-                   "struct: converting a classdef object into a struct "
-                   "overrides the access restrictions defined for properties. "
-                   "All properties are returned, including private and "
-                   "protected ones.");
-
-  cdef_class cls = get_class ();
-
-  if (cls.ok ())
-    {
-      std::map<std::string, cdef_property> props;
-
-      props = cls.get_property_map (cdef_class::property_all);
+  bool retval = false;
 
-      // FIXME: Why not const here?
-      for (auto& prop_val : props)
+  if (object.is_class ())
+    {
+      if (cname.empty ())
+        retval = true;
+      else
         {
-          if (is_array ())
-            {
-              Array<cdef_object> a_obj = array_value ();
-
-              Cell cvalue (a_obj.dims ());
+          octave::cdef_class cls (object);
 
-              for (octave_idx_type i = 0; i < a_obj.numel (); i++)
-                cvalue (i) = prop_val.second.get_value (a_obj(i), false);
-
-              retval.setfield (prop_val.first, cvalue);
-            }
-          else
-            {
-              Cell cvalue (dim_vector (1, 1),
-                           prop_val.second.get_value (*this, false));
-
-              retval.setfield (prop_val.first, cvalue);
-            }
+          if (cls.get_name () == cname)
+            retval = true;
         }
     }
 
   return retval;
 }
 
-string_vector
-cdef_object_rep::map_keys (void) const
-{
-  cdef_class cls = get_class ();
-
-  if (cls.ok ())
-    return cls.get_names ();
-
-  return string_vector ();
-}
-
 octave_value_list
-cdef_object_scalar::subsref (const std::string& type,
-                             const std::list<octave_value_list>& idx,
-                             int nargout, size_t& skip,
-                             const cdef_class& context, bool auto_add)
-{
-  skip = 0;
-
-  cdef_class cls = (context.ok () ? context : get_class ());
-
-  octave_value_list retval;
-
-  if (! cls.ok ())
-    return retval;
-
-  switch (type[0])
-    {
-    case '.':
-      {
-        std::string name = (idx.front ())(0).string_value ();
-
-        cdef_method meth = cls.find_method (name);
-
-        if (meth.ok ())
-          {
-            int _nargout = (type.length () > 2 ? 1 : nargout);
-
-            octave_value_list args;
-
-            skip = 1;
-
-            if (type.length () > 1 && type[1] == '(')
-              {
-                auto it = idx.begin ();
-
-                args = *++it;
-
-                skip++;
-              }
-
-            if (meth.is_static ())
-              retval = meth.execute (args, _nargout, true, "subsref");
-            else
-              {
-                refcount++;
-                retval = meth.execute (cdef_object (this), args, _nargout,
-                                       true, "subsref");
-              }
-          }
-
-        if (skip == 0)
-          {
-            cdef_property prop = cls.find_property (name);
-
-            if (! prop.ok ())
-              error ("subsref: unknown method or property: %s", name.c_str ());
-
-            if (prop.is_constant ())
-              retval(0) = prop.get_value (true, "subsref");
-            else
-              {
-                refcount++;
-                retval(0) = prop.get_value (cdef_object (this),
-                                            true, "subsref");
-              }
-
-            skip = 1;
-          }
-        break;
-      }
-
-    case '(':
-      {
-        const octave_value_list& ival = idx.front ();
-
-        refcount++;
-        cdef_object this_obj (this);
-
-        if (ival.empty ())
-          {
-            skip++;
-            retval(0) = to_ov (this_obj);
-          }
-        else
-          {
-            Array<cdef_object> arr (dim_vector (1, 1), this_obj);
-
-            cdef_object new_obj = cdef_object (new cdef_object_array (arr));
-
-            new_obj.set_class (get_class ());
-
-            retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
-          }
-      }
-      break;
-
-    default:
-      error ("object cannot be indexed with `%c'", type[0]);
-      break;
-    }
-
-  return retval;
-}
-
-octave_value
-cdef_object_scalar::subsasgn (const std::string& type,
-                              const std::list<octave_value_list>& idx,
-                              const octave_value& rhs)
-{
-  octave_value retval;
-
-  cdef_class cls = get_class ();
-
-  switch (type[0])
-    {
-    case '.':
-      {
-        std::string name = (idx.front ())(0).string_value ();
-
-        cdef_property prop = cls.find_property (name);
-
-        if (! prop.ok ())
-          error ("subsasgn: unknown property: %s", name.c_str ());
-
-        if (prop.is_constant ())
-          error ("subsasgn: cannot assign constant property: %s",
-                 name.c_str ());
-
-        refcount++;
-
-        cdef_object obj (this);
-
-        if (type.length () == 1)
-          {
-            prop.set_value (obj, rhs, true, "subsasgn");
-
-            retval = to_ov (obj);
-          }
-        else
-          {
-            octave_value val =
-              prop.get_value (obj, true, "subsasgn");
-
-            std::list<octave_value_list> args (idx);
-
-            args.erase (args.begin ());
-
-            val = val.assign (octave_value::op_asn_eq,
-                              type.substr (1), args, rhs);
-
-            if (val.class_name () != "object"
-                || ! to_cdef (val).is_handle_object ())
-              prop.set_value (obj, val, true, "subsasgn");
-
-            retval = to_ov (obj);
-          }
-      }
-      break;
-
-    case '(':
-      {
-        refcount++;
-
-        cdef_object this_obj (this);
-
-        Array<cdef_object> arr (dim_vector (1, 1), this_obj);
-
-        cdef_object new_obj = cdef_object (new cdef_object_array (arr));
-
-        new_obj.set_class (get_class ());
-
-        octave_value tmp = new_obj.subsasgn (type, idx, rhs);
-
-        retval = tmp;
-      }
-      break;
-
-    default:
-      error ("subsasgn: object cannot be index with `%c'", type[0]);
-      break;
-    }
-
-  return retval;
-}
-
-void
-cdef_object_scalar::mark_for_construction (const cdef_class& cls)
-{
-  std::string cls_name = cls.get_name ();
-
-  Cell supcls = cls.get ("SuperClasses").cell_value ();
-
-  std::list<cdef_class> supcls_list = lookup_classes (supcls);
-
-  ctor_list[cls] = supcls_list;
-}
-
-octave_value_list
-cdef_object_array::subsref (const std::string& type,
-                            const std::list<octave_value_list>& idx,
-                            int /* nargout */, size_t& skip,
-                            const cdef_class& /* context */, bool auto_add)
+octave_classdef_superclass_ref::call (octave::tree_evaluator& tw,
+                                      int nargout, const octave_value_list& idx)
 {
   octave_value_list retval;
 
-  skip = 1;
+  std::string meth_name;
+  bool in_constructor;
+  octave::cdef_class ctx;
 
-  switch (type[0])
-    {
-    case '(':
-      {
-        const octave_value_list& ival = idx.front ();
+  ctx = octave::get_class_context (meth_name, in_constructor);
 
-        if (ival.empty ())
-          {
-            refcount++;
-            retval(0) = to_ov (cdef_object (this));
-            break;
-          }
+  if (! ctx.ok ())
+    error ("superclass calls can only occur in methods or constructors");
 
-        bool is_scalar = true;
-        Array<idx_vector> iv (dim_vector (1, ival.length ()));
+  std::string mname = m_method_name;
+  std::string cname = m_class_name;
 
-        for (int i = 0; i < ival.length (); i++)
-          {
-            try
-              {
-                iv(i) = ival(i).index_vector ();
-              }
-            catch (octave::index_exception& e)
-              {
-                // Rethrow to allow more info to be reported later.
-                e.set_pos_if_unset (ival.length (), i+1);
-                throw;
-              }
+  // CLS is the superclass.  The lookup_class function handles
+  // pkg.class names.
 
-            is_scalar = is_scalar && iv(i).is_scalar ();
-          }
-
-        Array<cdef_object> ires = array.index (iv, auto_add);
+  octave::cdef_class cls = octave::lookup_class (cname);
 
-        // If resizing is enabled (auto_add = true), it's possible
-        // indexing was out-of-bound and the result array contains
-        // invalid cdef_objects.
-
-        if (auto_add)
-          fill_empty_values (ires);
+  if (in_constructor)
+    {
+      if (! is_direct_superclass (cls, ctx))
+        error ("'%s' is not a direct superclass of '%s'",
+               cname.c_str (), ctx.get_name ().c_str ());
 
-        if (is_scalar)
-          retval(0) = to_ov (ires(0));
-        else
-          {
-            cdef_object array_obj (new cdef_object_array (ires));
+      if (! is_constructed_object (tw, mname))
+        error ("cannot call superclass constructor with variable '%s'",
+               mname.c_str ());
 
-            array_obj.set_class (get_class ());
-
-            retval(0) = to_ov (array_obj);
-          }
-      }
-      break;
+      octave_value sym = tw.varval (mname);
 
-    case '.':
-      if (type.size () == 1 && idx.size () == 1)
-        {
-          Cell c (dims ());
-
-          octave_idx_type n = array.numel ();
-
-          // dummy variables
-          size_t dummy_skip;
-          cdef_class dummy_cls;
+      cls.run_constructor (octave::to_cdef_ref (sym), idx);
 
-          for (octave_idx_type i = 0; i < n; i++)
-            {
-              octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip,
-                                                      dummy_cls);
+      retval(0) = sym;
+    }
+  else
+    {
+      size_t pos = mname.find ('.');
 
-              if (r.length () > 0)
-                c(i) = r(0);
-            }
+      octave::cdef_object obj;
 
-          retval(0) = octave_value (c, true);
-
-          break;
-        }
-      OCTAVE_FALLTHROUGH;
+      if (pos != std::string::npos)
+        {
+          // We are looking at obj.meth.
 
-    default:
-      error ("can't perform indexing operation on array of %s objects",
-             class_name ().c_str ());
-      break;
-    }
+          std::string oname = m_method_name.substr (0, pos);
+          mname = mname.substr (pos + 1);
 
-  return retval;
-}
-
-octave_value
-cdef_object_array::subsasgn (const std::string& type,
-                             const std::list<octave_value_list>& idx,
-                             const octave_value& rhs)
-{
-  octave_value retval;
+          octave_value tval = tw.varval (oname);
 
-  switch (type[0])
-    {
-    case '(':
-      if (type.length () == 1)
-        {
-          cdef_object rhs_obj = to_cdef (rhs);
+          // FIXME: Can we only call superclass methods on the current
+          // object?  If so, and we are looking at something like
+          //
+          //   function meth (obj, ...)
+          //     obj.meth@superclass (...)
+          //
+          // Do we need to verify that the object that was passed to
+          // meth is the same as the object we find when looking up
+          // obj in the expression obj.meth?  If so, what is the right
+          // way to perform that check?
 
-          if (rhs_obj.get_class () != get_class ())
-            error ("can't assign %s object into array of %s objects.",
-                   rhs_obj.class_name ().c_str (),
-                   class_name ().c_str ());
-
-          const octave_value_list& ival = idx.front ();
-          bool is_scalar = true;
-          Array<idx_vector> iv (dim_vector (1, ival.length ()));
-
-          for (int i = 0; i < ival.length (); i++)
+          if (tval.is_classdef_object ())
             {
-              try
-                {
-                  iv(i) = ival(i).index_vector ();
-                }
-              catch (octave::index_exception& e)
-                {
-                  e.set_pos_if_unset (ival.length (), i+1);
-                  throw;   // var name set in pt-idx.cc / pt-assign.cc
-                }
-
-              is_scalar = is_scalar && iv(i).is_scalar ();
-            }
-
-          Array<cdef_object> rhs_mat;
+              octave_classdef *cdobj = tval.classdef_object_value ();
 
-          if (! rhs_obj.is_array ())
-            {
-              rhs_mat = Array<cdef_object> (dim_vector (1, 1));
-              rhs_mat(0) = rhs_obj;
+              obj = cdobj->get_object ();
             }
-          else
-            rhs_mat = rhs_obj.array_value ();
-
-          octave_idx_type n = array.numel ();
-
-          array.assign (iv, rhs_mat, cdef_object ());
-
-          if (array.numel () > n)
-            fill_empty_values ();
+        }
 
-          refcount++;
-          retval = to_ov (cdef_object (this));
-        }
-      else
-        {
-          const octave_value_list& ivl = idx.front ();
-
-          // Fill in trailing singleton dimensions so that
-          // array.index doesn't create a new blank entry (bug #46660).
-          const octave_idx_type one = static_cast<octave_idx_type> (1);
-          const octave_value_list& ival = ivl.length () >= 2
-                                            ? ivl : ((array.dims ()(0) == 1)
-                                                      ? ovl (one, ivl(0))
-                                                      : ovl (ivl(0), one));
-
-          bool is_scalar = true;
+      if (mname != meth_name)
+        error ("method name mismatch ('%s' != '%s')",
+               mname.c_str (), meth_name.c_str ());
 
-          Array<idx_vector> iv (dim_vector (1, ival.length ()));
-
-          for (int i = 0; i < ival.length (); i++)
-            {
-              try
-                {
-                  iv(i) = ival(i).index_vector ();
-                }
-              catch (octave::index_exception& e)
-                {
-                  // Rethrow to allow more info to be reported later.
-                  e.set_pos_if_unset (ival.length (), i+1);
-                  throw;
-                }
-
-              is_scalar = is_scalar && iv(i).is_scalar ();
+      if (! is_strict_superclass (cls, ctx))
+        error ("'%s' is not a superclass of '%s'",
+               cname.c_str (), ctx.get_name ().c_str ());
 
-              if (! is_scalar)
-                error ("subsasgn: invalid indexing for object array assignment"
-                       ", the index must reference a single object in the "
-                       "array.");
-            }
-
-          Array<cdef_object> a = array.index (iv, true);
-
-          if (a.numel () != 1)
-            error ("subsasgn: invalid indexing for object array assignment");
-
-          cdef_object obj = a(0);
-
-          int ignore_copies = 0;
-
-          // If the object in 'a' is not valid, this means the index
-          // was out-of-bound and we need to create a new object.
-
-          if (! obj.ok ())
-            obj = get_class ().construct_object (octave_value_list ());
-          else
-            // Optimize the subsasgn call to come.  There are 2 copies
-            // that we can safely ignore:
-            // - 1 in "array"
-            // - 1 in "a"
-            ignore_copies = 2;
-
-          std::list<octave_value_list> next_idx (idx);
-
-          next_idx.erase (next_idx.begin ());
-
-          octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
-                                           rhs, ignore_copies);
+      // I see 2 possible implementations here:
+      // 1) use cdef_object::subsref with a different class
+      //    context; this avoids duplicating code, but
+      //    assumes the object is always the first argument
+      // 2) lookup the method manually and call
+      //    cdef_method::execute; this duplicates part of
+      //    logic in cdef_object::subsref, but avoid the
+      //    assumption of 1)
+      // Not being sure about the assumption of 1), I
+      // go with option 2) for the time being.
 
-          cdef_object robj = to_cdef (tmp);
-
-          if (! robj.ok ()
-              || robj.is_array ()
-              || robj.get_class () != get_class ())
-            error ("subasgn: invalid assignment into array of %s objects",
-                   class_name ().c_str ());
-
-          // Small optimization, when dealing with handle
-          // objects, we don't need to re-assign the result
-          // of subsasgn back into the array.
-
-          if (! robj.is (a(0)))
-            {
-              Array<cdef_object> rhs_a (dim_vector (1, 1),
-                                        robj);
+      octave::cdef_method meth = cls.find_method (meth_name, false);
 
-              octave_idx_type n = array.numel ();
-
-              array.assign (iv, rhs_a);
-
-              if (array.numel () > n)
-                fill_empty_values ();
-            }
+      if (! meth.ok ())
+        error ("no method '%s' found in superclass '%s'",
+               meth_name.c_str (), cname.c_str ());
 
-          refcount++;
-
-          retval = to_ov (cdef_object (this));
-        }
-      break;
-
-    default:
-      error ("can't perform indexing operation on array of %s objects",
-             class_name ().c_str ());
-      break;
+      retval = (obj.ok ()
+                ? meth.execute (obj, idx, nargout, true, meth_name)
+                : meth.execute (idx, nargout, true, meth_name));
     }
 
   return retval;
 }
 
-void
-cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
-{
-  cdef_class cls = get_class ();
-
-  cdef_object obj;
-
-  int n = arr.numel ();
-
-  for (int i = 0; i < n; i++)
-    {
-      if (! arr.xelem (i).ok ())
-        {
-          if (! obj.ok ())
-            {
-              obj = cls.construct_object (octave_value_list ());
-
-              arr.xelem (i) = obj;
-            }
-          else
-            arr.xelem (i) = obj.copy ();
-        }
-    }
-}
-
-bool
-cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
-{
-  return (is_constructed ()
-          || ctor_list.find (cls) == ctor_list.end ());
-}
-
-bool
-cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
-{
-  std::map< cdef_class, std::list<cdef_class>>::const_iterator it;
-
-  if (is_constructed ())
-    return true;
-  else if ((it = ctor_list.find (cls)) == ctor_list.end ()
-           || it->second.empty ())
-    return true;
-
-  for (const auto& cdef_cls : it->second)
-    if (! is_constructed_for (cdef_cls))
-      return false;
-
-  return true;
-}
-
-inline void
-cdef_object_scalar::mark_as_constructed (const cdef_class& cls)
-{
-  ctor_list.erase (cls);
-}
-
-handle_cdef_object::~handle_cdef_object (void)
-{
-#if DEBUG_TRACE
-  std::cerr << "deleting " << get_class ().get_name ()
-            << " object (handle)" << std::endl;
-#endif
-}
-
-value_cdef_object::~value_cdef_object (void)
-{
-#if DEBUG_TRACE
-  std::cerr << "deleting " << get_class ().get_name ()
-            << " object (value)" << std::endl;
-#endif
-}
-
-cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
-  : cdef_meta_object_rep (), member_count (0), handle_class (false),
-    object_count (0), meta (false)
-{
-  put ("SuperClasses", to_ov (superclasses));
-  implicit_ctor_list = superclasses;
-}
-
-cdef_method
-cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
-{
-  auto it = method_map.find (nm);
-
-  if (it == method_map.end ())
-    {
-      // FIXME: look into class directory
-    }
-  else
-    {
-      cdef_method& meth = it->second;
-
-      // FIXME: check if method reload needed
-
-      if (meth.ok ())
-        return meth;
-    }
-
-  if (! local)
-    {
-      // Look into superclasses
-
-      Cell super_classes = get ("SuperClasses").cell_value ();
-
-      for (int i = 0; i < super_classes.numel (); i++)
-        {
-          cdef_class cls = lookup_class (super_classes(i));
-
-          cdef_method meth = cls.find_method (nm);
-
-          if (meth.ok ())
-            return meth;
-        }
-    }
-
-  return cdef_method ();
-}
-
-class ctor_analyzer : public octave::tree_walker
+bool octave_classdef_superclass_ref::is_constructed_object (octave::tree_evaluator& tw,
+                                                            const std::string& nm)
 {
-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)
-      stmt_p->accept (*this);
-  }
-
-  void visit_statement (octave::tree_statement& t)
-  {
-    if (t.is_expression ())
-      t.expression ()->accept (*this);
-  }
-
-  void visit_simple_assignment (octave::tree_simple_assignment& t)
-  {
-    t.right_hand_side ()->accept (*this);
-  }
-
-  void visit_multi_assignment (octave::tree_multi_assignment& t)
-  {
-    t.right_hand_side ()->accept (*this);
-  }
-
-  void visit_index_expression (octave::tree_index_expression& t)
-  {
-    t.expression ()->accept (*this);
-  }
-
-  void visit_funcall (octave::tree_funcall& t)
-  {
-    octave_value fcn = t.function ();
-
-    if (fcn.is_function ())
-      {
-        octave_function *of = fcn.function_value (true);
-
-        if (of)
-          {
-            if (of->name () == "__superclass_reference__")
-              {
-                octave_value_list args = t.arguments ();
-
-                if (args(0).string_value () == obj_name)
-                  {
-                    std::string class_name = args(1).string_value ();
-
-                    cdef_class cls = lookup_class (class_name, false);
-
-                    if (cls.ok ())
-                      ctor_list.push_back (cls);
-                  }
-              }
-          }
-      }
-  }
-
-  std::list<cdef_class> get_constructor_list (void) const
-  { return ctor_list; }
-
-  // NO-OP
-  void visit_anon_fcn_handle (octave::tree_anon_fcn_handle&) { }
-  void visit_argument_list (octave::tree_argument_list&) { }
-  void visit_binary_expression (octave::tree_binary_expression&) { }
-  void visit_break_command (octave::tree_break_command&) { }
-  void visit_colon_expression (octave::tree_colon_expression&) { }
-  void visit_continue_command (octave::tree_continue_command&) { }
-  void visit_decl_command (octave::tree_decl_command&) { }
-  void visit_decl_init_list (octave::tree_decl_init_list&) { }
-  void visit_decl_elt (octave::tree_decl_elt&) { }
-  void visit_simple_for_command (octave::tree_simple_for_command&) { }
-  void visit_complex_for_command (octave::tree_complex_for_command&) { }
-  void visit_octave_user_script (octave_user_script&) { }
-  void visit_octave_user_function (octave_user_function&) { }
-  void visit_function_def (octave::tree_function_def&) { }
-  void visit_identifier (octave::tree_identifier&) { }
-  void visit_if_clause (octave::tree_if_clause&) { }
-  void visit_if_command (octave::tree_if_command&) { }
-  void visit_if_command_list (octave::tree_if_command_list&) { }
-  void visit_switch_case (octave::tree_switch_case&) { }
-  void visit_switch_case_list (octave::tree_switch_case_list&) { }
-  void visit_switch_command (octave::tree_switch_command&) { }
-  void visit_matrix (octave::tree_matrix&) { }
-  void visit_cell (octave::tree_cell&) { }
-  void visit_no_op_command (octave::tree_no_op_command&) { }
-  void visit_constant (octave::tree_constant&) { }
-  void visit_fcn_handle (octave::tree_fcn_handle&) { }
-  void visit_parameter_list (octave::tree_parameter_list&) { }
-  void visit_postfix_expression (octave::tree_postfix_expression&) { }
-  void visit_prefix_expression (octave::tree_prefix_expression&) { }
-  void visit_return_command (octave::tree_return_command&) { }
-  void visit_return_list (octave::tree_return_list&) { }
-  void visit_try_catch_command (octave::tree_try_catch_command&) { }
-  void visit_unwind_protect_command (octave::tree_unwind_protect_command&) { }
-  void visit_while_command (octave::tree_while_command&) { }
-  void visit_do_until_command (octave::tree_do_until_command&) { }
-
-private:
-  // The name of the constructor being analyzed.
-  std::string who;
-
-  // The name of the first output argument of the constructor.
-  std::string obj_name;
-
-  // The list of superclass constructors that are explicitly called.
-  std::list<cdef_class> ctor_list;
-};
-
-void
-cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
-{
-  method_map[meth.get_name ()] = meth;
-
-  member_count++;
-
-  if (meth.is_constructor ())
-    {
-      // Analyze the constructor code to determine what superclass
-      // constructors are called explicitly.
-
-      octave_function *of = meth.get_function ().function_value (true);
-
-      if (of)
-        {
-          octave_user_function *uf = of->user_function_value (true);
-
-          if (uf)
-            {
-              octave::tree_parameter_list *ret_list = uf->return_list ();
-              octave::tree_statement_list *body = uf->body ();
-
-              if (! ret_list || ret_list->size () != 1)
-                error ("%s: invalid constructor output arguments",
-                       meth.get_name ().c_str ());
-
-              std::string obj_name = ret_list->front ()->name ();
-              ctor_analyzer a (meth.get_name (), obj_name);
-
-              body->accept (a);
-
-              std::list<cdef_class> explicit_ctor_list
-                = a.get_constructor_list ();
-
-              for (const auto& cdef_cls : explicit_ctor_list)
-                {
-#if DEBUG_TRACE
-                  std::cerr << "explicit superclass constructor: "
-                            << cdef_cls.get_name () << std::endl;
-#endif
-
-                  implicit_ctor_list.remove (cdef_cls);
-                }
-            }
-        }
-    }
-}
-
-void
-cdef_class::cdef_class_rep::load_all_methods (void)
-{
-  // FIXME: re-scan class directory
-}
-
-Cell
-cdef_class::cdef_class_rep::get_methods (void)
-{
-  std::map<std::string,cdef_method> meths;
-
-  find_methods (meths, false);
-
-  Cell c (meths.size (), 1);
-
-  int idx = 0;
-
-  for (const auto& nm_mthd : meths)
-    c(idx++, 0) = to_ov (nm_mthd.second);
-
-  return c;
-}
-
-void
-cdef_class::cdef_class_rep::find_methods (std::map<std::string,
-                                          cdef_method>& meths,
-                                          bool only_inherited)
-{
-  load_all_methods ();
-
-  method_const_iterator it;
-
-  for (it = method_map.begin (); it != method_map.end (); ++it)
-    {
-      if (! it->second.is_constructor ())
-        {
-          std::string nm = it->second.get_name ();
-
-          if (meths.find (nm) == meths.end ())
-            {
-              if (only_inherited)
-                {
-                  octave_value acc = it->second.get ("Access");
-
-                  if (! acc.is_string ()
-                      || acc.string_value () == "private")
-                    continue;
-                }
-
-              meths[nm] = it->second;
-            }
-        }
-    }
-
-  // Look into superclasses
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
-
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i));
-
-      cls.get_rep ()->find_methods (meths, true);
-    }
-}
-
-cdef_property
-cdef_class::cdef_class_rep::find_property (const std::string& nm)
-{
-  auto it = property_map.find (nm);
-
-  if (it != property_map.end ())
-    {
-      cdef_property& prop = it->second;
-
-      if (prop.ok ())
-        return prop;
-    }
-
-  // Look into superclasses
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
-
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i));
-
-      cdef_property prop = cls.find_property (nm);
-
-      if (prop.ok ())
-        return prop;
-    }
-
-  return cdef_property ();
-}
-
-void
-cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
-{
-  property_map[prop.get_name ()] = prop;
-
-  member_count++;
-}
-
-Cell
-cdef_class::cdef_class_rep::get_properties (int mode)
-{
-  std::map<std::string,cdef_property> props;
-
-  props = get_property_map (mode);
-
-  Cell c (props.size (), 1);
-
-  int idx = 0;
-
-  for (const auto& pname_prop : props)
-    c(idx++, 0) = to_ov (pname_prop.second);
-
-  return c;
-}
-
-std::map<std::string, cdef_property>
-cdef_class::cdef_class_rep::get_property_map (int mode)
-{
-  std::map<std::string,cdef_property> props;
-
-  find_properties (props, mode);
-
-  return props;
-}
-
-void
-cdef_class::cdef_class_rep::find_properties (std::map<std::string,
-                                             cdef_property>& props,
-                                             int mode)
-{
-  property_const_iterator it;
-
-  for (it = property_map.begin (); it != property_map.end (); ++it)
-    {
-      std::string nm = it->second.get_name ();
-
-      if (props.find (nm) == props.end ())
-        {
-          if (mode == property_inherited)
-            {
-              octave_value acc = it->second.get ("GetAccess");
-
-              if (! acc.is_string ()
-                  || acc.string_value () == "private")
-                continue;
-            }
-
-          props[nm] = it->second;
-        }
-    }
-
-  // Look into superclasses
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
+  octave_function *of = tw.current_function ();
 
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i));
-
-      cls.get_rep ()->find_properties (props,
-                                       (mode == property_all
-                                        ? property_all
-                                        : property_inherited));
-    }
-}
-
-void
-cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
-                                        bool all)
-{
-  load_all_methods ();
-
-  for (const auto& cls_fnmap : method_map)
-    {
-      if (! cls_fnmap.second.is_constructor ())
-        {
-          std::string nm = cls_fnmap.second.get_name ();
-
-          if (! all)
-            {
-              octave_value acc = cls_fnmap.second.get ("Access");
-
-              if (! acc.is_string()
-                  || acc.string_value () != "public")
-                continue;
-            }
-
-          names.insert (nm);
-        }
-    }
-
-  for (const auto& pname_prop : property_map)
-    {
-      std::string nm = pname_prop.second.get_name ();
-
-      if (! all)
-        {
-          octave_value acc = pname_prop.second.get ("GetAccess");
-
-          if (! acc.is_string()
-              || acc.string_value () != "public")
-            continue;
-        }
-
-      names.insert (nm);
-    }
-
-  // Look into superclasses
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
-
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i));
-
-      cls.get_rep ()->find_names (names, all);
-    }
-}
-
-string_vector
-cdef_class::cdef_class_rep::get_names (void)
-{
-  std::set<std::string> names;
-
-  find_names (names, false);
-
-  string_vector v (names);
-
-  return v.sort (true);
-}
-
-void
-cdef_class::cdef_class_rep::delete_object (const cdef_object& obj)
-{
-  cdef_method dtor = find_method ("delete");
-
-  if (dtor.ok ())
-    dtor.execute (obj, octave_value_list (), 0, true, "destructor");
-
-  // FIXME: should we destroy corresponding properties here?
-
-  // Call "delete" in super classes
-
-  Cell super_classes = get ("SuperClasses").cell_value ();
-
-  for (int i = 0; i < super_classes.numel (); i++)
-    {
-      cdef_class cls = lookup_class (super_classes(i));
-
-      if (cls.get_name () != "handle")
-        cls.delete_object (obj);
-    }
-}
-
-octave_value_list
-cdef_class::cdef_class_rep::meta_subsref (const std::string& type,
-                                          const std::list<octave_value_list>& idx,
-                                          int nargout)
-{
-  size_t skip = 1;
-
-  octave_value_list retval;
-
-  switch (type[0])
+  if (of->is_classdef_constructor ())
     {
-    case '(':
-      // Constructor call
-
-#if DEBUG_TRACE
-      std::cerr << "constructor" << std::endl;
-#endif
-
-      retval(0) = construct (idx.front ());
-      break;
-
-    case '.':
-      {
-        // Static method, constant (or property?)
-
-#if DEBUG_TRACE
-        std::cerr << "static method/property" << std::endl;
-#endif
-
-        if (idx.front ().length () != 1)
-          error ("invalid meta.class indexing");
-
-        std::string nm = idx.front ()(0).xstring_value ("invalid meta.class indexing, expected a method or property name");
-
-        cdef_method meth = find_method (nm);
-
-        if (meth.ok ())
-          {
-            if (! meth.is_static ())
-              error ("method `%s' is not static", nm.c_str ());
-
-            octave_value_list args;
-
-            if (type.length () > 1 && idx.size () > 1 && type[1] == '(')
-              {
-                args = *(++(idx.begin ()));
-                skip++;
-              }
-
-            retval = meth.execute (args, (type.length () > skip
-                                          ? 1 : nargout), true,
-                                   "meta.class");
-          }
-        else
-          {
-            cdef_property prop = find_property (nm);
-
-            if (! prop.ok ())
-              error ("no such method or property `%s'", nm.c_str ());
-
-            if (! prop.is_constant ())
-              error ("property `%s' is not constant", nm.c_str ());
-
-            retval(0) = prop.get_value (true, "meta.class");
-          }
-      }
-      break;
-
-    default:
-      error ("invalid meta.class indexing");
-      break;
-    }
-
-  if (type.length () > skip && idx.size () > skip && ! retval.empty ())
-    retval = retval(0).next_subsref (nargout, type, idx, skip);
-
-  return retval;
-}
-
-void
-cdef_class::cdef_class_rep::meta_release (void)
-{
-  cdef_manager& cdm
-    = octave::__get_cdef_manager__ ("cdef_class::cdef_class_rep::meta_release");
-
-  cdm.unregister_class (wrap ());
-}
-
-void
-cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
-{
-  // Populate the object with default property values
-
-  std::list<cdef_class> super_classes = lookup_classes (
-                                          get ("SuperClasses").cell_value ());
-
-  for (auto& cls : super_classes)
-    cls.initialize_object (obj);
-
-  for (const auto& pname_prop : property_map)
-    {
-      if (! pname_prop.second.get ("Dependent").bool_value ())
-        {
-          octave_value pvalue = pname_prop.second.get ("DefaultValue");
-
-          if (pvalue.is_defined ())
-            obj.put (pname_prop.first, pvalue);
-          else
-            obj.put (pname_prop.first, octave_value (Matrix ()));
-        }
-    }
-
-  refcount++;
-  obj.mark_for_construction (cdef_class (this));
-}
-
-void
-cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
-                                             const octave_value_list& args)
-{
-  octave_value_list empty_args;
-
-  for (const auto& cls : implicit_ctor_list)
-    {
-      cdef_class supcls = lookup_class (cls);
+      octave_user_function *uf = of->user_function_value (true);
 
-      supcls.run_constructor (obj, empty_args);
-    }
-
-  std::string cls_name = get_name ();
-  std::string ctor_name = get_base_name (cls_name);
-
-  cdef_method ctor = find_method (ctor_name);
-
-  if (ctor.ok ())
-    {
-      octave_value_list ctor_args (args);
-      octave_value_list ctor_retval;
-
-      ctor_args.prepend (to_ov (obj));
-      ctor_retval = ctor.execute (ctor_args, 1, true, "constructor");
-
-      if (ctor_retval.length () != 1)
-        error ("%s: invalid number of output arguments for classdef constructor",
-               ctor_name.c_str ());
-
-      obj = to_cdef (ctor_retval(0));
-    }
-
-  obj.mark_as_constructed (wrap ());
-}
-
-octave_value
-cdef_class::cdef_class_rep::construct (const octave_value_list& args)
-{
-  cdef_object obj = construct_object (args);
-
-  if (obj.ok ())
-    return to_ov (obj);
-
-  return octave_value ();
-}
-
-cdef_object
-cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
-{
-  if (is_abstract ())
-    error ("cannot instantiate object for abstract class `%s'",
-           get_name ().c_str ());
-
-  cdef_object obj;
-
-  if (is_meta_class ())
-    {
-      // This code path is only used to create empty meta objects
-      // as filler for the empty values within a meta object array.
-
-      cdef_class this_cls = wrap ();
-
-      static cdef_object empty_class;
-
-      cdef_manager& cdm
-        = octave::__get_cdef_manager__ ("cdef_class::cdef_class_rep::construct_object");
-
-      if (this_cls == cdm.meta_class ())
+      if (uf)
         {
-          if (! empty_class.ok ())
-            empty_class = cdm.make_class ("", std::list<cdef_class> ());
-          obj = empty_class;
-        }
-      else if (this_cls == cdm.meta_property ())
-        {
-          static cdef_property empty_property;
-
-          if (! empty_class.ok ())
-            empty_class = cdm.make_class ("", std::list<cdef_class> ());
-          if (! empty_property.ok ())
-            empty_property = cdm.make_property (empty_class, "");
-          obj = empty_property;
-        }
-      else if (this_cls == cdm.meta_method ())
-        {
-          static cdef_method empty_method;
-
-          if (! empty_class.ok ())
-            empty_class = cdm.make_class ("", std::list<cdef_class> ());
-          if (! empty_method.ok ())
-            empty_method = cdm.make_method (empty_class, "", octave_value ());
-          obj = empty_method;
-        }
-      else if (this_cls == cdm.meta_package ())
-        {
-          static cdef_package empty_package;
-
-          if (! empty_package.ok ())
-            empty_package = cdm.make_package ("");
-          obj = empty_package;
-        }
-      else
-        panic_impossible ();
-
-      return obj;
-    }
-  else
-    {
-      if (is_handle_class ())
-        obj = cdef_object (new handle_cdef_object ());
-      else
-        obj = cdef_object (new value_cdef_object ());
-      obj.set_class (wrap ());
-
-      initialize_object (obj);
-
-      run_constructor (obj, args);
-
-      return obj;
-    }
+          octave::tree_parameter_list *ret_list = uf->return_list ();
 
-  return cdef_object ();
-}
-
-static octave_value
-compute_attribute_value (octave::tree_evaluator& tw,
-                         octave::tree_classdef_attribute *t)
-{
-  octave::tree_expression *expr = t->expression ();
-
-  if (expr)
-    {
-      if (expr->is_identifier ())
-        {
-          std::string s = expr->name ();
-
-          if (s == "public")
-            return std::string ("public");
-          else if (s == "protected")
-            return std::string ("protected");
-          else if (s == "private")
-            return std::string ("private");
-        }
-
-      return tw.evaluate (expr);
-    }
-  else
-    return octave_value (true);
-}
-
-template <typename T>
-static std::string
-attribute_value_to_string (T *t, octave_value v)
-{
-  if (v.is_string ())
-    return v.string_value ();
-  else if (t->expression ())
-    return t->expression ()->original_text ();
-  else
-    return "true";
-}
-
-cdef_class
-cdef_class::make_meta_class (octave::interpreter& interp,
-                             octave::tree_classdef *t, bool is_at_folder)
-{
-  cdef_class retval;
-  std::string class_name, full_class_name;
-
-  // Class creation
-
-  class_name = full_class_name = t->ident ()->name ();
-  if (! t->package_name ().empty ())
-    full_class_name = t->package_name () + '.' + full_class_name;
-
-#if DEBUG_TRACE
-  std::cerr << "class: " << full_class_name << std::endl;
-#endif
-
-  std::list<cdef_class> slist;
-
-  if (t->superclass_list ())
-    {
-      for (auto& scls : (*t->superclass_list ()))
-        {
-          std::string sclass_name = (scls)->class_name ();
-
-#if DEBUG_TRACE
-          std::cerr << "superclass: " << sclass_name << std::endl;
-#endif
-
-          cdef_class sclass = lookup_class (sclass_name);
-
-          if (sclass.get ("Sealed").bool_value ())
-            error ("`%s' cannot inherit from `%s', because it is sealed",
-                   full_class_name.c_str (), sclass_name.c_str ());
-
-          slist.push_back (sclass);
-        }
-    }
-
-  cdef_manager& cdm
-    = octave::__get_cdef_manager__ ("cdef_class::make_meta_class");
-
-  retval = cdm.make_class (full_class_name, slist);
-
-  // Package owning this class
-
-  if (! t->package_name ().empty ())
-    {
-      cdef_package pack = cdm.find_package (t->package_name ());
-
-      if (pack.ok ())
-        retval.put ("ContainingPackage", to_ov (pack));
-    }
-
-  // Class attributes
-
-  octave::tree_evaluator& tw = interp.get_evaluator ();
-
-  if (t->attribute_list ())
-    {
-      for (const auto& attr : (*t->attribute_list ()))
-        {
-          std::string aname = attr->ident ()->name ();
-          octave_value avalue = compute_attribute_value (tw, attr);
-
-#if DEBUG_TRACE
-          std::cerr << "class attribute: " << aname << " = "
-                    << attribute_value_to_string (attr, avalue) << std::endl;
-#endif
-
-          retval.put (aname, avalue);
+          if (ret_list && ret_list->length () == 1)
+            return (ret_list->front ()->name () == nm);
         }
     }
 
-  octave::tree_classdef_body *b = t->body ();
-
-  if (b)
-    {
-      // Keep track of the get/set accessor methods.  They will be used
-      // later on when creating properties.
-
-      std::map<std::string, octave_value> get_methods;
-      std::map<std::string, octave_value> set_methods;
-
-      // Method blocks
-
-      std::list<octave::tree_classdef_methods_block *> mb_list = b->methods_list ();
-
-      octave::load_path& lp = interp.get_load_path ();
-
-      for (auto& mb_p : mb_list)
-        {
-          std::map<std::string, octave_value> amap;
-
-#if DEBUG_TRACE
-          std::cerr << "method block" << std::endl;
-#endif
-
-          // Method attributes
-
-          if (mb_p->attribute_list ())
-            {
-              for (auto& attr_p : *mb_p->attribute_list ())
-                {
-                  std::string aname = attr_p->ident ()->name ();
-                  octave_value avalue = compute_attribute_value (tw, attr_p);
-
-#if DEBUG_TRACE
-                  std::cerr << "method attribute: " << aname << " = "
-                            << attribute_value_to_string (attr_p, avalue)
-                            << std::endl;
-#endif
-
-                  amap[aname] = avalue;
-                }
-            }
-
-          // Methods
-
-          if (mb_p->element_list ())
-            {
-              for (auto& mtd : *mb_p->element_list ())
-                {
-                  std::string mname = mtd.function_value ()->name ();
-                  std::string mprefix = mname.substr (0, 4);
-
-                  if (mprefix == "get.")
-                    get_methods[mname.substr (4)] =
-                      make_fcn_handle (mtd, full_class_name + '>' + mname);
-                  else if (mprefix == "set.")
-                    set_methods[mname.substr (4)] =
-                      make_fcn_handle (mtd, full_class_name + '>' + mname);
-                  else
-                    {
-                      cdef_method meth = cdm.make_method (retval, mname, mtd);
-
-#if DEBUG_TRACE
-                      std::cerr << (mname == class_name ? "constructor"
-                                                        : "method")
-                                << ": " << mname << std::endl;
-#endif
-
-                      for (auto& attrnm_val : amap)
-                        meth.put (attrnm_val.first, attrnm_val.second);
-
-                      retval.install_method (meth);
-                    }
-                }
-            }
-        }
-
-      if (is_at_folder)
-        {
-          // Look for all external methods visible on octave path at the
-          // time of loading of the class.
-          //
-          // FIXME: This is an "extension" to Matlab behavior, which only looks
-          // in the @-folder containing the original classdef file.  However,
-          // this is easier to implement it that way at the moment.
-
-          std::list<std::string> external_methods
-            = lp.methods (full_class_name);
-
-          for (const auto& mtdnm : external_methods)
-            {
-              // FIXME: should we issue a warning if the method is already
-              // defined in the classdef file?
-
-              if (mtdnm != class_name
-                  && ! retval.find_method (mtdnm, true).ok ())
-                {
-                  // Create a dummy method that is used until the actual
-                  // method is loaded.
-                  octave_user_function *fcn = new octave_user_function ();
-
-                  fcn->stash_function_name (mtdnm);
-
-                  cdef_method meth
-                    = cdm.make_method (retval, mtdnm, octave_value (fcn));
-
-                  retval.install_method (meth);
-                }
-            }
-        }
-
-      // Property blocks
-
-      // FIXME: default property expression should be able to call static
-      //        methods of the class being constructed.  A restricted CLASSNAME
-      //        symbol should be added to the scope before evaluating default
-      //        value expressions.
-
-      std::list<octave::tree_classdef_properties_block *> pb_list
-        = b->properties_list ();
-
-      for (auto& pb_p : pb_list)
-        {
-          std::map<std::string, octave_value> amap;
-
-#if DEBUG_TRACE
-          std::cerr << "property block" << std::endl;
-#endif
-
-          // Property attributes
-
-          if (pb_p->attribute_list ())
-            {
-              for (auto& attr_p : *pb_p->attribute_list ())
-                {
-                  std::string aname = attr_p->ident ()->name ();
-                  octave_value avalue = compute_attribute_value (tw, attr_p);
-
-#if DEBUG_TRACE
-                  std::cerr << "property attribute: " << aname << " = "
-                            << attribute_value_to_string (attr_p, avalue)
-                            << std::endl;
-#endif
-
-                  if (aname == "Access")
-                    {
-                      amap["GetAccess"] = avalue;
-                      amap["SetAccess"] = avalue;
-                    }
-                  else
-                    amap[aname] = avalue;
-                }
-            }
-
-          // Properties
-
-          if (pb_p->element_list ())
-            {
-              for (auto& prop_p : *pb_p->element_list ())
-                {
-                  std::string prop_name = prop_p->ident ()->name ();
-
-                  cdef_property prop = cdm.make_property (retval, prop_name);
-
-#if DEBUG_TRACE
-                  std::cerr << "property: " << prop_p->ident ()->name ()
-                            << std::endl;
-#endif
-
-                  octave::tree_expression *expr = prop_p->expression ();
-                  if (expr)
-                    {
-                      octave_value pvalue = tw.evaluate (expr);
-
-#if DEBUG_TRACE
-                      std::cerr << "property default: "
-                                << attribute_value_to_string (*pit, pvalue)
-                                << std::endl;
-#endif
-
-                      prop.put ("DefaultValue", pvalue);
-                    }
-
-                  // Install property attributes.  This is done before assigning
-                  // the property accessors so we can do validation by using
-                  // cdef_property methods.
-
-                  for (auto& attrnm_val : amap)
-                    prop.put (attrnm_val.first, attrnm_val.second);
-
-                  // Install property access methods, if any.  Remove the
-                  // accessor methods from the temporary storage map, so we can
-                  // detect which ones are invalid and do not correspond to a
-                  // defined property.
-
-                  auto git = get_methods.find (prop_name);
-
-                  if (git != get_methods.end ())
-                    {
-                      make_function_of_class (retval, git->second);
-                      prop.put ("GetMethod", git->second);
-                      get_methods.erase (git);
-                    }
-
-                  auto sit = set_methods.find (prop_name);
-
-                  if (sit != set_methods.end ())
-                    {
-                      make_function_of_class (retval, sit->second);
-                      prop.put ("SetMethod", sit->second);
-                      set_methods.erase (sit);
-                    }
-
-                  retval.install_property (prop);
-                }
-            }
-        }
-    }
-
-  return retval;
-}
-
-octave_function*
-cdef_class::get_method_function (const std::string& /* nm */)
-{
-  octave_classdef_meta *p = new octave_classdef_meta (*this);
-
-  return p;
-}
-
-octave_value
-cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
-                                             bool do_check_access,
-                                             const std::string& who)
-{
-  octave_value retval;
-
-  if (do_check_access && ! check_get_access ())
-    err_property_access (who, wrap (), false);
-
-  if (! obj.is_constructed ())
-    {
-      cdef_class cls (to_cdef (get ("DefiningClass")));
-
-      if (! obj.is_partially_constructed_for (cls))
-        error ("cannot reference properties of class `%s' for non-constructed object",
-               cls.get_name ().c_str ());
-    }
-
-  octave_value get_fcn = get ("GetMethod");
-
-  // FIXME: should check whether we're already in get accessor method
-
-  if (get_fcn.isempty () || is_method_executing (get_fcn, obj))
-    retval = obj.get (get ("Name").string_value ());
-  else
-    {
-      octave_value_list args;
-
-      args(0) = to_ov (obj);
-
-      args = octave::feval (get_fcn, args, 1);
-
-      retval = args(0);
-    }
-
-  return retval;
-}
-
-octave_value
-cdef_property::cdef_property_rep::get_value (bool do_check_access,
-                                             const std::string& who)
-{
-  if (do_check_access && ! check_get_access ())
-    err_property_access (who, wrap (), false);
-
-  return get ("DefaultValue");
-}
-
-bool
-cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
-{
-  // FIXME: implement
-  return false;
-}
-
-void
-cdef_property::cdef_property_rep::set_value (cdef_object& obj,
-                                             const octave_value& val,
-                                             bool do_check_access,
-                                             const std::string& who)
-{
-  if (do_check_access && ! check_set_access ())
-    err_property_access (who, wrap (), true);
-
-  if (! obj.is_constructed ())
-    {
-      cdef_class cls (to_cdef (get ("DefiningClass")));
-
-      if (! obj.is_partially_constructed_for (cls))
-        error ("cannot reference properties of class `%s' for non-constructed object",
-               cls.get_name ().c_str ());
-    }
-
-  octave_value set_fcn = get ("SetMethod");
-
-  if (set_fcn.isempty () || is_method_executing (set_fcn, obj))
-    obj.put (get ("Name").string_value (), val);
-  else
-    {
-      octave_value_list args;
-
-      args(0) = to_ov (obj);
-      args(1) = val;
-
-      args = octave::feval (set_fcn, args, 1);
-
-      if (args.length () > 0 && args(0).is_defined ())
-        {
-          if (args (0).is_classdef_object ())
-            {
-              cdef_object new_obj = to_cdef (args(0));
-
-              obj = new_obj;
-            }
-          else
-            ::warning ("set-method of property `%s' returned a non-classdef object",
-                       get_name ().c_str ());
-        }
-    }
-}
-
-bool
-cdef_property::cdef_property_rep::check_get_access (void) const
-{
-  cdef_class cls (to_cdef (get ("DefiningClass")));
-
-  return ::check_access (cls, get ("GetAccess"), "",
-                         get_name (), false);
-
-  return false;
-}
-
-bool
-cdef_property::cdef_property_rep::check_set_access (void) const
-{
-  cdef_class cls (to_cdef (get ("DefiningClass")));
-
-  return ::check_access (cls, get ("SetAccess"), "",
-                         get_name (), true);
-
-  return false;
-}
-
-void
-cdef_method::cdef_method_rep::check_method (void)
-{
-  if (is_external ())
-    {
-      if (is_dummy_method (function))
-        {
-          octave::load_path& lp
-            = octave::__get_load_path__ ("cdef_method::cdef_method_rep::check_method");
-
-          std::string name = get_name ();
-          std::string cls_name = dispatch_type;
-          std::string pack_name;
-
-          size_t pos = cls_name.rfind ('.');
-
-          if (pos != std::string::npos)
-            {
-              pack_name = cls_name.substr (0, pos);
-              cls_name = cls_name.substr (pos + 1);
-            }
-
-          std::string dir_name;
-          std::string file_name = lp.find_method (cls_name, name,
-                                                  dir_name, pack_name);
-
-          if (! file_name.empty ())
-            {
-              octave_value ov_fcn
-                = octave::load_fcn_from_file (file_name, dir_name,
-                                              dispatch_type, pack_name);
-
-              if (ov_fcn.is_defined ())
-                {
-                  function = ov_fcn;
-
-                  make_function_of_class (dispatch_type, function);
-                }
-            }
-        }
-      else
-        {
-          // FIXME: check out-of-date status
-        }
-
-      if (is_dummy_method (function))
-        error ("no definition found for method `%s' of class `%s'",
-               get_name ().c_str (), dispatch_type.c_str ());
-    }
-}
-
-octave_value_list
-cdef_method::cdef_method_rep::execute (const octave_value_list& args,
-                                       int nargout, bool do_check_access,
-                                       const std::string& who)
-{
-  octave_value_list retval;
-
-  if (do_check_access && ! check_access ())
-    err_method_access (who, wrap ());
-
-  if (get ("Abstract").bool_value ())
-    error ("%s: cannot execute abstract method",
-           get ("Name").string_value ().c_str ());
-
-  check_method ();
-
-  if (function.is_defined ())
-    retval = octave::feval (function, args, nargout);
-
-  return retval;
-}
-
-octave_value_list
-cdef_method::cdef_method_rep::execute (const cdef_object& obj,
-                                       const octave_value_list& args,
-                                       int nargout, bool do_check_access,
-                                       const std::string& who)
-{
-  octave_value_list retval;
-
-  if (do_check_access && ! check_access ())
-    err_method_access (who, wrap ());
-
-  if (get ("Abstract").bool_value ())
-    error ("%s: cannot execute abstract method",
-           get ("Name").string_value ().c_str ());
-
-  check_method ();
-
-  if (function.is_defined ())
-    {
-      octave_value_list new_args;
-
-      new_args.resize (args.length () + 1);
-
-      new_args(0) = to_ov (obj);
-      for (int i = 0; i < args.length (); i++)
-        new_args(i+1) = args(i);
-
-      retval = octave::feval (function, new_args, nargout);
-    }
-
-  return retval;
-}
-
-bool
-cdef_method::cdef_method_rep::is_constructor (void) const
-{
-  if (function.is_function())
-    return function.function_value ()->is_classdef_constructor ();
-
   return false;
 }
 
-bool
-cdef_method::cdef_method_rep::check_access (void) const
-{
-  cdef_class cls (to_cdef (get ("DefiningClass")));
-
-  return ::check_access (cls, get ("Access"), get_name ());
-}
-
-octave_value_list
-cdef_method::cdef_method_rep::meta_subsref
-  (const std::string& type, const std::list<octave_value_list>& idx,
-   int nargout)
-{
-  octave_value_list retval;
-
-  switch (type[0])
-    {
-    case '(':
-      retval = (execute (idx.front (), type.length () > 1 ? 1 : nargout, true));
-      break;
-
-    default:
-      error ("invalid meta.method indexing");
-      break;
-    }
-
-  if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
-    retval = retval(0).next_subsref (nargout, type, idx, 1);
-
-  return retval;
-}
-
-static cdef_package
-lookup_package (const std::string& name, bool error_if_not_found = true,
-                bool load_if_not_found = true)
-{
-  cdef_manager& cdm = octave::__get_cdef_manager__ ("lookup_package");
-
-  return cdm.find_package (name, error_if_not_found, load_if_not_found);
-}
-
-static octave_value_list
-package_fromName (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval;
-
-  if (args.length () != 1)
-    error ("fromName: invalid number of parameters");
-
-  std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string");
-
-  retval(0) = to_ov (lookup_package (name, false));
-
-  return retval;
-}
-
-static octave_value_list
-package_get_classes (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval (1, Matrix ());
-
-  if (args.length () == 1 && args(0).type_name () == "object"
-      && args(0).class_name () == "meta.package")
-    {
-      cdef_package pack (to_cdef (args(0)));
-
-      retval(0) = pack.get_classes ();
-    }
-
-  return retval;
-}
-
-static octave_value_list
-package_get_functions (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval (1, Matrix ());
-
-  if (args.length () == 0 && args(0).type_name () == "object"
-      && args(0).class_name () == "meta.package")
-    {
-      cdef_package pack (to_cdef (args(0)));
-
-      retval(0) = pack.get_functions ();
-    }
-
-  return retval;
-}
-
-static octave_value_list
-package_get_packages (const octave_value_list& args, int /* nargout */)
-{
-  octave_value_list retval (1, Matrix ());
-
-  if (args.length () == 0 && args(0).type_name () == "object"
-      && args(0).class_name () == "meta.package")
-    {
-      cdef_package pack (to_cdef (args(0)));
-
-      retval(0) = pack.get_packages ();
-    }
-
-  return retval;
-}
-
-static octave_value_list
-package_getAllPackages (octave::interpreter& interp,
-                        const octave_value_list& /* args */, int /* nargout */)
-{
-  std::map<std::string, cdef_package> toplevel_packages;
-
-  octave::load_path& lp = interp.get_load_path ();
-
-  std::list<std::string> names = lp.get_all_package_names ();
-
-  cdef_manager& cdm = octave::__get_cdef_manager__ ("package_getAllPackages");
-
-  toplevel_packages["meta"] = cdm.find_package ("meta", false, false);
-
-  for (const auto& nm : names)
-    toplevel_packages[nm] = cdm.find_package (nm, false, true);
-
-  Cell c (toplevel_packages.size (), 1);
-
-  int i = 0;
-
-  for (const auto& nm_pkg : toplevel_packages)
-    c(i++,0) = to_ov (nm_pkg.second);
-
-  return octave_value_list (octave_value (c));
-}
-
-void
-cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
-                                               const std::string& nm)
-{
-  class_map[nm] = cls;
-
-  member_count++;
-}
-
-void
-cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
-                                                  const std::string& nm)
-{
-  function_map[nm] = fcn;
-}
-
-void
-cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
-                                                 const std::string& nm)
-{
-  package_map[nm] = pack;
-
-  member_count++;
-}
-
-template <typename T1, typename T2>
-Cell
-map2Cell (const std::map<T1, T2>& m)
-{
-  Cell retval (1, m.size ());
-  int i = 0;
-
-  for (auto it = m.begin (); it != m.end (); ++it, ++i)
-    retval(i) = to_ov (it->second);
-
-  return retval;
-}
-
-Cell
-cdef_package::cdef_package_rep::get_classes (void) const
-{ return map2Cell (class_map); }
-
-Cell
-cdef_package::cdef_package_rep::get_functions (void) const
-{ return map2Cell (function_map); }
-
-Cell
-cdef_package::cdef_package_rep::get_packages (void) const
-{ return map2Cell (package_map); }
-
-octave_value
-cdef_package::cdef_package_rep::find (const std::string& nm)
-{
-  std::string symbol_name = get_name () + '.' + nm;
-
-  octave::symbol_scope curr_scope
-    = octave::__get_current_scope__ ("cdef_package::cdef_package_rep::find");
-
-  return curr_scope.find (symbol_name);
-}
-
-octave_value_list
-cdef_package::cdef_package_rep::meta_subsref
-  (const std::string& type, const std::list<octave_value_list>& idx,
-   int nargout)
-{
-  octave_value_list retval;
-
-  switch (type[0])
-    {
-    case '.':
-      {
-        if (idx.front ().length () != 1)
-          error ("invalid meta.package indexing");
-
-        std::string nm = idx.front ()(0).xstring_value ("invalid meta.package indexing, expected a symbol name");
-
-#if DEBUG_TRACE
-        std::cerr << "meta.package query: " << nm << std::endl;
-#endif
-
-        octave_value o = find (nm);
-
-        if (! o.is_defined ())
-          error ("member `%s' in package `%s' does not exist",
-                 nm.c_str (), get_name ().c_str ());
-
-        if (o.is_function ())
-          {
-            octave_function *fcn = o.function_value ();
-
-            // NOTE: the case where the package query is the last
-            // part of this subsref index is handled in the parse
-            // tree, because there is some logic to handle magic
-            // "end" that makes it impossible to execute the
-            // function call at this stage.
-
-            if (type.size () > 1
-                && ! fcn->accepts_postfix_index (type[1]))
-              {
-                octave_value_list tmp_args;
-
-                retval = octave::feval (o, tmp_args, nargout);
-              }
-            else
-              retval(0) = o;
-
-            if (type.size () > 1 && idx.size () > 1)
-              retval = retval(0).next_subsref (nargout, type,
-                                               idx, 1);
-          }
-        else if (type.size () > 1 && idx.size () > 1)
-          retval = o.next_subsref (nargout, type, idx, 1);
-        else
-          retval(0) = o;
-      }
-      break;
-
-    default:
-      error ("invalid meta.package indexing");
-      break;
-    }
-
-  return retval;
-}
-
-void
-cdef_package::cdef_package_rep::meta_release (void)
-{
-  // FIXME: Do we really want to unregister the package, as it
-  //        could still be referenced by classes or sub-packages?
-  //        If the package object is recreated later on, it won't
-  //        match the one already referenced by those classes or
-  //        sub-packages.
-
-  cdef_manager& cdm
-    = octave::__get_cdef_manager__ ("cdef_package::cdef_package_rep::meta_release");
-
-  // Don't delete the "meta" package.
-  if (this != cdm.meta ().get_rep ())
-    cdm.unregister_package (wrap ());
-}
-
-//----------------------------------------------------------------------------
-
-cdef_manager::cdef_manager (octave::interpreter& interp)
-  : m_interpreter (interp), m_all_classes (), m_all_packages (),
-    m_meta_class (), m_meta_property (), m_meta_method (),
-    m_meta_package (), m_meta ()
-{
-  octave::type_info& ti = m_interpreter.get_type_info ();
-
-  octave_classdef::register_type (ti);
-
-  // bootstrap
-  cdef_class tmp_handle = make_class ("handle");
-
-  m_meta_class = make_meta_class ("meta.class", tmp_handle);
-
-  tmp_handle.set_class (m_meta_class);
-  m_meta_class.set_class (m_meta_class);
-
-  // meta classes
-  m_meta_property = make_meta_class ("meta.property", tmp_handle);
-
-  m_meta_method = make_meta_class ("meta.method", tmp_handle);
-
-  m_meta_package = make_meta_class ("meta.package", tmp_handle);
-
-  cdef_class tmp_meta_event
-    = make_meta_class ("meta.event", tmp_handle);
-
-  cdef_class tmp_meta_dynproperty
-    = make_meta_class ("meta.dynamicproperty", tmp_handle);
-
-  // meta.class properties
-  m_meta_class.install_property
-    (make_attribute (m_meta_class, "Abstract"));
-
-  m_meta_class.install_property
-    (make_attribute (m_meta_class, "ConstructOnLoad"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "ContainingPackage"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "Description"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "DetailedDescription"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "Events"));
-
-  m_meta_class.install_property
-    (make_attribute (m_meta_class, "HandleCompatible"));
-
-  m_meta_class.install_property
-    (make_attribute (m_meta_class, "Hidden"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "InferiorClasses",
-                    make_fcn_handle (class_get_inferiorclasses,
-                                     "meta.class>get.InferiorClasses"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "Methods",
-                    make_fcn_handle (class_get_methods,
-                                     "meta.class>get.Methods"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "MethodList",
-                     make_fcn_handle (class_get_methods,
-                                      "meta.class>get.MethodList"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property (make_attribute (m_meta_class, "Name"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "Properties",
-                    make_fcn_handle (class_get_properties,
-                                     "meta.class>get.Properties"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "PropertyList",
-                    make_fcn_handle (class_get_properties,
-                                     "meta.class>get.PropertyList"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property (make_attribute (m_meta_class, "Sealed"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "SuperClasses",
-                    make_fcn_handle (class_get_superclasses,
-                                     "meta.class>get.SuperClasses"),
-                    "public", Matrix (), "private"));
-
-  m_meta_class.install_property
-    (make_property (m_meta_class, "SuperClassList",
-                    make_fcn_handle (class_get_superclasses,
-                                     "meta.class>get.SuperClassList"),
-                    "public", Matrix (), "private"));
-
-  // meta.class methods
-  m_meta_class.install_method
-    (make_method (m_meta_class, "fromName", class_fromName, "public", true));
-
-  m_meta_class.install_method
-    (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public",
-                  false));
-
-  m_meta_class.install_method
-    (make_method (m_meta_class, "getConstant", class_getConstant, "public",
-                  false));
-
-  m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq));
-  m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne));
-  m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt));
-  m_meta_class.install_method (make_method (m_meta_class, "le", class_le));
-  m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt));
-  m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge));
-
-  // meta.method properties
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Abstract"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Access"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "DefiningClass"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Description"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "DetailedDescription"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Hidden"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Name"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Sealed"));
-
-  m_meta_method.install_property
-    (make_attribute (m_meta_method, "Static"));
-
-  // meta.property properties
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Name"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Description"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "DetailedDescription"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Abstract"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Constant"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "GetAccess"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "SetAccess"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Dependent"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Transient"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "Hidden"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "GetObservable"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "SetObservable"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "GetMethod"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "SetMethod"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "DefiningClass"));
-
-  m_meta_property.install_property
-    (make_property (m_meta_property, "DefaultValue",
-                    make_fcn_handle (property_get_defaultvalue,
-                                     "meta.property>get.DefaultValue"),
-                    "public", Matrix (), "private"));
-
-  m_meta_property.install_property
-    (make_attribute (m_meta_property, "HasDefault"));
-
-  // meta.property events
-  // FIXME: add events
-
-  // handle methods
-
-  tmp_handle.install_method
-    (make_method (tmp_handle, "delete", handle_delete));
-
-  // meta.package properties
-
-  m_meta_package.install_property
-    (make_attribute (m_meta_package, "Name"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "ContainingPackage"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "ClassList",
-                    make_fcn_handle (package_get_classes,
-                                     "meta.package>get.ClassList"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "Classes",
-                    make_fcn_handle (package_get_classes,
-                                     "meta.package>get.Classes"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "FunctionList",
-                    make_fcn_handle (package_get_functions,
-                                     "meta.package>get.FunctionList"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "Functions",
-                    make_fcn_handle (package_get_functions,
-                                     "meta.package>get.Functions"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "PackageList",
-                      make_fcn_handle (package_get_packages,
-                                       "meta.package>get.PackageList"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_property
-    (make_property (m_meta_package, "Packages",
-                    make_fcn_handle (package_get_packages,
-                                     "meta.package>get.Packages"),
-                    "public", Matrix (), "private"));
-
-  m_meta_package.install_method
-    (make_method (m_meta_package, "fromName", package_fromName,
-                  "public", true));
-
-  m_meta_package.install_method
-    (make_method (m_meta_package, "getAllPackages", package_getAllPackages,
-                  "public", true));
-
-  // create "meta" package
-  cdef_package package_meta
-    = m_meta
-    = make_package ("meta");
-
-  package_meta.install_class (m_meta_class, "class");
-  package_meta.install_class (m_meta_property, "property");
-  package_meta.install_class (m_meta_method, "method");
-  package_meta.install_class (m_meta_package, "package");
-  package_meta.install_class (tmp_meta_event, "event");
-  package_meta.install_class (tmp_meta_dynproperty, "dynproperty");
-
-  octave::symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-  // install built-in classes into the symbol table
-  symtab.install_built_in_function
-    ("meta.class",
-     octave_value (m_meta_class.get_constructor_function ()));
-
-  symtab.install_built_in_function
-    ("meta.method",
-     octave_value (m_meta_method.get_constructor_function ()));
-
-  symtab.install_built_in_function
-    ("meta.property",
-     octave_value (m_meta_property.get_constructor_function ()));
-
-  symtab.install_built_in_function
-    ("meta.package",
-     octave_value (m_meta_package.get_constructor_function ()));
-
-// FIXME: meta.event and meta.dynproperty are not implemented
-//        and should not be installed into symbol table.
-
-//  symtab.install_built_in_function
-//    ("meta.event",
-//     octave_value (tmp_meta_event.get_constructor_function ()));
-
-//  symtab.install_built_in_function
-//    ("meta.dynproperty",
-//     octave_value (tmp_meta_dynproperty.get_constructor_function ()));
-}
-
-cdef_class
-cdef_manager::find_class (const std::string& name, bool error_if_not_found,
-                          bool load_if_not_found)
-{
-  auto it = m_all_classes.find (name);
-
-  if (it == m_all_classes.end ())
-    {
-      if (load_if_not_found)
-        {
-          octave_value ov_cls;
-
-          size_t pos = name.rfind ('.');
-
-          if (pos == std::string::npos)
-            {
-              octave::symbol_scope curr_scope
-                = m_interpreter.get_current_scope ();
-
-              ov_cls = curr_scope.find (name);
-            }
-          else
-            {
-              std::string pack_name = name.substr (0, pos);
-
-              cdef_package pack = find_package (pack_name, false, true);
-
-              if (pack.ok ())
-                ov_cls = pack.find (name.substr (pos+1));
-            }
-
-          if (ov_cls.is_defined ())
-            it = m_all_classes.find (name);
-        }
-    }
-
-  if (it == m_all_classes.end ())
-    {
-      if (error_if_not_found)
-        error ("class not found: %s", name.c_str ());
-    }
-  else
-    {
-      cdef_class cls = it->second;
-
-      if (! cls.is_builtin ())
-        cls = lookup_class (cls);
-
-      if (cls.ok ())
-        return cls;
-      else
-        m_all_classes.erase (it);
-    }
-
-  return cdef_class ();
-}
-
-octave_function *
-cdef_manager::find_method_symbol (const std::string& method_name,
-                                  const std::string& class_name)
-{
-  octave_function *retval = nullptr;
-
-  cdef_class cls = find_class (class_name, false, false);
-
-  if (cls.ok ())
-    {
-      cdef_method meth = cls.find_method (method_name);
-
-      if (meth.ok ())
-        retval = new octave_classdef_meta (meth);
-    }
-
-  return retval;
-}
-
-cdef_package
-cdef_manager::find_package (const std::string& name, bool error_if_not_found,
-                            bool load_if_not_found)
-{
-  cdef_package retval;
-
-  std::map<std::string, cdef_package>::const_iterator it
-    = m_all_packages.find (name);
-
-  if (it != m_all_packages.end ())
-    {
-      retval = it->second;
-
-      if (! retval.ok ())
-        error ("invalid package `%s'", name.c_str ());
-    }
-  else
-    {
-      octave::load_path& lp = m_interpreter.get_load_path ();
-
-      if (load_if_not_found && lp.find_package (name))
-        {
-          size_t pos = name.find ('.');
-
-          if (pos == std::string::npos)
-            retval = make_package (name, "");
-          else
-            {
-              std::string parent_name = name.substr (0, pos);
-
-              retval = make_package (name, parent_name);
-            }
-        }
-      else if (error_if_not_found)
-        error ("unknown package `%s'", name.c_str ());
-    }
-
-  return retval;
-}
-
-octave_function *
-cdef_manager::find_package_symbol (const std::string& pack_name)
-{
-  octave_function *retval = nullptr;
-
-  cdef_package pack = find_package (pack_name, false);
-
-  if (pack.ok ())
-    retval = new octave_classdef_meta (pack);
-
-  return retval;
-}
-
-//----------------------------------------------------------------------------
-
 DEFUN (__meta_get_package__, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} __meta_get_package__ ()
@@ -3935,36 +518,7 @@
 
   std::string cname = args(0).xstring_value ("PACKAGE_NAME must be a string");
 
-  return to_ov (lookup_package (cname));
-}
-
-DEFUN (__superclass_reference__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __superclass_reference__ ()
-Undocumented internal function.
-@end deftypefn */)
-{
-  return ovl (new octave_classdef_superclass_ref (args));
-}
-
-DEFUN (__meta_class_query__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __meta_class_query__ ()
-Undocumented internal function.
-@end deftypefn */)
-{
-#if DEBUG_TRACE
-  std::cerr << "__meta_class_query__ ("
-            << args(0).string_value () << ')'
-            << std::endl;
-#endif
-
-  if (args.length () != 1)
-    print_usage ();
-
-  std::string cls = args(0).xstring_value ("CLASS_NAME must be a string");
-
-  return to_ov (lookup_class (cls));
+  return octave::to_ov (octave::lookup_package (cname));
 }
 
 DEFUN (metaclass, args, ,
@@ -3976,9 +530,151 @@
   if (args.length () != 1)
     print_usage ();
 
-  cdef_object obj = to_cdef (args(0));
+  octave::cdef_object obj = octave::to_cdef (args(0));
+
+  return octave::to_ov (obj.get_class ());
+}
+
+// FIXME: What about dynamic properties if obj is a scalar, or the
+// properties of the class of obj if obj is an array?  Probably there
+// should be a function to do this job so that the DEFUN is just a
+// simple wrapper.
+
+DEFUN (properties, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {} properties (@var{class_name})
+@deftypefnx {} {} properties (@var{obj})
+@deftypefnx {} {@var{plist} =} properties (@dots{})
+Return or display the public properties for the named class
+@var{class_name} or classdef object @var{obj}.
+
+If an output value is requested, return the list of property names in a
+cell array.
+
+Programming Note: Property names are returned if the @code{GetAccess}
+attribute is public and if the @code{Hidden} attribute is false.
+@seealso{methods}
+@end deftypefn */)
+{
+  if (args.length () != 1)
+    print_usage ();
+
+  octave_value arg = args(0);
+
+  std::string class_name;
+
+  if (arg.isobject ())
+    class_name = arg.class_name ();
+  else if (arg.is_string ())
+    class_name = arg.string_value ();
+  else
+    err_wrong_type_arg ("properties", arg);
+
+  octave::cdef_class cls;
+
+  cls = octave::lookup_class (class_name, false, true);
+
+  if (! cls.ok ())
+    error ("invalid class: %s", class_name.c_str ());
+
+  std::map<std::string, octave::cdef_property> property_map = cls.get_property_map ();
+
+  std::list<std::string> property_names;
+
+  for (const auto& pname_prop : property_map)
+    {
+      // FIXME: this loop duplicates a significant portion of the loops
+      // in octave_classdef::print_raw.
+
+      const octave::cdef_property& prop = pname_prop.second;
+
+      std::string nm = prop.get_name ();
+
+      octave_value acc = prop.get ("GetAccess");
+
+      if (! acc.is_string () || acc.string_value () != "public")
+        continue;
+
+      octave_value hid = prop.get ("Hidden");
+
+      if (hid.bool_value ())
+        continue;
+
+      property_names.push_back (nm);
+    }
 
-  return to_ov (obj.get_class ());
+  if (nargout > 0)
+    return octave_value (Cell (string_vector (property_names)));
+
+  octave_stdout << "properties for class " << class_name << ":\n\n";
+
+  for (const auto& nm : property_names)
+    octave_stdout << "  " << nm << "\n";
+
+  octave_stdout << std::endl;
+
+  return octave_value ();
+}
+
+/*
+%!assert (properties ("inputParser"),
+%!        {"CaseSensitive"; "FunctionName"; "KeepUnmatched";
+%!         "Parameters"; "PartialMatching"; "Results";
+%!         "StructExpand"; "Unmatched"; "UsingDefaults"});
+*/
+
+// FIXME: Need to implement the -full option.
+
+DEFMETHOD (__methods__, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {} __methods__ (@var{x})
+@deftypefnx {} {} __methods__ ("classname")
+Internal function.
+
+Implements @code{methods} for Octave class objects and classnames.
+@seealso{methods}
+@end deftypefn */)
+{
+  // Input validation has already been done in methods.m.
+  octave_value arg = args(0);
+
+  std::string class_name;
+
+  if (arg.isobject ())
+    class_name = arg.class_name ();
+  else if (arg.is_string ())
+    class_name = arg.string_value ();
+  else
+    err_wrong_type_arg ("__methods__", arg);
+
+  string_vector sv;
+
+  octave::cdef_class cls = octave::lookup_class (class_name, false, true);
+
+  if (cls.ok ())
+    {
+      std::map<std::string, octave::cdef_method> method_map
+        = cls.get_method_map (false, true);
+
+      std::list<std::string> method_names;
+
+      for (const auto& nm_mthd : method_map)
+        {
+          std::string nm = nm_mthd.first;
+
+          method_names.push_back (nm);
+        }
+
+      sv = string_vector (method_names);
+    }
+
+  // The following will also find methods for legacy @CLASS objects.
+
+  octave::load_path& lp = interp.get_load_path ();
+
+  sv.append (lp.methods (class_name));
+
+  return ovl (Cell (sv));
 }
 
 /*
--- a/libinterp/octave-value/ov-classdef.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-classdef.h	Fri Jul 12 12:14:43 2019 -0400
@@ -25,1458 +25,29 @@
 
 #include "octave-config.h"
 
-#include <map>
-#include <set>
 #include <string>
 
-#include "oct-refcount.h"
-
-#include "oct-map.h"
+#include "cdef-object.h"
 #include "ov-base.h"
-#include "ov-builtin.h"
-
-class cdef_object;
-class cdef_class;
-class cdef_property;
-class cdef_method;
-class cdef_package;
+#include "ov-fcn.h"
 
 namespace octave
 {
+  class cdef_object;
   class interpreter;
-  class tree_classdef;
+  class tree_evaluator;
   class type_info;
 }
 
-// This is mainly a boostrap class to declare the expected interface.
-// The actual base class is cdef_class_base, which is declared after
-// cdef_object, such that it can contain cdef_object objects.
-class
-cdef_object_rep
-{
-public:
-  friend class cdef_object;
-
-public:
-
-  cdef_object_rep (void) : refcount (1)
-  { }
-
-  cdef_object_rep& operator = (const cdef_object_rep&) = delete;
-
-  virtual ~cdef_object_rep (void) = default;
-
-  virtual cdef_class get_class (void) const;
-
-  virtual void set_class (const cdef_class&)
-  { err_invalid_object ("set_class"); }
-
-  virtual cdef_object_rep * clone (void) const
-  {
-    err_invalid_object ("clone");
-  }
-
-  virtual cdef_object_rep * empty_clone (void) const
-  {
-    err_invalid_object ("empty_clone");
-  }
-
-  virtual cdef_object_rep * copy (void) const
-  {
-    err_invalid_object ("copy");
-  }
-
-  virtual cdef_object_rep * make_array (void) const
-  {
-    err_invalid_object ("make_array");
-  }
-
-  virtual bool is_array (void) const { return false; }
-
-  virtual bool is_value_object (void) const { return false; }
-
-  virtual bool is_handle_object (void) const { return false; }
-
-  virtual bool is_meta_object (void) const { return false; }
-
-  virtual Array<cdef_object> array_value (void) const
-  {
-    err_invalid_object ("array_value");
-  }
-
-  virtual void put (const std::string&, const octave_value&)
-  { err_invalid_object ("put"); }
-
-  virtual octave_value get (const std::string&) const
-  {
-    err_invalid_object ("get");
-  }
-
-  virtual void set_property (octave_idx_type, const std::string&,
-                             const octave_value&)
-  {
-    err_invalid_object ("set_property");
-  }
-
-  virtual octave_value get_property (octave_idx_type, const std::string&) const
-  {
-    err_invalid_object ("get_property");
-  }
-
-  virtual octave_value_list
-  subsref (const std::string&, const std::list<octave_value_list>&,
-           int, size_t&, const cdef_class&, bool)
-  {
-    err_invalid_object ("subsref");
-  }
-
-  virtual octave_value
-  subsasgn (const std::string&, const std::list<octave_value_list>&,
-            const octave_value&)
-  {
-    err_invalid_object ("subsasgn");
-  }
-
-  virtual string_vector map_keys (void) const;
-
-  virtual bool is_valid (void) const { return false; }
-
-  std::string class_name (void) const;
-
-  virtual void mark_for_construction (const cdef_class&)
-  {
-    err_invalid_object ("mark_for_construction");
-  }
-
-  virtual bool is_constructed_for (const cdef_class&) const
-  {
-    err_invalid_object ("is_constructed_for");
-  }
-
-  virtual bool is_partially_constructed_for (const cdef_class&) const
-  {
-    err_invalid_object ("is_partially_constructed_for");
-  }
-
-  virtual void mark_as_constructed (void)
-  {
-    err_invalid_object ("mark_as_constructed");
-  }
-
-  virtual void mark_as_constructed (const cdef_class&)
-  {
-    err_invalid_object ("mark_as_constructed");
-  }
-
-  virtual bool is_constructed (void) const
-  {
-    err_invalid_object ("is_constructed");
-  }
-
-  virtual octave_idx_type static_count (void) const { return 0; }
-
-  virtual void destroy (void) { delete this; }
-
-  void release (const cdef_object& obj);
-
-  virtual dim_vector dims (void) const { return dim_vector (); }
-
-protected:
-
-  // Reference count
-  octave::refcount<octave_idx_type> refcount;
-
-protected:
-
-  // Restricted copying.
-
-  cdef_object_rep (const cdef_object_rep&)
-    : refcount (1)
-  { }
-
-private:
-
-  OCTAVE_NORETURN void err_invalid_object (const char *who) const
-  { error ("%s: invalid object", who); }
-};
-
-class
-cdef_object
-{
-public:
-  // FIXME: use a null object
-  cdef_object (void)
-    : rep (new cdef_object_rep ()) { }
-
-  cdef_object (const cdef_object& obj)
-    : rep (obj.rep) { rep->refcount++; }
-
-  cdef_object (cdef_object_rep *r)
-    : rep (r) { }
-
-  virtual ~cdef_object (void)
-  {
-    rep->release (*this);
-  }
-
-  cdef_object& operator = (const cdef_object& obj)
-  {
-    if (rep != obj.rep)
-      {
-        rep->release (*this);
-
-        rep = obj.rep;
-        rep->refcount++;
-      }
-
-    return *this;
-  }
-
-  cdef_class get_class (void) const;
-
-  void set_class (const cdef_class& cls) { rep->set_class (cls); }
-
-  std::string class_name (void) const
-  { return rep->class_name (); }
-
-  cdef_object clone (void) const
-  { return cdef_object (rep->clone ()); }
-
-  cdef_object empty_clone (void) const
-  { return cdef_object (rep->empty_clone ()); }
-
-  dim_vector dims (void) const { return rep->dims (); }
-
-  cdef_object make_array (void) const
-  { return cdef_object (rep->make_array ()); }
-
-  cdef_object copy (void) const
-  { return cdef_object (rep->copy ()); }
-
-  bool is_array (void) const { return rep->is_array (); }
-
-  bool is_value_object (void) const { return rep->is_value_object (); }
-
-  bool is_handle_object (void) const { return rep->is_handle_object (); }
-
-  bool is_meta_object (void) const { return rep->is_meta_object (); }
-
-  Array<cdef_object> array_value (void) const { return rep->array_value (); }
-
-  void put (const std::string& pname, const octave_value& val)
-  { rep->put (pname, val); }
-
-  octave_value get (const std::string& pname) const
-  { return rep->get (pname); }
-
-  void set_property (octave_idx_type idx, const std::string& pname,
-                     const octave_value& pval)
-  { return rep->set_property (idx, pname, pval); }
-
-  octave_value
-  get_property (octave_idx_type idx, const std::string& pname) const
-  { return rep->get_property (idx, pname); }
-
-  octave_value_list
-  subsref (const std::string& type, const std::list<octave_value_list>& idx,
-           int nargout, size_t& skip, const cdef_class& context,
-           bool auto_add = false)
-  { return rep->subsref (type, idx, nargout, skip, context, auto_add); }
-
-  octave_value
-  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
-            const octave_value& rhs, int ignore_copies = 0)
-  {
-    make_unique (ignore_copies);
-    return rep->subsasgn (type, idx, rhs);
-  }
-
-  string_vector map_keys (void) const { return rep->map_keys (); }
-
-  octave_map map_value (void) const;
-
-  const cdef_object_rep * get_rep (void) const { return rep; }
-
-  bool ok (void) const { return rep->is_valid (); }
-
-  void mark_for_construction (const cdef_class& cls)
-  { rep->mark_for_construction (cls); }
-
-  bool is_constructed (void) const { return rep->is_constructed (); }
-
-  bool is_constructed_for (const cdef_class& cls) const
-  { return rep->is_constructed_for (cls); }
-
-  bool is_partially_constructed_for (const cdef_class& cls) const
-  { return rep->is_partially_constructed_for (cls); }
-
-  void mark_as_constructed (void) { rep->mark_as_constructed (); }
-
-  void mark_as_constructed (const cdef_class& cls)
-  { rep->mark_as_constructed (cls); }
-
-  bool is (const cdef_object& obj) const { return rep == obj.rep; }
-
-protected:
-  cdef_object_rep * get_rep (void) { return rep; }
-
-  void make_unique (int ignore_copies)
-  {
-    if (rep->refcount > ignore_copies + 1)
-      *this = clone ();
-  }
-
-private:
-  cdef_object_rep *rep;
-};
-
-class
-cdef_object_base : public cdef_object_rep
-{
-public:
-  cdef_object_base (void)
-    : cdef_object_rep (), klass ()
-  {
-    register_object ();
-  }
-
-  cdef_object_base& operator = (const cdef_object_base&) = delete;
-
-  ~cdef_object_base (void) { unregister_object (); }
-
-  cdef_class get_class (void) const;
-
-  void set_class (const cdef_class& cls);
-
-  cdef_object_rep * empty_clone (void) const
-  { return new cdef_object_base (*this); }
-
-  cdef_object_rep * make_array (void) const;
-
-protected:
-  // Restricted copying!
-  cdef_object_base (const cdef_object_base& obj)
-    : cdef_object_rep (obj), klass (obj.klass)
-  {
-    register_object ();
-  }
-
-private:
-  void register_object (void);
-
-  void unregister_object (void);
-
-  // The class of the object
-  cdef_object klass;
-};
-
-class
-cdef_object_array : public cdef_object_base
-{
-public:
-  cdef_object_array (void) : cdef_object_base () { }
-
-  cdef_object_array (const Array<cdef_object>& a)
-    : cdef_object_base (), array (a) { }
-
-  cdef_object_array& operator = (const cdef_object_array&) = delete;
-
-  ~cdef_object_array (void) = default;
-
-  cdef_object_rep * clone (void) const
-  { return new cdef_object_array (*this); }
-
-  dim_vector dims (void) const { return array.dims (); }
-
-  bool is_valid (void) const { return true; }
-
-  bool is_array (void) const { return true; }
-
-  Array<cdef_object> array_value (void) const { return array; }
-
-  octave_value_list
-  subsref (const std::string& type, const std::list<octave_value_list>& idx,
-           int nargout, size_t& skip, const cdef_class& context,
-           bool auto_add);
-
-  octave_value
-  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
-            const octave_value& rhs);
-
-  void set_property (octave_idx_type idx, const std::string& pname,
-                     const octave_value& pval)
-  {
-    cdef_object& tmp = array.elem (idx);
-
-    return tmp.put (pname, pval);
-  }
-
-  octave_value
-  get_property (octave_idx_type idx, const std::string& pname) const
-  {
-    cdef_object tmp = array.elem (idx);
-
-    return tmp.get (pname);
-  }
-
-private:
-  Array<cdef_object> array;
-
-  void fill_empty_values (void) { fill_empty_values (array); }
-
-  void fill_empty_values (Array<cdef_object>& arr);
-
-  // Private copying!
-  cdef_object_array (const cdef_object_array& obj)
-    : cdef_object_base (obj), array (obj.array) { }
-};
-
-class
-cdef_object_scalar : public cdef_object_base
-{
-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); }
-
-  void put (const std::string& pname, const octave_value& val)
-  { map.assign (pname, val); }
-
-  octave_value get (const std::string& pname) const
-  {
-    Cell val = map.contents (pname);
-
-    if (val.numel () < 1)
-      error ("get: unknown slot: %s", pname.c_str ());
-
-    return val(0, 0);
-  }
-
-  void set_property (octave_idx_type idx, const std::string& pname,
-                     const octave_value& pval)
-  {
-    if (idx != 0)
-      error ("invalid index");  // FIXME
-
-    put (pname, pval);
-  }
-
-  octave_value
-  get_property (octave_idx_type idx, const std::string& pname) const
-  {
-    if (idx != 0)
-      error ("invalid index");  // FIXME
-
-    return get (pname);
-  }
-
-  octave_value_list
-  subsref (const std::string& type, const std::list<octave_value_list>& idx,
-           int nargout, size_t& skip, const cdef_class& context,
-           bool auto_add);
-
-  octave_value
-  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
-            const octave_value& rhs);
-
-  void mark_for_construction (const cdef_class&);
-
-  bool is_constructed_for (const cdef_class& cls) const;
-
-  bool is_partially_constructed_for (const cdef_class& cls) const;
-
-  void mark_as_constructed (void) { ctor_list.clear (); }
-
-  void mark_as_constructed (const cdef_class& cls);
-
-  bool is_constructed (void) const { return ctor_list.empty (); }
-
-protected:
-  // Object property values
-  octave_scalar_map map;
-
-  // Internal/temporary structure used during object construction
-  std::map< cdef_class, std::list<cdef_class>> ctor_list;
-
-protected:
-  // Restricted object copying!
-  cdef_object_scalar (const cdef_object_scalar& obj)
-    : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { }
-};
-
-class
-handle_cdef_object : public cdef_object_scalar
-{
-public:
-  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
-  {
-    handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
-    obj->refcount++;
-    return obj;
-  }
-
-  cdef_object_rep * copy (void) const
-  { return new handle_cdef_object (*this); }
-
-  bool is_valid (void) const { return true; }
-
-  bool is_handle_object (void) const { return true; }
-
-protected:
-  // Restricted copying!
-  handle_cdef_object (const handle_cdef_object& obj)
-    : cdef_object_scalar (obj) { }
-};
-
-class
-value_cdef_object : public cdef_object_scalar
-{
-public:
-  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
-  { return new value_cdef_object (*this); }
-
-  cdef_object_rep * copy (void) const { return clone (); }
-
-  bool is_valid (void) const { return true; }
-
-  bool is_value_object (void) const { return true; }
-
-private:
-  // Private copying!
-  value_cdef_object (const value_cdef_object& obj)
-    : cdef_object_scalar (obj) { }
-};
-
-class
-cdef_meta_object_rep : public handle_cdef_object
-{
-public:
-  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
-  { return new cdef_meta_object_rep (*this); }
-
-  bool is_meta_object (void) const { return true; }
-
-  virtual bool is_class (void) const { return false; }
-
-  virtual bool is_property (void) const { return false; }
-
-  virtual bool is_method (void) const { return false; }
-
-  virtual bool is_package (void) const { return false; }
-
-  virtual octave_value_list
-  meta_subsref (const std::string& /* type */,
-                const std::list<octave_value_list>& /* idx */,
-                int /* nargout */)
-  {
-    error ("subsref: invalid meta object");
-  }
-
-  virtual void meta_release (void) { }
-
-  virtual bool meta_accepts_postfix_index (char /* type */) const
-  { return false; }
-
-protected:
-  // Restricted copying!
-  cdef_meta_object_rep (const cdef_meta_object_rep& obj)
-    : handle_cdef_object (obj) { }
-};
-
-class
-cdef_meta_object : public cdef_object
-{
-public:
-  cdef_meta_object (void)
-    : cdef_object () { }
-
-  // Object consistency is checked in sub-classes.
-  cdef_meta_object (const cdef_meta_object& obj)
-    : cdef_object (obj) { }
-
-  cdef_meta_object (cdef_meta_object_rep *r)
-    : cdef_object (r) { }
-
-  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 (); }
-
-  bool is_property (void) const { return get_rep ()->is_property (); }
-
-  bool is_method (void) const { return get_rep ()->is_method (); }
-
-  bool is_package (void) const { return get_rep ()->is_package (); }
-
-  octave_value_list
-  meta_subsref (const std::string& type,
-                const std::list<octave_value_list>& idx, int nargout)
-  { return get_rep ()->meta_subsref (type, idx, nargout); }
-
-  void meta_release (void) { get_rep ()->meta_release (); }
-
-  bool meta_accepts_postfix_index (char type) const
-  { return get_rep ()->meta_accepts_postfix_index (type); }
-
-private:
-  cdef_meta_object_rep * get_rep (void)
-  { return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ()); }
-
-  const cdef_meta_object_rep * get_rep (void) const
-  { return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ()); }
-};
-
-class
-cdef_class : public cdef_meta_object
-{
-private:
-
-  class
-  cdef_class_rep : public cdef_meta_object_rep
-  {
-  public:
-    cdef_class_rep (void)
-      : cdef_meta_object_rep (), member_count (0), handle_class (false),
-        object_count (0), meta (false)
-    { }
-
-    cdef_class_rep (const std::list<cdef_class>& superclasses);
-
-    cdef_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; }
-
-    std::string get_name (void) const
-    { return get ("Name").string_value (); }
-
-    void set_name (const std::string& nm) { put ("Name", nm); }
-
-    bool is_abstract (void) const { return get ("Abstract").bool_value (); }
-
-    bool is_sealed (void) const { return get ("Sealed").bool_value (); }
-
-    cdef_method find_method (const std::string& nm, bool local = false);
-
-    void install_method (const cdef_method& meth);
-
-    Cell get_methods (void);
-
-    cdef_property find_property (const std::string& nm);
-
-    void install_property (const cdef_property& prop);
-
-    Cell get_properties (int mode);
-
-    std::map<std::string, cdef_property> get_property_map (int mode);
-
-    string_vector get_names (void);
-
-    void set_directory (const std::string& dir) { directory = dir; }
-
-    std::string get_directory (void) const { return directory; }
-
-    void delete_object (const cdef_object& obj);
-
-    octave_value_list
-    meta_subsref (const std::string& type,
-                  const std::list<octave_value_list>& idx, int nargout);
-
-    void meta_release (void);
-
-    bool meta_accepts_postfix_index (char type) const
-    { return (type == '(' || type == '.'); }
-
-    octave_value construct (const octave_value_list& args);
-
-    cdef_object construct_object (const octave_value_list& args);
-
-    void initialize_object (cdef_object& obj);
-
-    void run_constructor (cdef_object& obj, const octave_value_list& args);
-
-    void mark_as_handle_class (void) { handle_class = true; }
-
-    bool is_handle_class (void) const { return handle_class; }
-
-    void register_object (void) { object_count++; }
-
-    void unregister_object (void) { object_count--; }
-
-    octave_idx_type static_count (void) const { return member_count; }
-
-    void destroy (void)
-    {
-      if (member_count)
-        {
-          refcount++;
-          cdef_class lock (this);
-
-          member_count = 0;
-          method_map.clear ();
-          property_map.clear ();
-        }
-      else
-        delete this;
-    }
-
-    void mark_as_meta_class (void) { meta = true; }
-
-    bool is_meta_class (void) const { return meta; }
-
-  private:
-
-    void load_all_methods (void);
-
-    void find_names (std::set<std::string>& names, bool all);
-
-    void find_properties (std::map<std::string,cdef_property>& props,
-                          int mode = 0);
-
-    void find_methods (std::map<std::string, cdef_method>& meths,
-                       bool only_inherited);
-
-    cdef_class wrap (void)
-    {
-      refcount++;
-      return cdef_class (this);
-    }
-
-    // The @-directory were this class is loaded from.
-    // (not used yet)
-    std::string directory;
-
-    // The methods defined by this class.
-    std::map<std::string,cdef_method> method_map;
-
-    // The properties defined by this class.
-    std::map<std::string,cdef_property> property_map;
-
-    // The number of members in this class (methods, properties...)
-    octave_idx_type member_count;
-
-    // TRUE if this class is a handle class.  A class is a handle
-    // class when the abstract "handle" class is one of its superclasses.
-    bool handle_class;
-
-    // The list of super-class constructors that are called implicitly by the
-    // the classdef engine when creating an object.  These constructors are not
-    // called explicitly by the class constructor.
-    std::list<cdef_class> implicit_ctor_list;
-
-    // The number of objects of this class.
-    octave::refcount<octave_idx_type> object_count;
-
-    // TRUE if this class is a built-in meta class.
-    bool meta;
-
-    // Utility iterator typedef's.
-    typedef std::map<std::string,cdef_method>::iterator method_iterator;
-    typedef std::map<std::string,cdef_method>::const_iterator method_const_iterator;
-    typedef std::map<std::string,cdef_property>::iterator property_iterator;
-    typedef std::map<std::string,cdef_property>::const_iterator property_const_iterator;
-
-    cdef_class_rep (const cdef_class_rep& c)
-      : cdef_meta_object_rep (c), directory (c.directory),
-        method_map (c.method_map), property_map (c.property_map),
-        member_count (c.member_count), handle_class (c.handle_class),
-        implicit_ctor_list (c.implicit_ctor_list),
-        object_count (c.object_count), meta (c.meta) { }
-  };
-
-public:
-  // Create and invalid class object
-  cdef_class (void)
-    : cdef_meta_object () { }
-
-  cdef_class (const std::string& nm, const std::list<cdef_class>& superclasses)
-    : cdef_meta_object (new cdef_class_rep (superclasses))
-  { get_rep ()->set_name (nm); }
-
-  cdef_class (const cdef_class& cls)
-    : cdef_meta_object (cls) { }
-
-  cdef_class (const cdef_object& obj)
-    : cdef_meta_object (obj)
-  {
-    // This should never happen...
-    if (! is_class ())
-      error ("internal error: invalid assignment from %s to meta.class object",
-             class_name ().c_str ());
-  }
-
-  cdef_class& operator = (const cdef_class& cls)
-  {
-    cdef_object::operator = (cls);
-
-    return *this;
-  }
-
-  ~cdef_class (void) = default;
-
-  cdef_method find_method (const std::string& nm, bool local = false);
-
-  void install_method (const cdef_method& meth)
-  { get_rep ()->install_method (meth); }
-
-  Cell get_methods (void) { return get_rep ()->get_methods (); }
-
-  cdef_property find_property (const std::string& nm);
-
-  void install_property (const cdef_property& prop)
-  { get_rep ()->install_property (prop); }
-
-  Cell get_properties (int mode = property_normal)
-  { return get_rep ()->get_properties (mode); }
-
-  std::map<std::string, cdef_property>
-  get_property_map (int mode = property_normal)
-  { return get_rep ()->get_property_map (mode); }
-
-  string_vector get_names (void) { return get_rep ()->get_names (); }
-
-  bool is_abstract (void) const { return get_rep ()->is_abstract (); }
-
-  bool is_sealed (void) const { return get_rep ()->is_sealed (); }
-
-  void set_directory (const std::string& dir)
-  { get_rep ()->set_directory (dir); }
-
-  std::string get_directory (void) const
-  { return get_rep ()->get_directory (); }
-
-  std::string get_name (void) const
-  { return get_rep ()->get_name (); }
-
-  bool is_builtin (void) const
-  { return get_directory ().empty (); }
-
-  void delete_object (const cdef_object& obj)
-  { get_rep ()->delete_object (obj); }
-
-  //! Analyze the tree_classdef tree and transform it to a cdef_class
-  //!
-  //! <b>All attribute validation should occur here.</b>
-  //!
-  //! Classdef attribute values can be given in the form of
-  //! expressions.  These expressions must be evaluated before
-  //! assigning them as attribute values.  Evaluating them as they are
-  //! parsed causes trouble with possible recusion in the parser so we
-  //! do it here.  For example
-  //!
-  //! @code
-  //! classdef recursion_class
-  //!   methods (Access = ?recursion_class)
-  //!   endmethods
-  //! endclassdef
-  //! @endcode
-  //!
-  //! will fail because each attempt to compute the metaclass of
-  //! recursion_class will cause recursion_class to be parsed again.
-
-  static cdef_class
-  make_meta_class (octave::interpreter& interp, octave::tree_classdef *t,
-                   bool is_at_folder = false);
-
-  octave_function * get_method_function (const std::string& nm);
-
-  octave_function * get_constructor_function (void)
-  { return get_method_function (get_name ()); }
-
-  octave_value construct (const octave_value_list& args)
-  { return get_rep ()->construct (args); }
-
-  cdef_object construct_object (const octave_value_list& args)
-  { return get_rep ()->construct_object (args); }
-
-  void initialize_object (cdef_object& obj)
-  { get_rep ()->initialize_object (obj); }
-
-  void run_constructor (cdef_object& obj, const octave_value_list& args)
-  { get_rep ()->run_constructor (obj, args); }
-
-  void mark_as_handle_class (void)
-  { get_rep ()->mark_as_handle_class (); }
-
-  bool is_handle_class (void) const
-  { return get_rep ()->is_handle_class (); }
-
-  void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); }
-
-  bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
-
-  void register_object (void) { get_rep ()->register_object (); }
-
-  void unregister_object (void) { get_rep ()->unregister_object (); }
-
-public:
-  enum
-  {
-    property_normal,
-    property_inherited,
-    property_all
-  };
-
-private:
-  cdef_class_rep * get_rep (void)
-  { return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ()); }
-
-  const cdef_class_rep * get_rep (void) const
-  { return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ()); }
-
-  friend bool operator == (const cdef_class&, const cdef_class&);
-  friend bool operator != (const cdef_class&, const cdef_class&);
-  friend bool operator < (const cdef_class&, const cdef_class&);
-
-  friend void install_classdef (octave::interpreter& interp);
-};
-
-inline bool
-operator == (const cdef_class& clsa, const cdef_class& clsb)
-// FIXME: is this really the right way to check class equality?
-{ return (clsa.get_rep () == clsb.get_rep ()); }
-
-inline bool
-operator != (const cdef_class& clsa, const cdef_class& clsb)
-{ return ! (clsa == clsb); }
-
-// This is only to be able to use cdef_class as map keys.
-inline bool
-operator < (const cdef_class& clsa, const cdef_class& clsb)
-{ return clsa.get_rep () < clsb.get_rep (); }
-
-class
-cdef_property : public cdef_meta_object
-{
-  friend class cdef_class;
-
-private:
-
-  class
-  cdef_property_rep : public cdef_meta_object_rep
-  {
-  public:
-    cdef_property_rep (void)
-      : cdef_meta_object_rep () { }
-
-    cdef_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; }
-
-    std::string get_name (void) const { return get("Name").string_value (); }
-
-    void set_name (const std::string& nm) { put ("Name", nm); }
-
-    bool is_constant (void) const { return get("Constant").bool_value (); }
-
-    octave_value get_value (bool do_check_access = true,
-                            const std::string& who = "");
-
-    octave_value get_value (const cdef_object& obj,
-                            bool do_check_access = true,
-                            const std::string& who = "");
-
-    void set_value (cdef_object& obj, const octave_value& val,
-                    bool do_check_access = true,
-                    const std::string& who = "");
-
-    bool check_get_access (void) const;
-
-    bool check_set_access (void) const;
-
-  private:
-    cdef_property_rep (const cdef_property_rep& p)
-      : cdef_meta_object_rep (p) { }
-
-    bool is_recursive_set (const cdef_object& obj) const;
-
-    cdef_property wrap (void)
-    {
-      refcount++;
-      return cdef_property (this);
-    }
-  };
-
-public:
-  cdef_property (void) : cdef_meta_object () { }
-
-  cdef_property (const std::string& nm)
-    : cdef_meta_object (new cdef_property_rep ())
-  { get_rep ()->set_name (nm); }
-
-  cdef_property (const cdef_property& prop)
-    : cdef_meta_object (prop) { }
-
-  cdef_property (const cdef_object& obj)
-    : cdef_meta_object (obj)
-  {
-    // This should never happen...
-    if (! is_property ())
-      error ("internal error: invalid assignment from %s to meta.property object",
-             class_name ().c_str ());
-  }
-
-  cdef_property& operator = (const cdef_property& prop)
-  {
-    cdef_object::operator = (prop);
-
-    return *this;
-  }
-
-  ~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); }
-
-  octave_value get_value (bool do_check_access = true,
-                          const std::string& who = "")
-  { return get_rep ()->get_value (do_check_access, who); }
-
-  void set_value (cdef_object& obj, const octave_value& val,
-                  bool do_check_access = true,
-                  const std::string& who = "")
-  { get_rep ()->set_value (obj, val, do_check_access, who); }
-
-  bool check_get_access (void) const
-  { return get_rep ()->check_get_access (); }
-
-  bool check_set_access (void) const
-  { return get_rep ()->check_set_access (); }
-
-  std::string get_name (void) const { return get_rep ()->get_name (); }
-
-  bool is_constant (void) const { return get_rep ()->is_constant (); }
-
-private:
-  cdef_property_rep * get_rep (void)
-  { return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ()); }
-
-  const cdef_property_rep * get_rep (void) const
-  { return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ()); }
-};
-
-class
-cdef_method : public cdef_meta_object
-{
-  friend class cdef_class;
-
-private:
-
-  class
-  cdef_method_rep : public cdef_meta_object_rep
-  {
-  public:
-    cdef_method_rep (void)
-      : cdef_meta_object_rep (), function (), dispatch_type ()
-    { }
-
-    cdef_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; }
-
-    std::string get_name (void) const { return get("Name").string_value (); }
-
-    void set_name (const std::string& nm) { put ("Name", nm); }
-
-    bool is_static (void) const { return get("Static").bool_value (); }
-
-    octave_value get_function (void) const { return function; }
-
-    void set_function (const octave_value& fcn) { function = fcn; }
-
-    bool check_access (void) const;
-
-    bool is_external (void) const { return ! dispatch_type.empty (); }
-
-    void mark_as_external (const std::string& dtype)
-    { dispatch_type = dtype; }
-
-    octave_value_list execute (const octave_value_list& args, int nargout,
-                               bool do_check_access = true,
-                               const std::string& who = "");
-
-    octave_value_list execute (const cdef_object& obj,
-                               const octave_value_list& args, int nargout,
-                               bool do_check_access = true,
-                               const std::string& who = "");
-
-    bool is_constructor (void) const;
-
-    octave_value_list
-    meta_subsref (const std::string& type,
-                  const std::list<octave_value_list>& idx, int nargout);
-
-    bool meta_accepts_postfix_index (char type) const
-    { return (type == '(' || type == '.'); }
-
-  private:
-    cdef_method_rep (const cdef_method_rep& m)
-      : cdef_meta_object_rep (m), function (m.function),
-        dispatch_type (m.dispatch_type)
-    { }
-
-    void check_method (void);
-
-    cdef_method wrap (void)
-    {
-      refcount++;
-      return cdef_method (this);
-    }
-
-    octave_value function;
-
-    // When non-empty, the method is externally defined and this member
-    // is used to cache the dispatch type to look for the method.
-    std::string dispatch_type;
-  };
-
-public:
-  cdef_method (void) : cdef_meta_object () { }
-
-  cdef_method (const std::string& nm)
-    : cdef_meta_object (new cdef_method_rep ())
-  { get_rep ()->set_name (nm); }
-
-  cdef_method (const cdef_method& meth)
-    : cdef_meta_object (meth) { }
-
-  cdef_method (const cdef_object& obj)
-    : cdef_meta_object (obj)
-  {
-    // This should never happen...
-    if (! is_method ())
-      error ("internal error: invalid assignment from %s to meta.method object",
-             class_name ().c_str ());
-  }
-
-  cdef_method& operator = (const cdef_method& meth)
-  {
-    cdef_object::operator = (meth);
-
-    return *this;
-  }
-
-  ~cdef_method (void) = default;
-
-  // normal invocation
-  octave_value_list execute (const octave_value_list& args, int nargout,
-                             bool do_check_access = true,
-                             const std::string& who = "")
-  { return get_rep ()->execute (args, nargout, do_check_access, who); }
-
-  // dot-invocation: object is pushed as 1st argument
-  octave_value_list execute (const cdef_object& obj,
-                             const octave_value_list& args, int nargout,
-                             bool do_check_access = true,
-                             const std::string& who = "")
-  { return get_rep ()->execute (obj, args, nargout, do_check_access, who); }
-
-  bool check_access (void) const { return get_rep ()->check_access (); }
-
-  std::string get_name (void) const { return get_rep ()->get_name (); }
-
-  bool is_static (void) const { return get_rep ()->is_static (); }
-
-  void set_function (const octave_value& fcn)
-  { get_rep ()->set_function (fcn); }
-
-  octave_value get_function (void) const
-  { return get_rep ()->get_function (); }
-
-  bool is_constructor (void) const
-  { return get_rep ()->is_constructor (); }
-
-  bool is_external (void) const { return get_rep ()->is_external (); }
-
-  void mark_as_external (const std::string& dtype)
-  { get_rep ()->mark_as_external (dtype); }
-
-private:
-  cdef_method_rep * get_rep (void)
-  { return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ()); }
-
-  const cdef_method_rep * get_rep (void) const
-  { return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ()); }
-};
-
-inline cdef_class
-cdef_object_rep::get_class (void) const
-{
-  err_invalid_object ("get_class");
-}
-
-inline std::string
-cdef_object_rep::class_name (void) const
-{ return get_class ().get_name (); }
-
-inline cdef_class
-cdef_object::get_class (void) const
-{ return rep->get_class (); }
-
-inline cdef_class
-cdef_object_base::get_class (void) const
-{ return cdef_class (klass); }
-
-inline void
-cdef_object_base::set_class (const cdef_class& cls)
-{
-  if ((klass.ok () && cls.ok () && cls != get_class ())
-      || (klass.ok () && ! cls.ok ())
-      || (! klass.ok () && cls.ok ()))
-    {
-      unregister_object ();
-      klass = cls;
-      register_object ();
-    }
-}
-
-inline void
-cdef_object_base::register_object (void)
-{
-  if (klass.ok ())
-    {
-      cdef_class cls (get_class ());
-
-      if (cls.ok ())
-        cls.register_object ();
-    }
-}
-
-inline void
-cdef_object_base::unregister_object (void)
-{
-  if (klass.ok ())
-    {
-      cdef_class cls (get_class ());
-
-      if (cls.ok ())
-        cls.unregister_object ();
-    }
-}
-
-inline cdef_object_rep*
-cdef_object_base::make_array (void) const
-{
-  cdef_object_rep *r = new cdef_object_array ();
-
-  r->set_class (get_class ());
-
-  return r;
-}
-
-inline cdef_method
-cdef_class::find_method (const std::string& nm, bool local)
-{ return get_rep ()->find_method (nm, local); }
-
-inline cdef_property
-cdef_class::find_property (const std::string& nm)
-{ return get_rep ()->find_property (nm); }
-
-class
-cdef_package : public cdef_meta_object
-{
-  friend class cdef_class;
-
-private:
-
-  class
-  cdef_package_rep : public cdef_meta_object_rep
-  {
-  public:
-    cdef_package_rep (void)
-      : cdef_meta_object_rep (), member_count (0) { }
-
-    cdef_package_rep& operator = (const cdef_package_rep&) = delete;
-
-    ~cdef_package_rep (void) = default;
-
-    cdef_object_rep * copy (void) const { return new cdef_package_rep (*this); }
-
-    bool is_package (void) const { return true; }
-
-    std::string get_name (void) const { return get("Name").string_value (); }
-
-    void set_name (const std::string& nm) { put ("Name", nm); }
-
-    void install_class (const cdef_class& cls, const std::string& nm);
-
-    void install_function (const octave_value& fcn, const std::string& nm);
-
-    void install_package (const cdef_package& pack, const std::string& nm);
-
-    Cell get_classes (void) const;
-
-    Cell get_functions (void) const;
-
-    Cell get_packages (void) const;
-
-    octave_idx_type static_count (void) const { return member_count; }
-
-    void destroy (void)
-    {
-      if (member_count)
-        {
-          refcount++;
-          cdef_package lock (this);
-
-          member_count = 0;
-          class_map.clear ();
-          package_map.clear ();
-        }
-      else
-        delete this;
-    }
-
-    octave_value_list
-    meta_subsref (const std::string& type,
-                  const std::list<octave_value_list>& idx, int nargout);
-
-    void meta_release (void);
-
-    bool meta_accepts_postfix_index (char type) const
-    { return (type == '.'); }
-
-    octave_value find (const std::string& nm);
-
-  private:
-    std::string full_name;
-    std::map<std::string, cdef_class> class_map;
-    std::map<std::string, octave_value> function_map;
-    std::map<std::string, cdef_package> package_map;
-
-    // The number of registered members in this package (classes, packages).
-    // This only accounts for the members that back-reference to this package.
-    octave_idx_type member_count;
-
-    typedef std::map<std::string, cdef_class>::iterator class_iterator;
-    typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
-    typedef std::map<std::string, octave_value>::iterator function_iterator;
-    typedef std::map<std::string, octave_value>::const_iterator function_const_iterator;
-    typedef std::map<std::string, cdef_package>::iterator package_iterator;
-    typedef std::map<std::string, cdef_package>::const_iterator package_const_iterator;
-
-    cdef_package_rep (const cdef_package_rep& p)
-      : cdef_meta_object_rep (p), full_name (p.full_name),
-        class_map (p.class_map), function_map (p.function_map),
-        package_map (p.package_map), member_count (p.member_count)
-    { }
-
-    cdef_package wrap (void)
-    {
-      refcount++;
-      return cdef_package (this);
-    }
-  };
-
-public:
-  cdef_package (void) : cdef_meta_object () { }
-
-  cdef_package (const std::string& nm)
-    : cdef_meta_object (new cdef_package_rep ())
-  { get_rep ()->set_name (nm); }
-
-  cdef_package (const cdef_package& pack)
-    : cdef_meta_object (pack) { }
-
-  cdef_package (const cdef_object& obj)
-    : cdef_meta_object (obj)
-  {
-    // This should never happen...
-    if (! is_package ())
-      error ("internal error: invalid assignment from %s to meta.package object",
-             class_name ().c_str ());
-  }
-
-  cdef_package& operator = (const cdef_package& pack)
-  {
-    cdef_object::operator = (pack);
-
-    return *this;
-  }
-
-  ~cdef_package (void) = default;
-
-  void install_class (const cdef_class& cls, const std::string& nm)
-  { get_rep ()->install_class (cls, nm); }
-
-  void install_function (const octave_value& fcn, const std::string& nm)
-  { get_rep ()->install_function (fcn, nm); }
-
-  void install_package (const cdef_package& pack, const std::string& nm)
-  { get_rep ()->install_package (pack, nm); }
-
-  Cell get_classes (void) const
-  { return get_rep ()->get_classes (); }
-
-  Cell get_functions (void) const
-  { return get_rep ()->get_functions (); }
-
-  Cell get_packages (void) const
-  { return get_rep ()->get_packages (); }
-
-  std::string get_name (void) const { return get_rep ()->get_name (); }
-
-  octave_value find (const std::string& nm) { return get_rep ()->find (nm); }
-
-private:
-  cdef_package_rep * get_rep (void)
-  { return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ()); }
-
-  const cdef_package_rep * get_rep (void) const
-  { return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ()); }
-
-  friend void install_classdef (octave::interpreter& interp);
-};
-
 class
 octave_classdef : public octave_base_value
 {
 public:
+
   octave_classdef (void)
     : octave_base_value (), object () { }
 
-  octave_classdef (const cdef_object& obj)
+  octave_classdef (const octave::cdef_object& obj)
     : octave_base_value (), object (obj) { }
 
   octave_classdef (const octave_classdef&) = delete;
@@ -1486,16 +57,20 @@
   ~octave_classdef (void) = default;
 
   octave_base_value * clone (void) const
-  { return new octave_classdef (object.clone ()); }
+  {
+    return new octave_classdef (object.clone ());
+  }
 
   octave_base_value * empty_clone (void) const
-  { return new octave_classdef (object.empty_clone ()); }
+  {
+    return new octave_classdef (object.empty_clone ());
+  }
 
   octave_classdef * classdef_object_value (bool = false) { return this; }
 
-  cdef_object get_object (void) const { return object; }
+  octave::cdef_object get_object (void) const { return object; }
 
-  cdef_object& get_object_ref (void) { return object; }
+  octave::cdef_object& get_object_ref (void) { return object; }
 
   bool is_defined (void) const { return true; }
 
@@ -1509,11 +84,6 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  bool print_name_tag (std::ostream& os, const std::string& name) const;
-
-  void print_with_name (std::ostream& os, const std::string& name,
-                        bool print_padding = true);
-
   bool is_instance_of (const std::string& cls_name) const;
 
   octave_value_list subsref (const std::string& type,
@@ -1540,7 +110,7 @@
                   const std::list<octave_value_list>& idx,
                   const octave_value& rhs);
 
-  octave_idx_type numel (const octave_value_list&);
+  octave_idx_type xnumel (const octave_value_list&);
 
   string_vector map_keys (void) const { return object.map_keys (); }
 
@@ -1560,7 +130,13 @@
     return object.get_property (idx, name);
   }
 
+  static octave_value superclass_ref (const std::string& meth,
+                                      const std::string& cls);
+
+  static octave_value metaclass_query (const std::string& cls);
+
 public:
+
   int type_id (void) const { return t_id; }
   std::string type_name (void) const { return t_name; }
   std::string class_name (void) const { return object.class_name (); }
@@ -1572,161 +148,111 @@
 
 private:
 
-  cdef_object object;
+  octave::cdef_object object;
 
   static int t_id;
 
   static const std::string t_name;
 };
 
-inline octave_value
-to_ov (const cdef_object& obj)
-{
-  if (obj.ok ())
-    return octave_value (new octave_classdef (obj));
-  else
-    return octave_value (Matrix ());
-}
-
-inline octave_value
-to_ov (const octave_value& ov)
-{ return ov; }
-
-inline cdef_object
-to_cdef (const octave_value& val)
-{
-  if (val.type_name () != "object")
-    error ("cannot convert `%s' into `object'", val.type_name().c_str ());
-
-  return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();
-}
-
-inline cdef_object&
-to_cdef_ref (const octave_value& val)
-{
-  if (val.type_name () != "object")
-    error ("cannot convert `%s' into `object'", val.type_name().c_str ());
-
-  return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
-}
-
-inline cdef_object
-to_cdef (const cdef_object& obj)
-{ return obj; }
-
 OCTINTERP_API void install_classdef (octave::interpreter& interp);
 
-class
-cdef_manager
+class octave_classdef_meta : public octave_function
 {
 public:
 
-  cdef_manager (octave::interpreter& interp);
-
-  // No copying!
+  octave_classdef_meta (const octave::cdef_meta_object& obj)
+    : object (obj)
+  { }
 
-  cdef_manager (const cdef_manager&) = delete;
-
-  cdef_manager& operator = (const cdef_manager&) = delete;
-
-  ~cdef_manager (void) = default;
+  octave_classdef_meta (const octave_classdef_meta&) = delete;
 
-  cdef_class find_class (const std::string& name, bool error_if_not_found = true,
-                         bool load_if_not_found = true);
+  octave_classdef_meta& operator = (const octave_classdef_meta&) = delete;
+
+  ~octave_classdef_meta (void) { object.meta_release (); }
 
-  octave_function * find_method_symbol (const std::string& method_name,
-                                        const std::string& class_name);
+  bool is_classdef_meta (void) const { return true; }
 
-  cdef_package find_package (const std::string& name,
-                             bool error_if_not_found = true,
-                             bool load_if_not_found = true);
+  bool is_package (void) const { return object.is_package(); }
 
-  octave_function * find_package_symbol (const std::string& pack_name);
+  octave_function * function_value (bool = false) { return this; }
 
-  void register_class (const cdef_class& cls)
-  {
-    m_all_classes[cls.get_name ()] = cls;
-  }
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_function::subsref;
 
-  void unregister_class (const cdef_class& cls)
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
   {
-    m_all_classes.erase(cls.get_name ());
-  }
-
-  void register_package (const cdef_package& pkg)
-  {
-    m_all_packages[pkg.get_name ()] = pkg;
-  }
-
-  void unregister_package (const cdef_package& pkg)
-  {
-    m_all_packages.erase (pkg.get_name ());
+    return object.meta_subsref (type, idx, nargout);
   }
 
-  const cdef_class& meta_class (void) const { return m_meta_class; }
-  const cdef_class& meta_property (void) const { return m_meta_property; }
-  const cdef_class& meta_method (void) const { return m_meta_method; }
-  const cdef_class& meta_package (void) const { return m_meta_package; }
-
-  const cdef_package& meta (void) const { return m_meta; }
-
-  cdef_class
-  make_class (const std::string& name,
-              const std::list<cdef_class>& super_list = std::list<cdef_class> ());
+  // We don't need to override both forms of the call method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_function::call;
 
-  cdef_class
-  make_class (const std::string& name, const cdef_class& super);
-
-  cdef_class
-  make_meta_class (const std::string& name, const cdef_class& super);
-
-  cdef_property
-  make_property (const cdef_class& cls, const std::string& name,
-                 const octave_value& get_method = Matrix (),
-                 const std::string& get_access = "public",
-                 const octave_value& set_method = Matrix (),
-                 const std::string& set_access = "public");
+  octave_value_list call (octave::tree_evaluator&, int nargout,
+                          const octave_value_list& args)
+  {
+    // Emulate ()-type meta subsref
 
-  cdef_property
-  make_attribute (const cdef_class& cls, const std::string& name);
-
-  cdef_method
-  make_method (const cdef_class& cls, const std::string& name,
-               const octave_value& fcn,
-               const std::string& m_access = "public",
-               bool is_static = false);
+    std::list<octave_value_list> idx (1, args);
+    std::string type ("(");
 
-  cdef_method
-  make_method (const cdef_class& cls, const std::string& name,
-               octave_builtin::fcn ff,
-               const std::string& m_access = "public",
-               bool is_static = false);
+    return subsref (type, idx, nargout);
+  }
 
-  cdef_method
-  make_method (const cdef_class& cls, const std::string& name,
-               octave_builtin::meth mm,
-               const std::string& m_access = "public",
-               bool is_static = false);
+  bool accepts_postfix_index (char type) const
+  { return object.meta_accepts_postfix_index (type); }
 
-  cdef_package
-  make_package (const std::string& nm, const std::string& parent = "");
+  bool is_classdef_constructor (const std::string& cname = "") const;
 
 private:
 
-  octave::interpreter& m_interpreter;
+  octave::cdef_meta_object object;
+};
+
+class octave_classdef_superclass_ref : public octave_function
+{
+public:
+  octave_classdef_superclass_ref (void) = delete;
 
-  // All registered/loaded classes
-  std::map<std::string, cdef_class> m_all_classes;
+  octave_classdef_superclass_ref (const std::string& meth,
+                                  const std::string& cls)
+    : octave_function (), m_method_name (meth), m_class_name (cls)
+  { }
+
+  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;
 
-  // All registered/loaded packages
-  std::map<std::string, cdef_package> m_all_packages;
+  bool is_classdef_superclass_ref (void) const { return true; }
+
+  octave_function * function_value (bool = false) { return this; }
+
+  // We don't need to override both forms of the call method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_function::call;
 
-  cdef_class m_meta_class;
-  cdef_class m_meta_property;
-  cdef_class m_meta_method;
-  cdef_class m_meta_package;
+  octave_value_list
+  call (octave::tree_evaluator& tw, int nargout, const octave_value_list& idx);
+
+private:
 
-  cdef_package m_meta;
+  bool is_constructed_object (octave::tree_evaluator& tw,
+                              const std::string& nm);
+
+private:
+
+  std::string m_method_name;
+  std::string m_class_name;
 };
 
 #endif
--- a/libinterp/octave-value/ov-complex.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-complex.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -324,7 +324,7 @@
 }
 
 bool
-octave_complex::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_complex::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = static_cast<char> (LS_DOUBLE);
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-complex.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-complex.h	Fri Jul 12 12:14:43 2019 -0400
@@ -159,6 +159,11 @@
   octave_value as_double (void) const;
   octave_value as_single (void) const;
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_scalar<Complex>::diag;
+
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   void increment (void) { scalar += 1.0; }
@@ -169,7 +174,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-cs-list.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cs-list.h	Fri Jul 12 12:14:43 2019 -0400
@@ -71,6 +71,11 @@
 
   octave_value_list list_value (void) const { return lst; }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
--- a/libinterp/octave-value/ov-cx-diag.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-diag.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -177,7 +177,7 @@
 }
 
 bool
-octave_complex_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats)
+octave_complex_diag_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
 
   int32_t r = matrix.rows ();
--- a/libinterp/octave-value/ov-cx-diag.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-diag.h	Fri Jul 12 12:14:43 2019 -0400
@@ -82,7 +82,7 @@
   octave_value as_double (void) const;
   octave_value as_single (void) const;
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-cx-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -410,7 +410,7 @@
 }
 
 bool
-octave_complex_matrix::save_binary (std::ostream& os, bool& save_as_floats)
+octave_complex_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-cx-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -153,7 +153,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-cx-sparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -219,7 +219,7 @@
 
 bool
 octave_sparse_complex_matrix::save_binary (std::ostream& os,
-                                           bool& save_as_floats)
+                                           bool save_as_floats)
 {
   dim_vector dv = this->dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-cx-sparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-cx-sparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -138,7 +138,7 @@
   }
 #endif
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-fcn-handle.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -30,12 +30,12 @@
 #include <list>
 #include <ostream>
 #include <sstream>
+#include <string>
 #include <vector>
 
 #include "file-ops.h"
 #include "oct-locbuf.h"
 
-#include "call-stack.h"
 #include "defaults.h"
 #include "defun.h"
 #include "error.h"
@@ -54,7 +54,6 @@
 #include "parse.h"
 #include "pr-output.h"
 #include "pt-arg-list.h"
-#include "pt-anon-scopes.h"
 #include "pt-assign.h"
 #include "pt-cmd.h"
 #include "pt-eval.h"
@@ -63,6 +62,7 @@
 #include "pt-misc.h"
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
+#include "syminfo.h"
 #include "symscope.h"
 #include "unwind-prot.h"
 #include "variables.h"
@@ -81,22 +81,93 @@
 
 const std::string octave_fcn_handle::anonymous ("@<anonymous>");
 
-octave_fcn_handle::octave_fcn_handle (const octave_value& f,
+octave_fcn_handle::octave_fcn_handle (const octave::symbol_scope& scope,
                                       const std::string& n)
-  : fcn (f), nm (n), has_overloads (false)
+  : m_fcn (), m_obj (), m_name (n), m_scope (scope), m_is_nested (false),
+    m_closure_frames (nullptr), m_dispatch_class ()
 {
-  octave_user_function *uf = fcn.user_function_value (true);
+  if (! m_name.empty () && m_name[0] == '@')
+    m_name = m_name.substr (1);
+
+  size_t pos = m_name.find ('.');
+
+  if (pos != std::string::npos)
+    {
+      // If we are looking at
+      //
+      //   obj . meth
+      //
+      // Store the object so that calling METH for OBJ will work even if
+      // it is done outside of the scope whre OBJ was initially defined
+      // or if OBJ is cleared before the method call is made through the
+      // function handle.
+
+      std::string obj_name = m_name.substr (0, pos);
 
-  if (uf && nm != anonymous)
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::octave_fcn_handle");
+
+      octave_value val = interp.varval (obj_name);
+
+      if (val.is_classdef_object ())
+        m_obj = val;
+    }
+}
+
+octave_fcn_handle::octave_fcn_handle (const octave::symbol_scope& scope,
+                                      const octave_value& f,
+                                      const std::string& n)
+  : m_fcn (f), m_obj (), m_name (n), m_scope (scope), m_is_nested (false),
+    m_closure_frames (nullptr), m_dispatch_class ()
+{
+  octave_user_function *uf = m_fcn.user_function_value (true);
+
+  if (uf && m_name != anonymous)
     {
       octave::symbol_scope uf_scope = uf->scope ();
 
       if (uf_scope)
-        uf_scope.cache_name (nm);
+        uf_scope.cache_name (m_name);
     }
 
   if (uf && uf->is_nested_function () && ! uf->is_subfunction ())
-    error ("handles to nested functions are not yet supported");
+    m_is_nested = true;
+}
+
+octave_fcn_handle::octave_fcn_handle (const octave_value& f,
+                                      const std::string& n)
+  : m_fcn (f), m_obj (), m_name (n), m_scope (), m_is_nested (false),
+    m_closure_frames (nullptr), m_dispatch_class ()
+{
+  octave_user_function *uf = m_fcn.user_function_value (true);
+
+  if (uf && m_name != anonymous)
+    {
+      octave::symbol_scope uf_scope = uf->scope ();
+
+      if (uf_scope)
+        uf_scope.cache_name (m_name);
+    }
+
+  if (uf && uf->is_nested_function () && ! uf->is_subfunction ())
+    m_is_nested = true;
+}
+
+octave_fcn_handle::~octave_fcn_handle (void)
+{
+  if (m_closure_frames)
+    {
+      while (m_closure_frames->size () > 0)
+        {
+          octave::stack_frame *elt = m_closure_frames->back ();
+
+          delete elt;
+
+          m_closure_frames->pop_back ();
+        }
+
+      delete m_closure_frames;
+    }
 }
 
 octave_value_list
@@ -138,90 +209,188 @@
   return retval;
 }
 
+static void
+err_invalid_fcn_handle (const std::string& name)
+{
+  error ("%s: invalid function handle", name.c_str ());
+}
+
 octave_value_list
 octave_fcn_handle::call (int nargout, const octave_value_list& args)
 {
-  octave_value_list retval;
+  // FIXME: if m_name has a '.' in the name, lookup first component.  If
+  // it is a classdef meta object, then build TYPE and IDX arguments and
+  // make a subsref call using them.
 
-  octave::out_of_date_check (fcn, "", false);
+  octave_value fcn_to_call = m_fcn;
 
-  if (has_overloads)
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("octave_fcn_handle::call");
+
+  if (! fcn_to_call.is_defined ())
     {
-      // Possibly overloaded function.
-      octave_value ov_fcn;
-
-      // Compute dispatch type.
-      builtin_type_t btyp;
-      std::string dispatch_type = octave::get_dispatch_type (args, btyp);
+      // The following code is similar to part of
+      // tree_evaluator::visit_index_expression but simpler because it
+      // handles a more restricted case.
 
-      // Retrieve overload.
-      if (btyp != btyp_unknown)
+      octave::symbol_table& symtab = interp.get_symbol_table ();
+
+      size_t pos = m_name.find ('.');
+
+      if (pos != std::string::npos)
         {
-          octave::out_of_date_check (builtin_overloads[btyp], dispatch_type, false);
-          ov_fcn = builtin_overloads[btyp];
-        }
-      else
-        {
-          auto it = overloads.find (dispatch_type);
+          // We can have one of
+          //
+          //   pkg-list . fcn  (args)
+          //   pkg-list . cls . meth (args)
+          //   cls . meth  (args)
 
-          if (it == overloads.end ())
-            {
-              // Try parent classes too.
+          // Evaluate package elements until we find a function,
+          // classdef object, or classdef_meta object that is not a
+          // package.  An object may only appear as the first element,
+          // then it must be followed directly by a function name.
 
-              octave::symbol_table& symtab
-                = octave::__get_symbol_table__ ("octave_fcn_handle::call");
+          size_t beg = 0;
+          size_t end = pos;
 
-              const std::list<std::string> plist
-                = symtab.parent_classes (dispatch_type);
+          std::vector<std::string> idx_elts;
 
-              auto pit = plist.begin ();
+          while (true)
+            {
+              end = m_name.find ('.', beg);
+
+              idx_elts.push_back (m_name.substr (beg, end-beg));
 
-              while (pit != plist.end ())
-                {
-                  std::string pname = *pit;
+              if (end == std::string::npos)
+                break;
 
-                  std::string fnm = fcn_name ();
+              beg = end+1;
+            }
 
-                  octave_value ftmp = symtab.find_method (fnm, pname);
+          size_t n_elts = idx_elts.size ();
 
-                  if (ftmp.is_defined ())
-                    {
-                      set_overload (pname, ftmp);
+          bool have_object = false;
+          octave_value partial_expr_val;
 
-                      octave::out_of_date_check (ftmp, pname, false);
-                      ov_fcn = ftmp;
+          if (m_obj.is_defined ())
+            {
+              // The first element was already defined elsewhere,
+              // possibly in the scope where the function handle was
+              // created.
 
-                      break;
-                    }
+              partial_expr_val = m_obj;
 
-                  pit++;
-                }
+              if (m_obj.is_classdef_object ())
+                have_object = true;
+              else
+                err_invalid_fcn_handle (m_name);
             }
           else
             {
-              octave::out_of_date_check (it->second, dispatch_type, false);
-              ov_fcn = it->second;
+              // Lazy evaluation.  The first element was not known to be
+              // defined as an object in the scope where the handle was
+              // created.  See if there is a definition in the current
+              // scope.
+
+              partial_expr_val = interp.varval (idx_elts[0]);
+            }
+
+          if (partial_expr_val.is_defined ())
+            {
+              if (! partial_expr_val.is_classdef_object () || n_elts != 2)
+                err_invalid_fcn_handle (m_name);
+
+              have_object = true;
             }
-        }
+          else
+            partial_expr_val
+              = symtab.find_function (idx_elts[0], ovl (), m_scope);
+
+          std::string type;
+          std::list<octave_value_list> arg_list;
+
+          for (size_t i = 1; i < n_elts; i++)
+            {
+              if (partial_expr_val.is_package ())
+                {
+                  if (have_object)
+                    err_invalid_fcn_handle (m_name);
+
+                  type = ".";
+                  arg_list.push_back (ovl (idx_elts[i]));
+
+                  try
+                    {
+                      // Silently ignore extra output values.
+
+                      octave_value_list tmp_list
+                        = partial_expr_val.subsref (type, arg_list, 0);
 
-      if (ov_fcn.is_defined ())
-        retval = octave::feval (ov_fcn, args, nargout);
-      else if (fcn.is_defined ())
-        retval = octave::feval (fcn, args, nargout);
+                      partial_expr_val
+                        = tmp_list.length () ? tmp_list(0) : octave_value ();
+
+                      if (partial_expr_val.is_cs_list ())
+                        err_invalid_fcn_handle (m_name);
+
+                      arg_list.clear ();
+                    }
+                  catch (octave::index_exception&)
+                    {
+                      err_invalid_fcn_handle (m_name);
+                    }
+                }
+              else if (have_object || partial_expr_val.is_classdef_meta ())
+                {
+                  // Object or class name must be the next to the last
+                  // element (it was the previous one, so if this is the
+                  // final element, it should be a classdef method,
+                  // but we'll let the classdef or classdef_meta subsref
+                  // function sort that out.
+
+                  if (i != n_elts-1)
+                    err_invalid_fcn_handle (m_name);
+
+                  type = ".(";
+                  arg_list.push_back (ovl (idx_elts[i]));
+                  arg_list.push_back (args);
+
+                  return partial_expr_val.subsref (type, arg_list, nargout);
+                }
+              else
+                err_invalid_fcn_handle (m_name);
+            }
+
+          // If we get here, we must have a function to call.
+
+          if (! partial_expr_val.is_function ())
+            err_invalid_fcn_handle (m_name);
+
+          fcn_to_call = partial_expr_val;
+        }
       else
-        error ("%s: no method for class %s",
-               nm.c_str (), dispatch_type.c_str ());
-    }
-  else
-    {
-      // Non-overloaded function (anonymous, subfunction, private function).
-      if (fcn.is_defined ())
-        retval = octave::feval (fcn, args, nargout);
-      else
-        error ("%s: no longer valid function handle", nm.c_str ());
+        fcn_to_call = symtab.find_function (m_name, args, m_scope);
     }
 
-  return retval;
+  if (! fcn_to_call.is_defined ())
+    err_invalid_fcn_handle (m_name);
+
+  octave::stack_frame *closure_context = nullptr;
+
+  if (m_closure_frames && m_closure_frames->size () > 0)
+    closure_context = m_closure_frames->front ();
+
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave_function *of = fcn_to_call.function_value ();
+
+  octave::unwind_protect frame;
+
+  frame.add_method (tw, &octave::tree_evaluator::set_dispatch_class,
+                    std::string ());
+
+  tw.set_dispatch_class (m_dispatch_class);
+
+  return of->call (tw, nargout, args, closure_context);
 }
 
 dim_vector
@@ -231,25 +400,124 @@
   return dv;
 }
 
+octave_function * octave_fcn_handle::function_value (bool)
+{
+  if (m_fcn.is_defined ())
+    return m_fcn.function_value ();
+
+  octave::symbol_table& symtab
+    = octave::__get_symbol_table__ ("octave_fcn_handle::set_fcn");
+
+  // Cache this value so that the pointer will be valid as long as the
+  // function handle object is valid.
+
+  m_generic_fcn = symtab.find_function (m_name, octave_value_list (), m_scope);
+
+  return (m_generic_fcn.is_defined ()
+          ? m_generic_fcn.function_value () : nullptr);
+}
+
+octave_user_function * octave_fcn_handle::user_function_value (bool)
+{
+  if (m_fcn.is_defined ())
+    return m_fcn.user_function_value ();
+
+  octave::symbol_table& symtab
+    = octave::__get_symbol_table__ ("octave_fcn_handle::set_fcn");
+
+  // Cache this value so that the pointer will be valid as long as the
+  // function handle object is valid.
+
+  m_generic_fcn = symtab.find_user_function (m_name);
+
+  return (m_generic_fcn.is_defined ()
+          ? m_generic_fcn.user_function_value () : nullptr);
+}
+
+// Save call stack frames for handles to nested functions.
+
+void
+octave_fcn_handle::push_closure_context (octave::tree_evaluator& tw)
+{
+  if (! m_closure_frames)
+    m_closure_frames = new std::list<octave::stack_frame *> ();
+
+  octave::stack_frame& curr_frame = tw.get_current_stack_frame ();
+
+  octave::stack_frame *dup_frame = curr_frame.dup ();
+
+  if (! m_closure_frames->empty ())
+    {
+      octave::stack_frame *top_frame = m_closure_frames->back ();
+
+      // Arrange for static and access links in the top stack frame (the
+      // last one saved before this one) to point to the new duplicated
+      // frame.  This way we will look up through the duplicated frames
+      // when evaluating the function.
+
+      top_frame->set_closure_links (dup_frame);
+    }
+
+  m_closure_frames->push_back (dup_frame);
+}
+
+octave_value
+octave_fcn_handle::workspace (void) const
+{
+  if (m_name == anonymous)
+    {
+      octave_user_function *fu = m_fcn.user_function_value ();
+
+      octave_scalar_map ws;
+
+      if (fu)
+        {
+          for (const auto& nm_val : fu->local_var_init_vals ())
+            ws.assign (nm_val.first, nm_val.second);
+        }
+
+      return ws;
+    }
+  else if (m_closure_frames)
+    {
+      octave_idx_type num_frames = m_closure_frames->size ();
+
+      Cell ws_frames (num_frames, 1);
+
+      octave_idx_type i = 0;
+
+      for (auto elt : *m_closure_frames)
+        {
+          octave::symbol_info_list symbols = elt->all_variables ();
+
+          octave_scalar_map ws;
+
+          for (auto sym_name : symbols.names ())
+            {
+              octave_value val = symbols.varval (sym_name);
+
+              if (val.is_defined ())
+                ws.assign (sym_name, val);
+            }
+
+          ws_frames(i++) = ws;
+        }
+
+      return ws_frames;
+    }
+
+  return Cell ();
+}
+
 bool
 octave_fcn_handle::is_equal_to (const octave_fcn_handle& h) const
 {
-  bool retval = fcn.is_copy_of (h.fcn) && (has_overloads == h.has_overloads);
-  retval = retval && (overloads.size () == h.overloads.size ());
-
-  if (retval && has_overloads)
-    {
-      for (int i = 0; i < btyp_num_types && retval; i++)
-        retval = builtin_overloads[i].is_copy_of (h.builtin_overloads[i]);
-
-      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));
-    }
-
-  return retval;
+  if (m_fcn.is_defined () && h.m_fcn.is_defined ())
+    return m_fcn.is_copy_of (h.m_fcn);
+  else if (m_fcn.is_undefined () && h.m_fcn.is_undefined ())
+    return m_name == h.m_name;
+  else
+    return false;
 }
 
 bool
@@ -274,20 +542,20 @@
           std::string dir_name = str.substr (0, xpos);
 
           octave_value ov_fcn
-            = octave::load_fcn_from_file (str, dir_name, "", "", nm);
+            = octave::load_fcn_from_file (str, dir_name, "", "", m_name);
 
           if (ov_fcn.is_undefined ())
             error ("function handle points to non-existent function");
 
-          fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
+          m_fcn = octave_value (new octave_fcn_handle (ov_fcn, m_name));
         }
       else
         {
           // Next just search for it anywhere in the system path
           std::list<std::string> names;
-          names.push_back (nm + ".oct");
-          names.push_back (nm + ".mex");
-          names.push_back (nm + ".m");
+          names.push_back (m_name + ".oct");
+          names.push_back (m_name + ".mex");
+          names.push_back (m_name + ".m");
 
           octave::load_path& lp =
             octave::__get_load_path__ ("octave_fcn_handle::set_fcn");
@@ -301,12 +569,12 @@
           std::string dir_name = str.substr (0, xpos);
 
           octave_value ov_fcn
-            = octave::load_fcn_from_file (str, dir_name, "", "", nm);
+            = octave::load_fcn_from_file (str, dir_name, "", "", m_name);
 
           if (ov_fcn.is_undefined ())
             error ("function handle points to non-existent function");
 
-          fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
+          m_fcn = octave_value (new octave_fcn_handle (ov_fcn, m_name));
         }
     }
   else
@@ -318,21 +586,21 @@
           std::string dir_name = fpath.substr (0, xpos);
 
           octave_value ov_fcn
-            = octave::load_fcn_from_file (fpath, dir_name, "", "", nm);
+            = octave::load_fcn_from_file (fpath, dir_name, "", "", m_name);
 
           if (ov_fcn.is_undefined ())
             error ("function handle points to non-existent function");
 
-          fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
+          m_fcn = octave_value (new octave_fcn_handle (ov_fcn, m_name));
         }
       else
         {
           octave::symbol_table& symtab
             = octave::__get_symbol_table__ ("octave_fcn_handle::set_fcn");
 
-          fcn = symtab.find_function (nm);
+          m_fcn = symtab.find_function (m_name);
 
-          if (! fcn.is_function ())
+          if (! m_fcn.is_function ())
             error ("function handle points to non-existent function");
         }
     }
@@ -351,37 +619,30 @@
 bool
 octave_fcn_handle::save_ascii (std::ostream& os)
 {
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
-      if (fcn.is_undefined ())
+      if (m_fcn.is_undefined ())
         return false;
 
-      octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope f_scope = f->scope ();
+      octave_user_function *f = m_fcn.user_function_value ();
 
-      if (! f_scope)
-        error ("internal error, invalid scope");
+      octave_user_function::local_vars_map local_vars
+        = f->local_var_init_vals ();
 
-      octave::tree_anon_scopes tas (f);
+      size_t varlen = local_vars.size ();
 
-      os << nm << "\n";
+      os << m_name << "\n";
 
       print_raw (os, true);
       os << "\n";
 
-      size_t varlen = tas.symrec_map_size ();
-
       if (varlen > 0)
         {
-          octave::symbol_record::context_id context
-            = f_scope.current_context ();
-
           os << "# length: " << varlen << "\n";
 
-          for (const auto& name_symrec : tas)
+          for (const auto& nm_val : local_vars)
             {
-              if (! save_text_data (os, name_symrec.second.varval (context),
-                                    name_symrec.first, false, 0))
+              if (! save_text_data (os, nm_val.second, nm_val.first, false, 0))
                 return ! os.fail ();
             }
         }
@@ -394,7 +655,7 @@
       os << "# octaveroot: " << octave::config::octave_exec_home () << "\n";
       if (! fnm.empty ())
         os << "# path: " << fnm << "\n";
-      os << nm << "\n";
+      os << m_name << "\n";
     }
 
   return true;
@@ -418,16 +679,16 @@
 
       if (fh)
         {
-          fcn = fh->fcn;
+          m_fcn = fh->m_fcn;
 
-          octave_user_function *uf = fcn.user_function_value (true);
+          octave_user_function *uf = m_fcn.user_function_value (true);
 
           if (uf)
             {
               octave::symbol_scope uf_scope = uf->scope ();
 
               if (uf_scope)
-                uf_scope.cache_name (nm);
+                uf_scope.cache_name (m_name);
             }
         }
       else
@@ -459,9 +720,9 @@
       is.clear ();
     }
 
-  is >> nm;
+  is >> m_name;
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       skip_preceeding_newline (is);
 
@@ -483,18 +744,13 @@
       // Set up temporary scope to use for evaluating the text that
       // defines the anonymous function.
 
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::load_ascii");
-
-      octave::symbol_scope local_scope (buf);
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_ascii");
 
-      symtab.set_scope (local_scope);
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_ascii");
-
-      cs.push (local_scope, 0);
-      frame.add_method (cs, &octave::call_stack::pop);
+      tw.push_dummy_scope (buf);
+      frame.add_method (tw, &octave::tree_evaluator::pop_scope);
 
       octave_idx_type len = 0;
 
@@ -513,7 +769,7 @@
                   if (! is)
                     error ("load: failed to load anonymous function handle");
 
-                  local_scope.assign (name, t2, 0);
+                  interp.assign (name, t2);
                 }
             }
         }
@@ -535,29 +791,26 @@
 }
 
 bool
-octave_fcn_handle::save_binary (std::ostream& os, bool& save_as_floats)
+octave_fcn_handle::save_binary (std::ostream& os, bool save_as_floats)
 {
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       std::ostringstream nmbuf;
 
-      if (fcn.is_undefined ())
+      if (m_fcn.is_undefined ())
         return false;
 
-      octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope f_scope = f->scope ();
+      octave_user_function *f = m_fcn.user_function_value ();
 
-      if (! f_scope)
-        error ("internal error, invalid scope");
+      octave_user_function::local_vars_map local_vars
+        = f->local_var_init_vals ();
 
-      octave::tree_anon_scopes tas (f);
-
-      size_t varlen = tas.symrec_map_size ();
+      size_t varlen = local_vars.size ();
 
       if (varlen > 0)
-        nmbuf << nm << ' ' << varlen;
+        nmbuf << m_name << ' ' << varlen;
       else
-        nmbuf << nm;
+        nmbuf << m_name;
 
       std::string buf_str = nmbuf.str ();
       int32_t tmp = buf_str.length ();
@@ -573,13 +826,10 @@
 
       if (varlen > 0)
         {
-          octave::symbol_record::context_id context
-            = f_scope.current_context ();
-
-          for (const auto& name_symrec : tas)
+          for (const auto& nm_val : local_vars)
             {
-              if (! save_binary_data (os, name_symrec.second.varval (context),
-                                      name_symrec.first, "", 0, save_as_floats))
+              if (! save_binary_data (os, nm_val.second, nm_val.first,
+                                      "", 0, save_as_floats))
                 return ! os.fail ();
             }
         }
@@ -591,7 +841,7 @@
       octave_function *f = function_value ();
       std::string fnm = (f ? f->fcn_file_name () : "");
 
-      nmbuf << nm << "\n" << octave::config::octave_exec_home () << "\n" << fnm;
+      nmbuf << m_name << "\n" << octave::config::octave_exec_home () << "\n" << fnm;
 
       std::string buf_str = nmbuf.str ();
       int32_t tmp = buf_str.length ();
@@ -619,22 +869,22 @@
   // effectively not reading over file end
   is.read (ctmp1, tmp);
   ctmp1[tmp] = 0;
-  nm = std::string (ctmp1);
+  m_name = std::string (ctmp1);
 
   if (! is)
     return false;
 
   size_t anl = anonymous.length ();
 
-  if (nm.length () >= anl && nm.substr (0, anl) == anonymous)
+  if (m_name.length () >= anl && m_name.substr (0, anl) == anonymous)
     {
       octave_idx_type len = 0;
 
-      if (nm.length () > anl)
+      if (m_name.length () > anl)
         {
-          std::istringstream nm_is (nm.substr (anl));
+          std::istringstream nm_is (m_name.substr (anl));
           nm_is >> len;
-          nm = nm.substr (0, anl);
+          m_name = m_name.substr (0, anl);
         }
 
       if (! is.read (reinterpret_cast<char *> (&tmp), 4))
@@ -653,18 +903,13 @@
       // Set up temporary scope to use for evaluating the text that
       // defines the anonymous function.
 
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::load_binary");
-
-      octave::symbol_scope local_scope (ctmp2);
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_binary");
 
-      symtab.set_scope (local_scope);
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_binary");
-
-      cs.push (local_scope, 0);
-      frame.add_method (cs, &octave::call_stack::pop);
+      tw.push_dummy_scope (ctmp2);
+      frame.add_method (tw, &octave::tree_evaluator::pop_scope);
 
       if (len > 0)
         {
@@ -681,7 +926,7 @@
               if (! is)
                 error ("load: failed to load anonymous function handle");
 
-              local_scope.force_assign (name, t2);
+              interp.assign (name, t2);
             }
         }
 
@@ -695,13 +940,13 @@
       std::string octaveroot;
       std::string fpath;
 
-      if (nm.find_first_of ('\n') != std::string::npos)
+      if (m_name.find_first_of ('\n') != std::string::npos)
         {
-          size_t pos1 = nm.find_first_of ('\n');
-          size_t pos2 = nm.find_first_of ('\n', pos1 + 1);
-          octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1);
-          fpath = nm.substr (pos2 + 1);
-          nm = nm.substr (0, pos1);
+          size_t pos1 = m_name.find_first_of ('\n');
+          size_t pos2 = m_name.find_first_of ('\n', pos1 + 1);
+          octaveroot = m_name.substr (pos1 + 1, pos2 - pos1 - 1);
+          fpath = m_name.substr (pos2 + 1);
+          m_name = m_name.substr (0, pos1);
         }
 
       success = set_fcn (octaveroot, fpath);
@@ -733,7 +978,7 @@
 
   // attach the type of the variable
   type_hid = H5Tcopy (H5T_C_S1);
-  H5Tset_size (type_hid, nm.length () + 1);
+  H5Tset_size (type_hid, m_name.length () + 1);
   if (type_hid < 0)
     {
       H5Gclose (group_hid);
@@ -760,7 +1005,7 @@
 #endif
   if (data_hid < 0
       || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
-                   octave_H5P_DEFAULT, nm.c_str ()) < 0)
+                   octave_H5P_DEFAULT, m_name.c_str ()) < 0)
     {
       H5Sclose (space_hid);
       H5Tclose (type_hid);
@@ -769,7 +1014,7 @@
     }
   H5Dclose (data_hid);
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       std::ostringstream buf;
       print_raw (buf, true);
@@ -804,15 +1049,12 @@
 
       H5Dclose (data_hid);
 
-      octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope f_scope = f->scope ();
+      octave_user_function *f = m_fcn.user_function_value ();
 
-      if (! f_scope)
-        error ("internal error, invalid scope");
+      octave_user_function::local_vars_map local_vars
+                     = f->local_var_init_vals ();
 
-      octave::tree_anon_scopes tas (f);
-
-      size_t varlen = tas.symrec_map_size ();
+      size_t varlen = local_vars.size ();
 
       if (varlen > 0)
         {
@@ -857,15 +1099,10 @@
               return false;
             }
 
-          octave::symbol_record::context_id context
-            = f_scope.current_context ();
-
-          for (const auto& name_symrec : tas)
+          for (const auto& nm_val : local_vars)
             {
-              if (! add_hdf5_data (data_hid,
-                                   name_symrec.second.varval (context),
-                                   name_symrec.first, "", false,
-                                   save_as_floats))
+              if (! add_hdf5_data (data_hid, nm_val.second, nm_val.first,
+                                   "", false, save_as_floats))
                 break;
             }
           H5Gclose (data_hid);
@@ -1046,9 +1283,9 @@
     }
   H5Tclose (st_id);
   H5Dclose (data_hid);
-  nm = nm_tmp;
+  m_name = nm_tmp;
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
 #if defined (HAVE_HDF5_18)
       data_hid = H5Dopen (group_hid, "fcn", octave_H5P_DEFAULT);
@@ -1161,18 +1398,13 @@
       // Set up temporary scope to use for evaluating the text that
       // defines the anonymous function.
 
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("octave_fcn_handle::load_hdf5");
-
-      octave::symbol_scope local_scope (fcn_tmp);
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_hdf5");
 
-      symtab.set_scope (local_scope);
+      octave::tree_evaluator& tw = interp.get_evaluator ();
 
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_hdf5");
-
-      cs.push (local_scope, 0);
-      frame.add_method (cs, &octave::call_stack::pop);
+      tw.push_dummy_scope (fcn_tmp);
+      frame.add_method (tw, &octave::tree_evaluator::pop_scope);
 
       if (len > 0 && success)
         {
@@ -1196,14 +1428,12 @@
                                     &dsub) <= 0)
                 error ("load: failed to load anonymous function handle");
 
-              local_scope.force_assign (dsub.name, dsub.tc);
+              interp.assign (dsub.name, dsub.tc);
             }
         }
 
       if (success)
         success = parse_anon_fcn_handle (fcn_tmp);
-
-      frame.run ();
     }
   else
     {
@@ -1411,14 +1641,14 @@
 {
   bool printed = false;
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       octave::tree_print_code tpc (os);
 
       // FCN is const because this member function is, so we can't
       // use it to call user_function_value, so we make a copy first.
 
-      octave_value ftmp = fcn;
+      octave_value ftmp = m_fcn;
 
       octave_user_function *f = ftmp.user_function_value ();
 
@@ -1454,201 +1684,163 @@
     }
 
   if (! printed)
-    octave_print_internal (os, '@' + nm, pr_as_read_syntax,
+    octave_print_internal (os, '@' + m_name, pr_as_read_syntax,
                            current_print_indent_level ());
 }
 
-octave_value
-make_fcn_handle (const std::string& nm)
+namespace octave
 {
-  octave_value retval;
-
-  // Bow to the god of compatibility.
+  // Hmm, should this function be a member of the interpreter class,
+  // possibly forwarded to an actual implementation in the
+  // tree_evaluator class?
 
-  // FIXME: it seems ugly to put this here, but there is no single
-  // function in the parser that converts from the operator name to
-  // the corresponding function name.  At least try to do it without N
-  // string compares.
+  octave_value
+  make_fcn_handle (interpreter& interp, const std::string& nm)
+  {
+    octave_value retval;
 
-  std::string tnm = nm;
-
-  size_t len = nm.length ();
+    // Bow to the god of compatibility.
 
-  if (len == 3 && nm == ".**")
-    tnm = "power";
-  else if (len == 2)
-    {
-      if (nm[0] == '.')
-        {
-          switch (nm[1])
-            {
-            case '\'':
-              tnm = "transpose";
-              break;
+    // FIXME: it seems ugly to put this here, but there is no single
+    // function in the parser that converts from the operator name to
+    // the corresponding function name.  At least try to do it without N
+    // string compares.
+
+    std::string tnm = nm;
+
+    size_t len = nm.length ();
 
-            case '+':
-              tnm = "plus";
-              break;
-
-            case '-':
-              tnm = "minus";
-              break;
-
-            case '*':
-              tnm = "times";
-              break;
-
-            case '/':
-              tnm = "rdivide";
-              break;
+    if (len == 3 && nm == ".**")
+      tnm = "power";
+    else if (len == 2)
+      {
+        if (nm[0] == '.')
+          {
+            switch (nm[1])
+              {
+              case '\'':
+                tnm = "transpose";
+                break;
 
-            case '^':
-              tnm = "power";
-              break;
+              case '+':
+                tnm = "plus";
+                break;
+
+              case '-':
+                tnm = "minus";
+                break;
 
-            case '\\':
-              tnm = "ldivide";
-              break;
-            }
-        }
-      else if (nm[1] == '=')
-        {
-          switch (nm[0])
-            {
-            case '<':
-              tnm = "le";
-              break;
+              case '*':
+                tnm = "times";
+                break;
 
-            case '=':
-              tnm = "eq";
-              break;
+              case '/':
+                tnm = "rdivide";
+                break;
 
-            case '>':
-              tnm = "ge";
-              break;
+              case '^':
+                tnm = "power";
+                break;
 
-            case '~':
-            case '!':
-              tnm = "ne";
-              break;
-            }
-        }
-      else if (nm == "**")
-        tnm = "mpower";
-    }
-  else if (len == 1)
-    {
-      switch (nm[0])
-        {
-        case '~':
-        case '!':
-          tnm = "not";
-          break;
+              case '\\':
+                tnm = "ldivide";
+                break;
+              }
+          }
+        else if (nm[1] == '=')
+          {
+            switch (nm[0])
+              {
+              case '<':
+                tnm = "le";
+                break;
 
-        case '\'':
-          tnm = "ctranspose";
-          break;
+              case '=':
+                tnm = "eq";
+                break;
 
-        case '+':
-          tnm = "plus";
-          break;
+              case '>':
+                tnm = "ge";
+                break;
 
-        case '-':
-          tnm = "minus";
-          break;
-
-        case '*':
-          tnm = "mtimes";
-          break;
-
-        case '/':
-          tnm = "mrdivide";
-          break;
-
-        case '^':
+              case '~':
+              case '!':
+                tnm = "ne";
+                break;
+              }
+          }
+        else if (nm == "**")
           tnm = "mpower";
-          break;
-
-        case '\\':
-          tnm = "mldivide";
-          break;
+      }
+    else if (len == 1)
+      {
+        switch (nm[0])
+          {
+          case '~':
+          case '!':
+            tnm = "not";
+            break;
 
-        case '<':
-          tnm = "lt";
-          break;
+          case '\'':
+            tnm = "ctranspose";
+            break;
 
-        case '>':
-          tnm = "gt";
-          break;
-
-        case '&':
-          tnm = "and";
-          break;
+          case '+':
+            tnm = "plus";
+            break;
 
-        case '|':
-          tnm = "or";
-          break;
-        }
-    }
+          case '-':
+            tnm = "minus";
+            break;
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ("make_fcn_handle");
+          case '*':
+            tnm = "mtimes";
+            break;
 
-  octave_value f = symtab.find_function (tnm, octave_value_list ());
-
-  octave_function *fptr = f.function_value (true);
+          case '/':
+            tnm = "mrdivide";
+            break;
 
-  // Here we are just looking to see if FCN is a method or constructor
-  // for any class.
-  if (fptr && (fptr->is_subfunction () || fptr->is_private_function ()
-               || fptr->is_class_constructor ()
-               || fptr->is_classdef_constructor ()))
-    {
-      // Locally visible function.
-      retval = octave_value (new octave_fcn_handle (f, tnm));
-    }
-  else
-    {
-      octave::load_path& lp = octave::__get_load_path__ ("make_fcn_handle");
+          case '^':
+            tnm = "mpower";
+            break;
+
+          case '\\':
+            tnm = "mldivide";
+            break;
 
-      // Globally visible (or no match yet).  Query overloads.
-      std::list<std::string> classes = lp.overloads (tnm);
-      bool any_match = fptr != nullptr || classes.size () > 0;
-      if (! any_match)
-        {
-          // No match found, try updating load_path and query classes again.
-          lp.update ();
-          classes = lp.overloads (tnm);
-          any_match = classes.size () > 0;
-        }
+          case '<':
+            tnm = "lt";
+            break;
+
+          case '>':
+            tnm = "gt";
+            break;
+
+          case '&':
+            tnm = "and";
+            break;
 
-      if (! any_match)
-        error ("@%s: no function and no method found", tnm.c_str ());
+          case '|':
+            tnm = "or";
+            break;
+          }
+      }
 
-      octave_fcn_handle *fh = new octave_fcn_handle (f, tnm);
-      retval = fh;
+    tree_evaluator& tw = interp.get_evaluator ();
 
-      for (auto& cls : classes)
-        {
-          std::string class_name = cls;
-          octave_value fmeth = symtab.find_method (tnm, class_name);
+    symbol_scope curr_scope = tw.get_current_scope ();
 
-          bool is_builtin = false;
-          for (int i = 0; i < btyp_num_types; i++)
-            {
-              // FIXME: Too slow? Maybe binary lookup?
-              if (class_name == btyp_class_name[i])
-                {
-                  is_builtin = true;
-                  fh->set_overload (static_cast<builtin_type_t> (i), fmeth);
-                }
-            }
+    octave_fcn_handle *fh = new octave_fcn_handle (curr_scope, tnm);
+
+    std::string dispatch_class;
 
-          if (! is_builtin)
-            fh->set_overload (class_name, fmeth);
-        }
-    }
+    if (tw.is_class_method_executing (dispatch_class)
+        || tw.is_class_constructor_executing (dispatch_class))
+      fh->set_dispatch_class (dispatch_class);
 
-  return retval;
+    return octave_value (fh);
+  }
 }
 
 /*
@@ -1718,6 +1910,9 @@
 The function is a subfunction within an m-file.
 @end table
 
+@item nested
+The function is nested.
+
 @item file
 The m-file that will be called to perform the function.  This field is empty
 for anonymous and built-in functions.
@@ -1769,8 +1964,8 @@
         }
       else if (fcn->is_private_function ())
         m.setfield ("type", "private");
-      else if (fh->is_overloaded ())
-        m.setfield ("type", "overloaded");
+      else if (fh->is_nested ())
+        m.setfield ("type", "nested");
       else
         m.setfield ("type", "simple");
     }
@@ -1781,32 +1976,14 @@
     {
       m.setfield ("file", nm);
 
-      std::list<octave::symbol_record> vars;
-
-      octave_user_function *fu = fh->user_function_value ();
-      octave::symbol_scope fu_scope = fu->scope ();
-      octave::symbol_record::context_id context = 0;
-      if (fu_scope)
-        {
-          vars = fu_scope.all_variables ();
-          context = fu_scope.current_context ();
-        }
-
-      size_t varlen = vars.size ();
-
-      if (varlen > 0)
-        {
-          octave_scalar_map ws;
-          for (const auto& symrec : vars)
-            ws.assign (symrec.name (), symrec.varval (context));
-
-          m.setfield ("workspace", ws);
-        }
+      m.setfield ("workspace", fh->workspace ());
     }
   else if (fcn->is_user_function () || fcn->is_user_script ())
     {
       octave_function *fu = fh->function_value ();
       m.setfield ("file", fu->fcn_file_name ());
+
+      m.setfield ("workspace", fh->workspace ());
     }
   else
     m.setfield ("file", "");
@@ -1883,7 +2060,7 @@
         warning_with_id ("Octave:str2func-global-argument",
                          "str2func: second argument ignored");
 
-      retval = make_fcn_handle (nm);
+      retval = octave::make_fcn_handle (interp, nm);
     }
 
   return retval;
@@ -1948,208 +2125,12 @@
 %!error is_function_handle (1, 2)
 */
 
-octave_fcn_binder::octave_fcn_binder (const octave_value& f,
-                                      const octave_value& root,
-                                      const octave_value_list& templ,
-                                      const std::vector<int>& mask,
-                                      int exp_nargin)
-  : octave_fcn_handle (f), root_handle (root), arg_template (templ),
-    arg_mask (mask), expected_nargin (exp_nargin)
-{ }
-
-octave_fcn_handle *
-octave_fcn_binder::maybe_binder (const octave_value& f,
-                                 octave::tree_evaluator& tw)
-{
-  octave_fcn_handle *retval = nullptr;
-
-  octave_user_function *usr_fcn = f.user_function_value (false);
-  octave::tree_parameter_list *param_list = (usr_fcn ? usr_fcn->parameter_list ()
-                                                     : nullptr);
-
-  octave::tree_statement_list *cmd_list = nullptr;
-  octave::tree_expression *body_expr = nullptr;
-
-  if (usr_fcn)
-    {
-      cmd_list = usr_fcn->body ();
-      if (cmd_list)
-        {
-          // Verify that body is a single expression (always true in theory).
-          body_expr = (cmd_list->length () == 1
-                       ? cmd_list->front ()->expression () : nullptr);
-        }
-    }
-
-  if (body_expr && body_expr->is_index_expression ()
-      && ! (param_list && param_list->takes_varargs ()))
-    {
-      // It's an index expression.
-      octave::tree_index_expression *idx_expr = dynamic_cast<octave::tree_index_expression *> (body_expr);
-      octave::tree_expression *head_expr = idx_expr->expression ();
-      std::list<octave::tree_argument_list *> arg_lists = idx_expr->arg_lists ();
-      std::string type_tags = idx_expr->type_tags ();
-
-      if (type_tags.length () == 1 && type_tags[0] == '('
-          && head_expr->is_identifier ())
-        {
-          assert (arg_lists.size () == 1);
-
-          // It's a single index expression: a(x,y,....)
-          octave::tree_identifier *head_id =
-            dynamic_cast<octave::tree_identifier *> (head_expr);
-          octave::tree_argument_list *arg_list = arg_lists.front ();
-
-          // Build a map of input params to their position.
-          std::map<std::string, int> arginmap;
-          int npar = 0;
-
-          if (param_list)
-            {
-              for (auto& param_p : *param_list)
-                {
-                  octave::tree_decl_elt *elt = param_p;
-                  octave::tree_identifier *id = (elt ? elt->ident () : nullptr);
-                  if (id && ! id->is_black_hole ())
-                    arginmap[id->name ()] = npar;
-                }
-            }
-
-          if (arg_list && arg_list->length () > 0)
-            {
-              octave::symbol_scope scope = tw.get_current_scope ();
-
-              octave::symbol_record::context_id context
-                = scope.current_context ();
-
-              bool bad = false;
-              int nargs = arg_list->length ();
-              octave_value_list arg_template (nargs);
-              std::vector<int> arg_mask (nargs);
-
-              // Verify that each argument is either a named param, a constant,
-              // or a defined identifier.
-              int iarg = 0;
-              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_mask[iarg] = -1;
-                    }
-                  else if (elt && elt->is_identifier ())
-                    {
-                      octave::tree_identifier *elt_id =
-                        dynamic_cast<octave::tree_identifier *> (elt);
-                      if (arginmap.find (elt_id->name ()) != arginmap.end ())
-                        {
-                          arg_mask[iarg] = arginmap[elt_id->name ()];
-                        }
-                      else if (elt_id->is_defined (context))
-                        {
-                          arg_template(iarg) = tw.evaluate (elt_id);
-                          arg_mask[iarg] = -1;
-                        }
-                      else
-                        {
-                          bad = true;
-                          break;
-                        }
-                    }
-                  else
-                    {
-                      bad = true;
-                      break;
-                    }
-                }
-
-              octave_value root_val;
-
-              if (! bad)
-                {
-                  // If the head is a value, use it as root.
-                  if (head_id->is_defined (context))
-                    root_val = tw.evaluate (head_id);
-                  else
-                    {
-                      // It's a name.
-                      std::string head_name = head_id->name ();
-
-                      if (head_name == "eval" || head_name == "feval")
-                        bad = true;
-                      else
-                        {
-                          // Simulate try/catch.
-                          octave::unwind_protect frame;
-                          interpreter_try (frame);
-
-                          try
-                            {
-                              root_val = make_fcn_handle (head_name);
-                            }
-                          catch (const octave::execution_exception&)
-                            {
-                              octave::interpreter::recover_from_exception ();
-
-                              bad = true;
-                            }
-                        }
-                    }
-                }
-
-              if (! bad)
-                {
-                  // Stash proper name tags.
-                  std::list<string_vector> arg_names = idx_expr->arg_names ();
-                  assert (arg_names.size () == 1);
-                  arg_template.stash_name_tags (arg_names.front ());
-
-                  retval = new octave_fcn_binder (f, root_val, arg_template,
-                                                  arg_mask, npar);
-                }
-            }
-        }
-    }
-
-  if (! retval)
-    retval = new octave_fcn_handle (f, octave_fcn_handle::anonymous);
-
-  return retval;
-}
-
 /*
 %!test
 %! f = @(t) eval ('2*t');
 %! assert (f (21), 42);
 */
 
-octave_value_list
-octave_fcn_binder::call (int nargout, const octave_value_list& args)
-{
-  octave_value_list retval;
-
-  if (args.length () == expected_nargin)
-    {
-      for (int i = 0; i < arg_template.length (); i++)
-        {
-          int j = arg_mask[i];
-          if (j >= 0)
-            arg_template(i) = args(j); // May force a copy...
-        }
-
-      // Make a shallow copy of arg_template, to ensure consistency throughout
-      // the following call even if we happen to get back here.
-      octave_value_list tmp (arg_template);
-      retval = octave::feval (root_handle, tmp, nargout);
-    }
-  else
-    retval = octave_fcn_handle::call (nargout, args);
-
-  return retval;
-}
-
 /*
 %!function r = __f (g, i)
 %!  r = g(i);
--- a/libinterp/octave-value/ov-fcn-handle.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-handle.h	Fri Jul 12 12:14:43 2019 -0400
@@ -27,16 +27,18 @@
 #include "octave-config.h"
 
 #include <iosfwd>
+#include <list>
 #include <string>
-#include <memory>
 
 #include "ov-base.h"
-#include "ov-base-mat.h"
 #include "ov-fcn.h"
 #include "ov-typeinfo.h"
+#include "symscope.h"
 
 namespace octave
 {
+  class interpreter;
+  class stack_frame;
   class tree_evaluator;
 }
 
@@ -55,30 +57,33 @@
   static const std::string anonymous;
 
   octave_fcn_handle (void)
-    : fcn (), nm (), has_overloads (false), overloads () { }
+    : m_fcn (), m_obj (), m_name (), m_scope (), m_is_nested (false),
+      m_closure_frames (nullptr), m_dispatch_class ()
+  { }
 
-  octave_fcn_handle (const std::string& n)
-    : fcn (), nm (n), has_overloads (false), overloads () { }
-
-  octave_fcn_handle (const octave_value& f,  const std::string& n = anonymous);
+  octave_fcn_handle (const octave::symbol_scope& scope, const std::string& n);
 
-  octave_fcn_handle (const octave_fcn_handle& fh)
-    : octave_base_value (fh), fcn (fh.fcn), nm (fh.nm),
-      has_overloads (fh.has_overloads), overloads ()
-  {
-    for (int i = 0; i < btyp_num_types; i++)
-      builtin_overloads[i] = fh.builtin_overloads[i];
+  octave_fcn_handle (const octave::symbol_scope& scope,
+                     const octave_value& f,
+                     const std::string& n = anonymous);
 
-    overloads = fh.overloads;
-  }
+  octave_fcn_handle (const octave_value& f,
+                     const std::string& n = anonymous);
 
-  ~octave_fcn_handle (void) = default;
+  octave_fcn_handle (const octave_fcn_handle& fh) = default;
+
+  ~octave_fcn_handle (void);
 
   octave_base_value * clone (void) const
   { return new octave_fcn_handle (*this); }
   octave_base_value * empty_clone (void) const
   { return new octave_fcn_handle (); }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx)
   {
@@ -94,40 +99,31 @@
 
   bool is_function_handle (void) const { return true; }
 
-  builtin_type_t builtin_type (void) const { return btyp_func_handle; }
-
-  bool is_overloaded (void) const { return has_overloads; }
+  bool is_nested (void) const { return m_is_nested; }
 
   dim_vector dims (void) const;
 
-  octave_function * function_value (bool = false)
-  { return fcn.function_value (); }
-
-  octave_user_function * user_function_value (bool = false)
-  { return fcn.user_function_value (); }
+  // FIXME: These must go away.  They don't do the right thing for
+  // scoping or overloads.
+  octave_function * function_value (bool = false);
+  octave_user_function * user_function_value (bool = false);
 
   octave_fcn_handle * fcn_handle_value (bool = false) { return this; }
 
-  octave_value fcn_val (void) const { return fcn; }
+  octave_value fcn_val (void) const { return m_fcn; }
+
+  std::string fcn_name (void) const { return m_name; }
 
-  std::string fcn_name (void) const { return nm; }
+  void push_closure_context (octave::tree_evaluator& tw);
 
-  void set_overload (builtin_type_t btyp, const octave_value& ov_fcn)
+  octave_value workspace (void) const;
+
+  void set_dispatch_class (const std::string& class_name)
   {
-    if (btyp != btyp_unknown)
-      {
-        has_overloads = true;
-        builtin_overloads[btyp] = ov_fcn;
-      }
-
+    m_dispatch_class = class_name;
   }
 
-  void set_overload (const std::string& dispatch_type,
-                     const octave_value& ov_fcn)
-  {
-    has_overloads = true;
-    overloads[dispatch_type] = ov_fcn;
-  }
+  std::string get_dispatch_class (void) const { return m_dispatch_class; }
 
   bool is_equal_to (const octave_fcn_handle&) const;
 
@@ -137,7 +133,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -151,7 +147,7 @@
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
   // Simple function handles are printed without a newline.
-  bool print_as_scalar (void) const { return nm != anonymous; }
+  bool print_as_scalar (void) const { return m_name != anonymous; }
 
 private:
 
@@ -161,53 +157,49 @@
 
 protected:
 
-  // The function we are handling.
-  octave_value fcn;
+  // The function we are handling (this should be valid for handles to
+  // anonymous functions and some other special cases).  Otherwise, we
+  // perform dynamic lookup based on the name of the function we are
+  // handling and the scope where the function handle object was created.
+  octave_value m_fcn;
 
-  // The name of the handle, including the "@".
-  std::string nm;
+  // If defined, this is the classdef object corresponding to the
+  // classdef method we are handling.
+  octave_value m_obj;
+
+  // The function we would find without considering argument types.  We
+  // cache this value so that the function_value and user_function_value
+  // methods may continue to work.
+  octave_value m_generic_fcn;
 
-  // Whether the function is overloaded at all.
-  bool has_overloads;
+  // The name of the handle, not including the "@".
+  std::string m_name;
+
+  // The scope where this object was defined.
+  octave::symbol_scope m_scope;
+
+  // TRUE means this is a handle to a nested function.
+  bool m_is_nested;
 
-  // Overloads for builtin types.  We use array to make lookup faster.
-  octave_value builtin_overloads[btyp_num_types];
+  // Saved stack frames for handles to nested functions.  This allows us
+  // to access non-locals and other context info when calling nested
+  // functions indirectly through handles.
+  std::list<octave::stack_frame *> *m_closure_frames;
 
-  // Overloads for other classes.
-  str_ov_map overloads;
+  // The name of the class in which this handle was created, if any.
+  // Used to determine access permission when the referenced function is
+  // called.
+  std::string m_dispatch_class;
 
   bool parse_anon_fcn_handle (const std::string& fcn_text);
 
   virtual octave_value_list call (int nargout, const octave_value_list& args);
-
-  friend octave_value make_fcn_handle (const std::string &, bool);
 };
 
-extern octave_value make_fcn_handle (const std::string& nm);
-
-class
-OCTINTERP_API
-octave_fcn_binder : public octave_fcn_handle
+namespace octave
 {
-private:
-  // Private ctor.
-  octave_fcn_binder (const octave_value& f, const octave_value& root,
-                     const octave_value_list& templ,
-                     const std::vector<int>& mask, int exp_nargin);
-
-public:
+  extern octave_value
+  make_fcn_handle (interpreter& interp, const std::string& name);
+}
 
-  // Factory method.
-  static octave_fcn_handle * maybe_binder (const octave_value& f,
-                                           octave::tree_evaluator& tw);
-
-protected:
-
-  octave_value_list call (int nargout, const octave_value_list& args);
-
-  octave_value root_handle;
-  octave_value_list arg_template;
-  std::vector<int> arg_mask;
-  int expected_nargin;
-};
 #endif
--- a/libinterp/octave-value/ov-fcn-inline.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -35,7 +35,6 @@
 
 #include "oct-locbuf.h"
 
-#include "call-stack.h"
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
@@ -64,7 +63,7 @@
 octave_fcn_inline::octave_fcn_inline (const std::string& f,
                                       const string_vector& a,
                                       const std::string& n)
-  : octave_fcn_handle (n), iftext (f), ifargs (a)
+  : octave_fcn_handle (n), m_text (f), m_args (a)
 {
   // Form a string representing the function.
 
@@ -72,15 +71,15 @@
 
   buf << "@(";
 
-  for (int i = 0; i < ifargs.numel (); i++)
+  for (int i = 0; i < m_args.numel (); i++)
     {
       if (i > 0)
         buf << ", ";
 
-      buf << ifargs(i);
+      buf << m_args(i);
     }
 
-  buf << ") " << iftext;
+  buf << ") " << m_text;
 
   octave::interpreter& interp
     = octave::__get_interpreter__ ("octave_fcn_inline::octave_fcn_inline");
@@ -95,15 +94,15 @@
 
       if (fh)
         {
-          fcn = fh->fcn_val ();
+          m_fcn = fh->fcn_val ();
 
-          octave_user_function *uf = fcn.user_function_value ();
+          octave_user_function *uf = m_fcn.user_function_value ();
 
           if (uf)
             {
-              octave::call_stack& cs = interp.get_call_stack ();
+              octave::tree_evaluator& tw = interp.get_evaluator ();
 
-              octave_function *curr_fcn = cs.current ();
+              octave_function *curr_fcn = tw.current_function ();
 
               if (curr_fcn)
                 {
@@ -119,7 +118,7 @@
         }
     }
 
-  if (fcn.is_undefined ())
+  if (m_fcn.is_undefined ())
     error ("inline: unable to define function");
 }
 
@@ -152,15 +151,15 @@
 bool
 octave_fcn_inline::save_ascii (std::ostream& os)
 {
-  os << "# nargs: " <<  ifargs.numel () << "\n";
-  for (int i = 0; i < ifargs.numel (); i++)
-    os << ifargs(i) << "\n";
-  if (nm.length () < 1)
+  os << "# nargs: " <<  m_args.numel () << "\n";
+  for (int i = 0; i < m_args.numel (); i++)
+    os << m_args(i) << "\n";
+  if (m_name.length () < 1)
     // Write an invalid value to flag empty fcn handle name.
     os << "0\n";
   else
-    os << nm << "\n";
-  os << iftext << "\n";
+    os << m_name << "\n";
+  os << m_text << "\n";
   return true;
 }
 
@@ -170,12 +169,12 @@
   int nargs;
   if (extract_keyword (is, "nargs", nargs, true))
     {
-      ifargs.resize (nargs);
+      m_args.resize (nargs);
       for (int i = 0; i < nargs; i++)
-        is >> ifargs(i);
-      is >> nm;
-      if (nm == "0")
-        nm = "";
+        is >> m_args(i);
+      is >> m_name;
+      if (m_name == "0")
+        m_name = "";
 
       skip_preceeding_newline (is);
 
@@ -189,10 +188,10 @@
           buf = read_until_newline (is, true);
         }
 
-      iftext = buf;
+      m_text = buf;
 
-      octave_fcn_inline tmp (iftext, ifargs, nm);
-      fcn = tmp.fcn;
+      octave_fcn_inline tmp (m_text, m_args, m_name);
+      m_fcn = tmp.m_fcn;
 
       return true;
     }
@@ -201,22 +200,22 @@
 }
 
 bool
-octave_fcn_inline::save_binary (std::ostream& os, bool&)
+octave_fcn_inline::save_binary (std::ostream& os, bool)
 {
-  int32_t tmp = ifargs.numel ();
+  int32_t tmp = m_args.numel ();
   os.write (reinterpret_cast<char *> (&tmp), 4);
-  for (int i = 0; i < ifargs.numel (); i++)
+  for (int i = 0; i < m_args.numel (); i++)
     {
-      tmp = ifargs(i).length ();
+      tmp = m_args(i).length ();
       os.write (reinterpret_cast<char *> (&tmp), 4);
-      os.write (ifargs(i).c_str (), ifargs(i).length ());
+      os.write (m_args(i).c_str (), m_args(i).length ());
     }
-  tmp = nm.length ();
+  tmp = m_name.length ();
   os.write (reinterpret_cast<char *> (&tmp), 4);
-  os.write (nm.c_str (), nm.length ());
-  tmp = iftext.length ();
+  os.write (m_name.c_str (), m_name.length ());
+  tmp = m_text.length ();
   os.write (reinterpret_cast<char *> (&tmp), 4);
-  os.write (iftext.c_str (), iftext.length ());
+  os.write (m_text.c_str (), m_text.length ());
   return true;
 }
 
@@ -235,7 +234,7 @@
   else
     {
       int32_t tmp;
-      ifargs.resize (nargs);
+      m_args.resize (nargs);
       for (int i = 0; i < nargs; i++)
         {
           if (! is.read (reinterpret_cast<char *> (&tmp), 4))
@@ -245,7 +244,7 @@
 
           OCTAVE_LOCAL_BUFFER (char, ctmp, tmp+1);
           is.read (ctmp, tmp);
-          ifargs(i) = std::string (ctmp);
+          m_args(i) = std::string (ctmp);
 
           if (! is)
             return false;
@@ -258,7 +257,7 @@
 
       OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);
       is.read (ctmp1, tmp);
-      nm = std::string (ctmp1);
+      m_name = std::string (ctmp1);
 
       if (! is)
         return false;
@@ -270,13 +269,13 @@
 
       OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
       is.read (ctmp2, tmp);
-      iftext = std::string (ctmp2);
+      m_text = std::string (ctmp2);
 
       if (! is)
         return false;
 
-      octave_fcn_inline ftmp (iftext, ifargs, nm);
-      fcn = ftmp.fcn;
+      octave_fcn_inline ftmp (m_text, m_args, m_name);
+      m_fcn = ftmp.m_fcn;
     }
   return true;
 }
@@ -300,9 +299,9 @@
   if (group_hid < 0) return false;
 
   size_t len = 0;
-  for (int i = 0; i < ifargs.numel (); i++)
-    if (len < ifargs(i).length ())
-      len = ifargs(i).length ();
+  for (int i = 0; i < m_args.numel (); i++)
+    if (len < m_args(i).length ())
+      len = m_args(i).length ();
 
   hid_t space_hid, data_hid, type_hid;
   space_hid = data_hid = type_hid = -1;
@@ -313,7 +312,7 @@
   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);
 
   // Octave uses column-major, while HDF5 uses row-major ordering
-  hdims[1] = ifargs.numel ();
+  hdims[1] = m_args.numel ();
   hdims[0] = len + 1;
 
   space_hid = H5Screate_simple (2, hdims, nullptr);
@@ -336,15 +335,15 @@
       return false;
     }
 
-  OCTAVE_LOCAL_BUFFER (char, s, ifargs.numel () * (len + 1));
+  OCTAVE_LOCAL_BUFFER (char, s, m_args.numel () * (len + 1));
 
   // Save the args as a null teminated list
-  for (int i = 0; i < ifargs.numel (); i++)
+  for (int i = 0; i < m_args.numel (); i++)
     {
-      const char *cptr = ifargs(i).c_str ();
-      for (size_t j = 0; j < ifargs(i).length (); j++)
+      const char *cptr = m_args(i).c_str ();
+      for (size_t j = 0; j < m_args(i).length (); j++)
         s[i*(len+1)+j] = *cptr++;
-      s[ifargs(i).length ()] = '\0';
+      s[m_args(i).length ()] = '\0';
     }
 
   retval = H5Dwrite (data_hid, H5T_NATIVE_CHAR, octave_H5S_ALL, octave_H5S_ALL,
@@ -361,7 +360,7 @@
 
   // attach the type of the variable
   type_hid = H5Tcopy (H5T_C_S1);
-  H5Tset_size (type_hid, nm.length () + 1);
+  H5Tset_size (type_hid, m_name.length () + 1);
   if (type_hid < 0)
     {
       H5Gclose (group_hid);
@@ -385,7 +384,7 @@
 #endif
   if (data_hid < 0
       || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
-                   octave_H5P_DEFAULT, nm.c_str ()) < 0)
+                   octave_H5P_DEFAULT, m_name.c_str ()) < 0)
     {
       H5Sclose (space_hid);
       H5Tclose (type_hid);
@@ -395,7 +394,7 @@
   H5Dclose (data_hid);
 
   // attach the type of the variable
-  H5Tset_size (type_hid, iftext.length () + 1);
+  H5Tset_size (type_hid, m_text.length () + 1);
   if (type_hid < 0)
     {
       H5Gclose (group_hid);
@@ -411,7 +410,7 @@
 #endif
   if (data_hid < 0
       || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
-                   octave_H5P_DEFAULT, iftext.c_str ()) < 0)
+                   octave_H5P_DEFAULT, m_text.c_str ()) < 0)
     {
       H5Sclose (space_hid);
       H5Tclose (type_hid);
@@ -471,7 +470,7 @@
 
   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
 
-  ifargs.resize (hdims[1]);
+  m_args.resize (hdims[1]);
 
   OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]);
 
@@ -488,7 +487,7 @@
   H5Sclose (space_hid);
 
   for (size_t i = 0; i < hdims[1]; i++)
-    ifargs(i) = std::string (s1 + i*hdims[0]);
+    m_args(i) = std::string (s1 + i*hdims[0]);
 
 #if defined (HAVE_HDF5_18)
   data_hid = H5Dopen (group_hid, "nm", octave_H5P_DEFAULT);
@@ -551,7 +550,7 @@
     }
   H5Tclose (st_id);
   H5Dclose (data_hid);
-  nm = nm_tmp;
+  m_name = nm_tmp;
 
 #if defined (HAVE_HDF5_18)
   data_hid = H5Dopen (group_hid, "iftext", octave_H5P_DEFAULT);
@@ -614,10 +613,10 @@
     }
   H5Tclose (st_id);
   H5Dclose (data_hid);
-  iftext = iftext_tmp;
+  m_text = iftext_tmp;
 
-  octave_fcn_inline ftmp (iftext, ifargs, nm);
-  fcn = ftmp.fcn;
+  octave_fcn_inline ftmp (m_text, m_args, m_name);
+  m_fcn = ftmp.m_fcn;
 
   return true;
 
@@ -643,20 +642,20 @@
 {
   std::ostringstream buf;
 
-  if (nm.empty ())
+  if (m_name.empty ())
     buf << "f(";
   else
-    buf << nm << '(';
+    buf << m_name << '(';
 
-  for (int i = 0; i < ifargs.numel (); i++)
+  for (int i = 0; i < m_args.numel (); i++)
     {
       if (i)
         buf << ", ";
 
-      buf << ifargs(i);
+      buf << m_args(i);
     }
 
-  buf << ") = " << iftext;
+  buf << ") = " << m_text;
 
   octave_print_internal (os, buf.str (), pr_as_read_syntax,
                          current_print_indent_level ());
--- a/libinterp/octave-value/ov-fcn-inline.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-inline.h	Fri Jul 12 12:14:43 2019 -0400
@@ -43,13 +43,13 @@
 public:
 
   octave_fcn_inline (void)
-    : octave_fcn_handle (), iftext (), ifargs () { }
+    : octave_fcn_handle (), m_text (), m_args () { }
 
   octave_fcn_inline (const std::string& f, const string_vector& a,
                      const std::string& n = "");
 
   octave_fcn_inline (const octave_fcn_inline& fi)
-    : octave_fcn_handle (fi), iftext (fi.iftext), ifargs (fi.ifargs) { }
+    : octave_fcn_handle (fi), m_text (fi.m_text), m_args (fi.m_args) { }
 
   ~octave_fcn_inline (void) = default;
 
@@ -62,9 +62,9 @@
 
   octave_fcn_inline * fcn_inline_value (bool = false) { return this; }
 
-  std::string fcn_text (void) const { return iftext; }
+  std::string fcn_text (void) const { return m_text; }
 
-  string_vector fcn_arg_names (void) const { return ifargs; }
+  string_vector fcn_arg_names (void) const { return m_args; }
 
   octave_value convert_to_str_internal (bool, bool, char) const;
 
@@ -74,7 +74,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -92,10 +92,10 @@
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 
   // The expression of an inline function.
-  std::string iftext;
+  std::string m_text;
 
   // The args of an inline function.
-  string_vector ifargs;
+  string_vector m_args;
 };
 
 #endif
--- a/libinterp/octave-value/ov-fcn.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -33,12 +33,21 @@
 octave_function::clone (void) const
 {
   panic_impossible ();
-  return nullptr;
 }
 
 octave_base_value *
 octave_function::empty_clone (void) const
 {
   panic_impossible ();
-  return nullptr;
 }
+
+octave_value_list
+octave_function::call (octave::tree_evaluator& tw, int nargout,
+                       const octave_value_list& args,
+                       octave::stack_frame *closure_context)
+{
+  if (closure_context)
+    panic_impossible ();
+
+  return call (tw, nargout, args);
+}
--- a/libinterp/octave-value/ov-fcn.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-fcn.h	Fri Jul 12 12:14:43 2019 -0400
@@ -37,6 +37,7 @@
 
 namespace octave
 {
+  class stack_frame;
   class tree_evaluator;
   class tree_walker;
 }
@@ -93,16 +94,32 @@
   virtual octave::sys::time time_checked (void) const
   { return octave::sys::time (static_cast<time_t> (0)); }
 
+  virtual int call_depth (void) const { return 0; }
+
   virtual bool is_subfunction (void) const { return false; }
 
-  virtual bool is_class_constructor (const std::string& = "") const
+  bool is_class_constructor (const std::string& cname = "") const
+  {
+    return (is_classdef_constructor (cname) || is_legacy_constructor (cname));
+  }
+
+  bool is_class_method (const std::string& cname = "") const
+  {
+    return (is_classdef_method (cname) || is_legacy_method (cname));
+  }
+
+  virtual bool
+  is_legacy_constructor (const std::string& = "") const
   { return false; }
 
   virtual bool
   is_classdef_constructor (const std::string& = "") const
   { return false; }
 
-  virtual bool is_class_method (const std::string& = "") const
+  virtual bool is_legacy_method (const std::string& = "") const
+  { return false; }
+
+  virtual bool is_classdef_method (const std::string& = "") const
   { return false; }
 
   virtual bool takes_varargs (void) const { return false; }
@@ -204,7 +221,12 @@
   call (octave::tree_evaluator& tw, int nargout = 0,
         const octave_value_list& args = octave_value_list ()) = 0;
 
-protected:
+  virtual octave_value_list
+  call (octave::tree_evaluator& tw, int nargout,
+        const octave_value_list& args,
+        octave::stack_frame *closure_context);
+
+ protected:
 
   octave_function (const std::string& nm,
                    const std::string& ds = "")
--- a/libinterp/octave-value/ov-float.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-float.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -215,7 +215,7 @@
 }
 
 bool
-octave_float_scalar::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_float_scalar::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = LS_FLOAT;
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-float.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-float.h	Fri Jul 12 12:14:43 2019 -0400
@@ -229,6 +229,11 @@
   octave_value as_uint32 (void) const;
   octave_value as_uint64 (void) const;
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_scalar<float>::diag;
+
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
@@ -241,7 +246,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-flt-complex.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-complex.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -271,7 +271,7 @@
 }
 
 bool
-octave_float_complex::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_float_complex::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = static_cast<char> (LS_FLOAT);
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-flt-complex.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-complex.h	Fri Jul 12 12:14:43 2019 -0400
@@ -155,6 +155,11 @@
   octave_value as_double (void) const;
   octave_value as_single (void) const;
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_scalar<FloatComplex>::diag;
+
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   void increment (void) { scalar += 1.0; }
@@ -165,7 +170,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-flt-cx-diag.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -158,7 +158,7 @@
 
 bool
 octave_float_complex_diag_matrix::save_binary (std::ostream& os,
-                                               bool& /* save_as_floats */)
+                                               bool /* save_as_floats */)
 {
 
   int32_t r = matrix.rows ();
--- a/libinterp/octave-value/ov-flt-cx-diag.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-diag.h	Fri Jul 12 12:14:43 2019 -0400
@@ -80,7 +80,7 @@
   octave_value as_double (void) const;
   octave_value as_single (void) const;
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-flt-cx-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -384,7 +384,7 @@
 }
 
 bool
-octave_float_complex_matrix::save_binary (std::ostream& os, bool&)
+octave_float_complex_matrix::save_binary (std::ostream& os, bool)
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-flt-cx-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -149,7 +149,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-flt-re-diag.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -176,7 +176,7 @@
 
 bool
 octave_float_diag_matrix::save_binary (std::ostream& os,
-                                       bool& /* save_as_floats*/)
+                                       bool /* save_as_floats*/)
 {
 
   int32_t r = matrix.rows ();
--- a/libinterp/octave-value/ov-flt-re-diag.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-diag.h	Fri Jul 12 12:14:43 2019 -0400
@@ -90,7 +90,7 @@
   octave_value as_uint32 (void) const;
   octave_value as_uint64 (void) const;
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-flt-re-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -461,7 +461,7 @@
 }
 
 bool
-octave_float_matrix::save_binary (std::ostream& os, bool&)
+octave_float_matrix::save_binary (std::ostream& os, bool)
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-flt-re-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -197,7 +197,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-java.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-java.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -56,6 +56,7 @@
 #include "load-path.h"
 #include "lo-sysdep.h"
 #include "oct-env.h"
+#include "oct-process.h"
 #include "oct-shlib.h"
 #include "ov-java.h"
 #include "parse.h"
@@ -67,10 +68,13 @@
 
 #if defined (HAVE_JAVA)
 
+// FIXME: Should these values be configurable at run time?
+
 #if defined (OCTAVE_USE_WINDOWS_API)
 #  define LIBJVM_FILE_NAME "jvm.dll"
 #elif defined (__APPLE__)
 #  define LIBJVM_FILE_NAME "libjvm.dylib"
+#  define JAVA_HOME_CMD "/usr/libexec/java_home"
 #else
 #  define LIBJVM_FILE_NAME "libjvm.so"
 #endif
@@ -247,7 +251,7 @@
 
     void read_java_opts (const std::string& filename)
     {
-      std::string ascii_fname = octave::sys::get_ASCII_filename (filename);
+      std::string ascii_fname = sys::get_ASCII_filename (filename);
 
       std::ifstream js (ascii_fname.c_str ());
 
@@ -361,7 +365,7 @@
 //!
 //! @returns A string consisting of the lines of @c filepath which are neither
 //!   comments nor empty without trailing whitespace separated by
-//!   `octave::directory_path::path_sep_str()`.  The returned string also
+//!   'octave::directory_path::path_sep_str()'.  The returned string also
 //!   starts with that path separator.
 
 static std::string
@@ -528,10 +532,14 @@
 }
 
 #if defined (OCTAVE_USE_WINDOWS_API)
-// Declare function defined in sysdep.cc
-extern LONG
-get_regkey_value (HKEY h_rootkey, const std::string subkey,
-                  const std::string name, octave_value& value);
+
+namespace octave
+{
+  // Declare function defined in sysdep.cc
+  extern LONG
+  get_regkey_value (HKEY h_rootkey, const std::string subkey,
+                    const std::string name, octave_value& value);
+}
 
 static std::string
 get_jvm_lib_path_from_registry ()
@@ -549,14 +557,13 @@
   if (jversion.empty ())
     {
       value = "CurrentVersion";
-      retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+      retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
 
       if (retval != ERROR_SUCCESS)
         {
           // Search for JRE < 9
           key = R"(software\javasoft\java runtime environment)";
-          retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value,
-                                     regval);
+          retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
         }
 
       if (retval != ERROR_SUCCESS)
@@ -570,12 +577,12 @@
 
   key = key + '\\' + jversion;
   value = "RuntimeLib";
-  retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+  retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
   if (retval != ERROR_SUCCESS)
     {
       // Search for JRE < 9
       key = R"(software\javasoft\java runtime environment\)" + jversion;
-      retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+      retval = octave::get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
     }
 
   if (retval != ERROR_SUCCESS)
@@ -594,6 +601,7 @@
 }
 #endif
 
+
 //! Initialize the java virtual machine (jvm) and field #jvm if necessary.
 //!
 //! If the jvm exists and is initialized, #jvm points to it, i.e. is not 0
@@ -603,10 +611,10 @@
 //! it by setting #jvm_attached.  Otherwise, create a #jvm with some hard-
 //! coded options:
 //!
-//! - `-Djava.class.path=classpath`, where @c classpath is given by
+//! - '-Djava.class.path=classpath', where @c classpath is given by
 //!   #initial_class_path().
-//! - `-Djava.system.class.loader=org.octave.OctClassLoader`.
-//! - `-Xrs`
+//! - '-Djava.system.class.loader=org.octave.OctClassLoader'.
+//! - '-Xrs'
 //!
 //! Further options are read from the file @c java.opts in the directory given
 //! by #java_init_dir().
@@ -634,7 +642,7 @@
     locale = std::string (static_locale);
 
   octave::dynamic_library lib ("");
-  std::string jvm_lib_path = "linked in or loaded libraries";
+  std::string jvm_lib_path;
 
   // Check whether the Java VM library is already loaded or linked in.
   JNI_CreateJavaVM_t create_vm = reinterpret_cast<JNI_CreateJavaVM_t>
@@ -642,7 +650,9 @@
   JNI_GetCreatedJavaVMs_t get_vm = reinterpret_cast<JNI_GetCreatedJavaVMs_t>
                                    (lib.search ("JNI_GetCreatedJavaVMs"));
 
-  if (! create_vm || ! get_vm)
+  if (create_vm && get_vm)
+    jvm_lib_path = "linked in or loaded libraries";
+  else
     {
       // JAVA_HOME environment variable takes precedence
       std::string java_home_env = octave::sys::env::getenv ("JAVA_HOME");
@@ -655,7 +665,36 @@
           if (jvm_lib_path.empty ())
             jvm_lib_path = java_home_env + "/" LIBJVM_FILE_NAME;
         }
-      else
+
+#  if defined (__APPLE__)
+      // Use standard /usr/libexec/java_home if available.
+      if (jvm_lib_path.empty ())
+        {
+          octave::sys::file_stat libexec_java_home_exists (JAVA_HOME_CMD);
+          if (libexec_java_home_exists)
+            {
+              // FIXME: Should this command be fully configurable at run
+              // time?  Or is it OK for the options to be fixed here?
+
+              std::string java_home_cmd = std::string (JAVA_HOME_CMD)
+                + " --failfast --version 1.6+ 2>/dev/null";
+
+              octave::process_execution_result rslt
+                = octave::run_command_and_return_output (java_home_cmd);
+
+              if (rslt.exit_status () == 0)
+                {
+                  std::string output = rslt.stdout_output ();
+                  std::string found_path = output.substr (0, output.length() - 1);
+                  std::string jvm_lib_found = get_jvm_lib_path_in_subdir (found_path);
+                  if (!jvm_lib_found.empty ())
+                    jvm_lib_path = jvm_lib_found;
+                }
+            }
+        }
+#  endif
+
+      if (jvm_lib_path.empty ())
         {
 #if defined (OCTAVE_USE_WINDOWS_API)
           jvm_lib_path = get_jvm_lib_path_from_registry ();
@@ -1991,8 +2030,6 @@
           oct_args(i) = box (env, jobj, nullptr);
         }
 
-      BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
       if (val.is_function_handle ())
         {
           octave_function *fcn = val.function_value ();
@@ -2012,8 +2049,6 @@
         }
       else
         error ("trying to invoke non-invocable object");
-
-      END_INTERRUPT_WITH_EXCEPTIONS;
     }
 }
 
@@ -2340,7 +2375,7 @@
 }
 
 bool
-octave_java::save_binary (std::ostream& /* os */, bool& /* save_as_floats */)
+octave_java::save_binary (std::ostream& /* os */, bool /* save_as_floats */)
 {
   warning ("save: unable to save java objects, skipping");
 
--- a/libinterp/octave-value/ov-java.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-java.h	Fri Jul 12 12:14:43 2019 -0400
@@ -81,7 +81,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -91,6 +91,11 @@
 
   bool load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value_list
   subsref (const std::string& type,
            const std::list<octave_value_list>& idx, int nargout);
--- a/libinterp/octave-value/ov-lazy-idx.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-lazy-idx.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -237,7 +237,7 @@
   return true;
 }
 
-bool octave_lazy_index::save_binary (std::ostream& os, bool& save_as_floats)
+bool octave_lazy_index::save_binary (std::ostream& os, bool save_as_floats)
 {
   return save_binary_data (os, make_value (), value_save_tag,
                            "", false, save_as_floats);
--- a/libinterp/octave-value/ov-lazy-idx.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-lazy-idx.h	Fri Jul 12 12:14:43 2019 -0400
@@ -75,6 +75,11 @@
 
   bool isfloat (void) const { return true; }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx)
   { return make_value ().subsref (type, idx); }
@@ -177,6 +182,11 @@
   FORWARD_VALUE_QUERY1 (SparseMatrix, sparse_matrix_value)
   FORWARD_VALUE_QUERY1 (SparseComplexMatrix, sparse_complex_matrix_value)
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::diag;
+
   octave_value diag (octave_idx_type k = 0) const
   {
     return make_value ().diag (k);
@@ -209,7 +219,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-mex-fcn.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include "oct-shlib.h"
 
-#include "call-stack.h"
 #include "defaults.h"
 #include "dynamic-ld.h"
 #include "error.h"
@@ -98,12 +97,9 @@
 
   octave::unwind_protect frame;
 
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("octave_mex_function::call");
+  tw.push_stack_frame (this);
 
-  cs.push (this);
-
-  frame.add_method (cs, &octave::call_stack::pop);
+  frame.add_method (tw, &octave::tree_evaluator::pop_stack_frame);
 
   octave::profiler& profiler = tw.get_profiler ();
 
--- a/libinterp/octave-value/ov-mex-fcn.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-mex-fcn.h	Fri Jul 12 12:14:43 2019 -0400
@@ -85,6 +85,11 @@
 
   bool is_mex_function (void) const { return true; }
 
+  // We don't need to override both forms of the call method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_function::call;
+
   octave_value_list
   call (octave::tree_evaluator& tw, int nargout = 0,
         const octave_value_list& args = octave_value_list ());
--- a/libinterp/octave-value/ov-oncleanup.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-oncleanup.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,6 +26,7 @@
 
 #include "defun.h"
 #include "interpreter.h"
+#include "interpreter-private.h"
 #include "ov-oncleanup.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
@@ -64,49 +65,7 @@
 
 octave_oncleanup::~octave_oncleanup (void)
 {
-  if (fcn.is_undefined ())
-    return;
-
-  octave::unwind_protect frame;
-
-  // Clear interrupts.
-  frame.protect_var (octave_interrupt_state);
-  octave_interrupt_state = 0;
-
-  // Disallow quit().
-  frame.protect_var (quit_allowed);
-  quit_allowed = false;
-
-  interpreter_try (frame);
-
-  try
-    {
-      // Run the actual code.
-      octave::feval (fcn);
-    }
-  catch (const octave::interrupt_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      warning ("onCleanup: interrupt occurred in cleanup action");
-    }
-  catch (const octave::execution_exception&)
-    {
-      std::string msg = last_error_message ();
-      warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
-               msg.c_str ());
-
-    }
-  catch (const octave::exit_exception&)
-    {
-      // This shouldn't happen since we disabled quit above.
-      warning ("onCleanup: exit disabled while executing cleanup function");
-    }
-  catch (...) // Yes, the black hole.  We're in a d-tor.
-    {
-      // This shouldn't happen, in theory.
-      warning ("onCleanup: internal error: unhandled exception in cleanup action");
-    }
+  call_object_destructor ();
 }
 
 octave_scalar_map
@@ -134,7 +93,7 @@
 
 bool
 octave_oncleanup::save_binary (std::ostream& /* os */,
-                               bool& /* save_as_floats */)
+                               bool /* save_as_floats */)
 {
   warning ("save: unable to save onCleanup variables, skipping");
 
@@ -183,6 +142,61 @@
   os << ')';
 }
 
+void
+octave_oncleanup::call_object_destructor (void)
+{
+  if (fcn.is_undefined ())
+    return;
+
+  octave_value the_fcn = fcn;
+  fcn = octave_value ();
+
+  octave::unwind_protect frame;
+
+  // Clear interrupts.
+  frame.protect_var (octave_interrupt_state);
+  octave_interrupt_state = 0;
+
+  // Disallow quit().
+  frame.protect_var (quit_allowed);
+  quit_allowed = false;
+
+  interpreter_try (frame);
+
+  try
+    {
+      // Run the actual code.
+      octave::feval (the_fcn);
+    }
+  catch (const octave::interrupt_exception&)
+    {
+      octave::interpreter::recover_from_exception ();
+
+      warning ("onCleanup: interrupt occurred in cleanup action");
+    }
+  catch (const octave::execution_exception&)
+    {
+      octave::error_system& es
+        = octave::__get_error_system__ ("octave_oncleanup::call_object_destructor");
+
+      std::string msg = es.last_error_message ();
+
+      warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
+               msg.c_str ());
+
+    }
+  catch (const octave::exit_exception&)
+    {
+      // This shouldn't happen since we disabled quit above.
+      warning ("onCleanup: exit disabled while executing cleanup function");
+    }
+  catch (...) // Yes, the black hole.  We're in a d-tor.
+    {
+      // This shouldn't happen, in theory.
+      warning ("onCleanup: internal error: unhandled exception in cleanup action");
+    }
+}
+
 DEFUN (onCleanup, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{obj} =} onCleanup (@var{function})
--- a/libinterp/octave-value/ov-oncleanup.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-oncleanup.h	Fri Jul 12 12:14:43 2019 -0400
@@ -35,7 +35,8 @@
 class octave_oncleanup : public octave_base_value
 {
 public:
-  octave_oncleanup (void) : fcn () { }
+
+  octave_oncleanup (void) = default;
 
   octave_oncleanup (const octave_value& fcn);
 
@@ -72,7 +73,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -85,6 +86,8 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
+  void call_object_destructor (void);
+
 private:
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
--- a/libinterp/octave-value/ov-perm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-perm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -368,7 +368,7 @@
 }
 
 bool
-octave_perm_matrix::save_binary (std::ostream& os, bool&)
+octave_perm_matrix::save_binary (std::ostream& os, bool)
 {
 
   int32_t sz = matrix.rows ();
--- a/libinterp/octave-value/ov-perm.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-perm.h	Fri Jul 12 12:14:43 2019 -0400
@@ -56,6 +56,11 @@
 
   octave_value full_value (void) const { return to_dense (); }
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
@@ -86,6 +91,11 @@
   MatrixType matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::diag;
+
   octave_value diag (octave_idx_type k = 0) const
   { return to_dense () .diag (k); }
 
@@ -218,7 +228,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-range.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-range.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -566,7 +566,7 @@
 }
 
 bool
-octave_range::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_range::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = LS_DOUBLE;
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-range.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-range.h	Fri Jul 12 12:14:43 2019 -0400
@@ -93,6 +93,11 @@
 
   octave_base_value * try_narrowing_conversion (void);
 
+  // We don't need to override all three forms of subsref.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_value::subsref;
+
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx);
 
@@ -279,7 +284,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-re-diag.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-diag.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -243,7 +243,7 @@
 }
 
 bool
-octave_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats)
+octave_diag_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
 
   int32_t r = matrix.rows ();
--- a/libinterp/octave-value/ov-re-diag.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-diag.h	Fri Jul 12 12:14:43 2019 -0400
@@ -95,7 +95,7 @@
   octave_value as_uint32 (void) const;
   octave_value as_uint64 (void) const;
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-re-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -564,7 +564,7 @@
 }
 
 bool
-octave_matrix::save_binary (std::ostream& os, bool& save_as_floats)
+octave_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
 
   dim_vector dv = dims ();
--- a/libinterp/octave-value/ov-re-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -221,7 +221,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-re-sparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-sparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -244,7 +244,7 @@
 }
 
 bool
-octave_sparse_matrix::save_binary (std::ostream& os, bool& save_as_floats)
+octave_sparse_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
   dim_vector dv = this->dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-re-sparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-re-sparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -141,7 +141,7 @@
   { return os.write (matrix, block_size, output_type, skip, flt_fmt); }
 #endif
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-scalar.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-scalar.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -235,7 +235,7 @@
 }
 
 bool
-octave_scalar::save_binary (std::ostream& os, bool& /* save_as_floats */)
+octave_scalar::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
   char tmp = LS_DOUBLE;
   os.write (reinterpret_cast<char *> (&tmp), 1);
--- a/libinterp/octave-value/ov-scalar.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-scalar.h	Fri Jul 12 12:14:43 2019 -0400
@@ -232,6 +232,11 @@
   octave_value as_uint32 (void) const;
   octave_value as_uint64 (void) const;
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_base_scalar<double>::diag;
+
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
@@ -244,7 +249,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-str-mat.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-str-mat.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -456,7 +456,7 @@
 
 bool
 octave_char_matrix_str::save_binary (std::ostream& os,
-                                     bool& /* save_as_floats */)
+                                     bool /* save_as_floats */)
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 1)
--- a/libinterp/octave-value/ov-str-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-str-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -106,6 +106,11 @@
 
   octave_value resize (const dim_vector& dv, bool fill = false) const;
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_char_matrix::diag;
+
   octave_value diag (octave_idx_type k = 0) const
   { return octave_value (matrix.diag (k)); }
 
@@ -153,7 +158,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -237,6 +242,11 @@
     return octave_value (retval, '\'');
   }
 
+  // We don't need to override both forms of the diag method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_char_matrix_str::diag;
+
   octave_value diag (octave_idx_type k = 0) const
   { return octave_value (matrix.diag (k), '\''); }
 
--- a/libinterp/octave-value/ov-struct.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-struct.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -157,12 +157,10 @@
 
     case '.':
       {
-        if (map.numel () > 0)
-          {
-            const Cell t = dotref (idx.front ());
-
-            retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);
-          }
+        const Cell t = dotref (idx.front ());
+
+        if (! map.isempty ())
+          retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);
       }
       break;
 
@@ -539,7 +537,10 @@
 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
 {
   if (idx.length () == 0)
-    return map;
+    {
+      warn_empty_index (type_name ());
+      return map;
+    }
   else  // octave_map handles indexing itself.
     return map.index (idx, resize_ok);
 }
@@ -791,7 +792,7 @@
 }
 
 bool
-octave_struct::save_binary (std::ostream& os, bool& save_as_floats)
+octave_struct::save_binary (std::ostream& os, bool save_as_floats)
 {
   octave_map m = map_value ();
 
@@ -1451,7 +1452,7 @@
 }
 
 bool
-octave_scalar_struct::save_binary (std::ostream& os, bool& save_as_floats)
+octave_scalar_struct::save_binary (std::ostream& os, bool save_as_floats)
 {
   octave_map m = map_value ();
 
--- a/libinterp/octave-value/ov-struct.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-struct.h	Fri Jul 12 12:14:43 2019 -0400
@@ -138,7 +138,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
@@ -262,7 +262,7 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& save_as_floats);
+  bool save_binary (std::ostream& os, bool save_as_floats);
 
   bool load_binary (std::istream& is, bool swap,
                     octave::mach_info::float_format fmt);
--- a/libinterp/octave-value/ov-typeinfo.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-typeinfo.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -36,33 +36,31 @@
 #include "ov-typeinfo.h"
 #include "ov.h"
 
-// FIXME: we should also store all class names and provide a
-// way to list them (calling class with nargin == 0?).
-
-static NDArray
-as_nd_array (const Array<int>& x)
-{
-  NDArray retval (x.dims ());
-
-  for (int i = 0; i < x.numel (); i++)
-    retval.xelem(i) = x(i);
-
-  return retval;
-}
-
-static boolNDArray
-as_bool_nd_array (const Array<void *>& x)
-{
-  boolNDArray retval (x.dims ());
-
-  for (octave_idx_type i = 0; i < x.numel (); i++)
-    retval.xelem (i) = x(i);
-
-  return retval;
-}
-
 namespace octave
 {
+  // FIXME: we should also store all class names and provide a
+  // way to list them (calling class with nargin == 0?).
+
+  static NDArray as_nd_array (const Array<int>& x)
+  {
+    NDArray retval (x.dims ());
+
+    for (int i = 0; i < x.numel (); i++)
+      retval.xelem(i) = x(i);
+
+    return retval;
+  }
+
+  static boolNDArray as_bool_nd_array (const Array<void *>& x)
+  {
+    boolNDArray retval (x.dims ());
+
+    for (octave_idx_type i = 0; i < x.numel (); i++)
+      retval.xelem (i) = x(i);
+
+    return retval;
+  }
+
   type_info::type_info (int init_tab_sz)
     : num_types (0), types (dim_vector (init_tab_sz, 1), ""),
       vals (dim_vector (init_tab_sz, 1)),
@@ -770,112 +768,6 @@
     return type_info.register_type (t_name, c_name, val);
   }
 
-  bool register_unary_class_op (octave_value::unary_op op,
-                                unary_class_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_unary_class_op");
-
-    return type_info.register_unary_class_op (op, f);
-  }
-
-  bool register_unary_op (octave_value::unary_op op,
-                          int t, unary_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_unary_op");
-
-    return type_info.register_unary_op (op, t, f);
-  }
-
-  bool register_non_const_unary_op (octave_value::unary_op op,
-                                    int t, non_const_unary_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_non_const_unary_op");
-
-    return type_info.register_non_const_unary_op (op, t, f);
-  }
-
-  bool register_binary_class_op (octave_value::binary_op op,
-                                 binary_class_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_binary_class_op");
-
-    return type_info.register_binary_class_op (op, f);
-  }
-
-  bool register_binary_op (octave_value::binary_op op,
-                           int t1, int t2, binary_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_binary_op");
-
-    return type_info.register_binary_op (op, t1, t2, f);
-  }
-
-  bool register_binary_class_op (octave_value::compound_binary_op op,
-                                 binary_class_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_binary_class_op");
-
-    return type_info.register_binary_class_op (op, f);
-  }
-
-  bool register_binary_op (octave_value::compound_binary_op op,
-                           int t1, int t2, binary_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_binary_op");
-
-    return type_info.register_binary_op (op, t1, t2, f);
-  }
-
-  bool register_cat_op (int t1, int t2, cat_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_cat_op");
-
-    return type_info.register_cat_op (t1, t2, f);
-  }
-
-  bool register_assign_op (octave_value::assign_op op,
-                           int t_lhs, int t_rhs, assign_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_assign_op");
-
-    return type_info.register_assign_op (op, t_lhs, t_rhs, f);
-  }
-
-  bool register_assignany_op (octave_value::assign_op op,
-                              int t_lhs, assignany_op_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_assignany_op");
-
-    return type_info.register_assignany_op (op, t_lhs, f);
-  }
-
-  bool register_pref_assign_conv (int t_lhs, int t_rhs, int t_result)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_pref_assign_conv");
-
-    return type_info.register_pref_assign_conv (t_lhs, t_rhs, t_result);
-  }
-
-  bool register_widening_op (int t, int t_result,
-                             octave_base_value::type_conv_fcn f)
-  {
-    octave::type_info& type_info
-      = octave::__get_type_info__ ("register_widening_op");
-
-    return type_info.register_widening_op (t, t_result, f);
-  }
-
   octave_value lookup_type (const std::string& nm)
   {
     octave::type_info& type_info
--- a/libinterp/octave-value/ov-typeinfo.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-typeinfo.h	Fri Jul 12 12:14:43 2019 -0400
@@ -286,52 +286,6 @@
                             const std::string& c_name,
                             const octave_value& val);
 
-  OCTAVE_DEPRECATED(4.4, "use octave::type_info::register_unary_class_op instead")
-  extern bool register_unary_class_op (octave_value::unary_op op,
-                                       unary_class_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_unary_op instead")
-  extern bool register_unary_op (octave_value::unary_op op,
-                                 int t, unary_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_non_const_unary_op instead")
-  extern bool register_non_const_unary_op (octave_value::unary_op op,
-                                           int t, non_const_unary_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_binary_class_op instead")
-  extern bool register_binary_class_op (octave_value::binary_op op,
-                                        binary_class_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_binary_op instead")
-  extern bool register_binary_op (octave_value::binary_op op,
-                                  int t1, int t2, binary_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_binary_class_op instead")
-  extern bool register_binary_class_op (octave_value::compound_binary_op op,
-                                        binary_class_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_binary_op instead")
-  extern bool register_binary_op (octave_value::compound_binary_op op,
-                                  int t1, int t2, binary_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_cat_op instead")
-  extern bool register_cat_op (int t1, int t2, cat_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_assign_op instead")
-  extern bool register_assign_op (octave_value::assign_op op,
-                                  int t_lhs, int t_rhs, assign_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_assignany_op instead")
-  extern bool register_assignany_op (octave_value::assign_op op,
-                                     int t_lhs, assignany_op_fcn f);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_pref_assign_conv instead")
-  extern bool register_pref_assign_conv (int t_lhs, int t_rhs, int t_result);
-
-  OCTAVE_DEPRECATED (4.4, "use octave::type_info::register_widening_op instead")
-  extern bool register_widening_op (int t, int t_result,
-                                    octave_base_value::type_conv_fcn f);
-
   extern octave_value lookup_type (const std::string& nm);
 
   extern unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op op);
--- a/libinterp/octave-value/ov-usr-fcn.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -31,7 +31,6 @@
 #include "str-vec.h"
 
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defaults.h"
 #include "Cell.h"
 #include "defun.h"
@@ -64,6 +63,12 @@
 
 octave_user_code::~octave_user_code (void)
 {
+  // This function is no longer valid, so remove the pointer to it from
+  // the corresponding scope.
+  // FIXME: would it be better to use shared/weak pointers for this job
+  // instead of storing a bare pointer in the scope object?
+  m_scope.set_function (nullptr);
+
   // FIXME: shouldn't this happen automatically when deleting cmd_list?
   if (cmd_list)
     cmd_list->remove_all_breakpoints (file_name);
@@ -128,8 +133,7 @@
     = {{ "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 }};
+       { "time_checked", t_checked }};
 
   return octave_value (m);
 }
@@ -185,16 +189,18 @@
 
 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::tree_parameter_list *rl, octave::tree_statement_list *cl,
+   const local_vars_map& lviv)
   : octave_user_code ("", "", scope, cl, ""),
     param_list (pl), ret_list (rl),
+    m_local_var_init_vals (lviv),
     lead_comm (), trail_comm (),
     location_line (0), location_column (0),
     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),
-    class_constructor (none), class_method (false)
+    class_constructor (none), class_method (none)
 #if defined (HAVE_LLVM)
     , jit_info (0)
 #endif
@@ -450,9 +456,10 @@
 
 octave_value_list
 octave_user_function::call (octave::tree_evaluator& tw, int nargout,
-                            const octave_value_list& args)
+                            const octave_value_list& args,
+                            octave::stack_frame *closure_frames)
 {
-  return tw.execute_user_function (*this, nargout, args);
+  return tw.execute_user_function (*this, nargout, args, closure_frames);
 }
 
 void
@@ -515,6 +522,33 @@
   return retval;
 }
 
+std::string
+octave_user_function::method_type_str (void) const
+{
+  std::string retval;
+
+  switch (class_method)
+    {
+    case none:
+      retval = "none";
+      break;
+
+    case legacy:
+      retval = "legacy";
+      break;
+
+    case classdef:
+      retval = "classdef";
+      break;
+
+    default:
+      retval = "unrecognized enum value";
+      break;
+    }
+
+  return retval;
+}
+
 octave_value
 octave_user_function::dump (void) const
 {
@@ -556,11 +590,17 @@
 void
 octave_user_function::restore_warning_states (void)
 {
-  octave_value val = m_scope.varval (".saved_warning_states.");
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("octave_user_function::restore_warning_states");
+
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave_value val
+    = tw.get_auto_fcn_var (octave::stack_frame::SAVED_WARNING_STATES);
 
   if (val.is_defined ())
     {
-      // Fail spectacularly if .saved_warning_states. is not an
+      // Fail spectacularly if SAVED_WARNING_STATES is not an
       // octave_map (or octave_scalar_map) object.
 
       if (! val.isstruct ())
@@ -571,9 +611,6 @@
       Cell ids = m.contents ("identifier");
       Cell states = m.contents ("state");
 
-      octave::interpreter& interp
-        = octave::__get_interpreter__ ("octave_user_function::restore_warning_states");
-
       for (octave_idx_type i = 0; i < m.numel (); i++)
         Fwarning (interp, ovl (states(i), ids(i)));
     }
@@ -619,14 +656,14 @@
 
   octave_value retval;
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
   if (nargin == 1)
     {
       octave_value func = args(0);
 
       if (func.is_string ())
         {
+          octave::symbol_table& symtab = interp.get_symbol_table ();
+
           std::string name = func.string_value ();
           func = symtab.find_function (name);
           if (func.is_undefined ())
@@ -657,8 +694,9 @@
     }
   else
     {
-      octave::symbol_scope scope = symtab.require_current_scope ("nargin");
-      retval = scope.varval (".nargin.");
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
+      retval = tw.get_auto_fcn_var (octave::stack_frame::NARGIN);
 
       if (retval.is_undefined ())
         retval = 0;
@@ -729,14 +767,14 @@
 
   octave_value retval;
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
   if (nargin == 1)
     {
       octave_value func = args(0);
 
       if (func.is_string ())
         {
+          octave::symbol_table& symtab = interp.get_symbol_table ();
+
           std::string name = func.string_value ();
           func = symtab.find_function (name);
           if (func.is_undefined ())
@@ -780,11 +818,12 @@
     }
   else
     {
-      if (symtab.at_top_level ())
+      if (interp.at_top_level ())
         error ("nargout: invalid call at top level");
 
-      octave::symbol_scope scope = symtab.require_current_scope ("nargout");
-      retval = scope.varval (".nargout.");
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
+      retval = tw.get_auto_fcn_var (octave::stack_frame::NARGOUT);
 
       if (retval.is_undefined ())
         retval = 0;
@@ -851,17 +890,20 @@
   if (args.length () != 1)
     print_usage ();
 
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
-  if (symtab.at_top_level ())
+  if (interp.at_top_level ())
     error ("isargout: invalid call at top level");
 
-  octave::symbol_scope scope = symtab.require_current_scope ("isargout");
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave_value tmp;
 
-  int nargout1 = scope.varval (".nargout.").int_value ();
+  int nargout1 = 0;
+  tmp = tw.get_auto_fcn_var (octave::stack_frame::NARGOUT);
+  if (tmp.is_defined ())
+    nargout1 = tmp.int_value ();
 
   Matrix ignored;
-  octave_value tmp = scope.varval (".ignored.");
+  tmp = tw.get_auto_fcn_var (octave::stack_frame::IGNORED);
   if (tmp.is_defined ())
     ignored = tmp.matrix_value ();
 
--- a/libinterp/octave-value/ov-usr-fcn.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov-usr-fcn.h	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include <ctime>
 
 #include <string>
-#include <stack>
 
 #include "comment-list.h"
 #include "ovl.h"
@@ -44,6 +43,7 @@
 namespace octave
 {
   class file_info;
+  class stack_frame;
   class tree_parameter_list;
   class tree_statement_list;
   class tree_evaluator;
@@ -67,8 +67,7 @@
     : 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)
+      m_file_info (nullptr), cmd_list (cmds)
   { }
 
 public:
@@ -113,13 +112,6 @@
     return octave_value ();
   }
 
-  // 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;
 
   octave::tree_statement_list * body (void) { return cmd_list; }
@@ -143,9 +135,6 @@
   // 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;
@@ -191,15 +180,17 @@
 
   bool is_user_script (void) const { return true; }
 
+  // We don't need to override both forms of the call method.  The using
+  // declaration will avoid warnings about partially-overloaded virtual
+  // functions.
+  using octave_user_code::call;
+
   octave_value_list
   call (octave::tree_evaluator& tw, int nargout = 0,
         const octave_value_list& args = octave_value_list ());
 
   void accept (octave::tree_walker& tw);
 
-  // XXX FIXME
-  void set_call_depth (int val) { octave_user_code::set_call_depth (val); }
-
 private:
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
@@ -212,10 +203,13 @@
 {
 public:
 
+  typedef std::map<std::string, octave_value> local_vars_map;
+
   octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope (),
                         octave::tree_parameter_list *pl = nullptr,
                         octave::tree_parameter_list *rl = nullptr,
-                        octave::tree_statement_list *cl = nullptr);
+                        octave::tree_statement_list *cl = nullptr,
+                        const local_vars_map& lviv = local_vars_map ());
 
   // No copying!
 
@@ -225,12 +219,6 @@
 
   ~octave_user_function (void);
 
-  octave::symbol_record::context_id active_context () const
-  {
-    return is_anonymous_function ()
-      ? 0 : static_cast<octave::symbol_record::context_id>(m_call_depth);
-  }
-
   octave_function * function_value (bool = false) { return this; }
 
   octave_user_function * user_function_value (bool = false) { return this; }
@@ -340,37 +328,54 @@
     return is_inline_function () || is_anonymous_function ();
   }
 
+  void mark_as_nested_function (void) { nested_function = true; }
+
   bool is_nested_function (void) const { return nested_function; }
 
-  void mark_as_nested_function (void) { nested_function = true; }
+  bool is_parent_function (void) const { return m_scope.is_parent (); }
+
+  void mark_as_legacy_constructor (void) { class_constructor = legacy; }
 
-  void mark_as_class_constructor (void) { class_constructor = legacy; }
+  bool is_legacy_constructor (const std::string& cname = "") const
+  {
+    return (class_constructor == legacy
+            ? (cname.empty () ? true : cname == dispatch_class ()) : false);
+  }
 
   void mark_as_classdef_constructor (void) { class_constructor = classdef; }
 
-  bool is_class_constructor (const std::string& cname = "") const
-  {
-    return class_constructor == legacy
-      ? (cname.empty () ? true : cname == dispatch_class ()) : false;
-  }
-
   bool is_classdef_constructor (const std::string& cname = "") const
   {
-    return class_constructor == classdef
-      ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    return (class_constructor == classdef
+            ? (cname.empty () ? true : cname == dispatch_class ()) : false);
   }
 
-  void mark_as_class_method (void) { class_method = true; }
+  void mark_as_legacy_method (void) { class_method = legacy; }
 
-  bool is_class_method (const std::string& cname = "") const
+  bool is_legacy_method (const std::string& cname = "") const
   {
-    return class_method
-           ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    return (class_method == legacy
+            ? (cname.empty () ? true : cname == dispatch_class ()) : false);
+  }
+
+  void mark_as_classdef_method (void) { class_method = classdef; }
+
+  bool is_classdef_method (const std::string& cname = "") const
+  {
+    return (class_method == classdef
+            ? (cname.empty () ? true : cname == dispatch_class ()) : false);
   }
 
   octave_value_list
   call (octave::tree_evaluator& tw, int nargout = 0,
-        const octave_value_list& args = octave_value_list ());
+        const octave_value_list& args = octave_value_list ())
+  {
+    return call (tw, nargout, args, nullptr);
+  }
+
+  octave_value_list
+  call (octave::tree_evaluator& tw, int nargout,
+        const octave_value_list& args, octave::stack_frame *);
 
   octave::tree_parameter_list * parameter_list (void) { return param_list; }
 
@@ -380,6 +385,11 @@
 
   octave::comment_list * trailing_comment (void) { return trail_comm; }
 
+  const local_vars_map& local_var_init_vals (void) const
+  {
+    return m_local_var_init_vals;
+  }
+
   // If is_special_expr is true, retrieve the sigular expression that forms the
   // body.  May be null (even if is_special_expr is true).
   octave::tree_expression * special_expr (void);
@@ -396,12 +406,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
+  enum class_method_type
   {
     none,
     legacy,
@@ -409,6 +416,7 @@
   };
 
   std::string ctor_type_str (void) const;
+  std::string method_type_str (void) const;
 
   // List of arguments for this function.  These are local variables.
   octave::tree_parameter_list *param_list;
@@ -417,6 +425,9 @@
   // this function.
   octave::tree_parameter_list *ret_list;
 
+  // For anonymous function values inherited from parent scope.
+  local_vars_map m_local_var_init_vals;
+
   // The comments preceding the FUNCTION token.
   octave::comment_list *lead_comm;
 
@@ -449,14 +460,17 @@
   // TRUE means this is an anonymous function.
   bool anonymous_function;
 
-  // TRUE means this is a nested function. (either a child or parent)
+  // TRUE means this is a nested function.
   bool nested_function;
 
+  // TRUE means this function contains a nested function.
+  bool parent_function;
+
   // Enum describing whether this function is the constructor for class object.
-  class_ctor_type class_constructor;
+  class_method_type class_constructor;
 
-  // TRUE means this function is a method for a class.
-  bool class_method;
+  // Enum describing whether this function is a method for a class.
+  class_method_type class_method;
 
 #if defined (HAVE_LLVM)
   octave::jit_function_info *jit_info;
--- a/libinterp/octave-value/ov.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -1106,10 +1106,6 @@
   : rep (new octave_class (m, id, plist))
 { }
 
-octave_value::octave_value (const octave_value_list& l, bool)
-  : rep (new octave_cs_list (l))
-{ }
-
 octave_value::octave_value (const octave_value_list& l)
   : rep (new octave_cs_list (l))
 { }
--- a/libinterp/octave-value/ov.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave-value/ov.h	Fri Jul 12 12:14:43 2019 -0400
@@ -291,9 +291,6 @@
   octave_value (const octave_scalar_map& m, const std::string& id,
                 const std::list<std::string>& plist);
 
-  OCTAVE_DEPRECATED (4.4, "note: second argument is always ignored; use octave_value (const octave_value_list&) instead")
-  octave_value (const octave_value_list& m, bool);
-
   // This one is explicit because it can cause some trouble to
   // accidentally create a cs-list when one was not intended.
   explicit octave_value (const octave_value_list& m);
@@ -409,8 +406,13 @@
   Matrix size (void)
   { return rep->size (); }
 
-  octave_idx_type numel (const octave_value_list& idx)
-  { return rep->numel (idx); }
+  // FIXME: should this function be deprecated and removed?  It supports
+  // an undocumented feature of Matlab.
+  octave_idx_type xnumel (const octave_value_list& idx)
+  { return rep->xnumel (idx); }
+
+  // FIXME: Do we really need all these different versions of subsref
+  // and related functions?
 
   octave_value single_subsref (const std::string& type,
                                const octave_value_list& idx);
@@ -487,10 +489,6 @@
   octave_idx_type numel (void) const
   { return rep->numel (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type capacity (void) const
-  { return rep->numel (); }
-
   size_t byte_size (void) const
   { return rep->byte_size (); }
 
@@ -530,24 +528,12 @@
   bool isempty (void) const
   { return rep->isempty (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isempty' instead")
-  bool is_empty (void) const
-  { return rep->isempty (); }
-
   bool iscell (void) const
   { return rep->iscell (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'iscell' instead")
-  bool is_cell (void) const
-  { return rep->iscell (); }
-
   bool iscellstr (void) const
   { return rep->iscellstr (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'iscellstr' instead")
-  bool is_cellstr (void) const
-  { return rep->iscellstr (); }
-
   bool is_real_scalar (void) const
   { return rep->is_real_scalar (); }
 
@@ -590,10 +576,6 @@
   bool isstruct (void) const
   { return rep->isstruct (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isstruct' instead")
-  bool is_map (void) const
-  { return rep->isstruct (); }
-
   bool is_classdef_meta (void) const
   { return rep->is_classdef_meta (); }
 
@@ -609,17 +591,9 @@
   bool isobject (void) const
   { return rep->isobject (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isobject' instead")
-  bool is_object (void) const
-  { return rep->isobject (); }
-
   bool isjava (void) const
   { return rep->isjava (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isjava' instead")
-  bool is_java (void) const
-  { return rep->isjava (); }
-
   bool is_cs_list (void) const
   { return rep->is_cs_list (); }
 
@@ -629,10 +603,6 @@
   bool isnull (void) const
   { return rep->isnull (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isnull' instead")
-  bool is_null_value (void) const
-  { return rep->isnull (); }
-
   // Are any or all of the elements in this constant nonzero?
 
   octave_value all (int dim = 0) const
@@ -655,10 +625,6 @@
   bool isfloat (void) const
   { return rep->isfloat (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isfloat' instead")
-  bool is_float_type (void) const
-  { return rep->isfloat (); }
-
   // Integer types.
 
   bool is_int8_type (void) const
@@ -688,33 +654,17 @@
   bool isinteger (void) const
   { return rep->isinteger (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isinteger' instead")
-  bool is_integer_type (void) const
-  { return rep->isinteger (); }
-
   // Other type stuff.
 
   bool islogical (void) const
   { return rep->islogical (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'islogical' instead")
-  bool is_bool_type (void) const
-  { return rep->islogical (); }
-
   bool isreal (void) const
   { return rep->isreal (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isreal' instead")
-  bool is_real_type (void) const
-  { return rep->isreal (); }
-
   bool iscomplex (void) const
   { return rep->iscomplex (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'iscomplex' instead")
-  bool is_complex_type (void) const
-  { return rep->iscomplex (); }
-
   bool is_scalar_type (void) const
   { return rep->is_scalar_type (); }
 
@@ -724,17 +674,9 @@
   bool isnumeric (void) const
   { return rep->isnumeric (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isnumeric' instead")
-  bool is_numeric_type (void) const
-  { return rep->isnumeric (); }
-
   bool issparse (void) const
   { return rep->issparse (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'issparse' instead")
-  bool is_sparse_type (void) const
-  { return rep->issparse (); }
-
   // Does this constant correspond to a truth value?
 
   bool is_true (void) const
@@ -959,10 +901,6 @@
   string_vector string_vector_value (bool pad = false) const
   { return rep->string_vector_value (pad); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'string_vector_value' instead")
-  string_vector all_strings (bool pad = false) const
-  { return string_vector_value (pad); }
-
   Cell cell_value (void) const;
 
   Array<std::string> cellstr_value (void) const
@@ -1336,7 +1274,7 @@
 
   bool load_ascii (std::istream& is) { return rep->load_ascii (is); }
 
-  bool save_binary (std::ostream& os, bool& save_as_floats)
+  bool save_binary (std::ostream& os, bool save_as_floats)
   { return rep->save_binary (os, save_as_floats); }
 
   bool load_binary (std::istream& is, bool swap,
@@ -1381,10 +1319,6 @@
   sortmode issorted (sortmode mode = UNSORTED) const
   { return rep->issorted (mode); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
-  sortmode is_sorted (sortmode mode = UNSORTED) const
-  { return rep->issorted (mode); }
-
   Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const
   { return rep->sort_rows_idx (mode); }
 
@@ -1397,6 +1331,8 @@
 
   bool islocked (void) const { return rep->islocked (); }
 
+  void call_object_destructor (void) { return rep->call_object_destructor (); }
+
   octave_value dump (void) const { return rep->dump (); }
 
 #define MAPPER_FORWARD(F) \
@@ -1474,9 +1410,9 @@
   octave_value map (octave_base_value::unary_mapper_t umap) const
   { return rep->map (umap); }
 
-  //! Extract the n-th element, aka `val(n)`.
+  //! Extract the n-th element, aka 'val(n)'.
   //!
-  //! @return Result is undefined if `val` is not an array type
+  //! @return Result is undefined if 'val' is not an array type
   //!         or @p n is out of range.
   //!
   //! @warning Function calls should never error.
@@ -1485,9 +1421,9 @@
   fast_elem_extract (octave_idx_type n) const
   { return rep->fast_elem_extract (n); }
 
-  //! Assign the n-th element, aka `val(n) = x`.
+  //! Assign the n-th element, aka 'val(n) = x'.
   //!
-  //! @returns false if `val` is not an array type,
+  //! @returns false if 'val' is not an array type,
   //!          @p x is not a matching scalar type,
   //!          or @p n is out of range.
   //!
--- a/libinterp/octave.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -202,7 +202,7 @@
             break;
 
           case NO_SITE_FILE_OPTION:
-            m_read_site_files = 0;
+            m_read_site_files = false;
             break;
 
           case PERSIST_OPTION:
@@ -396,28 +396,6 @@
   }
 }
 
-// embedded is int here because octave_main is extern "C".
-
-int
-octave_main (int argc, char **argv, int embedded)
-{
-  if (embedded)
-    {
-      if (argc > 0)
-        std::cerr << "warning: ignoring command line options for embedded octave\n";
-
-      static octave::interpreter embedded_interpreter;
-      return embedded_interpreter.execute ();
-    }
-  else
-    {
-      std::cerr << "warning: octave_main should only be used to create an embedded interpreter";
-
-      static octave::cli_application app (argc, argv);
-      return app.execute ();
-    }
-}
-
 DEFUN (isguirunning, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} isguirunning ()
--- a/libinterp/octave.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/octave.h	Fri Jul 12 12:14:43 2019 -0400
@@ -25,8 +25,6 @@
 
 #include "octave-config.h"
 
-#if defined  (__cplusplus)
-
 #include <list>
 #include <string>
 
@@ -54,9 +52,6 @@
     bool debug_jit (void) const { return m_debug_jit; }
     bool echo_commands (void) const { return m_echo_commands; }
 
-    OCTAVE_DEPRECATED (4.4, "use 'gui' instead")
-    bool force_gui (void) const { return m_gui; }
-
     bool forced_interactive (void) const { return m_forced_interactive; }
     bool forced_line_editing (void) const { return m_forced_line_editing; }
     bool gui (void) const { return m_gui; }
@@ -64,9 +59,6 @@
     bool jit_compiler (void) const { return m_jit_compiler; }
     bool line_editing (void) const { return m_line_editing; }
 
-    OCTAVE_DEPRECATED (4.4, "use '! gui' instead")
-    bool no_gui (void) const { return ! gui (); }
-
     bool no_window_system (void) const { return m_no_window_system; }
     bool persist (void) const { return m_persist; }
     bool read_history_file (void) const { return m_read_history_file; }
@@ -90,9 +82,6 @@
     void debug_jit (bool arg) { m_debug_jit = arg; }
     void echo_commands (bool arg) { m_echo_commands = arg; }
 
-    OCTAVE_DEPRECATED (4.4, "use 'gui' instead")
-    void force_gui (bool arg) { m_gui = arg; }
-
     void forced_line_editing (bool arg) { m_forced_line_editing = arg; }
     void forced_interactive (bool arg) { m_forced_interactive = arg; }
     void gui (bool arg) { m_gui = arg; }
@@ -100,9 +89,6 @@
     void jit_compiler (bool arg) { m_jit_compiler = arg; }
     void line_editing (bool arg) { m_line_editing = arg; }
 
-    OCTAVE_DEPRECATED (4.4, "this has been removed and is the default now")
-    void no_gui (bool) { return; }
-
     void no_window_system (bool arg) { m_no_window_system = arg; }
     void persist (bool arg) { m_persist = arg; }
     void read_history_file (bool arg) { m_read_history_file = arg; }
@@ -386,16 +372,3 @@
 }
 
 #endif
-
-#if defined  (__cplusplus)
-extern "C" {
-#endif
-
-OCTAVE_DEPRECATED (4.4, "see the Octave documentation for other options")
-extern OCTINTERP_API int octave_main (int argc, char **argv, int embedded);
-
-#if defined  (__cplusplus)
-}
-#endif
-
-#endif
--- a/libinterp/op-kw-docs	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/op-kw-docs	Fri Jul 12 12:14:43 2019 -0400
@@ -16,6 +16,17 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <https://www.gnu.org/licenses/>.
 
+## FIXME: Can't have duplicate DOCSTRING entries.  The function properties
+##        already has a docstring which overrides this keyword definition.
+##        If this is ever fixed this entry can be re-inserted after the
+##        keyword "persistent".
+## properties
+##  libinterp/parse-tree/oct-parse.yy
+## -*- texinfo -*-
+## @deftypefn {} {} properties
+## Begin a properties block in a classdef definition.
+## @end deftypefn
+
 !
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
@@ -707,12 +718,6 @@
 elsewhere.
 @seealso{global}
 @end deftypefn
-properties
-@c libinterp/parse-tree/oct-parse.yy
--*- texinfo -*-
-@deftypefn {} {} properties
-Begin a properties block in a classdef definition.
-@end deftypefn
 return
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
--- a/libinterp/operators/op-class.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-class.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -20,6 +20,9 @@
 
 */
 
+//! @file op-class.cc
+//! Unary and binary operators for classdef and old style classes.
+
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
@@ -37,189 +40,182 @@
 #include "symtab.h"
 #include "parse.h"
 
-// class ops.
+//! Default unary class operator.
+//!
+//! @param a operand
+//! @param opname operator name
+
+static octave_value
+oct_unop_default (const octave_value& a, const std::string& opname)
+{
+  std::string class_name = a.class_name ();
+
+  octave_value meth
+    = octave::__get_symbol_table__ ("oct_unop_" + opname)
+      .find_method (opname, class_name);
+
+  if (meth.is_defined ())
+    {
+      // Call overloaded unary class operator.
+      octave_value_list tmp = octave::feval (meth.function_value (),
+                                             ovl (a), 1);
+
+      // Return first element if present.
+      if (tmp.length () > 0)
+        return tmp(0);
+
+      return octave_value ();
+    }
+
+  // Matlab compatibility:  If (conjugate) transpose is not overloaded and
+  // the number of dimensions is maximal two, just transpose the array of
+  // that class.
 
-#define DEF_CLASS_UNOP(name)                                            \
-  static octave_value                                                   \
-  oct_unop_ ## name (const octave_value& a)                             \
-  {                                                                     \
-    octave_value retval;                                                \
-                                                                        \
-    std::string class_name = a.class_name ();                           \
-                                                                        \
-    octave::symbol_table& symtab                                        \
-      = octave::__get_symbol_table__ ("oct_unop_" #name);               \
-                                                                        \
-    octave_value meth = symtab.find_method (#name, class_name);         \
-                                                                        \
-    if (meth.is_undefined ())                                           \
-      error ("%s method not defined for %s class", #name,               \
-             class_name.c_str ());                                      \
-                                                                        \
-    octave_value_list args;                                             \
-                                                                        \
-    args(0) = a;                                                        \
-                                                                        \
-    octave_value_list tmp = octave::feval (meth.function_value (), args, 1); \
-                                                                        \
-    if (tmp.length () > 0)                                              \
-      retval = tmp(0);                                                  \
-                                                                        \
-    return retval;                                                      \
+  if ((opname == "transpose") || (opname == "ctranspose"))
+    {
+      if (a.ndims () > 2)
+        error ("%s not defined for N-D objects of %s class", opname.c_str (),
+               class_name.c_str ());
+
+      if (a.is_classdef_object ())
+        {
+          // FIXME: Default transposition for classdef arrays.
+
+          error ("%s method not defined for %s class", opname.c_str (),
+                 class_name.c_str ());
+        }
+      else
+        {
+          const octave_class& v
+            = dynamic_cast<const octave_class&> (a.get_rep ());
+
+          return octave_value (v.map_value ().transpose (),
+                               v.class_name (),
+                               v.parent_class_name_list ());
+        }
+    }
+  else
+    error ("%s method not defined for %s class", opname.c_str (),
+           class_name.c_str ());
+}
+
+//! Helper macro to define unary class operators.
+
+#define DEF_CLASS_UNOP(opname)                 \
+  static octave_value                          \
+  oct_unop_ ## opname (const octave_value& a)  \
+  {                                            \
+    return oct_unop_default (a, #opname);      \
   }
 
-DEF_CLASS_UNOP (not)
-DEF_CLASS_UNOP (uplus)
-DEF_CLASS_UNOP (uminus)
+DEF_CLASS_UNOP (not)         // !a or ~a
+DEF_CLASS_UNOP (uplus)       // +a
+DEF_CLASS_UNOP (uminus)      // -a
+DEF_CLASS_UNOP (transpose)   //  a.'
+DEF_CLASS_UNOP (ctranspose)  //  a'
+#undef DEF_CLASS_UNOP
+
+//! Default binary class operator.
+//!
+//! @param a1 first  operand
+//! @param a2 second operand
+//! @param opname operator name
+//!
+//! The operator precedence is as follows:
+//!
+//! 1.   If exactly one of the operands is a user defined class object, then
+//!      the class method of that operand is invoked.
+//!
+//! 2.   If both operands are user defined class objects, then
+//! 2.1  The superior class method is invoked.
+//! 2.2  The leftmost class method is invoked if both classes are the same
+//!      or their precedence is not defined by superiorto/inferiorto.
+
+static octave_value
+oct_binop_default (const octave_value& a1, const octave_value& a2,
+                   const std::string& opname)
+{
+  octave::symbol_table& symtab
+    = octave::__get_symbol_table__ ("oct_binop_" + opname);
 
-// In case of (conjugate) transpose first check for overloaded class method.
-// If not overloaded, just transpose the underlying map_value, if the number
-// of dimensions is maximal two.  Matlab compatibility.
+  // Dispatch to first (leftmost) operand by default.
+  std::string dispatch_type = a1.class_name ();
+
+  // Determine, if second operand takes precedence (see rules above).
+  if (! a1.isobject ()
+      || (a1.isobject () && a2.isobject ()
+          && symtab.is_superiorto (a2.class_name (), dispatch_type)))
+    dispatch_type = a2.class_name ();
+
+  octave_value meth = symtab.find_method (opname, dispatch_type);
+
+  if (meth.is_undefined ())
+    error ("%s method not defined for %s class", opname.c_str (),
+           dispatch_type.c_str ());
 
-// FIXME: Default transposition for classdef arrays.
+  octave_value_list tmp = octave::feval (meth.function_value (),
+                                         ovl (a1, a2), 1);
+
+  if (tmp.length () > 0)
+    return tmp(0);
 
-#define DEF_CLASS_UNOP_TRANS(name)                                       \
+  return octave_value ();
+}
+
+//! Helper macro to define binary class operators.
+
+#define DEF_CLASS_BINOP(opname)                                          \
   static octave_value                                                    \
-  oct_unop_ ## name (const octave_value& a)                              \
+  oct_binop_ ## opname (const octave_value& a1, const octave_value& a2)  \
   {                                                                      \
-    octave_value retval;                                                 \
-                                                                         \
-    std::string class_name = a.class_name ();                            \
-                                                                         \
-    octave::symbol_table& symtab                                         \
-      = octave::__get_symbol_table__ ("oct_unop_" #name);                \
-                                                                         \
-    octave_value meth = symtab.find_method (#name, class_name);          \
-                                                                         \
-    if (meth.is_undefined ())                                            \
-      {                                                                  \
-        if (a.ndims () > 2)                                              \
-          error ("#name not defined for N-D objects");                   \
-                                                                         \
-        if (! a.is_classdef_object ())                                   \
-          {                                                              \
-            const octave_class& v                                        \
-              = dynamic_cast<const octave_class&> (a.get_rep ());        \
-                                                                         \
-            return octave_value (v.map_value ().transpose (),            \
-                                 v.class_name (),                        \
-                                 v.parent_class_name_list ());           \
-          }                                                              \
-        else                                                             \
-          error ("%s method not defined for %s class", #name,            \
-             class_name.c_str ());                                       \
-      }                                                                  \
-                                                                         \
-    octave_value_list args;                                              \
-                                                                         \
-    args(0) = a;                                                         \
-                                                                         \
-    octave_value_list tmp = octave::feval (meth.function_value (), args, 1); \
-                                                                         \
-    if (tmp.length () > 0)                                               \
-      retval = tmp(0);                                                   \
-                                                                         \
-    return retval;                                                       \
+    return oct_binop_default (a1, a2, #opname);                          \
   }
 
-DEF_CLASS_UNOP_TRANS (transpose)
-DEF_CLASS_UNOP_TRANS (ctranspose)
-
-// The precedence of the oct_binop_*-functions is as follows:
-//
-// 1.   If exactly one of the arguments is a user defined class object, then
-//      the function of that operand's class is invoked.
-//
-// 2.   If both arguments are user defined class objects, then
-// 2.1  The superior class function is invoked.
-// 2.2  The leftmost class function is invoked if both classes are the same
-//      or their precedence is not defined by superiorto/inferiorto.
-
-#define DEF_CLASS_BINOP(name)                                           \
-  static octave_value                                                   \
-  oct_binop_ ## name (const octave_value& a1, const octave_value& a2)   \
-  {                                                                     \
-    octave_value retval;                                                \
-                                                                        \
-    octave::symbol_table& symtab                                        \
-      = octave::__get_symbol_table__ ("oct_binop_" #name);              \
-                                                                        \
-    std::string dispatch_type = a1.class_name ();                       \
-                                                                        \
-    if (! a1.isobject ()                                                \
-        || (a1.isobject () && a2.isobject ()                            \
-            && symtab.is_superiorto (a2.class_name (), dispatch_type))) \
-      dispatch_type = a2.class_name ();                                 \
-                                                                        \
-    octave_value meth = symtab.find_method (#name, dispatch_type);      \
-                                                                        \
-    if (meth.is_undefined ())                                           \
-      error ("%s method not defined for %s class", #name,               \
-             dispatch_type.c_str ());                                   \
-                                                                        \
-    octave_value_list args;                                             \
-                                                                        \
-    args(1) = a2;                                                       \
-    args(0) = a1;                                                       \
-                                                                        \
-    octave_value_list tmp = octave::feval (meth.function_value (), args, 1); \
-                                                                        \
-    if (tmp.length () > 0)                                              \
-      retval = tmp(0);                                                  \
-                                                                        \
-    return retval;                                                      \
-  }
-
-DEF_CLASS_BINOP (plus)
-DEF_CLASS_BINOP (minus)
-DEF_CLASS_BINOP (mtimes)
-DEF_CLASS_BINOP (mrdivide)
-DEF_CLASS_BINOP (mpower)
-DEF_CLASS_BINOP (mldivide)
-DEF_CLASS_BINOP (lt)
-DEF_CLASS_BINOP (le)
-DEF_CLASS_BINOP (eq)
-DEF_CLASS_BINOP (ge)
-DEF_CLASS_BINOP (gt)
-DEF_CLASS_BINOP (ne)
-DEF_CLASS_BINOP (times)
-DEF_CLASS_BINOP (rdivide)
-DEF_CLASS_BINOP (power)
-DEF_CLASS_BINOP (ldivide)
-DEF_CLASS_BINOP (and)
-DEF_CLASS_BINOP (or)
-
-#define INSTALL_CLASS_UNOP_TI(ti, op, f)                        \
-  ti.install_unary_class_op (octave_value::op, oct_unop_ ## f)
-
-#define INSTALL_CLASS_BINOP_TI(ti, op, f)                       \
-  ti.install_binary_class_op (octave_value::op, oct_binop_ ## f)
+DEF_CLASS_BINOP (plus)     // a1 + a2
+DEF_CLASS_BINOP (minus)    // a1 - a2
+DEF_CLASS_BINOP (mtimes)   // a1 * a2
+DEF_CLASS_BINOP (mrdivide) // a1 / a2
+DEF_CLASS_BINOP (mpower)   // a1 ^ a2
+DEF_CLASS_BINOP (mldivide) // a1 \ a2
+DEF_CLASS_BINOP (lt)       // a1 <  a2
+DEF_CLASS_BINOP (le)       // a1 <= a2
+DEF_CLASS_BINOP (eq)       // a1 <= a2
+DEF_CLASS_BINOP (ge)       // a1 >= a2
+DEF_CLASS_BINOP (gt)       // a1 >  a2
+DEF_CLASS_BINOP (ne)       // a1 ~= a2 or a1 != a2
+DEF_CLASS_BINOP (times)    // a1 .* a2
+DEF_CLASS_BINOP (rdivide)  // a1 ./ a2
+DEF_CLASS_BINOP (power)    // a1 .^ a2
+DEF_CLASS_BINOP (ldivide)  // a1 .\ a2
+DEF_CLASS_BINOP (and)      // a1 & a2
+DEF_CLASS_BINOP (or)       // a1 | a2
+#undef DEF_CLASS_BINOP
 
 void
 install_class_ops (octave::type_info& ti)
 {
-  INSTALL_CLASS_UNOP_TI (ti, op_not, not);
-  INSTALL_CLASS_UNOP_TI (ti, op_uplus, uplus);
-  INSTALL_CLASS_UNOP_TI (ti, op_uminus, uminus);
-  INSTALL_CLASS_UNOP_TI (ti, op_transpose, transpose);
-  INSTALL_CLASS_UNOP_TI (ti, op_hermitian, ctranspose);
+  ti.install_unary_class_op (octave_value::op_not,       oct_unop_not);
+  ti.install_unary_class_op (octave_value::op_uplus,     oct_unop_uplus);
+  ti.install_unary_class_op (octave_value::op_uminus,    oct_unop_uminus);
+  ti.install_unary_class_op (octave_value::op_transpose, oct_unop_transpose);
+  ti.install_unary_class_op (octave_value::op_hermitian, oct_unop_ctranspose);
 
-  INSTALL_CLASS_BINOP_TI (ti, op_add, plus);
-  INSTALL_CLASS_BINOP_TI (ti, op_sub, minus);
-  INSTALL_CLASS_BINOP_TI (ti, op_mul, mtimes);
-  INSTALL_CLASS_BINOP_TI (ti, op_div, mrdivide);
-  INSTALL_CLASS_BINOP_TI (ti, op_pow, mpower);
-  INSTALL_CLASS_BINOP_TI (ti, op_ldiv, mldivide);
-  INSTALL_CLASS_BINOP_TI (ti, op_lt, lt);
-  INSTALL_CLASS_BINOP_TI (ti, op_le, le);
-  INSTALL_CLASS_BINOP_TI (ti, op_eq, eq);
-  INSTALL_CLASS_BINOP_TI (ti, op_ge, ge);
-  INSTALL_CLASS_BINOP_TI (ti, op_gt, gt);
-  INSTALL_CLASS_BINOP_TI (ti, op_ne, ne);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_mul, times);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_div, rdivide);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_pow, power);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_ldiv, ldivide);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_and, and);
-  INSTALL_CLASS_BINOP_TI (ti, op_el_or, or);
+  ti.install_binary_class_op (octave_value::op_add,     oct_binop_plus);
+  ti.install_binary_class_op (octave_value::op_sub,     oct_binop_minus);
+  ti.install_binary_class_op (octave_value::op_mul,     oct_binop_mtimes);
+  ti.install_binary_class_op (octave_value::op_div,     oct_binop_mrdivide);
+  ti.install_binary_class_op (octave_value::op_pow,     oct_binop_mpower);
+  ti.install_binary_class_op (octave_value::op_ldiv,    oct_binop_mldivide);
+  ti.install_binary_class_op (octave_value::op_lt,      oct_binop_lt);
+  ti.install_binary_class_op (octave_value::op_le,      oct_binop_le);
+  ti.install_binary_class_op (octave_value::op_eq,      oct_binop_eq);
+  ti.install_binary_class_op (octave_value::op_ge,      oct_binop_ge);
+  ti.install_binary_class_op (octave_value::op_gt,      oct_binop_gt);
+  ti.install_binary_class_op (octave_value::op_ne,      oct_binop_ne);
+  ti.install_binary_class_op (octave_value::op_el_mul,  oct_binop_times);
+  ti.install_binary_class_op (octave_value::op_el_div,  oct_binop_rdivide);
+  ti.install_binary_class_op (octave_value::op_el_pow,  oct_binop_power);
+  ti.install_binary_class_op (octave_value::op_el_ldiv, oct_binop_ldivide);
+  ti.install_binary_class_op (octave_value::op_el_and,  oct_binop_and);
+  ti.install_binary_class_op (octave_value::op_el_or,   oct_binop_or);
 }
--- a/libinterp/operators/op-cm-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cm-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-cx-mat.h"
@@ -47,12 +46,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_array_value () / d);
+  return octave_value (v1.complex_array_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (pow, complex_matrix, complex, xpow)
@@ -93,12 +87,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_array_value () / d);
+  return octave_value (v1.complex_array_value () / v2.complex_value ());
 }
 
 DEFNDBINOP_FN (el_pow, complex_matrix, complex, complex_array, complex,
--- a/libinterp/operators/op-cm-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cm-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -27,7 +27,6 @@
 #include "mx-cm-s.h"
 #include "mx-cnda-s.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-cx-mat.h"
@@ -50,12 +49,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_array_value () / d);
+  return octave_value (v1.complex_array_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (pow, complex_matrix, scalar, xpow)
@@ -91,12 +85,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_array_value () / d);
+  return octave_value (v1.complex_array_value () / v2.double_value ());
 }
 
 DEFNDBINOP_FN (el_pow, complex_matrix, scalar, complex_array, scalar, elem_xpow)
--- a/libinterp/operators/op-cm-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cm-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -54,14 +53,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.complex_array_value () / d);
-    }
+    return octave_value (v1.complex_array_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-cm-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cm-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -54,14 +53,7 @@
     = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.complex_array_value () / d);
-    }
+    return octave_value (v1.complex_array_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-cs-cm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-cm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -64,12 +63,7 @@
   const octave_complex_matrix& v2
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_array_value () / d);
+  return octave_value (v2.complex_array_value () / v1.complex_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, complex, complex_matrix, complex, complex_array,
@@ -97,12 +91,7 @@
   const octave_complex_matrix& v2
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_array_value () / d);
+  return octave_value (v2.complex_array_value () / v1.complex_value ());
 }
 
 DEFNDBINOP_FN (el_and, complex, complex_matrix, complex, complex_array,
--- a/libinterp/operators/op-cs-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include "Array-util.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -75,12 +74,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_value () / d);
+  return octave_value (v1.complex_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (pow, complex, complex, xpow)
@@ -90,12 +84,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_value () / d);
+  return octave_value (v2.complex_value () / v1.complex_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, complex, complex, <)
@@ -112,12 +101,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_value () / d);
+  return octave_value (v1.complex_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (el_pow, complex, complex, xpow)
@@ -127,12 +111,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_value () / d);
+  return octave_value (v2.complex_value () / v1.complex_value ());
 }
 
 DEFBINOP (el_and, complex, complex)
--- a/libinterp/operators/op-cs-m.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-m.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include "mx-cs-nda.h"
 #include "mx-nda-cs.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -68,12 +67,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.array_value () / d);
+  return octave_value (v2.array_value () / v1.complex_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, complex, matrix, complex, array, mx_el_lt)
@@ -92,12 +86,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.array_value () / d);
+  return octave_value (v2.array_value () / v1.complex_value ());
 }
 
 DEFNDBINOP_FN (el_and, complex, matrix, complex, array, mx_el_and)
--- a/libinterp/operators/op-cs-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -46,12 +45,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_value () / d);
+  return octave_value (v1.complex_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (pow, complex, scalar, xpow)
@@ -61,12 +55,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.double_value () / d);
+  return octave_value (v2.double_value () / v1.complex_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, complex, scalar, <)
@@ -83,12 +72,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.complex_value () / d);
+  return octave_value (v1.complex_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (el_pow, complex, scalar, xpow)
@@ -98,12 +82,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.double_value () / d);
+  return octave_value (v2.double_value () / v1.complex_value ());
 }
 
 DEFBINOP (el_and, complex, scalar)
--- a/libinterp/operators/op-cs-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -51,14 +50,8 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v1.complex_value ()
+                                                  / v2.complex_value ()));
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -84,12 +77,7 @@
   const octave_sparse_complex_matrix& v2
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.sparse_complex_matrix_value () / d);
+  return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
 }
 
 DEFBINOP_FN (lt, complex, sparse_complex_matrix, mx_el_lt)
@@ -110,15 +98,7 @@
   const octave_sparse_complex_matrix& v2
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
 }
 
 DEFBINOP_FN (el_and, complex, sparse_complex_matrix, mx_el_and)
--- a/libinterp/operators/op-cs-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-cs-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -52,14 +51,7 @@
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () / v2.scalar_value ()));
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -83,15 +75,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
 }
 
 DEFBINOP_FN (lt, complex, sparse_matrix, mx_el_lt)
@@ -110,15 +94,7 @@
   const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
-  Complex d = v1.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
 }
 
 DEFBINOP_FN (el_and, complex, sparse_matrix, mx_el_and)
@@ -136,8 +112,7 @@
 {
   const octave_complex& v = dynamic_cast<const octave_complex&> (a);
 
-  return new octave_sparse_matrix
-         (SparseMatrix (v.matrix_value ()));
+  return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));
 }
 
 void
--- a/libinterp/operators/op-dm-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-dm-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -33,7 +33,6 @@
 #include "mx-m-cs.h"
 #include "mx-cs-m.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -372,14 +371,7 @@
   const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -396,14 +388,7 @@
     = dynamic_cast<const octave_complex_diag_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      std::complex<double> d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -420,14 +405,7 @@
     = dynamic_cast<const octave_complex_diag_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      std::complex<double> d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-dm-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-dm-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -136,14 +135,7 @@
   const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-dms-template.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-dms-template.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #endif
 
 #include "ops.h"
-#include "errwarn.h"
 #include "xpow.h"
 #include SINCLUDE
 #include MINCLUDE
@@ -48,22 +47,12 @@
 #define MATRIX_VALUE CONCAT2(MATRIXV, _value)
 #define SCALAR_VALUE CONCAT2(SCALARV, _value)
 
-template <typename T>
-static T
-gripe_if_zero (T x)
-{
-  if (x == T ())
-    warn_divide_by_zero ();
-
-  return x;
-}
-
 DEFBINOP (dmsdiv, MATRIX, SCALAR)
 {
   const OCTAVE_MATRIX& v1 = dynamic_cast<const OCTAVE_MATRIX&> (a1);
   const OCTAVE_SCALAR& v2 = dynamic_cast<const OCTAVE_SCALAR&> (a2);
 
-  return v1.MATRIX_VALUE () / gripe_if_zero (v2.SCALAR_VALUE ());
+  return v1.MATRIX_VALUE () / v2.SCALAR_VALUE ();
 }
 
 DEFBINOP (sdmldiv, SCALAR, MATRIX)
@@ -71,7 +60,7 @@
   const OCTAVE_SCALAR& v1 = dynamic_cast<const OCTAVE_SCALAR&> (a1);
   const OCTAVE_MATRIX& v2 = dynamic_cast<const OCTAVE_MATRIX&> (a2);
 
-  return v2.MATRIX_VALUE () / gripe_if_zero (v1.SCALAR_VALUE ());
+  return v2.MATRIX_VALUE () / v1.SCALAR_VALUE ();
 }
 
 DEFBINOP (dmspow, MATRIX, SCALAR)
--- a/libinterp/operators/op-fcm-fcs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcm-fcs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-cx-mat.h"
@@ -52,12 +51,7 @@
   const octave_float_complex& v2
     = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_array_value () / d);
+  return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (pow, float_complex_matrix, float_complex, xpow)
@@ -101,12 +95,7 @@
   const octave_float_complex& v2
     = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_array_value () / d);
+  return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());
 }
 
 DEFNDBINOP_FN (el_pow, float_complex_matrix, float_complex,
--- a/libinterp/operators/op-fcm-fs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcm-fs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include "mx-fcnda-fs.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-cx-mat.h"
@@ -55,12 +54,7 @@
   const octave_float_scalar& v2
     = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_array_value () / d);
+  return octave_value (v1.float_complex_array_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (pow, float_complex_matrix, float_scalar, xpow)
@@ -105,12 +99,7 @@
   const octave_float_scalar& v2
     = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_array_value () / d);
+  return octave_value (v1.float_complex_array_value () / v2.float_value ());
 }
 
 DEFNDBINOP_FN (el_pow, float_complex_matrix, float_scalar, float_complex_array,
--- a/libinterp/operators/op-fcs-fcm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcs-fcm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -71,12 +70,7 @@
   const octave_float_complex_matrix& v2
     = dynamic_cast<const octave_float_complex_matrix&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_array_value () / d);
+  return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, float_complex, float_complex_matrix, float_complex,
@@ -106,12 +100,7 @@
   const octave_float_complex_matrix& v2
     = dynamic_cast<const octave_float_complex_matrix&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_array_value () / d);
+  return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());
 }
 
 DEFNDBINOP_FN (el_and, float_complex, float_complex_matrix, float_complex,
--- a/libinterp/operators/op-fcs-fcs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcs-fcs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -73,12 +72,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_value () / d);
+  return octave_value (v1.float_complex_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (pow, float_complex, float_complex, xpow)
@@ -88,12 +82,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_value () / d);
+  return octave_value (v2.float_complex_value () / v1.float_complex_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, float_complex, float_complex, <)
@@ -110,12 +99,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_value () / d);
+  return octave_value (v1.float_complex_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (el_pow, float_complex, float_complex, xpow)
@@ -125,12 +109,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_value () / d);
+  return octave_value (v2.float_complex_value () / v1.float_complex_value ());
 }
 
 DEFBINOP (el_and, float_complex, float_complex)
--- a/libinterp/operators/op-fcs-fm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcs-fm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -27,7 +27,6 @@
 #include "mx-fcs-fnda.h"
 #include "mx-fnda-fcs.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -69,12 +68,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_array_value () / d);
+  return octave_value (v2.float_array_value () / v1.float_complex_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, float_complex, float_matrix, float_complex,
@@ -102,12 +96,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_array_value () / d);
+  return octave_value (v2.float_array_value () / v1.float_complex_value ());
 }
 
 DEFNDBINOP_FN (el_and, float_complex, float_matrix, float_complex,
--- a/libinterp/operators/op-fcs-fs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fcs-fs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-complex.h"
@@ -49,12 +48,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_value () / d);
+  return octave_value (v1.float_complex_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (pow, float_complex, float_scalar, xpow)
@@ -64,12 +58,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_value () / d);
+  return octave_value (v2.float_value () / v1.float_complex_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, float_complex, float_scalar, <)
@@ -86,12 +75,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_complex_value () / d);
+  return octave_value (v1.float_complex_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (el_pow, float_complex, float_scalar, xpow)
@@ -101,12 +85,7 @@
   const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  FloatComplex d = v1.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_value () / d);
+  return octave_value (v2.float_value () / v1.float_complex_value ());
 }
 
 DEFBINOP (el_and, float_complex, float)
--- a/libinterp/operators/op-fm-fcs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fm-fcs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include "mx-fnda-fcs.h"
 #include "mx-fcs-fnda.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-re-mat.h"
@@ -54,12 +53,7 @@
   const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_array_value () / d);
+  return octave_value (v1.float_array_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (pow, float_matrix, float_complex, xpow)
@@ -100,12 +94,7 @@
   const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_array_value () / d);
+  return octave_value (v1.float_array_value () / v2.float_complex_value ());
 }
 
 DEFNDBINOP_FN (el_pow, float_matrix, float_complex, float_array,
--- a/libinterp/operators/op-fm-fs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fm-fs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-flt-re-mat.h"
@@ -46,12 +45,7 @@
   const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_array_value () / d);
+  return octave_value (v1.float_array_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (pow, float_matrix, float_scalar, xpow)
@@ -91,12 +85,7 @@
   const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_array_value () / d);
+  return octave_value (v1.float_array_value () / v2.float_value ());
 }
 
 DEFNDBINOP_FN (el_pow, float_matrix, float_scalar, float_array,
--- a/libinterp/operators/op-fs-fcm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fs-fcm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include "mx-fs-fcnda.h"
 #include "mx-fcnda-fs.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -77,12 +76,7 @@
   const octave_float_complex_matrix& v2
     = dynamic_cast<const octave_float_complex_matrix&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_array_value () / d);
+  return octave_value (v2.float_complex_array_value () / v1.float_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, float_scalar, float_complex_matrix, float_scalar,
@@ -112,12 +106,7 @@
   const octave_float_complex_matrix& v2
     = dynamic_cast<const octave_float_complex_matrix&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_array_value () / d);
+  return octave_value (v2.float_complex_array_value () / v1.float_value ());
 }
 
 DEFNDBINOP_FN (el_and, float_scalar, float_complex_matrix, float_scalar,
--- a/libinterp/operators/op-fs-fcs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fs-fcs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -49,12 +48,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_value () / d);
+  return octave_value (v1.float_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (pow, float_scalar, float_complex, xpow)
@@ -64,12 +58,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_value () / d);
+  return octave_value (v2.float_complex_value () / v1.float_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, float_scalar, float_complex, <)
@@ -86,12 +75,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  FloatComplex d = v2.float_complex_value ();
-
-  if (d == 0.0f)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_value () / d);
+  return octave_value (v1.float_value () / v2.float_complex_value ());
 }
 
 DEFBINOP_FN (el_pow, float_scalar, float_complex, xpow)
@@ -101,12 +85,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_complex_value () / d);
+  return octave_value (v2.float_complex_value () / v1.float_value ());
 }
 
 DEFBINOP (el_and, float_scalar, float_complex)
--- a/libinterp/operators/op-fs-fm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fs-fm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -64,12 +63,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_array_value () / d);
+  return octave_value (v2.float_array_value () / v1.float_value ());
 }
 
 DEFNDBINOP_FN (lt, float_scalar, float_matrix, float_scalar,
@@ -97,12 +91,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_array_value () / d);
+  return octave_value (v2.float_array_value () / v1.float_value ());
 }
 
 DEFNDBINOP_FN (el_and, float_scalar, float_matrix, float_scalar,
--- a/libinterp/operators/op-fs-fs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-fs-fs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include "Array-util.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -69,12 +68,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_value () / d);
+  return octave_value (v1.float_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (pow, float_scalar, float_scalar, xpow)
@@ -84,12 +78,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_value () / d);
+  return octave_value (v2.float_value () / v1.float_value ());
 }
 
 DEFBINOP_OP (lt, float_scalar, float_scalar, <)
@@ -106,12 +95,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v2.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.float_value () / d);
+  return octave_value (v1.float_value () / v2.float_value ());
 }
 
 DEFBINOP_FN (el_pow, float_scalar, float_scalar, xpow)
@@ -121,12 +105,7 @@
   const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
   const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
 
-  float d = v1.float_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.float_value () / d);
+  return octave_value (v2.float_value () / v1.float_value ());
 }
 
 DEFSCALARBOOLOP_OP (el_and, float_scalar, float_scalar, &&)
--- a/libinterp/operators/op-int.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-int.h	Fri Jul 12 12:14:43 2019 -0400
@@ -198,11 +198,7 @@
     const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
     const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
                                                                         \
-    if (! v2.T2 ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
   }                                                                     \
                                                                         \
   DEFINTBINOP_FN (PFX ## _pow, T1 ## scalar, T2 ## scalar, xpow, T3, ^) \
@@ -212,11 +208,7 @@
     const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
     const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
                                                                         \
-    if (! v1.T1 ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
   }                                                                     \
                                                                         \
   DEFINTBINOP_OP (PFX ## _el_mul, T1 ## scalar, T2 ## scalar, *, T3)    \
@@ -226,11 +218,7 @@
     const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
     const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
                                                                         \
-    if (! v2.T2 ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
   }                                                                     \
                                                                         \
   DEFINTBINOP_FN (PFX ## _el_pow, T1 ## scalar, T2 ## scalar, xpow, T3, .^) \
@@ -240,11 +228,7 @@
     const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
     const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
                                                                         \
-    if (! v1.T1 ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
   }
 
 #define OCTAVE_SS_INT_BOOL_OPS(PFX, T1, T2, Z1, Z2)                     \
@@ -347,11 +331,7 @@
    const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); \
    const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); \
                                                                         \
-   if (! v1.TS ## scalar_value ())                                      \
-     warn_divide_by_zero ();                                            \
-                                                                        \
-   octave_value retval = octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
-   return retval;                                                       \
+   return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
    }                                                                    \
                                                                         \
   DEFINTNDBINOP_OP (PFX ## _el_mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \
@@ -371,11 +351,7 @@
    const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); \
    const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); \
                                                                         \
-   if (! v1.TS ## scalar_value ())                                      \
-     warn_divide_by_zero ();                                            \
-                                                                        \
-   octave_value retval = octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
-   return retval;                                                       \
+   return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
    }
 
 #define OCTAVE_SM_INT_CMP_OPS(PFX, TS, TM)                              \
@@ -494,11 +470,7 @@
     const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); \
     const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); \
                                                                         \
-    if (! v2.TS ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
   }                                                                     \
                                                                         \
   /* DEFBINOP_FN (PFX ## _pow, TM ## matrix, TS ## scalar, xpow) */     \
@@ -521,11 +493,7 @@
     const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); \
     const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); \
                                                                         \
-    if (! v2.TS ## scalar_value ())                                     \
-      warn_divide_by_zero ();                                           \
-                                                                        \
-    octave_value retval = octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
-    return retval;                                                      \
+    return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
   }                                                                     \
                                                                         \
   DEFINTNDBINOP_FN (PFX ## _el_pow, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, elem_xpow, TI, .^) \
--- a/libinterp/operators/op-m-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-m-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include "mx-nda-cs.h"
 #include "mx-cs-nda.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-re-mat.h"
@@ -53,12 +52,7 @@
   const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.array_value () / d);
+  return octave_value (v1.array_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (pow, matrix, complex, xpow)
@@ -92,12 +86,7 @@
   const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.array_value () / d);
+  return octave_value (v1.array_value () / v2.complex_value ());
 }
 
 DEFNDBINOP_FN (el_pow, matrix, complex, array, complex, elem_xpow)
--- a/libinterp/operators/op-m-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-m-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-re-mat.h"
@@ -47,12 +46,7 @@
   const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.array_value () / d);
+  return octave_value (v1.array_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (pow, matrix, scalar, xpow)
@@ -86,12 +80,7 @@
   const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.array_value () / d);
+  return octave_value (v1.array_value () / v2.double_value ());
 }
 
 DEFNDBINOP_FN (el_pow, matrix, scalar, array, scalar, elem_xpow)
--- a/libinterp/operators/op-m-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-m-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -54,14 +53,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.array_value () / d);
-    }
+    return octave_value (v1.array_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-m-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-m-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -52,14 +51,7 @@
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.array_value () / d);
-    }
+    return octave_value (v1.array_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
--- a/libinterp/operators/op-s-cm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-cm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include "mx-s-cnda.h"
 #include "mx-cnda-s.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -72,12 +71,7 @@
   const octave_complex_matrix& v2
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_array_value () / d);
+  return octave_value (v2.complex_array_value () / v1.double_value ());
 }
 
 DEFNDCMPLXCMPOP_FN (lt, scalar, complex_matrix, scalar, complex_array, mx_el_lt)
@@ -97,12 +91,7 @@
   const octave_complex_matrix& v2
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_array_value () / d);
+  return octave_value (v2.complex_array_value () / v1.double_value ());
 }
 
 DEFNDBINOP_FN (el_and, scalar, complex_matrix, scalar, complex_array, mx_el_and)
--- a/libinterp/operators/op-s-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -48,12 +47,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.double_value () / d);
+  return octave_value (v1.double_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (pow, scalar, complex, xpow)
@@ -63,12 +57,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_value () / d);
+  return octave_value (v2.complex_value () / v1.double_value ());
 }
 
 DEFCMPLXCMPOP_OP (lt, scalar, complex, <)
@@ -85,12 +74,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.double_value () / d);
+  return octave_value (v1.double_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (el_pow, scalar, complex, xpow)
@@ -100,12 +84,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.complex_value () / d);
+  return octave_value (v2.complex_value () / v1.double_value ());
 }
 
 DEFBINOP (el_and, scalar, complex)
--- a/libinterp/operators/op-s-m.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-m.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -64,12 +63,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.array_value () / d);
+  return octave_value (v2.array_value () / v1.double_value ());
 }
 
 DEFNDBINOP_FN (lt, scalar, matrix, scalar, array, mx_el_lt)
@@ -88,12 +82,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.array_value () / d);
+  return octave_value (v2.array_value () / v1.double_value ());
 }
 
 DEFNDBINOP_FN (el_and, scalar, matrix, scalar, array, mx_el_and)
--- a/libinterp/operators/op-s-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,6 @@
 
 #include "Array-util.h"
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-scalar.h"
@@ -70,12 +69,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.double_value () / d);
+  return octave_value (v1.double_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (pow, scalar, scalar, xpow)
@@ -85,12 +79,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.double_value () / d);
+  return octave_value (v2.double_value () / v1.double_value ());
 }
 
 DEFBINOP_OP (lt, scalar, scalar, <)
@@ -107,12 +96,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v1.double_value () / d);
+  return octave_value (v1.double_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (el_pow, scalar, scalar, xpow)
@@ -122,12 +106,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v1.double_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  return octave_value (v2.double_value () / d);
+  return octave_value (v2.double_value () / v1.double_value ());
 }
 
 DEFSCALARBOOLOP_OP (el_and, scalar, scalar, &&)
--- a/libinterp/operators/op-s-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -54,14 +53,8 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v1.scalar_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v1.scalar_value ()
+                                                  / v2.complex_value ()));
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -87,15 +80,7 @@
   const octave_sparse_complex_matrix& v2
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
-  double d = v1.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());
 }
 
 DEFBINOP_FN (lt, scalar, sparse_complex_matrix, mx_el_lt)
@@ -115,15 +100,7 @@
   const octave_sparse_complex_matrix& v2
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
-  double d = v1.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());
 }
 
 DEFBINOP_FN (el_and, scalar, sparse_complex_matrix, mx_el_and)
--- a/libinterp/operators/op-s-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-s-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -49,14 +48,7 @@
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseMatrix (1, 1, v1.scalar_value () / d));
-    }
+    return octave_value (SparseMatrix (1, 1, v1.scalar_value () / v2.scalar_value ()));
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -80,15 +72,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
-  double d = v1.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_matrix_value () / v1.double_value ());
 }
 
 DEFBINOP_FN (lt, scalar, sparse_matrix, mx_el_lt)
@@ -107,15 +91,7 @@
   const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
-  double d = v1.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v2.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v2.sparse_matrix_value () / v1.double_value ());
 }
 
 DEFBINOP_FN (el_and, scalar, sparse_matrix, mx_el_and)
--- a/libinterp/operators/op-scm-cm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-cm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -74,14 +73,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.complex_array_value () / d);
-    }
+    return octave_value (v2.complex_array_value () / v1.complex_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-scm-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -50,15 +49,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP (pow, sparse_complex_matrix, complex)
@@ -76,14 +67,8 @@
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v2.complex_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()
+                                                  / v1.complex_value ()));
   else
     {
       MatrixType typ = v1.matrix_type ();
@@ -110,16 +95,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  octave_value retval;
-
-  Complex d = v2.complex_value ();
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (el_pow, sparse_complex_matrix, complex, elem_xpow)
--- a/libinterp/operators/op-scm-m.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-m.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -73,14 +72,7 @@
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.array_value () / d);
-    }
+    return octave_value (v2.array_value () / v1.complex_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-scm-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -53,15 +52,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP (pow, sparse_complex_matrix, scalar)
@@ -84,14 +75,8 @@
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v2.scalar_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v2.scalar_value ()
+                                                  / v1.complex_value ()));
   else
     {
       MatrixType typ = v1.matrix_type ();
@@ -118,15 +103,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_complex_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (el_pow, sparse_complex_matrix, scalar, elem_xpow)
--- a/libinterp/operators/op-scm-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -34,15 +33,10 @@
 
 #include "sparse-xdiv.h"
 #include "sparse-xpow.h"
+#include "ov-cx-mat.h"
+#include "ov-cx-sparse.h"
 #include "ov-re-sparse.h"
-#include "ov-cx-sparse.h"
 
-#include "errwarn.h"
-#include "ovl.h"
-#include "ov.h"
-#include "ov-cx-mat.h"
-#include "ov-typeinfo.h"
-#include "ops.h"
 #include "xdiv.h"
 #include "xpow.h"
 
@@ -70,24 +64,6 @@
           v.matrix_type ().transpose ());
 }
 
-#if 0
-DEFUNOP (incr, sparse_complex_matrix)
-{
-  const octave_sparse_complex_matrix& v
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a);
-
-  return octave_value (v.complex_matrix_value () .increment ());
-}
-
-DEFUNOP (decr, sparse_complex_matrix)
-{
-  const octave_sparse_complex_matrix& v
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a);
-
-  return octave_value (v.complex_matrix_value () .decrement ());
-}
-#endif
-
 // complex matrix by complex matrix ops.
 
 DEFBINOP_OP (add, sparse_complex_matrix, sparse_complex_matrix, +)
@@ -103,14 +79,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -135,14 +104,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
@@ -196,11 +158,6 @@
   INSTALL_UNOP_TI (ti, op_transpose, octave_sparse_complex_matrix, transpose);
   INSTALL_UNOP_TI (ti, op_hermitian, octave_sparse_complex_matrix, hermitian);
 
-#if 0
-  INSTALL_NCUNOP_TI (ti, op_incr, octave_sparse_complex_matrix, incr);
-  INSTALL_NCUNOP_TI (ti, op_decr, octave_sparse_complex_matrix, decr);
-#endif
-
   INSTALL_BINOP_TI (ti, op_add, octave_sparse_complex_matrix,
                     octave_sparse_complex_matrix, add);
   INSTALL_BINOP_TI (ti, op_sub, octave_sparse_complex_matrix,
--- a/libinterp/operators/op-scm-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-scm-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -53,14 +52,7 @@
     = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -85,14 +77,7 @@
     = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      Complex d = v1.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.sparse_matrix_value () / d);
-    }
+    return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-sm-cm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-cm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -74,14 +73,7 @@
     = dynamic_cast<const octave_complex_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.complex_array_value () / d);
-    }
+    return octave_value (v2.complex_array_value () / v1.scalar_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-sm-cs.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-cs.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -51,15 +50,7 @@
   const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP (pow, sparse_matrix, complex)
@@ -75,14 +66,8 @@
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseComplexMatrix (1, 1, v2.complex_value () / d));
-    }
+    return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()
+                                                  / v1.scalar_value ()));
   else
     {
       MatrixType typ = v1.matrix_type ();
@@ -108,15 +93,7 @@
   const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
   const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
 
-  Complex d = v2.complex_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP_FN (el_pow, sparse_matrix, complex, elem_xpow)
--- a/libinterp/operators/op-sm-m.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-m.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -69,14 +68,7 @@
   const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.array_value () / d);
-    }
+    return octave_value (v2.array_value () / v1.scalar_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-sm-s.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-s.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -48,15 +47,7 @@
   const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP (pow, sparse_matrix, scalar)
@@ -77,14 +68,7 @@
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (SparseMatrix(1, 1, v2.scalar_value () / d));
-    }
+    return octave_value (SparseMatrix(1, 1, v2.scalar_value () / v1.scalar_value ()));
   else
     {
       MatrixType typ = v1.matrix_type ();
@@ -110,15 +94,7 @@
   const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
   const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
 
-  double d = v2.double_value ();
-  octave_value retval;
-
-  if (d == 0.0)
-    warn_divide_by_zero ();
-
-  retval = octave_value (v1.sparse_matrix_value () / d);
-
-  return retval;
+  return octave_value (v1.sparse_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP_FN (el_pow, sparse_matrix, scalar, elem_xpow)
--- a/libinterp/operators/op-sm-scm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-scm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -53,14 +52,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      Complex d = v2.complex_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -85,14 +77,7 @@
     = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.sparse_complex_matrix_value () / d);
-    }
+    return octave_value (v2.sparse_complex_matrix_value () / v1.scalar_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/op-sm-sm.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/op-sm-sm.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -25,7 +25,6 @@
 #  include "config.h"
 #endif
 
-#include "errwarn.h"
 #include "ovl.h"
 #include "ov.h"
 #include "ov-typeinfo.h"
@@ -76,14 +75,7 @@
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
-    {
-      double d = v2.scalar_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v1.sparse_matrix_value () / d);
-    }
+    return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());
   else
     {
       MatrixType typ = v2.matrix_type ();
@@ -106,14 +98,7 @@
   const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
-    {
-      double d = v1.double_value ();
-
-      if (d == 0.0)
-        warn_divide_by_zero ();
-
-      return octave_value (v2.sparse_matrix_value () / d);
-    }
+    return octave_value (v2.sparse_matrix_value () / v1.double_value ());
   else
     {
       MatrixType typ = v1.matrix_type ();
--- a/libinterp/operators/ops.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/operators/ops.h	Fri Jul 12 12:14:43 2019 -0400
@@ -76,42 +76,6 @@
   ti.install_widening_op                                                \
   (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));
 
-// The following INSTALL_* macros are obsolete.
-
-#define INSTALL_UNOP(op, t, f)                                          \
-  octave_value_typeinfo::register_unary_op                              \
-  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
-
-#define INSTALL_NCUNOP(op, t, f)                                        \
-  octave_value_typeinfo::register_non_const_unary_op                    \
-  (octave_value::op, t::static_type_id (), CONCAT2 (oct_unop_, f));
-
-#define INSTALL_BINOP(op, t1, t2, f)                                    \
-  octave_value_typeinfo::register_binary_op                             \
-  (octave_value::op, t1::static_type_id (), t2::static_type_id (),      \
-   CONCAT2 (oct_binop_, f));
-
-#define INSTALL_CATOP(t1, t2, f)                                        \
-  octave_value_typeinfo::register_cat_op                                \
-  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_catop_, f));
-
-#define INSTALL_ASSIGNOP(op, t1, t2, f)                                 \
-  octave_value_typeinfo::register_assign_op                             \
-  (octave_value::op, t1::static_type_id (), t2::static_type_id (),      \
-   CONCAT2 (oct_assignop_, f));
-
-#define INSTALL_ASSIGNANYOP(op, t1, f)                                  \
-  octave_value_typeinfo::register_assignany_op                          \
-  (octave_value::op, t1::static_type_id (), CONCAT2 (oct_assignop_, f));
-
-#define INSTALL_ASSIGNCONV(t1, t2, tr)                                  \
-  octave_value_typeinfo::register_pref_assign_conv                      \
-  (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
-
-#define INSTALL_WIDENOP(t1, t2, f)                                      \
-  octave_value_typeinfo::register_widening_op                           \
-  (t1::static_type_id (), t2::static_type_id (), CONCAT2 (oct_conv_, f));
-
 #define DEFASSIGNOP(name, t1, t2)                               \
   static octave_value                                           \
   CONCAT2 (oct_assignop_, name) (octave_base_value& a1,         \
--- a/libinterp/parse-tree/bp-table.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/bp-table.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -36,7 +36,6 @@
 
 #include "bp-table.h"
 #include "defun-int.h"
-#include "call-stack.h"
 #include "error.h"
 #include "interpreter.h"
 #include "interpreter-private.h"
@@ -58,13 +57,16 @@
 
   void bp_table::dbclear_all_signals (void)
   {
-    Vdebug_on_error = false;
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
+    es.debug_on_error (false);
     bp_table::m_errors_that_stop.clear ();
 
-    Vdebug_on_caught = false;
+    es.debug_on_caught (false);
     bp_table::m_caught_that_stop.clear ();
 
-    Vdebug_on_warning = false;
+    es.debug_on_warning (false);
     bp_table::m_warnings_that_stop.clear ();
 
     Vdebug_on_interrupt = false;
@@ -75,6 +77,9 @@
 
   void bp_table::dbstop_process_map_args (const octave_map& mv)
   {
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
     // process errs
     // why so many levels of indirection needed?
     bool fail = false;
@@ -85,7 +90,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_error = 1;    // like "dbstop if error" with no identifier
+          es.debug_on_error (true);    // like "dbstop if error" with no identifier
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -94,7 +99,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_errors_that_stop.insert (V(i).string_value ());
-                Vdebug_on_error = 1;
+                es.debug_on_error (true);
               }
           }
       }
@@ -112,7 +117,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_caught = 1;    // like "dbstop if caught error" with no ID
+          es.debug_on_caught (true);    // like "dbstop if caught error" with no ID
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -121,7 +126,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_caught_that_stop.insert (V(i).string_value ());
-                Vdebug_on_caught = 1;
+                es.debug_on_caught (true);
               }
           }
       }
@@ -139,7 +144,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_warning = 1;    // like "dbstop if warning" with no identifier
+          es.debug_on_warning (true);    // like "dbstop if warning" with no identifier
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -148,7 +153,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_warnings_that_stop.insert (V(i).string_value ());
-                Vdebug_on_warning = 1;
+                es.debug_on_warning (true);
               }
           }
       }
@@ -158,7 +163,7 @@
 
     // process interrupt
     if (mv.isfield ("intr"))
-      Vdebug_on_interrupt = 1;
+      Vdebug_on_interrupt = true;
   }
 
   // Insert a breakpoint in function fcn at line within file fname,
@@ -252,29 +257,38 @@
     dbstop_none
   };
 
+  // FIXME: This function probalby needs to be completely overhauled to
+  // correctly parse the full syntax of the dbstop command and properly
+  // reject incorrect forms.
+
   // Parse parameters (args) of dbstop and dbclear commands.
   // For dbstop, who=="dbstop"; for dbclear, who=="dbclear".
-  // The syntax is: dbstop [[in] symbol] [[at] line [line [...]]] [if condition]
+  // The syntax is: dbstop [[in] symbol] [[at] [method | line [line [...]]]] [if condition]
   // where the form of condition depends on whether or not a file or line has
-  // been seen.
+  // been seen.  IF symbol and method are specified, then symbol should
+  // be a class name.  Otherwise it should be a function name.
   // Also execute "if [error|warning|interrupt|naninf]" clauses.
 
   void bp_table::parse_dbfunction_params (const char *who,
                                           const octave_value_list& args,
-                                          std::string& symbol_name,
+                                          std::string& func_name,
+                                          std::string& class_name,
                                           bp_table::intmap& lines,
                                           std::string& cond)
   {
     int nargin = args.length ();
     int list_idx = 0;
-    symbol_name = "";
+    func_name = "";
+    class_name = "";
     lines = bp_table::intmap ();
 
     if (nargin == 0 || ! args(0).is_string ())
       print_usage (who);
 
     // elements already processed
-    bool seen_in = false, seen_at = false, seen_if = false;
+    bool seen_in = false;
+    bool seen_at = false;
+    bool seen_if = false;
     int pos = 0;
     dbstop_args tok = dbstop_none;
     while (pos < nargin)
@@ -315,10 +329,10 @@
         switch (tok)
           {
           case dbstop_in:
-            symbol_name = args(pos).string_value ();
+            func_name = args(pos).string_value ();
             if (seen_in)
               error ("%s: Too many function names specified -- %s",
-                     who, symbol_name.c_str ());
+                     who, func_name.c_str ());
             else if (seen_at || seen_if)
               error ("%s: function name must come before line number and 'if'",
                      who);
@@ -334,18 +348,36 @@
               error ("%s: line number must come before 'if' clause\n", who);
             seen_at = true;
 
-            if (! seen_in)
+            if (seen_if)
+              error ("%s: line number must come before 'if' clause\n", who);
+            else if (seen_in)
+              {
+                std::string arg = args(pos).string_value ();
+
+                // FIXME: we really want to distinguish number
+                // vs. method name here.
+
+                if (atoi (arg.c_str ()) == 0)
+                  {
+                    // We have class and function names but already
+                    // stored the class name in func_name.
+                    class_name = func_name;
+                    func_name = arg;
+                    pos++;
+                    break;
+                  }
+
+              }
+            else
               {
                 // It was a line number.  Get function name from debugger.
-                if (Vdebugging)
-                  symbol_name = m_evaluator.get_user_code ()->profiler_name ();
+                if (m_evaluator.in_debug_repl ())
+                  func_name = m_evaluator.get_user_code ()->profiler_name ();
                 else
                   error ("%s: function name must come before line number "
                          "and 'if'", who);
                 seen_in = true;
               }
-            else if (seen_if)
-              error ("%s: line number must come before 'if' clause\n", who);
 
             // Read a list of line numbers (or arrays thereof)
             for ( ; pos < nargin; pos++)
@@ -357,7 +389,7 @@
                     if (line > 0)
                       lines[list_idx++] = line;
                     else
-                      break;        // may be "if"
+                      break;        // may be "if" or a method name
                   }
                 else if (args(pos).isnumeric ())
                   {
@@ -389,28 +421,23 @@
             else    // stop on event (error, warning, interrupt, NaN/inf)
               {
                 std::string condition = args(pos).string_value ();
-                int on_off = ! strcmp(who, "dbstop");
+                bool on_off = ! strcmp (who, "dbstop");
 
-                // list of error/warning IDs to update
-                std::set<std::string> *id_list = nullptr;
-                bool *stop_flag = nullptr;         // Vdebug_on_... flag
+                // FIXME: the following seems a bit messy in the way it
+                // duplicates checks on CONDITION.
 
                 if (condition == "error")
-                  {
-                    id_list = &m_errors_that_stop;
-                    stop_flag = &Vdebug_on_error;
-                  }
+                  process_id_list (who, condition, args, nargin, pos, on_off,
+                                   m_errors_that_stop);
                 else if (condition == "warning")
-                  {
-                    id_list = &m_warnings_that_stop;
-                    stop_flag = &Vdebug_on_warning;
-                  }
+                  process_id_list (who, condition, args, nargin, pos, on_off,
+                                   m_warnings_that_stop);
                 else if (condition == "caught" && nargin > pos+1
                          && args(pos+1).string_value () == "error")
                   {
-                    id_list = &m_caught_that_stop;
-                    stop_flag = &Vdebug_on_caught;
                     pos++;
+                    process_id_list (who, condition, args, nargin, pos, on_off,
+                                     m_caught_that_stop);
                   }
                 else if (condition == "interrupt")
                   {
@@ -430,38 +457,6 @@
                   error ("%s: invalid condition %s",
                          who, condition.c_str ());
 
-                // process ID list for "dbstop if error <error_ID>" etc
-                if (id_list)
-                  {
-                    pos++;
-                    if (pos < nargin)       // only affect a single error ID
-                      {
-                        if (! args(pos).is_string () || nargin > pos+1)
-                          error ("%s: ID must be a single string", who);
-                        else if (on_off == 1)
-                          {
-                            id_list->insert (args(pos).string_value ());
-                            *stop_flag = true;
-                          }
-                        else
-                          {
-                            id_list->erase (args(pos).string_value ());
-                            if (id_list->empty ())
-                              *stop_flag = false;
-                          }
-                      }
-                    else   // unqualified.  Turn all on or off
-                      {
-                        id_list->clear ();
-                        *stop_flag = on_off;
-                        if (stop_flag == &Vdebug_on_error)
-                          {
-                            // Matlab stops on both.
-                            Vdebug_on_interrupt = on_off;
-                          }
-                      }
-                  }
-
                 pos = nargin;
               }
             break;
@@ -488,6 +483,59 @@
 %! assert (s.errs, {"Octave:undefined-function"});
 */
 
+  void bp_table::set_stop_flag (const char *who, const std::string& condition,
+                                bool on_off)
+  {
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
+    if (condition == "error")
+      es.debug_on_error (on_off);
+    else if (condition == "warning")
+      es.debug_on_warning (on_off);
+    else if (condition == "caught")
+      es.debug_on_caught (on_off);
+    else
+      error ("%s: internal error in set_stop_flag", who);
+  }
+
+  void bp_table::process_id_list (const char *who,
+                                  const std::string& condition,
+                                  const octave_value_list& args,
+                                  int nargin, int& pos, bool on_off,
+                                  std::set<std::string>& id_list)
+  {
+    pos++;
+
+    if (nargin > pos)       // only affect a single error ID
+      {
+        if (! args(pos).is_string () || nargin > pos+1)
+          error ("%s: ID must be a single string", who);
+        else if (on_off)
+          {
+            id_list.insert (args(pos).string_value ());
+            set_stop_flag (who, condition, true);
+          }
+        else
+          {
+            id_list.erase (args(pos).string_value ());
+            if (id_list.empty ())
+              set_stop_flag (who, condition, false);
+          }
+      }
+    else   // unqualified.  Turn all on or off
+      {
+        id_list.clear ();
+        set_stop_flag (who, condition, on_off);
+
+        if (condition == "error")
+          {
+            // Matlab stops on both.
+            Vdebug_on_interrupt = on_off;
+          }
+      }
+  }
+
   // Return the sub/nested/main function of MAIN_FCN that contains
   // line number LINENO of the source file.
   // If END_LINE != 0, *END_LINE is set to last line of the returned function.
@@ -554,10 +602,11 @@
   // Given file name fname, find the subfunction at line and create
   // a breakpoint there.  Put the system into debug_mode.
   bp_table::intmap bp_table::add_breakpoint (const std::string& fname,
+                                             const std::string& class_name,
                                              const bp_table::intmap& line,
                                              const std::string& condition)
   {
-    octave_user_code *main_fcn = m_evaluator.get_user_code (fname);
+    octave_user_code *main_fcn = m_evaluator.get_user_code (fname, class_name);
 
     if (! main_fcn)
       error ("add_breakpoint: unable to find function '%s'\n", fname.c_str ());
@@ -588,7 +637,7 @@
           }
       }
 
-    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
+    m_evaluator.reset_debug_state ();
 
     return retval;
   }
@@ -684,7 +733,7 @@
           }
       }
 
-    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
+    m_evaluator.reset_debug_state ();
 
     return retval;
   }
@@ -718,7 +767,7 @@
       error ("remove_all_breakpoint_in_file: "
              "unable to find function %s\n", fname.c_str ());
 
-    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
+    m_evaluator.reset_debug_state ();
 
     return retval;
   }
@@ -735,7 +784,7 @@
         remove_all_breakpoints_in_file (*it);
       }
 
-    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
+    m_evaluator.reset_debug_state ();
   }
 
   std::string find_bkpt_list (octave_value_list slist, std::string match)
@@ -834,8 +883,11 @@
   {
     octave_map retval;
 
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
     // print dbstop if error information
-    if (Vdebug_on_error)
+    if (es.debug_on_error ())
       {
         if (m_errors_that_stop.empty ())
           {
@@ -862,7 +914,7 @@
       }
 
     // print dbstop if caught error information
-    if (Vdebug_on_caught)
+    if (es.debug_on_caught ())
       {
         if (m_caught_that_stop.empty ())
           {
@@ -889,7 +941,7 @@
       }
 
     // print dbstop if warning information
-    if (Vdebug_on_warning)
+    if (es.debug_on_warning ())
       {
         if (m_warnings_that_stop.empty ())
           {
--- a/libinterp/parse-tree/bp-table.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/bp-table.h	Fri Jul 12 12:14:43 2019 -0400
@@ -75,6 +75,7 @@
 
     // Add a breakpoint at the nearest executable line.
     intmap add_breakpoint (const std::string& fname = "",
+                           const std::string& class_name = "",
                            const intmap& lines = intmap (),
                            const std::string& condition = "");
 
@@ -121,9 +122,9 @@
 
     bool condition_valid (const std::string& cond);
 
-    void parse_dbfunction_params (const char *, const octave_value_list&,
-                                  std::string&, bp_table::intmap&,
-                                  std::string&);
+    void parse_dbfunction_params (const char *who, const octave_value_list& args,
+                                  std::string& func_name, std::string& class_name,
+                                  bp_table::intmap& lines, std::string& cond);
 
   private:
 
@@ -142,6 +143,14 @@
     std::set<std::string> m_caught_that_stop;
     std::set<std::string> m_warnings_that_stop;
 
+    void set_stop_flag (const char *who, const std::string& condition,
+                        bool on_off);
+
+    void process_id_list (const char *who, const std::string& condition,
+                          const octave_value_list& args,
+                          int nargin, int& pos, bool on_off,
+                          std::set<std::string>& id_list);
+
     bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname,
                            const intmap& line, const std::string& condition,
                            intmap& retval);
--- a/libinterp/parse-tree/comment-list.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/comment-list.h	Fri Jul 12 12:14:43 2019 -0400
@@ -102,14 +102,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::comment_list' instead")
-typedef octave::comment_list octave_comment_list;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::comment_elt' instead")
-typedef octave::comment_elt octave_comment_elt;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/jit-typeinfo.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -222,7 +222,7 @@
   extern "C" void
   octave_jit_ginvalid_index (void)
   {
-    // FIXME: 0-argument form of octave::err_invalid_index removed in
+    // FIXME: 0-argument form of err_invalid_index removed in
     //        cset dd6345fd8a97.  Report -1 as the bad index for all
     //        occurrences.
     err_invalid_index (static_cast<octave_idx_type> (-1));
@@ -386,10 +386,6 @@
   extern "C" Complex
   octave_jit_complex_div (Complex lhs, Complex rhs)
   {
-    // see src/OPERATORS/op-cs-cs.cc
-    if (rhs == 0.0)
-      warn_divide_by_zero ();
-
     return lhs / rhs;
   }
 
@@ -1355,10 +1351,6 @@
     add_binary_fcmp (m_scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
     add_binary_fcmp (m_scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
 
-    jit_function gripe_div0 = create_external (JIT_FN (warn_divide_by_zero),
-                                               nullptr);
-    gripe_div0.mark_can_error ();
-
     // divide is annoying because it might error
     fn = create_internal ("octave_jit_div_scalar_scalar", m_scalar, m_scalar,
                           m_scalar);
@@ -1376,7 +1368,6 @@
       m_builder.CreateCondBr (check, warn_block, normal_block);
 
       m_builder.SetInsertPoint (warn_block);
-      gripe_div0.call (m_builder);
       m_builder.CreateBr (normal_block);
 
       m_builder.SetInsertPoint (normal_block);
--- a/libinterp/parse-tree/lex.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/lex.h	Fri Jul 12 12:14:43 2019 -0400
@@ -259,6 +259,7 @@
 
     lexical_feedback (void)
       : m_end_of_input (false),
+        m_allow_command_syntax (true),
         m_at_beginning_of_statement (true),
         m_looking_at_anon_fcn_args (false),
         m_looking_at_return_list (false),
@@ -270,6 +271,8 @@
         m_looking_at_indirect_ref (false),
         m_parsing_class_method (false),
         m_parsing_classdef (false),
+        m_parsing_classdef_decl (false),
+        m_parsing_classdef_superclass (false),
         m_maybe_classdef_get_set_method (false),
         m_parsing_classdef_get_method (false),
         m_parsing_classdef_set_method (false),
@@ -344,6 +347,9 @@
     // true means that we have encountered eof on the input stream.
     bool m_end_of_input;
 
+    // true means command syntax is allowed.
+    bool m_allow_command_syntax;
+
     // true means we are at the beginning of a statement, where a
     // command name is possible.
     bool m_at_beginning_of_statement;
@@ -382,6 +388,15 @@
     // true means we are parsing a classdef file
     bool m_parsing_classdef;
 
+    // true means we are parsing the initial classdef declaration
+    // portion of classdef file, from the "classdef" token through the
+    // optional list of superclasses.
+    bool m_parsing_classdef_decl;
+
+    // true means we are parsing the superclass part of a classdef
+    // declaration.
+    bool m_parsing_classdef_superclass;
+
     // true means we are parsing a class method declaration line in a
     // classdef file and can accept a property get or set method name.
     // for example, "get.propertyname" is recognized as a function name.
@@ -500,7 +515,7 @@
 
   // base_lexer inherits from lexical_feedback because we will
   // eventually have several different constructors and it is easier to
-  // intialize if everything is grouped in a parent class rather than
+  // initialize if everything is grouped in a parent class rather than
   // listing all the members in the base_lexer class.
 
   class
@@ -747,8 +762,6 @@
 
     int show_token (int tok);
 
-    void enable_fq_identifier (void);
-
   protected:
 
     std::stack<int> start_state_stack;
@@ -760,15 +773,15 @@
   public:
 
     lexer (interpreter& interp)
-      : base_lexer (interp), m_reader (this)
+      : base_lexer (interp), m_reader (*this)
     { }
 
     lexer (FILE *file, interpreter& interp)
-      : base_lexer (interp), m_reader (file, this)
+      : base_lexer (interp), m_reader (file, *this)
     { }
 
     lexer (const std::string& eval_string, interpreter& interp)
-      : base_lexer (interp), m_reader (eval_string, this)
+      : base_lexer (interp), m_reader (eval_string, *this)
     { }
 
     // No copying!
--- a/libinterp/parse-tree/lex.ll	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/lex.ll	Fri Jul 12 12:14:43 2019 -0400
@@ -323,6 +323,18 @@
      }                                                                  \
    while (0)
 
+static inline bool
+is_space_or_tab (char c)
+{
+  return c == ' ' || c == '\t';
+}
+
+static inline bool
+is_space_or_tab_or_eol (char c)
+{
+  return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+}
+
 %}
 
 D       [0-9]
@@ -332,7 +344,7 @@
 Im      [iIjJ]
 CCHAR   [#%]
 IDENT   ([_$a-zA-Z][_$a-zA-Z0-9]*)
-FQIDENT ({IDENT}(\.{IDENT})*)
+FQIDENT ({IDENT}({S}*\.{S}*{IDENT})*)
 EXPON   ([DdEe][+-]?{D}{D_}*)
 NUMBIN  (0[bB][01_]+)
 NUMHEX  (0[xX][0-9a-fA-F][0-9a-fA-F_]*)
@@ -725,7 +737,7 @@
     while (i < len)
       {
         char c = yytext[i];
-        if (c == ' ' || c == '\t')
+        if (is_space_or_tab (c))
           {
             have_space = true;
             i++;
@@ -759,7 +771,7 @@
             while (i < len)
               {
                 char c = yytext[i++];
-                if (! (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+                if (! is_space_or_tab_or_eol (c))
                   {
                     looks_like_block_comment = false;
                     break;
@@ -1079,7 +1091,8 @@
 %}
 
 <FQ_IDENT_START>{FQIDENT} {
-    curr_lexer->lexer_debug ("<FQ_IDENT_START>{FQIDENT}");
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{FQIDENT}{S}*");
+
     curr_lexer->pop_start_state ();
 
     int id_tok = curr_lexer->handle_fq_identifier ();
@@ -1093,12 +1106,26 @@
   }
 
 <FQ_IDENT_START>{S}+ {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{S}+");
+
     curr_lexer->m_current_input_column += yyleng;
 
     curr_lexer->mark_previous_token_trailing_space ();
   }
 
-<FQ_IDENT_START>. {
+<FQ_IDENT_START>(\.\.\.){ANY_EXCEPT_NL}*{NL} {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>(\\.\\.\\.){ANY_EXCEPT_NL}*{NL}");
+
+    curr_lexer->m_input_line_number++;
+    curr_lexer->m_current_input_column = 1;
+  }
+
+<FQ_IDENT_START>{ANY_INCLUDING_NL} {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{ANY_INCLUDING_NL}");
+
+    // If input doesn't match FQIDENT, return char and go to previous
+    // start state.
+
     yyless (0);
     curr_lexer->pop_start_state ();
   }
@@ -1245,8 +1272,8 @@
 // Superclass method identifiers.
 %}
 
-{IDENT}@{FQIDENT} {
-    curr_lexer->lexer_debug ("{IDENT}@{FQIDENT}");
+{FQIDENT}{S}*@{S}*{FQIDENT} {
+    curr_lexer->lexer_debug ("{FQIDENT}{S}*@{S}*{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ())
       {
@@ -1255,11 +1282,30 @@
       }
     else
       {
+        if (curr_lexer->m_at_beginning_of_statement)
+          {
+            std::string txt = yytext;
+
+            size_t at_or_dot_pos = txt.find_first_of ("@.");
+
+            if (at_or_dot_pos != std::string::npos)
+              {
+                size_t spc_pos = txt.find_first_of (" \t");
+
+                if (spc_pos != std::string::npos && spc_pos < at_or_dot_pos)
+                  {
+                    yyless (spc_pos);
+                    return curr_lexer->handle_identifier ();
+                  }
+              }
+          }
+
         int id_tok = curr_lexer->handle_superclass_identifier ();
 
         if (id_tok >= 0)
           {
             curr_lexer->m_looking_for_object_index = true;
+            curr_lexer->m_at_beginning_of_statement = false;
 
             return curr_lexer->count_token_internal (id_tok);
           }
@@ -1270,8 +1316,8 @@
 // Metaclass query
 %}
 
-\?{FQIDENT} {
-    curr_lexer->lexer_debug ("\\?{FQIDENT}");
+\?{S}*{FQIDENT} {
+    curr_lexer->lexer_debug ("\\?{S}*{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ()
         &&  curr_lexer->space_follows_previous_token ())
@@ -1292,8 +1338,9 @@
       }
   }
 
-"@" {
-    curr_lexer->lexer_debug ("@");
+\@ |
+\@{S}*{FQIDENT} {
+    curr_lexer->lexer_debug ("\\@|\\@{S}*{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ()
         &&  curr_lexer->space_follows_previous_token ())
@@ -1303,11 +1350,11 @@
       }
     else
       {
-        int tok = curr_lexer->previous_token_value ();
+        int tok_val = curr_lexer->previous_token_value ();
 
         if (curr_lexer->whitespace_is_significant ()
             && curr_lexer->space_follows_previous_token ()
-            && ! (tok == '[' || tok == '{'
+            && ! (tok_val == '[' || tok_val == '{'
                   || curr_lexer->previous_token_is_binop ()))
           {
             yyless (0);
@@ -1317,13 +1364,46 @@
           }
         else
           {
-            curr_lexer->m_current_input_column++;
-
-            curr_lexer->m_looking_at_function_handle++;
-            curr_lexer->m_looking_for_object_index = false;
+            curr_lexer->m_current_input_column += yyleng;
             curr_lexer->m_at_beginning_of_statement = false;
 
-            return curr_lexer->count_token ('@');
+            std::string ident = yytext;
+
+            if (ident == "@")
+              {
+                curr_lexer->m_looking_at_function_handle++;
+                curr_lexer->m_looking_for_object_index = false;
+
+                return curr_lexer->count_token ('@');
+              }
+            else
+              {
+                ident = ident.substr (1);
+                ident.erase (std::remove_if (ident.begin (), ident.end (),
+                                             is_space_or_tab), ident.end ());
+
+                int kw_token = curr_lexer->is_keyword_token (ident);
+
+                octave::token *tok;
+
+                if (kw_token)
+                  tok = new octave::token (LEXICAL_ERROR,
+                                           "function handles may not refer to keywords",
+                                           curr_lexer->m_input_line_number,
+                                           curr_lexer->m_current_input_column);
+                else
+                  {
+                    curr_lexer->m_looking_for_object_index = true;
+
+                    tok = new octave::token (FCN_HANDLE, ident,
+                                             curr_lexer->m_input_line_number,
+                                             curr_lexer->m_current_input_column);
+                  }
+
+                curr_lexer->push_token (tok);
+
+                return curr_lexer->count_token_internal (tok->token_value ());
+              }
           }
       }
   }
@@ -2085,6 +2165,7 @@
   lexical_feedback::reset (void)
   {
     m_end_of_input = false;
+    m_allow_command_syntax = true;
     m_at_beginning_of_statement = true;
     m_looking_at_anon_fcn_args = false;
     m_looking_at_return_list = false;
@@ -2096,6 +2177,8 @@
     m_looking_at_indirect_ref = false;
     m_parsing_class_method = false;
     m_parsing_classdef = false;
+    m_parsing_classdef_decl = false;
+    m_parsing_classdef_superclass = false;
     m_maybe_classdef_get_set_method = false;
     m_parsing_classdef_get_method = false;
     m_parsing_classdef_set_method = false;
@@ -2197,6 +2280,9 @@
   bool
   lexical_feedback::previous_token_may_be_command (void) const
   {
+    if (! m_allow_command_syntax)
+      return false;
+
     const token *tok = m_tokens.front ();
     return tok ? tok->may_be_command () : false;
   }
@@ -2228,7 +2314,8 @@
       size_t offset = s.find_first_not_of (" \t");
 
       retval = (s.substr (offset, 9) == "Copyright"
-                || s.substr (offset, 6) == "Author");
+                || s.substr (offset, 6) == "Author"
+                || s.substr (offset, 23) == "SPDX-License-Identifier");
     }
 
   return retval;
@@ -2449,7 +2536,7 @@
   {
     int c = text_yyinput ();
     xunput (c);
-    return (c == ' ' || c == '\t');
+    return is_space_or_tab (c);
   }
 
   bool
@@ -2471,9 +2558,10 @@
 
   bool
   base_lexer::is_variable (const std::string& name,
-                           const symbol_scope& scope)
+                           const symbol_scope& /*scope*/)
   {
-    return ((scope && scope.is_variable (name))
+    return ((m_interpreter.at_top_level ()
+             && m_interpreter.is_variable (name))
             || (m_pending_local_variables.find (name)
                 != m_pending_local_variables.end ()));
   }
@@ -2853,7 +2941,7 @@
     while (offset < yylng)
       {
         char c = yytxt[offset];
-        if (c == ' ' || c == '\t')
+        if (is_space_or_tab (c))
           {
             have_space = true;
             offset++;
@@ -2947,6 +3035,9 @@
   bool
   base_lexer::looks_like_command_arg (void)
   {
+    if (! m_allow_command_syntax)
+      return false;
+
     bool space_before = space_follows_previous_token ();
     bool space_after = looking_at_space ();
 
@@ -2957,11 +3048,15 @@
   int
   base_lexer::handle_superclass_identifier (void)
   {
-    std::string meth = flex_yytext ();
-
-    size_t pos = meth.find ("@");
-    std::string cls = meth.substr (pos + 1);
-    meth = meth.substr (0, pos);
+    std::string txt = flex_yytext ();
+
+    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
+               txt.end ());
+
+    size_t pos = txt.find ("@");
+
+    std::string meth = txt.substr (0, pos);
+    std::string cls = txt.substr (pos + 1);
 
     bool kw_token = (is_keyword_token (meth)
                      || fq_identifier_contains_keyword (cls));
@@ -2989,7 +3084,13 @@
   int
   base_lexer::handle_meta_identifier (void)
   {
-    std::string cls = std::string(flex_yytext ()).substr (1);
+    std::string txt = flex_yytext ();
+
+    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
+               txt.end ());
+
+    // Eliminate leading '?'
+    std::string cls = txt.substr (1);
 
     if (fq_identifier_contains_keyword (cls))
       {
@@ -3012,9 +3113,12 @@
   int
   base_lexer::handle_fq_identifier (void)
   {
-    std::string fq_id = flex_yytext ();
-
-    if (fq_identifier_contains_keyword (fq_id))
+    std::string txt = flex_yytext ();
+
+    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
+               txt.end ());
+
+    if (fq_identifier_contains_keyword (txt))
       {
         token *tok
           = new token (LEXICAL_ERROR,
@@ -3026,7 +3130,7 @@
         return count_token_internal (LEXICAL_ERROR);
       }
 
-    push_token (new token (FQ_IDENT, fq_id, m_input_line_number,
+    push_token (new token (FQ_IDENT, txt, m_input_line_number,
                            m_current_input_column));
 
     m_current_input_column += flex_yyleng ();
@@ -3065,33 +3169,6 @@
 
     int kw_token = is_keyword_token (ident);
 
-    if (m_looking_at_function_handle)
-      {
-        if (kw_token)
-          {
-            token *tok
-              = new token (LEXICAL_ERROR,
-                           "function handles may not refer to keywords",
-                           m_input_line_number, m_current_input_column);
-
-            push_token (tok);
-
-            return count_token_internal (LEXICAL_ERROR);
-          }
-        else
-          {
-            push_token (new token (FCN_HANDLE, ident, m_input_line_number,
-                                   m_current_input_column));
-
-            m_current_input_column += flex_yyleng ();
-            m_looking_for_object_index = true;
-
-            m_at_beginning_of_statement = false;
-
-            return FCN_HANDLE;
-          }
-      }
-
     // If we have a regular keyword, return it.
     // Keywords can be followed by identifiers.
 
@@ -3458,7 +3535,7 @@
         break;
 
       case INPUT_FILE_START:
-        std::cerr << "INPUT_FILE_BEGIN" << std::endl;
+        std::cerr << "INPUT_FILE_START" << std::endl;
         break;
 
       case BLOCK_COMMENT_START:
@@ -3477,6 +3554,10 @@
         std::cerr << "SQ_STRING_START" << std::endl;
         break;
 
+      case FQ_IDENT_START:
+        std::cerr << "FQ_IDENT_START" << std::endl;
+        break;
+
       default:
         std::cerr << "UNKNOWN START STATE!" << std::endl;
         break;
@@ -3512,7 +3593,7 @@
         int c = text_yyinput ();
         xunput (c);
 
-        bool space_after = (c == ' ' || c == '\t');
+        bool space_after = is_space_or_tab (c);
 
         if (! (prev_tok == '[' || prev_tok == '{'
                || previous_token_is_binop ()
@@ -3549,6 +3630,25 @@
     m_looking_for_object_index = false;
     m_at_beginning_of_statement = bos;
 
+    switch (tok)
+      {
+      case EXPR_LT:
+        if (m_parsing_classdef_decl)
+          {
+            m_parsing_classdef_superclass = true;
+            push_start_state (FQ_IDENT_START);
+          }
+        break;
+
+      case EXPR_AND:
+        if (m_parsing_classdef_superclass)
+          push_start_state (FQ_IDENT_START);
+        break;
+
+      default:
+        break;
+      }
+
     return count_token_internal (tok);
   }
 
@@ -3610,12 +3710,6 @@
     return tok;
   }
 
-  void
-  base_lexer::enable_fq_identifier (void)
-  {
-    push_start_state (FQ_IDENT_START);
-  }
-
   int
   lexer::fill_flex_buffer (char *buf, unsigned max_size)
   {
--- a/libinterp/parse-tree/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -27,7 +27,6 @@
   %reldir%/pt-except.h \
   %reldir%/pt-exp.h \
   %reldir%/pt-fcn-handle.h \
-  %reldir%/pt-funcall.h \
   %reldir%/pt-id.h \
   %reldir%/pt-idx.h \
   %reldir%/pt-jit.h \
@@ -77,7 +76,6 @@
   %reldir%/pt-except.cc \
   %reldir%/pt-exp.cc \
   %reldir%/pt-fcn-handle.cc \
-  %reldir%/pt-funcall.cc \
   %reldir%/pt-id.cc \
   %reldir%/pt-idx.cc \
   %reldir%/pt-jit.cc \
--- a/libinterp/parse-tree/oct-lvalue.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/oct-lvalue.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -31,16 +31,26 @@
 
 namespace octave
 {
+  bool octave_lvalue::is_defined (void) const
+  {
+    return ! is_black_hole () && m_frame.is_defined (m_sym);
+  }
+
+  bool octave_lvalue::is_undefined (void) const
+  {
+    return ! is_defined ();
+  }
+
+  void octave_lvalue::define (const octave_value& v)
+  {
+    m_frame.assign (m_sym, v);
+  }
+
   void octave_lvalue::assign (octave_value::assign_op op,
                               const octave_value& rhs)
   {
     if (! is_black_hole ())
-      {
-        if (m_idx.empty ())
-          m_sym.assign (op, rhs, m_context);
-        else
-          m_sym.assign (op, m_type, m_idx, rhs, m_context);
-      }
+      m_frame.assign (op, m_sym, m_type, m_idx, rhs);
   }
 
   void octave_lvalue::set_index (const std::string& t,
@@ -70,37 +80,12 @@
   void octave_lvalue::do_unary_op (octave_value::unary_op op)
   {
     if (! is_black_hole ())
-      {
-        if (m_idx.empty ())
-          m_sym.do_non_const_unary_op (op, m_context);
-        else
-          m_sym.do_non_const_unary_op (op, m_type, m_idx, m_context);
-      }
+      m_frame.do_non_const_unary_op (op, m_sym, m_type, m_idx);
   }
 
   octave_value octave_lvalue::value (void) const
   {
-    octave_value retval;
-
-    if (! is_black_hole ())
-      {
-        octave_value val = m_sym.varval (m_context);
-
-        if (m_idx.empty ())
-          retval = val;
-        else
-          {
-            if (val.is_constant ())
-              retval = val.subsref (m_type, m_idx);
-            else
-              {
-                octave_value_list t = val.subsref (m_type, m_idx, 1);
-                if (t.length () > 0)
-                  retval = t(0);
-              }
-          }
-      }
-
-    return retval;
+    return (is_black_hole ()
+            ? octave_value () : m_frame.value (m_sym, m_type, m_idx));
   }
 }
--- a/libinterp/parse-tree/oct-lvalue.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/oct-lvalue.h	Fri Jul 12 12:14:43 2019 -0400
@@ -28,6 +28,7 @@
 #include <string>
 
 #include "ovl.h"
+#include "stack-frame.h"
 #include "symrec.h"
 
 namespace octave
@@ -36,19 +37,14 @@
   {
   public:
 
-    octave_lvalue (void)
-      : m_sym (), m_context (0), m_black_hole (false), m_type (),
-        m_idx (), m_nel (1)
-    { }
-
-    octave_lvalue (const symbol_record& sr, symbol_record::context_id context)
-      : m_sym (sr), m_context (context), m_black_hole (false),
+    octave_lvalue (const symbol_record& sr, stack_frame& frame)
+      : m_sym (sr), m_frame (frame), m_black_hole (false),
         m_type (), m_idx (), m_nel (1)
     { }
 
     octave_lvalue (const octave_lvalue&) = default;
 
-    octave_lvalue& operator = (const octave_lvalue&) = default;
+    octave_lvalue& operator = (const octave_lvalue&) = delete;
 
     ~octave_lvalue (void) = default;
 
@@ -56,19 +52,13 @@
 
     void mark_black_hole (void) { m_black_hole = true; }
 
-    bool is_defined (void) const
-    {
-      return ! is_black_hole () && m_sym.is_defined (m_context);
-    }
+    bool is_defined (void) const;
 
-    bool is_undefined (void) const
-    {
-      return is_black_hole () || m_sym.is_undefined (m_context);
-    }
+    bool is_undefined (void) const;
 
     bool isstruct (void) const { return value().isstruct (); }
 
-    void define (const octave_value& v) { m_sym.assign (v, m_context); }
+    void define (const octave_value& v);
 
     void assign (octave_value::assign_op, const octave_value&);
 
@@ -92,7 +82,7 @@
 
     symbol_record m_sym;
 
-    symbol_record::context_id m_context;
+    stack_frame& m_frame;
 
     bool m_black_hole;
 
--- a/libinterp/parse-tree/oct-parse.yy	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/oct-parse.yy	Fri Jul 12 12:14:43 2019 -0400
@@ -54,7 +54,6 @@
 
 #include "Cell.h"
 #include "builtin-defun-decls.h"
-#include "call-stack.h"
 #include "defun.h"
 #include "dirfns.h"
 #include "dynamic-ld.h"
@@ -75,7 +74,6 @@
 #include "parse.h"
 #include "pt-all.h"
 #include "pt-eval.h"
-#include "pt-funcall.h"
 #include "symtab.h"
 #include "token.h"
 #include "unwind-prot.h"
@@ -87,9 +85,6 @@
 
 extern int octave_lex (YYSTYPE *, void *);
 
-// List of autoloads (function -> file mapping).
-static std::map<std::string, std::string> autoload_map;
-
 // Forward declarations for some functions defined at the bottom of
 // the file.
 
@@ -150,7 +145,8 @@
   octave::tree_expression *tree_expression_type;
   octave::tree_constant *tree_constant_type;
   octave::tree_fcn_handle *tree_fcn_handle_type;
-  octave::tree_funcall *tree_funcall_type;
+  octave::tree_superclass_ref *tree_superclass_ref_type;
+  octave::tree_metaclass_query *tree_metaclass_query_type;
   octave::tree_function_def *tree_function_def_type;
   octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   octave::tree_identifier *tree_identifier_type;
@@ -248,7 +244,8 @@
 %type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <tree_superclass_ref_type> superclass_identifier
+%type <tree_metaclass_query_type> meta_identifier
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
@@ -325,7 +322,8 @@
 %destructor { delete $$; } <tree_expression_type>
 %destructor { delete $$; } <tree_constant_type>
 %destructor { delete $$; } <tree_fcn_handle_type>
-%destructor { delete $$; } <tree_funcall_type>
+%destructor { delete $$; } <tree_superclass_ref_type>
+%destructor { delete $$; } <tree_metaclass_query_type>
 %destructor { delete $$; } <tree_function_def_type>
 %destructor { delete $$; } <tree_anon_fcn_handle_type>
 %destructor { delete $$; } <tree_identifier_type>
@@ -484,6 +482,7 @@
                         // make_index_expression deleted $1 and $2.
                         YYABORT;
                       }
+                    $$->mark_word_list_cmd ();
                   }
                 ;
 
@@ -502,26 +501,30 @@
 
 identifier      : NAME
                   {
-                    octave::symbol_record sr = $1->sym_rec ();
-                    $$ = new octave::tree_identifier (sr, $1->line (), $1->column ());
+                    $$ = new octave::tree_identifier ($1->sym_rec (),
+                                                      $1->line (),
+                                                      $1->column ());
                   }
                 ;
 
 superclass_identifier
                 : SUPERCLASSREF
                   {
-                    std::string method_nm = $1->superclass_method_name ();
-                    std::string class_nm = $1->superclass_class_name ();
-
-                    $$ = parser.make_superclass_ref (method_nm, class_nm);
+                    std::string meth = $1->superclass_method_name ();
+                    std::string cls = $1->superclass_class_name ();
+
+                    $$ = new octave::tree_superclass_ref (meth, cls,
+                                                          $1->line (),
+                                                          $1->column ());
                   }
                 ;
 
 meta_identifier : METAQUERY
                   {
-                    std::string class_nm = $1->text ();
-
-                    $$ = parser.make_meta_class_query (class_nm);
+                    std::string cls = $1->text ();
+
+                    $$ = new octave::tree_metaclass_query (cls, $1->line (),
+                                                           $1->column ());
                   }
                 ;
 
@@ -597,11 +600,8 @@
                   { $$ = $2; }
                 ;
 
-fcn_handle      : '@' FCN_HANDLE
-                  {
-                    $$ = parser.make_fcn_handle ($2);
-                    lexer.m_looking_at_function_handle--;
-                  }
+fcn_handle      : FCN_HANDLE
+                  { $$ = parser.make_fcn_handle ($1); }
                 ;
 
 anon_fcn_handle : '@' param_list stmt_begin expr_no_assign
@@ -1224,7 +1224,10 @@
                       YYABORT;
                   }
                 | CONTINUE
-                  { $$ = parser.make_continue_command ($1); }
+                  {
+                    if (! ($$ = parser.make_continue_command ($1)))
+                      YYABORT;
+                  }
                 | FUNC_RET
                   { $$ = parser.make_return_command ($1); }
                 ;
@@ -1650,6 +1653,7 @@
                     // Create invalid parent scope.
                     lexer.m_symtab_context.push (octave::symbol_scope ());
                     lexer.m_parsing_classdef = true;
+                    lexer.m_parsing_classdef_decl = true;
                     $$ = $1;
                   }
                 ;
@@ -1716,28 +1720,30 @@
 
 opt_superclass_list
                 : // empty
-                  { $$ = nullptr; }
+                  {
+                    lexer.m_parsing_classdef_decl = false;
+                    lexer.m_parsing_classdef_superclass = false;
+                    $$ = nullptr;
+                  }
                 | superclass_list
-                  { $$ = $1; }
+                  {
+                    lexer.m_parsing_classdef_decl = false;
+                    lexer.m_parsing_classdef_superclass = false;
+                    $$ = $1;
+                  }
                 ;
 
-superclass_list : EXPR_LT
+superclass_list : EXPR_LT superclass
                   {
                     YYUSE ($1);
 
-                    lexer.enable_fq_identifier ();
+                    $$ = new octave::tree_classdef_superclass_list ($2);
                   }
-                  superclass
-                  { $$ = new octave::tree_classdef_superclass_list ($3); }
-                | superclass_list EXPR_AND
+                | superclass_list EXPR_AND superclass
                   {
                     YYUSE ($2);
 
-                    lexer.enable_fq_identifier ();
-                  }
-                  superclass
-                  {
-                    $1->append ($4);
+                    $1->append ($3);
                     $$ = $1;
                   }
                 ;
@@ -2494,13 +2500,18 @@
   {
     tree_expression *retval = nullptr;
 
+    interpreter& interp = __get_interpreter__ ("finish_colon_expression");
+    error_system& es = interp.get_error_system ();
+
     unwind_protect frame;
 
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
+    frame.add_method (es, &error_system::set_discard_error_messages,
+                      es.discard_error_messages ());
+    frame.add_method (es, &error_system::set_discard_warning_messages,
+                      es.discard_warning_messages ());
+
+    es.discard_error_messages (true);
+    es.discard_warning_messages (true);
 
     if (! base || ! limit)
       {
@@ -2522,8 +2533,7 @@
       {
         try
           {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_colon_expression");
+            tree_evaluator& tw = interp.get_evaluator ();
 
             octave_value tmp = tw.evaluate (e);
 
@@ -2969,7 +2979,7 @@
 
     if (! m_lexer.m_looping)
       {
-        bison_error ("break must appear in a loop in the same file as loop command");
+        bison_error ("break must appear within a loop");
         return nullptr;
       }
     else
@@ -2984,7 +2994,13 @@
     int l = continue_tok->line ();
     int c = continue_tok->column ();
 
-    return new tree_continue_command (l, c);
+    if (! m_lexer.m_looping)
+      {
+        bison_error ("continue must appear within a loop");
+        return nullptr;
+      }
+    else
+      return new tree_continue_command (l, c);
   }
 
   // Build a return command.
@@ -3343,14 +3359,11 @@
       = new octave_user_function (m_lexer.m_symtab_context.curr_scope (),
                                   param_list, nullptr, body);
 
-    if (fcn)
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        fcn->stash_trailing_comment (tc);
-        fcn->stash_fcn_end_location (end_fcn_stmt->line (),
-                                     end_fcn_stmt->column ());
-      }
+    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+    fcn->stash_trailing_comment (tc);
+    fcn->stash_fcn_end_location (end_fcn_stmt->line (),
+                                 end_fcn_stmt->column ());
 
     // If input is coming from a file, issue a warning if the name of
     // the file does not match the name of the function stated in the
@@ -3396,10 +3409,20 @@
 
         if (m_lexer.m_parsing_class_method)
           {
-            if (m_curr_class_name == id_name)
-              fcn->mark_as_class_constructor ();
+            if (m_lexer.m_parsing_classdef)
+              {
+                if (m_curr_class_name == id_name)
+                  fcn->mark_as_classdef_constructor ();
+                else
+                  fcn->mark_as_classdef_method ();
+              }
             else
-              fcn->mark_as_class_method ();
+              {
+                if (m_curr_class_name == id_name)
+                  fcn->mark_as_legacy_constructor ();
+                else
+                  fcn->mark_as_legacy_method ();
+              }
 
             fcn->stash_dispatch_class (m_curr_class_name);
           }
@@ -3470,7 +3493,6 @@
 
         symbol_scope fcn_scope = fcn->scope ();
         fcn_scope.cache_name (tmp);
-        fcn_scope.install_auto_fcn_vars ();
 
         if (lc)
           fcn->stash_leading_comment (lc);
@@ -3550,40 +3572,6 @@
     m_lexer.m_looking_at_parameter_list = false;
   }
 
-  tree_funcall *
-  base_parser::make_superclass_ref (const std::string& method_nm,
-                                    const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(1) = class_nm;
-    args(0) = method_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_superclass_ref");
-
-    octave_value fcn
-      = symtab.find_built_in_function ("__superclass_reference__");
-
-    return new tree_funcall (fcn, args);
-  }
-
-  tree_funcall *
-  base_parser::make_meta_class_query (const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(0) = class_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_meta_class_query");
-
-    octave_value fcn
-      = symtab.find_built_in_function ("__meta_class_query__");
-
-    return new tree_funcall (fcn, args);
-  }
-
   // A CLASSDEF block defines a class that has a constructor and other
   // methods, but it is not an executable command.  Parsing the block
   // makes some changes in the symbol table (inserting the constructor
@@ -3613,12 +3601,15 @@
 
     if (nm != cls_name)
       {
+        int l = id->line ();
+        int c = id->column ();
+
         delete a;
         delete id;
         delete sc;
         delete body;
 
-        bison_error ("invalid classdef definition, the class name must match the filename");
+        bison_error ("invalid classdef definition, the class name must match the filename", l, c);
 
       }
     else
@@ -3633,7 +3624,8 @@
             if (! body)
               body = new tree_classdef_body ();
 
-            retval = new tree_classdef (a, id, sc, body, lc, tc,
+            retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (),
+                                        a, id, sc, body, lc, tc,
                                         m_curr_package_name, l, c);
           }
         else
@@ -3795,7 +3787,7 @@
         // Methods that cannot be declared outside the classdef file:
         // - methods with '.' character (e.g. property accessors)
         // - class constructor
-        // - `delete'
+        // - 'delete'
 
         if (mname.find_first_of (".") == std::string::npos
             && mname != "delete"
@@ -3815,7 +3807,7 @@
           }
         else
           bison_error ("invalid external method declaration, an external "
-                       "method cannot be the class constructor, `delete' "
+                       "method cannot be the class constructor, 'delete' "
                        "or have a dot (.) character in its name");
       }
     else
@@ -3901,8 +3893,8 @@
 
         if (expr->is_index_expression ())
           {
-            tree_index_expression *tmp =
-              static_cast<tree_index_expression *> (expr);
+            tree_index_expression *tmp
+              = dynamic_cast<tree_index_expression *> (expr);
 
             tmp->append (args, type);
 
@@ -3931,7 +3923,8 @@
 
     if (expr->is_index_expression ())
       {
-        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+        tree_index_expression *tmp
+          = dynamic_cast<tree_index_expression *> (expr);
 
         tmp->append (elt);
 
@@ -3961,7 +3954,8 @@
 
     if (expr->is_index_expression ())
       {
-        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+        tree_index_expression *tmp
+          = dynamic_cast<tree_index_expression *> (expr);
 
         tmp->append (elt);
 
@@ -4174,20 +4168,24 @@
   {
     tree_expression *retval = array_list;
 
+    interpreter& interp = __get_interpreter__ ("finish_array_list");
+    error_system& es = interp.get_error_system ();
+
     unwind_protect frame;
 
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
+    frame.add_method (es, &error_system::set_discard_error_messages,
+                      es.discard_error_messages ());
+    frame.add_method (es, &error_system::set_discard_warning_messages,
+                      es.discard_warning_messages ());
+
+    es.discard_error_messages (true);
+    es.discard_warning_messages (true);
 
     if (array_list->all_elements_are_constant ())
       {
         try
           {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_array_list");
+            tree_evaluator& tw = interp.get_evaluator ();
 
             octave_value tmp = tw.evaluate (array_list);
 
@@ -4317,6 +4315,42 @@
   }
 
   void
+  base_parser::disallow_command_syntax (void)
+  {
+    m_lexer.m_allow_command_syntax = false;
+  }
+
+  // FIXME: this function partially duplicates do_dbtype in debug.cc.
+  static std::string
+  get_file_line (const std::string& name, int line)
+  {
+    // NAME should be an absolute file name and the file should exist.
+
+    std::string ascii_fname = sys::get_ASCII_filename (name);
+
+    std::ifstream fs (ascii_fname.c_str (), std::ios::in);
+
+    std::string text;
+
+    if (fs)
+      {
+        int i = 1;
+
+        do
+          {
+            if (! std::getline (fs, text))
+              {
+                text = "";
+                break;
+              }
+          }
+        while (i++ < line);
+      }
+
+    return text;
+  }
+
+  void
   base_parser::bison_error (const std::string& str, int l, int c)
   {
     int err_line = l < 0 ? m_lexer.m_input_line_number : l;
@@ -4336,10 +4370,20 @@
 
     output_buf << "\n\n";
 
-    std::string curr_line = m_lexer.m_current_input_line;
+    std::string curr_line;
+
+    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
+        || m_lexer.m_reading_classdef_file)
+      curr_line = get_file_line (m_lexer.m_fcn_file_full_name, err_line);
+    else
+      curr_line = m_lexer.m_current_input_line;
 
     if (! curr_line.empty ())
       {
+        // FIXME: we could do better if we just cached lines from the
+        // input file in a list.  See also functions for managing input
+        // buffers in lex.ll.
+
         size_t len = curr_line.length ();
 
         if (curr_line[len-1] == '\n')
@@ -4473,126 +4517,6 @@
     return status;
   }
 
-  static void
-  safe_fclose (FILE *f)
-  {
-    if (f)
-      fclose (static_cast<FILE *> (f));
-  }
-
-  static octave_value
-  parse_fcn_file (const std::string& full_file, const std::string& file,
-                  const std::string& dir_name, const std::string& dispatch_type,
-                  const std::string& package_name, bool require_file,
-                  bool force_script, bool autoload, bool relative_lookup,
-                  const std::string& warn_for)
-  {
-    octave_value retval;
-
-    unwind_protect frame;
-
-    octave_function *fcn_ptr = nullptr;
-
-    // Open function file and parse.
-
-    FILE *in_stream = command_editor::get_input_stream ();
-
-    frame.add_fcn (command_editor::set_input_stream, in_stream);
-
-    frame.add_fcn (command_history::ignore_entries,
-                   command_history::ignoring_entries ());
-
-    command_history::ignore_entries ();
-
-    FILE *ffile = nullptr;
-
-    if (! full_file.empty ())
-      ffile = octave::sys::fopen (full_file, "rb");
-
-    if (ffile)
-      {
-        frame.add_fcn (safe_fclose, ffile);
-
-        interpreter& interp = __get_interpreter__ ("parse_fcn_file");
-
-        parser parser (ffile, interp);
-
-        parser.m_curr_class_name = dispatch_type;
-        parser.m_curr_package_name = package_name;
-        parser.m_autoloading = autoload;
-        parser.m_fcn_file_from_relative_lookup = relative_lookup;
-
-        parser.m_lexer.m_force_script = force_script;
-        parser.m_lexer.prep_for_file ();
-        parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
-
-        parser.m_lexer.m_fcn_file_name = file;
-        parser.m_lexer.m_fcn_file_full_name = full_file;
-        parser.m_lexer.m_dir_name = dir_name;
-        parser.m_lexer.m_package_name = package_name;
-
-        int status = parser.run ();
-
-        fcn_ptr = parser.m_primary_fcn_ptr;
-
-        if (status == 0)
-          {
-            if (parser.m_lexer.m_reading_classdef_file
-                && parser.m_classdef_object)
-              {
-                // Convert parse tree for classdef object to
-                // meta.class info (and stash it in the symbol
-                // table?).  Return pointer to constructor?
-
-                if (fcn_ptr)
-                  panic_impossible ();
-
-                bool is_at_folder = ! dispatch_type.empty ();
-
-                try
-                  {
-                    fcn_ptr = parser.m_classdef_object->make_meta_class (interp, is_at_folder);
-                  }
-                catch (const execution_exception&)
-                  {
-                    delete parser.m_classdef_object;
-                    throw;
-                  }
-
-                if (fcn_ptr)
-                  retval = octave_value (fcn_ptr);
-
-                delete parser.m_classdef_object;
-
-                parser.m_classdef_object = nullptr;
-              }
-            else if (fcn_ptr)
-              {
-                retval = octave_value (fcn_ptr);
-
-                fcn_ptr->maybe_relocate_end ();
-
-                if (parser.m_parsing_subfunctions)
-                  {
-                    if (! parser.m_endfunction_found)
-                      parser.m_subfunction_names.reverse ();
-
-                    fcn_ptr->stash_subfunction_names (parser.m_subfunction_names);
-                  }
-              }
-          }
-        else
-          error ("parse error while reading file %s", full_file.c_str ());
-      }
-    else if (require_file)
-      error ("no such file, '%s'", full_file.c_str ());
-    else if (! warn_for.empty ())
-      error ("%s: unable to open file '%s'", warn_for.c_str (),
-             full_file.c_str ());
-
-    return retval;
-  }
-
   std::string
   get_help_from_file (const std::string& nm, bool& symbol_found,
                       std::string& full_file)
@@ -4619,11 +4543,13 @@
 
     if (! file.empty ())
       {
+        interpreter& interp = __get_interpreter__ ("get_help_from_file");
+
         symbol_found = true;
 
         octave_value ov_fcn
-          = parse_fcn_file (full_file, file, "", "", "", true,
-                            false, false, false, "");
+          = interp.parse_fcn_file (full_file, file, "", "", "", true,
+                                   false, false, false, "");
 
         if (ov_fcn.is_defined ())
           {
@@ -4644,49 +4570,6 @@
     return get_help_from_file (nm, symbol_found, file);
   }
 
-  std::string
-  lookup_autoload (const std::string& nm)
-  {
-    std::string retval;
-
-    typedef std::map<std::string, std::string>::const_iterator am_iter;
-
-    am_iter p = autoload_map.find (nm);
-
-    if (p != autoload_map.end ())
-      {
-        load_path& lp = __get_load_path__ ("lookup_autoload");
-
-        retval = lp.find_file (p->second);
-      }
-
-    return retval;
-  }
-
-  string_vector
-  autoloaded_functions (void)
-  {
-    string_vector names (autoload_map.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& fcn_fname : autoload_map)
-      names[i++] = fcn_fname.first;
-
-    return names;
-  }
-
-  string_vector
-  reverse_lookup_autoload (const std::string& nm)
-  {
-    string_vector names;
-
-    for (const auto& fcn_fname : autoload_map)
-      if (nm == fcn_fname.second)
-        names.append (fcn_fname.first);
-
-    return names;
-  }
-
   octave_value
   load_fcn_from_file (const std::string& file_name,
                       const std::string& dir_name,
@@ -4726,8 +4609,9 @@
 
     int len = file.length ();
 
-      dynamic_loader& dyn_loader
-        = __get_dynamic_loader__ ("~octave_mex_function");
+    interpreter& interp = __get_interpreter__ ("load_fcn_from_file");
+
+    dynamic_loader& dyn_loader = interp.get_dynamic_loader ();
 
     if (len > 4 && file.substr (len-4, len-1) == ".oct")
       {
@@ -4751,9 +4635,9 @@
         std::string doc_string;
 
         octave_value ov_fcn
-          = parse_fcn_file (file.substr (0, len - 2), nm, dir_name,
-                            dispatch_type, package_name, false,
-                            autoload, autoload, relative_lookup, "");
+          = interp.parse_fcn_file (file.substr (0, len - 2), nm, dir_name,
+                                   dispatch_type, package_name, false,
+                                   autoload, autoload, relative_lookup, "");
 
         if (ov_fcn.is_defined ())
           {
@@ -4776,9 +4660,9 @@
       }
     else if (len > 2)
       {
-        retval = parse_fcn_file (file, nm, dir_name, dispatch_type,
-                                 package_name, true, autoload, autoload,
-                                 relative_lookup, "");
+        retval = interp.parse_fcn_file (file, nm, dir_name, dispatch_type,
+                                        package_name, true, autoload,
+                                        autoload, relative_lookup, "");
       }
 
     return retval;
@@ -4825,248 +4709,32 @@
 @seealso{PKG_ADD}
 @end deftypefn */)
 {
-  octave_value retval;
-
   int nargin = args.length ();
 
   if (nargin == 1 || nargin > 3)
     print_usage ();
 
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
   if (nargin == 0)
-    {
-      Cell func_names (dim_vector (autoload_map.size (), 1));
-      Cell file_names (dim_vector (autoload_map.size (), 1));
-
-      octave_idx_type i = 0;
-      for (const auto& fcn_fname : autoload_map)
-        {
-          func_names(i) = fcn_fname.first;
-          file_names(i) = fcn_fname.second;
-
-          i++;
-        }
-
-      octave_map m;
-
-      m.assign ("function", func_names);
-      m.assign ("file", file_names);
-
-      retval = m;
-    }
+    return octave_value (tw.get_autoload_map ());
   else
     {
       string_vector argv = args.make_argv ("autoload");
 
-      std::string nm = argv[2];
-
-      if (! octave::sys::env::absolute_pathname (nm))
-        {
-          octave::call_stack& cs = interp.get_call_stack ();
-
-          octave_user_code *fcn = cs.caller_user_code ();
-
-          bool found = false;
-
-          if (fcn)
-            {
-              std::string fname = fcn->fcn_file_name ();
-
-              if (! fname.empty ())
-                {
-                  fname = octave::sys::env::make_absolute (fname);
-                  fname = fname.substr (0, fname.find_last_of (octave::sys::file_ops::dir_sep_str ()) + 1);
-
-                  octave::sys::file_stat fs (fname + nm);
-
-                  if (fs.exists ())
-                    {
-                      nm = fname + nm;
-                      found = true;
-                    }
-                }
-            }
-          if (! found)
-            warning_with_id ("Octave:autoload-relative-file-name",
-                             "autoload: '%s' is not an absolute filename",
-                             nm.c_str ());
-        }
       if (nargin == 2)
-        autoload_map[argv[1]] = nm;
+        tw.add_autoload (argv[1], argv[2]);
       else if (nargin == 3)
         {
           if (argv[3] != "remove")
             error_with_id ("Octave:invalid-input-arg",
                            "autoload: third argument can only be 'remove'");
 
-          // Remove function from symbol table and autoload map.
-          octave::symbol_table& symtab = interp.get_symbol_table ();
-          symtab.clear_dld_function (argv[1]);
-          autoload_map.erase (argv[1]);
+          tw.remove_autoload (argv[1], argv[2]);
         }
     }
 
-  return retval;
-}
-
-namespace octave
-{
-  // Execute the contents of a script file.  For compatibility with
-  // Matlab, also execute a function file by calling the function it
-  // defines with no arguments and nargout = 0.
-
-  void
-  source_file (const std::string& file_name, const std::string& context,
-               bool verbose, bool require_file, const std::string& warn_for)
-  {
-    // Map from absolute name of script file to recursion level.  We
-    // use a map instead of simply placing a limit on recursion in the
-    // source_file function so that two mutually recursive scripts
-    // written as
-    //
-    //   foo1.m:
-    //   ------
-    //   foo2
-    //
-    //   foo2.m:
-    //   ------
-    //   foo1
-    //
-    // and called with
-    //
-    //   foo1
-    //
-    // (for example) will behave the same if they are written as
-    //
-    //   foo1.m:
-    //   ------
-    //   source ("foo2.m")
-    //
-    //   foo2.m:
-    //   ------
-    //   source ("foo1.m")
-    //
-    // and called with
-    //
-    //   source ("foo1.m")
-    //
-    // (for example).
-
-    static std::map<std::string, int> source_call_depth;
-
-    std::string file_full_name
-      = sys::file_ops::tilde_expand (file_name);
-
-    size_t pos
-      = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
-
-    std::string dir_name = file_full_name.substr (0, pos);
-
-    file_full_name = sys::env::make_absolute (file_full_name);
-
-    unwind_protect frame;
-
-    if (source_call_depth.find (file_full_name) == source_call_depth.end ())
-      source_call_depth[file_full_name] = -1;
-
-    frame.protect_var (source_call_depth[file_full_name]);
-
-    source_call_depth[file_full_name]++;
-
-    tree_evaluator& tw = __get_evaluator__ ("source_file");
-
-    if (source_call_depth[file_full_name] >= tw.max_recursion_depth ())
-      error ("max_recursion_depth exceeded");
-
-    if (! context.empty ())
-      {
-        call_stack& cs = __get_call_stack__ ("source_file");
-
-        if (context == "caller")
-          cs.goto_caller_frame ();
-        else if (context == "base")
-          cs.goto_base_frame ();
-        else
-          error ("source: context must be \"caller\" or \"base\"");
-
-        frame.add_method (cs, &call_stack::pop);
-      }
-
-    // Find symbol name that would be in symbol_table, if it were loaded.
-    size_t dir_end
-      = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
-    dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
-
-    size_t extension = file_name.find_last_of ('.');
-    if (extension == std::string::npos)
-      extension = file_name.length ();
-
-    std::string symbol = file_name.substr (dir_end, extension - dir_end);
-    std::string full_name = sys::canonicalize_file_name (file_name);
-
-    // Check if this file is already loaded (or in the path)
-    symbol_scope curr_scope = __get_current_scope__ ("source_file");
-    octave_value ov_code = curr_scope.find (symbol);
-
-    // For compatibility with Matlab, accept both scripts and
-    // functions.
-
-    if (ov_code.is_user_code ())
-      {
-        octave_user_code *code = ov_code.user_code_value ();
-
-        if (! code
-            || (sys::canonicalize_file_name (code->fcn_file_name ())
-                != full_name))
-          {
-            // Wrong file, so load it below.
-            ov_code = octave_value ();
-          }
-      }
-    else
-      {
-        // Not a script, so load it below.
-        ov_code = octave_value ();
-      }
-
-    // If no symbol of this name, or the symbol is for a different
-    // file, load.
-
-    if (ov_code.is_undefined ())
-      {
-        try
-          {
-            ov_code = parse_fcn_file (file_full_name, file_name, dir_name,
-                                      "", "", require_file, true, false,
-                                      false, warn_for);
-          }
-        catch (execution_exception& e)
-          {
-            error (e, "source: error sourcing file '%s'",
-                   file_full_name.c_str ());
-          }
-      }
-
-    // Return or error if we don't have a valid script or function.
-
-    if (ov_code.is_undefined ())
-      return;
-
-    if (! ov_code.is_user_code ())
-      error ("source: %s is not a script", full_name.c_str ());
-
-    if (verbose)
-      {
-        octave_stdout << "executing commands from " << full_name << " ... ";
-        octave_stdout.flush ();
-      }
-
-    octave_user_code *code = ov_code.user_code_value ();
-
-    code->call (tw, 0, octave_value_list ());
-
-    if (verbose)
-      octave_stdout << "done." << std::endl;
-  }
+  return octave_value_list ();
 }
 
 DEFMETHOD (mfilename, interp, args, ,
@@ -5088,55 +4756,37 @@
 @seealso{inputname, dbstack}
 @end deftypefn */)
 {
-  octave_value retval;
-
   int nargin = args.length ();
 
   if (nargin > 1)
     print_usage ();
 
-  std::string arg;
+  std::string opt;
 
   if (nargin == 1)
-    arg = args(0).xstring_value ("mfilename: argument must be a string");
-
-  std::string fname;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  octave_user_code *fcn = cs.caller_user_code ();
-
-  if (fcn)
-    {
-      fname = fcn->fcn_file_name ();
-
-      if (fname.empty ())
-        fname = fcn->name ();
-    }
-
-  if (arg == "fullpathext")
-    retval = fname;
-  else
-    {
-      size_t dpos = fname.rfind (octave::sys::file_ops::dir_sep_char ());
-      size_t epos = fname.rfind ('.');
-
-      if (epos <= dpos+1)
-        epos = std::string::npos;
-
-      fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
-
-      if (arg == "fullpath")
-        retval = fname;
-      else
-        retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
-    }
-
-  return retval;
+    opt = args(0).xstring_value ("mfilename: option argument must be a string");
+
+  return octave_value (interp.mfilename (opt));
 }
 
-DEFUN (source, args, ,
-       doc: /* -*- texinfo -*-
+namespace octave
+{
+  // Execute the contents of a script file.  For compatibility with
+  // Matlab, also execute a function file by calling the function it
+  // defines with no arguments and nargout = 0.
+
+  void
+  source_file (const std::string& file_name, const std::string& context,
+               bool verbose, bool require_file, const std::string& warn_for)
+  {
+    interpreter& interp = __get_interpreter__ ("source_file");
+
+    interp.source_file (file_name, context, verbose, require_file, warn_for);
+  }
+}
+
+DEFMETHOD (source, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} source (@var{file})
 @deftypefnx {} {} source (@var{file}, @var{context})
 Parse and execute the contents of @var{file}.
@@ -5151,23 +4801,21 @@
 @seealso{run}
 @end deftypefn */)
 {
-  octave_value_list retval;
-
   int nargin = args.length ();
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  std::string file_name = args(0).xstring_value ("source: FILE must be a string");
+  std::string file_name
+    = args(0).xstring_value ("source: FILE must be a string");
 
   std::string context;
-
   if (nargin == 2)
     context = args(1).xstring_value ("source: CONTEXT must be a string");
 
-  octave::source_file (file_name, context);
-
-  return retval;
+  interp.source_file (file_name, context);
+
+  return octave_value_list ();
 }
 
 namespace octave
@@ -5182,107 +4830,48 @@
   //!         necessarily the same as @c nargout.
 
   octave_value_list
+  feval (const char *name, const octave_value_list& args, int nargout)
+  {
+    interpreter& interp = __get_interpreter__ ("feval");
+
+    return interp.feval (name, args, nargout);
+  }
+
+  octave_value_list
   feval (const std::string& name, const octave_value_list& args, int nargout)
   {
-    octave_value_list retval;
-
-    symbol_table& symtab = __get_symbol_table__ ("feval");
-
-    octave_value fcn = symtab.find_function (name, args);
-
-    if (fcn.is_defined ())
-      {
-        tree_evaluator& tw = __get_evaluator__ ("feval");
-
-        octave_function *of = fcn.function_value ();
-
-        retval = of->call (tw, nargout, args);
-      }
-    else
-      error ("feval: function '%s' not found", name.c_str ());
-
-    return retval;
+    interpreter& interp = __get_interpreter__ ("feval");
+
+    return interp.feval (name, args, nargout);
   }
 
   octave_value_list
   feval (octave_function *fcn, const octave_value_list& args, int nargout)
   {
-    octave_value_list retval;
-
-    if (fcn)
-      {
-        tree_evaluator& tw = __get_evaluator__ ("feval");
-
-        retval = fcn->call (tw, nargout, args);
-      }
-
-    return retval;
+    interpreter& interp = __get_interpreter__ ("feval");
+
+    return interp.feval (fcn, args, nargout);
   }
 
   octave_value_list
-  feval (octave_value& val, const octave_value_list& args, int nargout)
+  feval (const octave_value& val, const octave_value_list& args, int nargout)
   {
-    if (val.is_function ())
-      {
-        return feval (val.function_value (), args, nargout);
-      }
-    else if (val.is_function_handle ())
-      {
-        // This covers function handles, inline functions, and anonymous
-        //  functions.
-
-        std::list<octave_value_list> arg_list;
-        arg_list.push_back (args);
-
-        return val.subsref ("(", arg_list, nargout);
-      }
-    else if (val.is_string ())
-      {
-        return feval (val.string_value (), args, nargout);
-      }
-    else
-      error ("feval: first argument must be a string, inline function, or a function handle");
-
-    return ovl ();
+    interpreter& interp = __get_interpreter__ ("feval");
+
+    return interp.feval (val, args, nargout);
   }
 
-  static octave_value_list
-  get_feval_args (const octave_value_list& args)
-  {
-    return args.slice (1, args.length () - 1, true);
-  }
-
-  //! Evaluate an Octave function (built-in or interpreted) and return
-  //! the list of result values.
-  //!
-  //! @param args The first element of @c args is the function to call.
-  //!             It may be the name of the function as a string, a function
-  //!             handle, or an inline function.  The remaining arguments are
-  //!             passed to the function.
-  //! @param nargout The number of output arguments expected.
-  //! @return A list of output values.  The length of the list is not
-  //!         necessarily the same as @c nargout.
-
   octave_value_list
   feval (const octave_value_list& args, int nargout)
   {
-    if (args.length () > 0)
-      {
-        octave_value f_arg = args(0);
-
-        octave_value_list tmp_args = get_feval_args (args);
-
-        return feval (f_arg, tmp_args, nargout);
-      }
-    else
-      error ("feval: first argument must be a string, inline function, or a function handle");
-
-    return ovl ();
+    interpreter& interp = __get_interpreter__ ("feval");
+
+    return interp.feval (args, nargout);
   }
 }
 
-DEFUN (feval, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (feval, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} feval (@var{name}, @dots{})
 Evaluate the function named @var{name}.
 
@@ -5324,7 +4913,7 @@
   if (args.length () == 0)
     print_usage ();
 
-  return octave::feval (args, nargout);
+  return interp.feval (args, nargout);
 }
 
 DEFMETHOD (builtin, interp, args, nargout,
@@ -5365,7 +4954,7 @@
   octave_value fcn = symtab.builtin_find (name);
 
   if (fcn.is_defined ())
-    retval = octave::feval (fcn.function_value (), args.splice (0, 1), nargout);
+    retval = interp.feval (fcn.function_value (), args.splice (0, 1), nargout);
   else
     error ("builtin: lookup for symbol '%s' failed", name.c_str ());
 
@@ -5402,23 +4991,6 @@
   }
 }
 
-octave_value_list
-eval_string (const std::string& str, bool silent, int& parse_status,
-             int nargout)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("eval_string");
-
-  return interp.eval_string (str, silent, parse_status, nargout);
-}
-
-octave_value
-eval_string (const std::string& str, bool silent, int& parse_status)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("eval_string");
-
-  return interp.eval_string (str, silent, parse_status);
-}
-
 DEFMETHOD (eval, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} eval (@var{try})
@@ -5459,62 +5031,28 @@
 @seealso{evalin, evalc, assignin, feval}
 @end deftypefn */)
 {
-  octave_value_list retval;
-
   int nargin = args.length ();
 
-  if (nargin == 0)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  octave::unwind_protect frame;
-
-  if (nargin > 1)
-    {
-      frame.protect_var (buffer_error_messages);
-      buffer_error_messages++;
-    }
-
-  int parse_status = 0;
-
-  bool execution_error = false;
-
-  octave_value_list tmp;
-
-  try
-    {
-      tmp = interp.eval_string (args(0), nargout > 0, parse_status, nargout);
-    }
-  catch (const octave::execution_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      execution_error = true;
-    }
-
-  if (nargin > 1 && (parse_status != 0 || execution_error))
-    {
-      // Set up for letting the user print any messages from
-      // errors that occurred in the first part of this eval().
-
-      buffer_error_messages--;
-
-      tmp = interp.eval_string (args(1), nargout > 0, parse_status, nargout);
-
-      if (nargout > 0)
-        retval = tmp;
-    }
+  if (! args(0).is_string () || args(0).rows () > 1 || args(0).ndims () != 2) 
+    error ("eval: TRY must be a string");
+
+  std::string try_code = args(0).string_value ();
+
+  if (nargin == 1)
+    return interp.eval (try_code, nargout);
   else
     {
-      if (nargout > 0)
-        retval = tmp;
-
-      // FIXME: we should really be rethrowing whatever exception occurred,
-      // not just throwing an execution exception.
-      if (execution_error)
-        octave_throw_execution_exception ();
+      if (! args(1).is_string () || args(1).rows () > 1
+          || args(1).ndims () != 2) 
+        error ("eval: CATCH must be a string");
+
+      std::string catch_code = args(1).string_value ();
+
+      return interp.eval (try_code, catch_code, nargout);
     }
-
-  return retval;
 }
 
 /*
@@ -5548,13 +5086,25 @@
 %!endfunction
 %!assert (__f(), 2)
 
-% bug #35645
-%!test
+%!test <*35645>
 %! [a,] = gcd (1,2);
 %! [a,b,] = gcd (1, 2);
 
+## Can't assign to a keyword
 %!error eval ("switch = 13;")
 
+%!shared str
+%! str = "disp ('hello');";
+%! str(:,:,2) = str(:,:,1);
+
+%!error <TRY must be a string> eval (1)
+%!error <TRY must be a string> eval (['a';'b'])
+%!error <TRY must be a string> eval (str)
+
+%!error <CATCH must be a string> eval (str(:,:,1), 1)
+%!error <CATCH must be a string> eval (str(:,:,1), ['a';'b'])
+%!error <CATCH must be a string> eval (str(:,:,1), str)
+
 */
 
 DEFMETHOD (assignin, interp, args, ,
@@ -5565,46 +5115,18 @@
 @seealso{evalin}
 @end deftypefn */)
 {
-  octave_value_list retval;
-
   if (args.length () != 3)
     print_usage ();
 
-  std::string context = args(0).xstring_value ("assignin: CONTEXT must be a string");
-
-  octave::unwind_protect frame;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  if (context == "caller")
-    cs.goto_caller_frame ();
-  else if (context == "base")
-    cs.goto_base_frame ();
-  else
-    error ("assignin: CONTEXT must be \"caller\" or \"base\"");
-
-  frame.add_method (cs, &octave::call_stack::pop);
-
-  std::string nm = args(1).xstring_value ("assignin: VARNAME must be a string");
-
-  if (octave::valid_identifier (nm))
-    {
-      // Put the check here so that we don't slow down assignments
-      // generally.  Any that go through Octave's parser should have
-      // already been checked.
-
-      if (octave::iskeyword (nm))
-        error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
-
-      octave::symbol_scope scope = interp.get_current_scope ();
-
-      if (scope)
-        scope.assign (nm, args(2));
-    }
-  else
-    error ("assignin: invalid variable name in argument VARNAME");
-
-  return retval;
+  std::string context
+    = args(0).xstring_value ("assignin: CONTEXT must be a string");
+
+  std::string varname
+    = args(1).xstring_value ("assignin: VARNAME must be a string");
+
+  interp.assignin (context, varname, args(2));
+
+  return octave_value_list ();
 }
 
 /*
@@ -5622,85 +5144,45 @@
 @seealso{eval, assignin}
 @end deftypefn */)
 {
-  octave_value_list retval;
-
   int nargin = args.length ();
 
-  if (nargin < 2)
+  if (nargin < 2 || nargin > 3)
     print_usage ();
 
-  std::string context = args(0).xstring_value ("evalin: CONTEXT must be a string");
-
-  octave::unwind_protect frame;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  if (context == "caller")
-    cs.goto_caller_frame ();
-  else if (context == "base")
-    cs.goto_base_frame ();
-  else
-    error ("evalin: CONTEXT must be \"caller\" or \"base\"");
-
-  frame.add_method (cs, &octave::call_stack::pop);
-
-  if (nargin > 2)
+  std::string context
+    = args(0).xstring_value ("evalin: CONTEXT must be a string");
+
+  std::string try_code
+    = args(1).xstring_value ("evalin: TRY must be a string");
+
+  if (nargin == 3)
     {
-      frame.protect_var (buffer_error_messages);
-      buffer_error_messages++;
+      std::string catch_code
+        = args(2).xstring_value ("evalin: CATCH must be a string");
+
+      return interp.evalin (context, try_code, catch_code, nargout);
     }
 
-  int parse_status = 0;
-
-  bool execution_error = false;
-
-  octave_value_list tmp;
-
-  try
-    {
-      tmp = interp.eval_string (args(1), nargout > 0, parse_status, nargout);
-    }
-  catch (const octave::execution_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      execution_error = true;
-    }
-
-  if (nargin > 2 && (parse_status != 0 || execution_error))
-    {
-      // Set up for letting the user print any messages from
-      // errors that occurred in the first part of this eval().
-
-      buffer_error_messages--;
-
-      tmp = interp.eval_string (args(2), nargout > 0, parse_status, nargout);
-
-      retval = (nargout > 0) ? tmp : octave_value_list ();
-    }
-  else
-    {
-      if (nargout > 0)
-        retval = tmp;
-
-      // FIXME: we should really be rethrowing whatever
-      // exception occurred, not just throwing an
-      // execution exception.
-      if (execution_error)
-        octave_throw_execution_exception ();
-    }
-
-  return retval;
+  return interp.evalin (context, try_code, nargout);
 }
 
 static void
 maybe_print_last_error_message (bool *doit)
 {
   if (doit && *doit)
-    // Print error message again, which was lost because of the stderr buffer
-    // Note: this keeps error_state and last_error_stack intact
-    message_with_id ("error", last_error_id ().c_str (),
-                     "%s", last_error_message ().c_str ());
+    {
+      // Print error message again, which was lost because of the stderr
+      // buffer.  Note: this keeps error_state and last_error_stack
+      // intact.
+
+      octave::error_system& es
+        = octave::__get_error_system__ ("maybe_print_last_error_message");
+
+      std::string id = es.last_error_id ();
+      std::string msg = es.last_error_message ();
+
+      message_with_id ("error", id.c_str (), "%s", msg.c_str ());
+    }
 }
 
 static void
@@ -5784,7 +5266,17 @@
 
 /*
 
-%!assert (evalc ("1"), "ans =  1\n")
+%!test
+%! [old_fmt, old_spacing] = format ();
+%! unwind_protect
+%!   format short;
+%!   str = evalc ("1");
+%!   assert (str, "ans =  1\n");
+%! unwind_protect_cleanup
+%!   format (old_fmt);
+%!   format (old_spacing);
+%! end_unwind_protect
+
 %!assert (evalc ("1;"), "")
 
 %!test
@@ -5798,8 +5290,16 @@
 %! assert (y, 1);
 
 %!test
-%! assert (evalc ("y = 2"), "y =  2\n");
-%! assert (y, 2);
+%! [old_fmt, old_spacing] = format ();
+%! unwind_protect
+%!   format short;
+%!   str = evalc ("y = 2");
+%!   assert (str, "y =  2\n");
+%!   assert (y, 2);
+%! unwind_protect_cleanup
+%!   format (old_fmt);
+%!   format (old_spacing);
+%! end_unwind_protect
 
 %!test
 %! assert (evalc ("y = 3;"), "");
@@ -5867,8 +5367,8 @@
   return retval;
 }
 
-DEFUN (__parse_file__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__parse_file__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __parse_file__ (@var{file}, @var{verbose})
 Undocumented internal function.
 @end deftypefn */)
@@ -5910,8 +5410,8 @@
     octave_stdout << "parsing " << full_file << std::endl;
 
   octave_value ov_fcn
-    = octave::parse_fcn_file (full_file, file, dir_name, "", "", true, false,
-                              false, false, "__parse_file__");
+    = interp.parse_fcn_file (full_file, file, dir_name, "", "", true, false,
+                             false, false, "__parse_file__");
 
   return retval;
 }
--- a/libinterp/parse-tree/parse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/parse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -68,7 +68,6 @@
   class tree_decl_init_list;
   class tree_expression;
   class tree_fcn_handle;
-  class tree_funcall;
   class tree_function_def;
   class tree_identifier;
   class tree_if_clause;
@@ -304,13 +303,6 @@
     void
     recover_from_parsing_function (void);
 
-    tree_funcall *
-    make_superclass_ref (const std::string& method_nm,
-                         const std::string& class_nm);
-
-    tree_funcall *
-    make_meta_class_query (const std::string& class_nm);
-
     tree_classdef *
     make_classdef (token *tok_val, tree_classdef_attribute_list *a,
                    tree_identifier *id, tree_classdef_superclass_list *sc,
@@ -409,6 +401,11 @@
     append_statement_list (tree_statement_list *list, char sep,
                            tree_statement *stmt, bool warn_missing_semi);
 
+    // Don't allow parsing command syntax.  If the parser/lexer is
+    // reset, this setting is also reset to the default (allow command
+    // syntax).
+    void disallow_command_syntax (void);
+
     // Generic error messages.
     void bison_error (const std::string& s, int l = -1, int c = -1);
 
@@ -543,15 +540,6 @@
   extern OCTINTERP_API std::string
   get_help_from_file (const std::string& nm, bool& symbol_found);
 
-  extern OCTINTERP_API
-  std::string lookup_autoload (const std::string& nm);
-
-  extern OCTINTERP_API string_vector
-  autoloaded_functions (void);
-
-  extern OCTINTERP_API string_vector
-  reverse_lookup_autoload (const std::string& nm);
-
   extern OCTINTERP_API octave_value
   load_fcn_from_file (const std::string& file_name,
                       const std::string& dir_name = "",
@@ -567,6 +555,11 @@
                const std::string& warn_for = "");
 
   extern OCTINTERP_API octave_value_list
+  feval (const char *name,
+         const octave_value_list& args = octave_value_list (),
+         int nargout = 0);
+
+  extern OCTINTERP_API octave_value_list
   feval (const std::string& name,
          const octave_value_list& args = octave_value_list (),
          int nargout = 0);
@@ -577,7 +570,7 @@
          int nargout = 0);
 
   extern OCTINTERP_API octave_value_list
-  feval (octave_value& val,
+  feval (const octave_value& val,
          const octave_value_list& args = octave_value_list (),
          int nargout = 0);
 
@@ -596,95 +589,4 @@
   cleanup_statement_list (tree_statement_list **lst);
 }
 
-OCTAVE_DEPRECATED (4.4, "use 'octave::interpreter::eval_string' instead")
-extern OCTINTERP_API octave_value_list
-eval_string (const std::string& str, bool silent, int& parse_status,
-             int nargout);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::interpreter::eval_string' instead")
-extern OCTINTERP_API octave_value
-eval_string (const std::string& str, bool silent, int& parse_status);
-
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::get_help_from_file' instead")
-static inline std::string
-get_help_from_file (const std::string& nm, bool& symbol_found,
-                    std::string& file)
-{
-  return octave::get_help_from_file (nm, symbol_found, file);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::get_help_from_file' instead")
-static inline std::string
-get_help_from_file (const std::string& nm, bool& symbol_found)
-{
-  return octave::get_help_from_file (nm, symbol_found);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::lookup_autoload' instead")
-static inline std::string
-lookup_autoload (const std::string& nm)
-{
-  return octave::lookup_autoload (nm);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::autoloaded_functions' instead")
-static inline string_vector
-autoloaded_functions (void)
-{
-  return octave::autoloaded_functions ();
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::reverse_lookup_autoload' instead")
-static inline string_vector
-reverse_lookup_autoload (const std::string& nm)
-{
-  return octave::reverse_lookup_autoload (nm);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::source_file' instead")
-static inline void
-source_file (const std::string& file_name,
-             const std::string& context = "",
-             bool verbose = false, bool require_file = true,
-             const std::string& warn_for = "")
-{
-  octave::source_file (file_name, context, verbose, require_file, warn_for);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::feval' instead")
-static inline octave_value_list
-feval (const std::string& name,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0)
-{
-  return octave::feval (name, args, nargout);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::feval' instead")
-static inline octave_value_list
-feval (octave_function *fcn,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0)
-{
-  return octave::feval (fcn, args, nargout);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::feval' instead")
-static inline octave_value_list
-feval (const octave_value_list& args, int nargout = 0)
-{
-  return octave::feval (args, nargout);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::cleanup_statement_list' instead")
-static inline void
-cleanup_statement_list (octave::tree_statement_list **lst)
-{
-  octave::cleanup_statement_list (lst);
-}
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-all.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-all.h	Fri Jul 12 12:14:43 2019 -0400
@@ -40,7 +40,6 @@
 #include "pt-except.h"
 #include "pt-exp.h"
 #include "pt-fcn-handle.h"
-#include "pt-funcall.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-jump.h"
--- a/libinterp/parse-tree/pt-anon-scopes.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-anon-scopes.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -33,46 +33,38 @@
 
 namespace octave
 {
-  tree_anon_scopes::tree_anon_scopes (octave_user_function *f)
-    : scopes (), merged_tables ()
+  tree_anon_scopes::tree_anon_scopes (tree_anon_fcn_handle& anon_fh)
+    : m_params (), m_vars ()
   {
-    if (f)
-      {
-        if (! f->is_anonymous_function ())
-          panic_impossible ();
-
-        // Collect the scope of the outer anonymous function.
-
-        stash_scope_if_valid (f->scope ());
-
-        // Further walk the tree to find nested definitions of further
-        // anonymous functions.
-
-        tree_statement_list *cmd_list = f->body ();
-
-        if (cmd_list)
-          cmd_list->accept (*this);
-
-        // Collect symbol records of all collected scopes.
-
-        merge_tables ();
-      }
+    visit_anon_fcn_handle (anon_fh);
   }
 
   void
   tree_anon_scopes::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)
   {
-    // Collect the scope of this anonymous function.
+    tree_parameter_list *param_list = afh.parameter_list ();
+    tree_expression *expr = afh.expression ();
+
+    // Collect names of parameters.
 
-    stash_scope_if_valid (afh.scope ());
+    if (param_list)
+      {
+        std::list<std::string> pnames = param_list->variable_names ();
+
+        for (const auto& nm : pnames)
+          m_params.insert (nm);
 
-    // Further walk the tree to find nested definitions of further
-    // anonymous functions.
+        // Hmm, should this be included in the list returned from
+        // tree_parameter_list::variable_names?
+        if (param_list->takes_varargs ())
+          m_params.insert ("varargin");
+      }
 
-    tree_expression *e = afh.expression ();
+    // Further walk the tree to find free variables in this expression
+    // and any nested definitions of additional anonymous functions.
 
-    if (e)
-      e->accept (*this);
+    if (expr)
+      expr->accept (*this);
   }
 
   // The rest of visit_... methods is only for walking the tree. Many of
@@ -191,8 +183,12 @@
   }
 
   void
-  tree_anon_scopes::visit_identifier (tree_identifier& /* id */)
+  tree_anon_scopes::visit_identifier (tree_identifier& id)
   {
+    std::string nm = id.name ();
+
+    if (m_params.find (nm) == m_params.end ())
+      m_vars.insert (nm);
   }
 
   void
@@ -306,11 +302,6 @@
   }
 
   void
-  tree_anon_scopes::visit_funcall (tree_funcall& /* fc */)
-  {
-  }
-
-  void
   tree_anon_scopes::visit_parameter_list (tree_parameter_list&)
   {
     // In visit_anon_fcn_handle we only accept/visit the body of
@@ -417,17 +408,5 @@
   {
     panic_impossible ();
   }
-
-  void
-  tree_anon_scopes::merge_tables (void)
-  {
-    for (const auto& sc : scopes)
-      {
-        symrec_list vars = sc.all_variables ();
-
-        for (const auto& symrec : vars)
-          merged_tables[symrec.name ()] = symrec;
-      }
-  }
 }
 
--- a/libinterp/parse-tree/pt-anon-scopes.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-anon-scopes.h	Fri Jul 12 12:14:43 2019 -0400
@@ -24,8 +24,10 @@
 #if !defined (octave_pt_anon_scopes_h)
 #define octave_pt_anon_scopes_h 1
 
+#include <set>
+#include <string>
+
 #include "pt-walk.h"
-#include "ov-usr-fcn.h"
 
 namespace octave
 {
@@ -37,33 +39,9 @@
   {
   public:
 
-    tree_anon_scopes (void) : scopes (), merged_tables () { }
-
-    tree_anon_scopes (octave_user_function *);
-
-    tree_anon_scopes& operator = (tree_anon_scopes&& tas)
-    {
-      scopes = std::move (tas.scopes);
-      merged_tables = std::move (tas.merged_tables);
-      return *this;
-    }
-
-    typedef std::map<std::string, symbol_record> symrec_map;
+    tree_anon_scopes (void) = delete;
 
-    symrec_map::const_iterator begin (void)
-    {
-      return merged_tables.cbegin ();
-    }
-
-    symrec_map::const_iterator end (void)
-    {
-      return merged_tables.cend ();
-    }
-
-    unsigned int symrec_map_size (void)
-    {
-      return merged_tables.size ();
-    }
+    tree_anon_scopes (tree_anon_fcn_handle& anon_fh);
 
     // No copying!
 
@@ -71,7 +49,11 @@
 
     tree_anon_scopes& operator = (const tree_anon_scopes&) = delete;
 
-    ~tree_anon_scopes (void) { }
+    ~tree_anon_scopes (void) = default;
+
+    std::set<std::string> fcn_parameters (void) const { return m_params; }
+
+    std::set<std::string> free_variables (void) const { return m_vars; }
 
     // The following methods, though public, don't belong to the
     // intended user interface of this class.
@@ -132,8 +114,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
@@ -160,27 +140,11 @@
 
   private:
 
-    void stash_scope_if_valid (const symbol_scope& sc)
-    {
-      if (sc)
-        scopes.push_back (sc);
-      else
-        error ("internal error, invalid scope");
-    }
+    // Variable names that are function parameters.
+    std::set<std::string> m_params;
 
-    // The scope of this anonymous function and the collected scopes
-    // of all anonymous functions whose definitions are nested in the
-    // current anonymous function definition.
-
-    std::vector<symbol_scope> scopes;
-
-    // Symbol records of all collected scopes are merged over variable names.
-
-    typedef std::list<symbol_record> symrec_list;
-
-    void merge_tables (void);
-
-    symrec_map merged_tables;
+    // Other variable names.
+    std::set<std::string> m_vars;
   };
 }
 
--- a/libinterp/parse-tree/pt-array-list.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-array-list.h	Fri Jul 12 12:14:43 2019 -0400
@@ -85,11 +85,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_array_list' instead")
-typedef octave::tree_array_list tree_array_list;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-assign.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-assign.h	Fri Jul 12 12:14:43 2019 -0400
@@ -171,14 +171,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_simple_assignment' instead")
-typedef octave::tree_simple_assignment tree_simple_assignment;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_multi_assignment' instead")
-typedef octave::tree_multi_assignment tree_multi_assignment;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-binop.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-binop.h	Fri Jul 12 12:14:43 2019 -0400
@@ -185,14 +185,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_binary_expression' instead")
-typedef octave::tree_binary_expression tree_binary_expression;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_boolean_expression' instead")
-typedef octave::tree_boolean_expression tree_boolean_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-bp.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-bp.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -277,12 +277,6 @@
   }
 
   void
-  tree_breakpoint::visit_funcall (tree_funcall&)
-  {
-    panic_impossible ();
-  }
-
-  void
   tree_breakpoint::visit_parameter_list (tree_parameter_list&)
   {
     panic_impossible ();
--- a/libinterp/parse-tree/pt-bp.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-bp.h	Fri Jul 12 12:14:43 2019 -0400
@@ -115,8 +115,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
@@ -175,11 +173,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_breakpoint' instead")
-typedef octave::tree_breakpoint tree_breakpoint;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-cbinop.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-cbinop.h	Fri Jul 12 12:14:43 2019 -0400
@@ -87,11 +87,4 @@
                                     = octave_value::unknown_binary_op);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_compound_binary_expression' instead")
-typedef octave::tree_compound_binary_expression tree_compound_binary_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-cell.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-cell.h	Fri Jul 12 12:14:43 2019 -0400
@@ -69,11 +69,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_cell' instead")
-typedef octave::tree_cell tree_cell;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-check.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-check.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -340,10 +340,6 @@
   { }
 
   void
-  tree_checker::visit_funcall (tree_funcall& /* fc */)
-  { }
-
-  void
   tree_checker::visit_parameter_list (tree_parameter_list& lst)
   {
     auto p = lst.begin ();
--- a/libinterp/parse-tree/pt-check.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-check.h	Fri Jul 12 12:14:43 2019 -0400
@@ -100,8 +100,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
@@ -142,11 +140,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_checker' instead")
-typedef octave::tree_checker tree_checker;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-classdef.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-classdef.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,6 +29,29 @@
 
 namespace octave
 {
+  tree_superclass_ref *
+  tree_superclass_ref::dup (symbol_scope&) const
+  {
+    tree_superclass_ref *new_scr
+      = new tree_superclass_ref (m_method_name, m_class_name,
+                                 line (), column ());
+
+    new_scr->copy_base (*this);
+
+    return new_scr;
+  }
+
+  tree_metaclass_query *
+  tree_metaclass_query::dup (symbol_scope&) const
+  {
+    tree_metaclass_query *new_mcq
+      = new tree_metaclass_query (m_class_name, line (), column ());
+
+    new_mcq->copy_base (*this);
+
+    return new_mcq;
+  }
+
   // Classdef attribute
 
   // Classdef attribute_list
--- a/libinterp/parse-tree/pt-classdef.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-classdef.h	Fri Jul 12 12:14:43 2019 -0400
@@ -41,6 +41,82 @@
 {
   class interpreter;
 
+  class tree_superclass_ref : public tree_expression
+  {
+  public:
+
+    tree_superclass_ref (void) = delete;
+
+    tree_superclass_ref (const std::string& meth, const std::string& cls,
+                         int l = -1, int c = -1)
+      : tree_expression (l, c), m_method_name (meth), m_class_name (cls)
+    { }
+
+    // No copying!
+
+    tree_superclass_ref (const tree_superclass_ref&) = delete;
+
+    tree_superclass_ref& operator = (const tree_superclass_ref&) = delete;
+
+    std::string method_name (void) const
+    {
+      return m_method_name;
+    }
+
+    std::string class_name (void) const { return m_class_name; }
+
+    bool has_magic_end (void) const { return false; }
+
+    tree_superclass_ref * dup (symbol_scope& scope) const;
+
+    void accept (tree_walker& tw)
+    {
+      tw.visit_superclass_ref (*this);
+    }
+
+  private:
+
+    // The name of the method to call.  This is the text before the
+    // "@" and may be of the form "object.method".
+    std::string m_method_name;
+
+    // The name of the superclass.  This is the text after the "@"
+    // and may be of the form "object.method".
+    std::string m_class_name;
+  };
+
+  class tree_metaclass_query : public tree_expression
+  {
+  public:
+
+    tree_metaclass_query (void) = delete;
+
+    tree_metaclass_query (const std::string& cls, int l = -1, int c = -1)
+      : tree_expression (l, c), m_class_name (cls)
+    { }
+
+    // No copying!
+
+    tree_metaclass_query (const tree_metaclass_query&) = delete;
+
+    tree_metaclass_query& operator = (const tree_metaclass_query&) = delete;
+
+    std::string class_name (void) const { return m_class_name; }
+
+    bool has_magic_end (void) const { return false; }
+
+    tree_metaclass_query * dup (symbol_scope& scope) const;
+
+    void accept (tree_walker& tw)
+    {
+      tw.visit_metaclass_query (*this);
+    }
+
+  private:
+
+    std::string m_class_name;
+  };
+
   class tree_classdef_attribute
   {
   public:
@@ -651,13 +727,14 @@
   {
   public:
 
-    tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i,
+    tree_classdef (const octave::symbol_scope& scope,
+                   tree_classdef_attribute_list *a, tree_identifier *i,
                    tree_classdef_superclass_list *sc,
                    tree_classdef_body *b, comment_list *lc,
                    comment_list *tc,
                    const std::string& pn = "", int l = -1,
                    int c = -1)
-      : tree_command (l, c), m_attr_list (a), m_id (i),
+      : tree_command (l, c), m_scope (scope), m_attr_list (a), m_id (i),
         m_supclass_list (sc), m_element_list (b), m_lead_comm (lc),
         m_trail_comm (tc), m_pack_name (pn)
     { }
@@ -678,6 +755,8 @@
       delete m_trail_comm;
     }
 
+    octave::symbol_scope scope (void) { return m_scope; }
+
     tree_classdef_attribute_list *
     attribute_list (void) { return m_attr_list; }
 
@@ -703,6 +782,12 @@
 
   private:
 
+    // The scope that was used when parsing the classdef object and that
+    // corresponds to any identifiers that were found in attribute lists
+    // (for example).  Used again when computing the meta class object.
+
+    octave::symbol_scope m_scope;
+
     tree_classdef_attribute_list *m_attr_list;
 
     tree_identifier *m_id;
--- a/libinterp/parse-tree/pt-cmd.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-cmd.h	Fri Jul 12 12:14:43 2019 -0400
@@ -124,17 +124,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_command' instead")
-typedef octave::tree_command tree_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_no_op_command' instead")
-typedef octave::tree_no_op_command tree_no_op_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_function_def' instead")
-typedef octave::tree_function_def tree_function_def;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-colon.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-colon.h	Fri Jul 12 12:14:43 2019 -0400
@@ -109,11 +109,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_colon_expression' instead")
-typedef octave::tree_colon_expression tree_colon_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-const.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-const.h	Fri Jul 12 12:14:43 2019 -0400
@@ -106,11 +106,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_constant' instead")
-typedef octave::tree_constant tree_constant;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-decl.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-decl.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -41,6 +41,13 @@
 {
   // Declarations (global, static, etc.).
 
+  tree_decl_elt::tree_decl_elt (tree_identifier *i, tree_expression *e)
+    : type (unknown), m_id (i), m_expr (e)
+  {
+    if (! m_id)
+      error ("tree_decl_elt: invalid ID");
+  }
+
   tree_decl_elt::~tree_decl_elt (void)
   {
     delete m_id;
@@ -50,7 +57,7 @@
   tree_decl_elt *
   tree_decl_elt::dup (symbol_scope& scope) const
   {
-    return new tree_decl_elt (m_id ? m_id->dup (scope) : nullptr,
+    return new tree_decl_elt (m_id->dup (scope),
                               m_expr ? m_expr->dup (scope) : nullptr);
   }
 
--- a/libinterp/parse-tree/pt-decl.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-decl.h	Fri Jul 12 12:14:43 2019 -0400
@@ -33,7 +33,6 @@
 #include "pt-cmd.h"
 #include "pt-id.h"
 #include "pt-walk.h"
-#include "symrec.h"
 
 namespace octave
 {
@@ -55,8 +54,7 @@
       persistent
     };
 
-    tree_decl_elt (tree_identifier *i = nullptr, tree_expression *e = nullptr)
-      : type (unknown), m_id (i), m_expr (e) { }
+    tree_decl_elt (tree_identifier *i, tree_expression *e = nullptr);
 
     // No copying!
 
@@ -66,27 +64,16 @@
 
     ~tree_decl_elt (void);
 
-    bool is_defined (symbol_record::context_id context)
+    void mark_as_formal_parameter (void)
     {
-      return m_id ? m_id->is_defined (context) : false;
+      m_id->mark_as_formal_parameter ();
     }
 
-    bool is_variable (symbol_record::context_id context)
-    {
-      return m_id ? m_id->is_variable (context) : false;
-    }
-
-    void mark_as_formal_parameter (void)
-    {
-      if (m_id)
-        m_id->mark_as_formal_parameter ();
-    }
-
-    bool lvalue_ok (void) { return m_id ? m_id->lvalue_ok () : false; }
+    bool lvalue_ok (void) { return m_id->lvalue_ok (); }
 
     octave_lvalue lvalue (tree_evaluator& tw)
     {
-      return m_id ? m_id->lvalue (tw) : octave_lvalue ();
+      return m_id->lvalue (tw);
     }
 
     void mark_global (void) { type = global; }
@@ -97,7 +84,7 @@
 
     tree_identifier * ident (void) { return m_id; }
 
-    std::string name (void) const { return m_id ? m_id->name () : ""; }
+    std::string name (void) const { return m_id->name (); }
 
     tree_expression * expression (void) { return m_expr; }
 
@@ -227,16 +214,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_decl_elt' instead")
-typedef octave::tree_decl_elt tree_decl_elt;
-
-// tree_decl_init_list is derived from a template.
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_decl_command' instead")
-typedef octave::tree_decl_command tree_decl_command;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-eval.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,22 +32,30 @@
 
 #include "cmd-edit.h"
 #include "file-ops.h"
+#include "file-stat.h"
+#include "lo-ieee.h"
 #include "oct-env.h"
 
 #include "bp-table.h"
 #include "call-stack.h"
+#include "cdef-manager.h"
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
+#include "octave-link.h"
+#include "octave.h"
+#include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "ov-re-sparse.h"
 #include "ov-cx-sparse.h"
+#include "parse.h"
 #include "profiler.h"
 #include "pt-all.h"
+#include "pt-anon-scopes.h"
 #include "pt-eval.h"
 #include "pt-tm-const.h"
 #include "symtab.h"
@@ -62,15 +70,233 @@
 {
   // 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 ();
-    m_lvalue_list_stack.clear ();
-    m_nargout_stack.clear ();
+  class debugger
+  {
+  public:
+
+    debugger (interpreter& interp, size_t level)
+      : m_interpreter (interp), m_level (level), m_in_debug_repl (false),
+        m_exit_debug_repl (false), m_abort_debug_repl (false)
+    { }
+
+    void repl (const std::string& prompt = "debug> ");
+
+    bool in_debug_repl (void) const { return m_in_debug_repl; }
+
+    bool in_debug_repl (bool flag)
+    {
+      bool val = m_in_debug_repl;
+      m_in_debug_repl = flag;
+      return val;
+    }
+
+    bool exit_debug_repl (void) const { return m_exit_debug_repl; }
+
+    bool exit_debug_repl (bool flag)
+    {
+      bool val = m_exit_debug_repl;
+      m_exit_debug_repl = flag;
+      return val;
+    }
+
+    bool abort_debug_repl (void) const { return m_abort_debug_repl; }
+
+    bool abort_debug_repl (bool flag)
+    {
+      bool val = m_abort_debug_repl;
+      m_abort_debug_repl = flag;
+      return val;
+    }
+
+  private:
+
+    interpreter& m_interpreter;
+
+    size_t m_level;
+    size_t m_debug_frame;
+    bool m_in_debug_repl;
+    bool m_exit_debug_repl;
+    bool m_abort_debug_repl;
+  };
+
+  static void
+  execute_in_debugger_handler (const std::pair<std::string, int>& arg)
+  {
+    octave_link::execute_in_debugger_event (arg.first, arg.second);
+  }
+
+  void debugger::repl (const std::string& prompt)
+  {
+    unwind_protect frame;
+
+    frame.protect_var (m_in_debug_repl);
+
+    m_in_debug_repl = true;
+
+    tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+    bool silent = tw.quiet_breakpoint_flag (false);
+
+    frame.add_method (tw, &tree_evaluator::restore_frame,
+                      tw.current_call_stack_frame_number ());
+
+    tw.goto_frame (tw.debug_frame ());
+
+    octave_user_code *caller = tw.current_user_code ();
+    std::string nm;
+
+    if (caller)
+      {
+        nm = caller->fcn_file_name ();
+
+        if (nm.empty ())
+          nm = caller->name ();
+      }
+
+    int curr_debug_line = tw.current_line ();
+
+    std::ostringstream buf;
+
+    input_system& input_sys = m_interpreter.get_input_system ();
+
+    if (! nm.empty ())
+      {
+        if (input_sys.gud_mode ())
+          {
+            static char ctrl_z = 'Z' & 0x1f;
+
+            buf << ctrl_z << ctrl_z << nm << ':' << curr_debug_line;
+          }
+        else
+          {
+            // FIXME: we should come up with a clean way to detect
+            // that we are stopped on the no-op command that marks the
+            // end of a function or script.
+
+            if (! silent)
+              {
+                stack_frame *frm = tw.current_user_frame ();
+
+                frm->display_stopped_in_message (buf);
+              }
+
+            octave_link::enter_debugger_event (nm, curr_debug_line);
+
+            octave_link::set_workspace ();
+
+            frame.add_fcn (execute_in_debugger_handler,
+                           std::pair<std::string, int> (nm, curr_debug_line));
+
+            if (! silent)
+              {
+                std::string line_buf;
+
+                if (caller)
+                  line_buf = caller->get_code_line (curr_debug_line);
+
+                if (! line_buf.empty ())
+                  buf << curr_debug_line << ": " << line_buf;
+              }
+          }
+      }
+
+    if (silent)
+      command_editor::erase_empty_line (true);
+
+    std::string msg = buf.str ();
+
+    if (! msg.empty ())
+      std::cerr << msg << std::endl;
+
+    std::string tmp_prompt = prompt;
+    if (m_level > 0)
+      tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt;
+
+    frame.add_method (input_sys, &input_system::set_PS1, input_sys.PS1 ());
+    input_sys.PS1 (tmp_prompt);
+
+    // FIXME: should debugging be possible in an embedded interpreter?
+
+    application *app = application::app ();
+
+    if (! app->interactive ())
+      {
+
+        frame.add_method (app, &application::interactive,
+                          app->interactive ());
+
+        frame.add_method (app, &application::forced_interactive,
+                          app->forced_interactive ());
+
+        app->interactive (true);
+
+        app->forced_interactive (true);
+      }
+
+    parser curr_parser (m_interpreter);
+
+    error_system& es = m_interpreter.get_error_system ();
+
+    while (m_in_debug_repl)
+      {
+        if (m_exit_debug_repl || tw.dbstep_flag ())
+          break;
+
+        if (m_abort_debug_repl)
+          throw interrupt_exception ();
+
+        try
+          {
+            Vtrack_line_num = false;
+
+            es.reset ();
+
+            curr_parser.reset ();
+
+            int retval = curr_parser.run ();
+
+            if (command_editor::interrupt (false))
+              break;
+            else
+              {
+                if (retval == 0 && curr_parser.m_stmt_list)
+                  {
+                    curr_parser.m_stmt_list->accept (tw);
+
+                    if (octave_completion_matches_called)
+                      octave_completion_matches_called = false;
+
+                    // FIXME: the following statement is here because
+                    // the last command may have been a dbup, dbdown, or
+                    // dbstep command that changed the current debug
+                    // frame.  If so, we need to reset the current frame
+                    // for the call stack.  But is this right way to do
+                    // this job?  What if the statement list was
+                    // something like "dbup; dbstack"?  Will the call to
+                    // dbstack use the right frame?  If not, how can we
+                    // fix this problem?
+                    tw.goto_frame (tw.debug_frame ());
+                  }
+
+                octave_quit ();
+              }
+          }
+        catch (const execution_exception& e)
+          {
+            std::string stack_trace = e.info ();
+
+            if (! stack_trace.empty ())
+              std::cerr << stack_trace;
+
+            // Ignore errors when in debugging mode;
+            interpreter::recover_from_exception ();
+          }
+      }
+  }
+
+  bool tree_evaluator::at_top_level (void) const
+  {
+    return m_call_stack.at_top_level ();
   }
 
   int tree_evaluator::repl (bool interactive)
@@ -84,17 +310,17 @@
                         ? new lexer (m_interpreter)
                         : new lexer (stdin, m_interpreter));
 
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
+    error_system& es = m_interpreter.get_error_system ();
 
     do
       {
         try
           {
-            reset_error_handler ();
+            es.reset ();
 
             repl_parser.reset ();
 
-            if (symtab.at_top_level ())
+            if (at_top_level ())
               reset_debug_state ();
 
             retval = repl_parser.run ();
@@ -174,7 +400,9 @@
           }
 
 #if defined (DBSTOP_NANINF)
-        if (Vdebug_on_naninf)
+        error_system& es = m_interpreter.get_error_system ();
+
+        if (es.debug_on_naninf ())
           {
             if (setjump (naninf_jump) != 0)
               debug_or_throw_exception (true);  // true = stack trace
@@ -194,6 +422,42 @@
     return retval;
   }
 
+  std::string
+  tree_evaluator::mfilename (const std::string& opt) const
+  {
+    std::string fname;
+
+    octave_user_code *fcn = m_call_stack.current_user_code ();
+
+    if (fcn)
+      {
+        fname = fcn->fcn_file_name ();
+
+        if (fname.empty ())
+          fname = fcn->name ();
+      }
+
+    if (opt == "fullpathext")
+      return fname;
+
+    size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ());
+    size_t epos = fname.rfind ('.');
+
+    if (epos <= dpos+1)
+      epos = std::string::npos;
+
+    if (epos != std::string::npos)
+      fname = fname.substr (0, epos);
+
+    if (opt == "fullpath")
+      return fname;
+
+    if (dpos != std::string::npos)
+      fname = fname.substr (dpos+1);
+
+    return fname;
+  }
+
   octave_value_list
   tree_evaluator::eval_string (const std::string& eval_str, bool silent,
                                int& parse_status, int nargout)
@@ -206,6 +470,15 @@
       {
         eval_parser.reset ();
 
+        // If we are looking at
+        //
+        //   val = eval ("code");
+        //
+        // then don't allow code to be parsed as a command.
+
+        if (nargout > 0)
+          eval_parser.disallow_command_syntax ();
+
         parse_status = eval_parser.run ();
 
         if (parse_status == 0)
@@ -223,24 +496,14 @@
                     if (silent)
                       expr->set_print_flag (false);
 
+                    retval = evaluate_n (expr, nargout);
+
                     bool do_bind_ans = false;
 
                     if (expr->is_identifier ())
-                      {
-                        symbol_scope scope = get_current_scope ();
-
-                        symbol_record::context_id context
-                          = scope.current_context ();
-
-                        tree_identifier *id
-                          = dynamic_cast<tree_identifier *> (expr);
-
-                        do_bind_ans = (! id->is_variable (context));
-                      }
+                      do_bind_ans = ! is_variable (expr);
                     else
-                      do_bind_ans = (! expr->is_assignment_expression ());
-
-                    retval = evaluate_n (expr, nargout);
+                      do_bind_ans = ! expr->is_assignment_expression ();
 
                     if (do_bind_ans && ! retval.empty ())
                       bind_ans (retval(0), expr->print_result ());
@@ -287,6 +550,162 @@
     return eval_string (s, silent, parse_status, nargout);
   }
 
+  octave_value_list tree_evaluator::eval (const std::string& try_code,
+                                          int nargout)
+  {
+    int parse_status = 0;
+
+    return eval_string (try_code, nargout > 0, parse_status, nargout);
+  }
+
+  octave_value_list tree_evaluator::eval (const std::string& try_code,
+                                          const std::string& catch_code,
+                                          int nargout)
+  {
+    octave_value_list retval;
+
+    error_system& es = m_interpreter.get_error_system ();
+
+    unwind_protect frame;
+
+    int bem = es.buffer_error_messages ();
+    frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+    es.buffer_error_messages (bem + 1);
+
+    int parse_status = 0;
+
+    bool execution_error = false;
+
+    octave_value_list tmp;
+
+    try
+      {
+        tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
+      }
+    catch (const execution_exception&)
+      {
+        interpreter::recover_from_exception ();
+
+        execution_error = true;
+      }
+
+    if (parse_status != 0 || execution_error)
+      {
+        // Set up for letting the user print any messages from
+        // errors that occurred in the first part of this eval().
+
+        es.buffer_error_messages (es.buffer_error_messages () - 1);
+
+        tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
+
+        retval = (nargout > 0) ? tmp : octave_value_list ();
+      }
+    else
+      {
+        if (nargout > 0)
+          retval = tmp;
+
+        // FIXME: we should really be rethrowing whatever
+        // exception occurred, not just throwing an
+        // execution exception.
+        if (execution_error)
+          octave_throw_execution_exception ();
+      }
+
+    return retval;
+  }
+
+  octave_value_list tree_evaluator::evalin (const std::string& context,
+                                            const std::string& try_code,
+                                            int nargout)
+  {
+    unwind_protect frame;
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    if (context == "caller")
+      m_call_stack.goto_caller_frame ();
+    else if (context == "base")
+      m_call_stack.goto_base_frame ();
+    else
+      error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+    int parse_status = 0;
+
+    return eval_string (try_code, nargout > 0, parse_status, nargout);
+  }
+
+  octave_value_list tree_evaluator::evalin (const std::string& context,
+                                            const std::string& try_code,
+                                            const std::string& catch_code,
+                                            int nargout)
+  {
+    octave_value_list retval;
+
+    unwind_protect frame;
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    if (context == "caller")
+      m_call_stack.goto_caller_frame ();
+    else if (context == "base")
+      m_call_stack.goto_base_frame ();
+    else
+      error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+    error_system& es = m_interpreter.get_error_system ();
+
+    int bem = es.buffer_error_messages ();
+    frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+    es.buffer_error_messages (bem + 1);
+
+    int parse_status = 0;
+
+    bool execution_error = false;
+
+    octave_value_list tmp;
+
+    try
+      {
+        tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
+      }
+    catch (const execution_exception&)
+      {
+        interpreter::recover_from_exception ();
+
+        execution_error = true;
+      }
+
+    if (parse_status != 0 || execution_error)
+      {
+        // Set up for letting the user print any messages from
+        // errors that occurred in the first part of this eval().
+
+        es.buffer_error_messages (es.buffer_error_messages () - 1);
+
+        tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
+
+        retval = (nargout > 0) ? tmp : octave_value_list ();
+      }
+    else
+      {
+        if (nargout > 0)
+          retval = tmp;
+
+        // FIXME: we should really be rethrowing whatever
+        // exception occurred, not just throwing an
+        // execution exception.
+        if (execution_error)
+          octave_throw_execution_exception ();
+      }
+
+    return retval;
+  }
+
   void
   tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle& anon_fh)
   {
@@ -298,19 +717,10 @@
 
     symbol_scope af_scope = anon_fh.scope ();
 
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-    symbol_scope af_parent_scope;
-    if (anon_fh.has_parent_scope ())
-      af_parent_scope = symtab.current_scope ();
-
     symbol_scope new_scope;
     if (af_scope)
       new_scope = af_scope.dup ();
 
-    if (new_scope && af_parent_scope)
-      new_scope.inherit (af_parent_scope);
-
     tree_parameter_list *param_list_dup
       = param_list ? param_list->dup (new_scope) : nullptr;
 
@@ -318,6 +728,11 @@
 
     tree_statement_list *stmt_list = nullptr;
 
+    symbol_scope parent_scope = get_current_scope ();
+
+    new_scope.set_parent (parent_scope);
+    new_scope.set_primary_parent (parent_scope);
+
     if (expr)
       {
         tree_expression *expr_dup = expr->dup (new_scope);
@@ -325,11 +740,25 @@
         stmt_list = new tree_statement_list (stmt);
       }
 
+    tree_anon_scopes anon_fcn_ctx (anon_fh);
+
+    std::set<std::string> free_vars = anon_fcn_ctx.free_variables ();
+
+    octave_user_function::local_vars_map local_var_init_vals;
+
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    for (auto& name : free_vars)
+      {
+        octave_value val = frame.varval (name);
+
+        if (val.is_defined ())
+          local_var_init_vals[name] = val;
+      }
+
     octave_user_function *af
       = new octave_user_function (new_scope, param_list_dup, ret_list,
-                                  stmt_list);
-
-    new_scope.set_parent (af_parent_scope);
+                                  stmt_list, local_var_init_vals);
 
     octave_function *curr_fcn = m_call_stack.current ();
 
@@ -341,19 +770,22 @@
         af->stash_parent_fcn_name (curr_fcn->name ());
         af->stash_dir_name (curr_fcn->dir_name ());
 
+        // The following is needed so that class method dispatch works
+        // properly for anonymous functions that wrap class methods.
+
         if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ())
           af->stash_dispatch_class (curr_fcn->dispatch_class ());
+
+        af->stash_fcn_file_name (curr_fcn->fcn_file_name ());
       }
 
     af->mark_as_anonymous_function ();
 
-    // FIXME: these should probably come from ANON_FH.
-    //    af->stash_fcn_file_name (expr.file_name ());
-    //    af->stash_fcn_location (expr.line (), expr.column ());
-
     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, m_interpreter));
+
+    octave_value fh (new octave_fcn_handle (ov_fcn, octave_fcn_handle::anonymous));
 
     push_result (fh);
   }
@@ -640,17 +1072,65 @@
   void
   tree_evaluator::reset_debug_state (void)
   {
-    m_debug_mode = m_bp_table.have_breakpoints () || Vdebugging;
-
-    m_dbstep_flag = 0;
+    m_debug_mode = (m_bp_table.have_breakpoints () ||
+                    m_dbstep_flag != 0 || in_debug_repl ());
   }
 
   void
   tree_evaluator::reset_debug_state (bool mode)
   {
     m_debug_mode = mode;
-
-    m_dbstep_flag = 0;
+  }
+
+  void
+  tree_evaluator::enter_debugger (const std::string& prompt)
+  {
+    unwind_protect frame;
+
+    frame.add_fcn (command_history::ignore_entries,
+                   command_history::ignoring_entries ());
+
+    command_history::ignore_entries (false);
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    // Go up to the nearest user code frame.
+    m_call_stack.dbupdown (0);
+
+    // 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);
+
+    Vtrack_line_num = false;
+
+    debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ());
+
+    m_debug_frame = m_call_stack.current_frame ();
+
+    m_debugger_stack.push (dbgr);
+
+    frame.add ([this] (void)
+               {
+                 delete m_debugger_stack.top ();
+                 m_debugger_stack.pop ();
+               });
+
+    dbgr->repl (prompt);
+  }
+
+  void
+  tree_evaluator::keyboard (const std::string& prompt)
+  {
+    enter_debugger (prompt);
+  }
+
+  void
+  tree_evaluator::dbupdown (int n, bool verbose)
+  {
+    m_debug_frame = m_call_stack.dbupdown (n, verbose);
   }
 
   Matrix
@@ -751,6 +1231,344 @@
     return id ? evaluate (id).storable_value () : octave_value ();
   }
 
+  bool
+  tree_evaluator::is_variable (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_variable (name);
+  }
+
+  bool
+  tree_evaluator::is_local_variable (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_local_variable (name);
+  }
+
+  bool
+  tree_evaluator::is_variable (const tree_expression *expr) const
+  {
+    if (expr->is_identifier ())
+      {
+        const tree_identifier *id
+          = dynamic_cast<const tree_identifier *> (expr);
+
+        if (id->is_black_hole ())
+          return false;
+
+        return is_variable (id->symbol ());
+      }
+
+    return false;
+  }
+
+  bool
+  tree_evaluator::is_defined (const tree_expression *expr) const
+  {
+    if (expr->is_identifier ())
+      {
+        const tree_identifier *id
+          = dynamic_cast<const tree_identifier *> (expr);
+
+        return is_defined (id->symbol ());
+      }
+
+    return false;
+  }
+
+  bool
+  tree_evaluator::is_variable (const symbol_record& sym) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_variable (sym);
+  }
+
+  bool
+  tree_evaluator::is_defined (const symbol_record& sym) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_defined (sym);
+  }
+
+  bool tree_evaluator::is_global (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_global (name);
+  }
+
+  octave_value
+  tree_evaluator::varval (const symbol_record& sym) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.varval (sym);
+  }
+
+  octave_value
+  tree_evaluator::varval (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.varval (name);
+  }
+
+  void tree_evaluator::install_variable (const std::string& name,
+                                         const octave_value& value,
+                                         bool global)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.install_variable (name, value, global);
+  }
+
+  octave_value
+  tree_evaluator::global_varval (const std::string& name) const
+  {
+    return m_call_stack.global_varval (name);
+  }
+
+  octave_value&
+  tree_evaluator::global_varref (const std::string& name)
+  {
+    return m_call_stack.global_varref (name);
+  }
+
+  void
+  tree_evaluator::global_assign (const std::string& name,
+                                 const octave_value& val)
+  {
+    m_call_stack.global_varref (name) = val;
+  }
+
+  octave_value
+  tree_evaluator::top_level_varval (const std::string& name) const
+  {
+    return m_call_stack.get_top_level_value (name);
+  }
+
+  void
+  tree_evaluator::top_level_assign (const std::string& name,
+                                const octave_value& val)
+  {
+    m_call_stack.set_top_level_value (name, val);
+  }
+
+  void
+  tree_evaluator::assign (const std::string& name, const octave_value& val)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.assign (name, val);
+  }
+
+  void
+  tree_evaluator::assignin (const std::string& context,
+                            const std::string& name, const octave_value& val)
+  {
+    // FIXME: Can this be done without an unwind-protect frame, simply
+    // by geting a reference to the caller or base stack frame and
+    // calling assign on that?
+
+    unwind_protect frame;
+
+    frame.add_method (m_call_stack, &call_stack::restore_frame,
+                      m_call_stack.current_frame ());
+
+    if (context == "caller")
+      m_call_stack.goto_caller_frame ();
+    else if (context == "base")
+      m_call_stack.goto_base_frame ();
+    else
+      error ("assignin: CONTEXT must be \"caller\" or \"base\"");
+
+    if (valid_identifier (name))
+      {
+        // Put the check here so that we don't slow down assignments
+        // generally.  Any that go through Octave's parser should have
+        // already been checked.
+
+        if (iskeyword (name))
+          error ("assignin: invalid assignment to keyword '%s'",
+                 name.c_str ());
+
+        assign (name, val);
+      }
+    else
+      error ("assignin: invalid variable name '%s'", name.c_str ());
+  }
+
+  void
+  tree_evaluator::source_file (const std::string& file_name,
+                               const std::string& context,
+                               bool verbose, bool require_file,
+                               const std::string& warn_for)
+  {
+    // Map from absolute name of script file to recursion level.  We
+    // use a map instead of simply placing a limit on recursion in the
+    // source_file function so that two mutually recursive scripts
+    // written as
+    //
+    //   foo1.m:
+    //   ------
+    //   foo2
+    //
+    //   foo2.m:
+    //   ------
+    //   foo1
+    //
+    // and called with
+    //
+    //   foo1
+    //
+    // (for example) will behave the same if they are written as
+    //
+    //   foo1.m:
+    //   ------
+    //   source ("foo2.m")
+    //
+    //   foo2.m:
+    //   ------
+    //   source ("foo1.m")
+    //
+    // and called with
+    //
+    //   source ("foo1.m")
+    //
+    // (for example).
+
+    static std::map<std::string, int> source_call_depth;
+
+    std::string file_full_name
+      = sys::file_ops::tilde_expand (file_name);
+
+    size_t pos
+      = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
+
+    std::string dir_name = file_full_name.substr (0, pos);
+
+    file_full_name = sys::env::make_absolute (file_full_name);
+
+    unwind_protect frame;
+
+    if (source_call_depth.find (file_full_name) == source_call_depth.end ())
+      source_call_depth[file_full_name] = -1;
+
+    frame.protect_var (source_call_depth[file_full_name]);
+
+    source_call_depth[file_full_name]++;
+
+    if (source_call_depth[file_full_name] >= max_recursion_depth ())
+      error ("max_recursion_depth exceeded");
+
+    if (! context.empty ())
+      {
+        frame.add_method (m_call_stack, &call_stack::restore_frame,
+                          m_call_stack.current_frame ());
+
+        if (context == "caller")
+          m_call_stack.goto_caller_frame ();
+        else if (context == "base")
+          m_call_stack.goto_base_frame ();
+        else
+          error ("source: context must be \"caller\" or \"base\"");
+      }
+
+    // Find symbol name that would be in symbol_table, if it were loaded.
+    size_t dir_end
+      = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
+    dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
+
+    size_t extension = file_name.find_last_of ('.');
+    if (extension == std::string::npos)
+      extension = file_name.length ();
+
+    std::string symbol = file_name.substr (dir_end, extension - dir_end);
+    std::string full_name = sys::canonicalize_file_name (file_name);
+
+    // Check if this file is already loaded (or in the path)
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+    octave_value ov_code = symtab.fcn_table_find (symbol);
+
+    // For compatibility with Matlab, accept both scripts and
+    // functions.
+
+    if (ov_code.is_user_code ())
+      {
+        octave_user_code *code = ov_code.user_code_value ();
+
+        if (! code
+            || (sys::canonicalize_file_name (code->fcn_file_name ())
+                != full_name))
+          {
+            // Wrong file, so load it below.
+            ov_code = octave_value ();
+          }
+      }
+    else
+      {
+        // Not a script, so load it below.
+        ov_code = octave_value ();
+      }
+
+    // If no symbol of this name, or the symbol is for a different
+    // file, load.
+
+    if (ov_code.is_undefined ())
+      {
+        try
+          {
+            ov_code = m_interpreter.parse_fcn_file (file_full_name, file_name,
+                                                    dir_name, "", "",
+                                                    require_file, true, false,
+                                                    false, warn_for);
+          }
+        catch (execution_exception& e)
+          {
+            error (e, "source: error sourcing file '%s'",
+                   file_full_name.c_str ());
+          }
+      }
+
+    // Return or error if we don't have a valid script or function.
+
+    if (ov_code.is_undefined ())
+      return;
+
+    if (! ov_code.is_user_code ())
+      error ("source: %s is not a script", full_name.c_str ());
+
+    if (verbose)
+      {
+        octave_stdout << "executing commands from " << full_name << " ... ";
+        octave_stdout.flush ();
+      }
+
+    octave_user_code *code = ov_code.user_code_value ();
+
+    code->call (*this, 0, octave_value_list ());
+
+    if (verbose)
+      octave_stdout << "done." << std::endl;
+  }
+
+  void
+  tree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt,
+                                    const octave_value& val)
+  {
+    m_call_stack.set_auto_fcn_var (avt, val);
+  }
+
+  octave_value
+  tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const
+  {
+    return m_call_stack.get_auto_fcn_var (avt);
+  }
+
   void
   tree_evaluator::define_parameter_list_from_arg_vector
     (tree_parameter_list *param_list, const octave_value_list& args)
@@ -825,8 +1643,11 @@
   int index_position = tw.index_position ();
   int num_indices = tw.num_indices ();
 
+  // Return invalid index value instead of throwing an error so that we
+  // will see an error about the object that is indexed rather than
+  // "end" being used incorrectly.
   if (! indexed_object)
-    error ("invalid use of end");
+    return ovl (octave_NaN);
 
   if (indexed_object->isobject ())
     {
@@ -875,6 +1696,11 @@
   return retval;
 }
 
+/*
+%!test <*33637>
+%! fail ("__undef_sym__ (end)", "'__undef_sym__' undefined");
+*/
+
 namespace octave
 {
   octave_value_list
@@ -949,17 +1775,13 @@
       return varargout;
     else if (nargout <= len)
       {
-        symbol_scope scope = get_current_scope ();
-
-        symbol_record::context_id context = scope.current_context ();
-
         octave_value_list retval (nargout);
 
         int i = 0;
 
         for (tree_decl_elt *elt : *ret_list)
           {
-            if (elt->is_defined (context))
+            if (is_defined (elt->ident ()))
               {
                 octave_value tmp = evaluate (elt);
                 retval(i) = tmp;
@@ -1040,12 +1862,332 @@
     return false;
   }
 
-  symbol_scope
-  tree_evaluator::get_current_scope (void)
-  {
+  void tree_evaluator::push_stack_frame (const symbol_scope& scope)
+  {
+    m_call_stack.push (scope);
+  }
+
+  void tree_evaluator::push_stack_frame (octave_user_function *fcn,
+                                         unwind_protect *up_frame,
+                                         stack_frame *closure_frames)
+  {
+    m_call_stack.push (fcn, up_frame, closure_frames);
+  }
+
+  void tree_evaluator::push_stack_frame (octave_user_script *script,
+                                         unwind_protect *up_frame)
+  {
+    m_call_stack.push (script, up_frame);
+  }
+
+  void tree_evaluator::push_stack_frame (octave_function *fcn)
+  {
+    m_call_stack.push (fcn);
+  }
+
+  void tree_evaluator::pop_stack_frame (void)
+  {
+    m_call_stack.pop ();
+  }
+
+  int tree_evaluator::current_line (void) const
+  {
+    return m_call_stack.current_line ();
+  }
+
+  int tree_evaluator::current_column (void) const
+  {
+    return m_call_stack.current_column ();
+  }
+
+  int tree_evaluator::debug_user_code_line (void) const
+  {
+    return m_call_stack.debug_user_code_line ();
+  }
+
+  int tree_evaluator::debug_user_code_column (void) const
+  {
+    return m_call_stack.debug_user_code_column ();
+  }
+
+  void tree_evaluator::debug_where (std::ostream& os) const
+  {
+    stack_frame *frm = m_call_stack.current_user_frame ();
+
+    frm->display_stopped_in_message (os);
+  }
+
+  octave_user_code * tree_evaluator::current_user_code (void) const
+  {
+    return m_call_stack.current_user_code ();
+  }
+
+  unwind_protect * tree_evaluator::curr_fcn_unwind_protect_frame (void) const
+  {
+    return m_call_stack.curr_fcn_unwind_protect_frame ();
+  }
+
+  octave_user_code * tree_evaluator::debug_user_code (void) const
+  {
+    return m_call_stack.debug_user_code ();
+  }
+
+  octave_function * tree_evaluator::current_function (void) const
+  {
+    return m_call_stack.current ();
+  }
+
+  octave_function * tree_evaluator::caller_function (void) const
+  {
+    return m_call_stack.caller ();
+  }
+
+  bool tree_evaluator::goto_frame (size_t n, bool verbose)
+  {
+    return m_call_stack.goto_frame (n, verbose);
+  }
+
+  void tree_evaluator::goto_caller_frame (void)
+  {
+    m_call_stack.goto_caller_frame ();
+  }
+
+  void tree_evaluator::goto_base_frame (void)
+  {
+    m_call_stack.goto_base_frame ();
+  }
+
+  void tree_evaluator::restore_frame (size_t n)
+  {
+    return m_call_stack.restore_frame (n);
+  }
+
+  std::string tree_evaluator::get_dispatch_class (void) const
+  {
+    return m_call_stack.get_dispatch_class ();
+  }
+
+  void tree_evaluator::set_dispatch_class (const std::string& class_name)
+  {
+    m_call_stack.set_dispatch_class (class_name);
+  }
+
+  bool
+  tree_evaluator::is_class_method_executing (std::string& dclass) const
+  {
+    return m_call_stack.is_class_method_executing (dclass);
+  }
+
+  bool
+  tree_evaluator::is_class_constructor_executing (std::string& dclass) const
+  {
+    return m_call_stack.is_class_constructor_executing (dclass);
+  }
+
+  std::list<stack_frame *>
+  tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const
+  {
+    return m_call_stack.backtrace_frames (curr_user_frame);
+  }
+
+  std::list<stack_frame *>
+  tree_evaluator::backtrace_frames (void) const
+  {
+    return m_call_stack.backtrace_frames ();
+  }
+
+  octave_map
+  tree_evaluator::backtrace (octave_idx_type& curr_user_frame,
+                             bool print_subfn) const
+  {
+    return m_call_stack.backtrace (curr_user_frame, print_subfn);
+  }
+
+  octave_map tree_evaluator::backtrace (void)
+  {
+    return m_call_stack.backtrace ();
+  }
+
+  octave_map tree_evaluator::empty_backtrace (void) const
+  {
+    return m_call_stack.empty_backtrace ();
+  }
+
+  void tree_evaluator::push_dummy_scope (const std::string& name)
+  {
+    symbol_scope dummy_scope (name + "$dummy");
+
+    m_call_stack.push (dummy_scope);
+  }
+
+  void tree_evaluator::pop_scope (void)
+  {
+    m_call_stack.pop ();
+  }
+
+  symbol_scope tree_evaluator::get_top_scope (void) const
+  {
+    return m_call_stack.top_scope ();
+  }
+
+  symbol_scope tree_evaluator::get_current_scope (void) const
+  {
+    return m_call_stack.current_scope ();
+  }
+
+  void tree_evaluator::mlock (void) const
+  {
+    octave_function *fcn = m_call_stack.current ();
+
+    if (! fcn)
+      error ("mlock: invalid use outside a function");
+
+    fcn->lock ();
+  }
+
+  octave_value
+  tree_evaluator::max_stack_depth (const octave_value_list& args, int nargout)
+  {
+    return m_call_stack.max_stack_depth (args, nargout);
+  }
+
+  void tree_evaluator::display_call_stack (void) const
+  {
+    m_call_stack.display ();
+  }
+
+  octave_value tree_evaluator::find (const std::string& name)
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    octave_value val = frame.varval (name);
+
+    if (val.is_defined ())
+      return val;
+
+    // Subfunction.  I think it only makes sense to check for
+    // subfunctions if we are currently executing a function defined
+    // from a .m file.
+
+    octave_value fcn = frame.find_subfunction (name);
+
+    if (fcn.is_defined ())
+      return fcn;
+
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    return symtab.current_scope ();
+    return symtab.fcn_table_find (name, ovl ());
+  }
+
+  void tree_evaluator::clear_objects (void)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.clear_objects ();
+  }
+
+  void tree_evaluator::clear_variable (const std::string& name)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.clear_variable (name);
+  }
+
+  void tree_evaluator::clear_variable_pattern (const std::string& pattern)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.clear_variable_pattern (pattern);
+  }
+
+  void tree_evaluator::clear_variable_regexp (const std::string& pattern)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.clear_variable_regexp (pattern);
+  }
+
+  void tree_evaluator::clear_variables (void)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    frame.clear_variables ();
+  }
+
+  void tree_evaluator::clear_global_variable (const std::string& name)
+  {
+    m_call_stack.clear_global_variable (name);
+  }
+
+  void
+  tree_evaluator::clear_global_variable_pattern (const std::string& pattern)
+  {
+    m_call_stack.clear_global_variable_pattern (pattern);
+  }
+
+  void tree_evaluator::clear_global_variable_regexp(const std::string& pattern)
+  {
+    m_call_stack.clear_global_variable_regexp (pattern);
+  }
+
+  void tree_evaluator::clear_global_variables (void)
+  {
+    m_call_stack.clear_global_variables ();
+  }
+
+  void tree_evaluator::clear_all (bool force)
+  {
+    // FIXME: should this also clear objects?
+
+    clear_variables ();
+    clear_global_variables ();
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    symtab.clear_functions (force);
+  }
+
+  void tree_evaluator::clear_symbol (const std::string& name)
+  {
+    // FIXME: are we supposed to do both here?
+
+    clear_variable (name);
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    symtab.clear_function (name);
+  }
+
+  void tree_evaluator::clear_symbol_pattern (const std::string& pattern)
+  {
+    // FIXME: are we supposed to do both here?
+
+    clear_variable_pattern (pattern);
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    symtab.clear_function_pattern (pattern);
+  }
+
+  void tree_evaluator::clear_symbol_regexp (const std::string& pattern)
+  {
+    // FIXME: are we supposed to do both here?
+
+    clear_variable_regexp (pattern);
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    symtab.clear_function_regexp (pattern);
+  }
+
+  std::list<std::string> tree_evaluator::global_variable_names (void) const
+  {
+    return m_call_stack.global_variable_names ();
+  }
+
+  std::list<std::string> tree_evaluator::variable_names (void) const
+  {
+    return m_call_stack.variable_names ();
   }
 
   // Return a pointer to the user-defined function FNAME.  If FNAME is empty,
@@ -1053,7 +2195,8 @@
   // current call stack.
 
   octave_user_code *
-  tree_evaluator::get_user_code (const std::string& fname)
+  tree_evaluator::get_user_code (const std::string& fname,
+                                 const std::string& class_name)
   {
     octave_user_code *user_code = nullptr;
 
@@ -1081,7 +2224,7 @@
         symbol_table& symtab = m_interpreter.get_symbol_table ();
 
         octave_value fcn;
-        size_t p2;
+        size_t p2 = std::string::npos;
 
         if (name[0] == '@')
           {
@@ -1098,6 +2241,16 @@
 
             fcn = symtab.find_method (method, dispatch_type);
           }
+        else if (! class_name.empty ())
+          {
+            cdef_manager& cdm = m_interpreter.get_cdef_manager ();
+
+            fcn = cdm.find_method (class_name, name);
+
+            // If there is no classdef method, then try legacy classes.
+            if (fcn.is_undefined ())
+              fcn = symtab.find_method (name, class_name);
+          }
         else
           {
             p2 = name.find ('>');
@@ -1130,6 +2283,23 @@
     return user_code;
   }
 
+  std::string
+  tree_evaluator::current_function_name (void) const
+  {
+    octave_function *curfcn = m_call_stack.current ();
+
+    if (curfcn)
+      return curfcn->name ();
+
+    return "";
+  }
+
+  bool
+  tree_evaluator::in_user_code (void) const
+  {
+    return m_call_stack.current_user_code () != nullptr;
+  }
+
   void
   tree_evaluator::visit_decl_command (tree_decl_command& cmd)
   {
@@ -1164,60 +2334,9 @@
     if (id)
       {
         if (elt.is_global ())
-          {
-            std::string name = id->name ();
-
-            symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-            symbol_scope global_scope = symtab.global_scope ();
-
-            symbol_record global_sr = global_scope.find_symbol (name);
-
-            // FIXME: Hmmm.  Seems like this should happen automatically
-            // for symbols coming from the global scope...
-            global_sr.mark_global ();
-
-            symbol_scope scope = symtab.current_scope ();
-
-            if (! scope.is_global (name))
-              {
-                octave_value val = scope.varval (name);
-
-                bool local_val_is_defined = val.is_defined ();
-
-                if (local_val_is_defined)
-                  {
-                    warning_with_id ("Octave:global-local-conflict",
-                                     "global: '%s' is defined in the current scope.\n",
-                                     name.c_str ());
-                    warning_with_id ("Octave:global-local-conflict",
-                                     "global: in a future version, global variables must be declared before use.\n");
-
-                    // If the symbol is defined in the local but not the
-                    // global scope, then use the local value as the
-                    // initial value.  This value will also override any
-                    // initializer in the global statement.
-                    octave_value global_val = global_scope.varval (name);
-
-                    if (global_val.is_defined ())
-                      {
-                        warning_with_id ("Octave:global-local-conflict",
-                                         "global: global value overrides existing local value");
-                      }
-                    else
-                      {
-                        warning_with_id ("Octave:global-local-conflict",
-                                         "global: existing local value used to initialize global variable");
-
-                        global_scope.assign (name, val);
-                      }
-                  }
-
-                id->link_to_global (global_scope, global_sr);
-              }
-          }
+          m_call_stack.make_global (id->symbol ());
         else if (elt.is_persistent ())
-          id->mark_persistent ();
+          m_call_stack.make_persistent (id->symbol ());
         else
           error ("declaration list element not global or persistent");
 
@@ -1481,12 +2600,7 @@
 
     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 ())
+    if (m_call_stack.size () >= static_cast<size_t> (m_max_recursion_depth))
       error ("max_recursion_depth exceeded");
 
     m_call_stack.push (&user_script, &frame);
@@ -1506,10 +2620,6 @@
 
     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);
 
@@ -1534,7 +2644,8 @@
   octave_value_list
   tree_evaluator::execute_user_function (octave_user_function& user_function,
                                          int nargout,
-                                         const octave_value_list& xargs)
+                                         const octave_value_list& xargs,
+                                         stack_frame *closure_frames)
   {
     octave_value_list retval;
 
@@ -1568,56 +2679,31 @@
 
     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 ())
+    if (m_call_stack.size () >= static_cast<size_t> (m_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);
+    m_call_stack.push (&user_function, &frame, closure_frames);
 
     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);
-      }
-
-    bind_auto_fcn_vars (fcn_scope, xargs.name_tags (), args.length (),
+    bind_auto_fcn_vars (xargs.name_tags (), args.length (),
                         nargout, user_function.takes_varargs (),
                         user_function.all_va_args (args));
 
+    if (user_function.is_anonymous_function ())
+      init_local_fcn_vars (user_function);
+
     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);
-      }
+      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.
@@ -1637,32 +2723,17 @@
     // 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);
+    //    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);
-      }
+    //    if (ret_list)
+    //      frame.add_method (this, &tree_evaluator::undefine_parameter_list,
+    //                        ret_list);
 
     frame.add_method (&user_function,
                       &octave_user_function::restore_warning_states);
@@ -1672,6 +2743,8 @@
     frame.protect_var (m_statement_context);
     m_statement_context = SC_FUNCTION;
 
+    frame.add_method (m_call_stack, &call_stack::clear_current_frame_values);
+
     {
       profiler::enter<octave_user_function> block (m_profiler, user_function);
 
@@ -1712,7 +2785,7 @@
 
         if (ret_list->takes_varargs ())
           {
-            octave_value varargout_varval = fcn_scope.varval ("varargout");
+            octave_value varargout_varval = varval ("varargout");
 
             if (varargout_varval.is_defined ())
               varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
@@ -1722,6 +2795,25 @@
                                                       varargout);
       }
 
+    if (user_function.is_nested_function ()
+        || user_function.is_parent_function ())
+      {
+        // Copy current stack frame to handles to nested functions.
+
+        for (octave_idx_type i = 0; i < retval.length (); i++)
+          {
+            octave_value val = retval(i);
+
+            if (val.is_function_handle ())
+              {
+                octave_fcn_handle *fh = val.fcn_handle_value ();
+
+                if (fh)
+                  fh->push_closure_context (*this);
+              }
+          }
+      }
+
     return retval;
   }
 
@@ -1755,10 +2847,7 @@
         // Make sure that any variable with the same name as the new
         // function is cleared.
 
-        symbol_scope scope = symtab.current_scope ();
-
-        if (scope)
-          scope.assign (nm);
+        assign (nm);
       }
   }
 
@@ -1767,13 +2856,16 @@
   {
     octave_value_list retval;
 
-    symbol_scope scope = get_current_scope ();
-
-    symbol_record::context_id context = scope.current_context ();
-
     symbol_record sym = expr.symbol ();
 
-    octave_value val = sym.find (context);
+    octave_value val = varval (sym);
+
+    if (val.is_undefined ())
+      {
+        symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+        val = symtab.find_function (sym.name ());
+      }
 
     if (val.is_defined ())
       {
@@ -1970,11 +3062,14 @@
       {
         tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
 
-        symbol_scope scope = get_current_scope ();
-
-        symbol_record::context_id context = scope.current_context ();
-
-        if (! id->is_variable (context))
+        bool is_var = is_variable (expr);
+
+        std::string nm =  id->name ();
+
+        if (is_var && idx_expr.is_word_list_cmd ())
+          error ("%s used as variable and later as function", nm.c_str ());
+
+        if (! is_var)
           {
             octave_value_list first_args;
 
@@ -1997,10 +3092,19 @@
                 first_args.stash_name_tags (anm);
               }
 
+            symbol_record sym = id->symbol ();
+
+            octave_value val = varval (sym);
+
+            if (val.is_undefined ())
+              {
+                symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+                val = symtab.find_function (sym.name (), first_args);
+              }
+
             octave_function *fcn = nullptr;
 
-            octave_value val = id->do_lookup (context, first_args);
-
             if (val.is_function ())
               fcn = val.function_value (true);
 
@@ -2034,6 +3138,12 @@
                   {
                     // No more indices, so we are done.
 
+                    // See note at end of function about deleting
+                    // temporaries prior to pushing result.
+
+                    base_expr_val = octave_value ();
+                    first_args = octave_value_list ();
+
                     push_result (retval);
                     return;
                   }
@@ -2221,6 +3331,19 @@
           }
       }
 
+    // Delete any temporary values prior to pushing the result and
+    // returning so that destructors for any temporary classdef handle
+    // objects will be called before we return.  Otherwise, the
+    // destructor may push result values that will wipe out the result
+    // that we push below.  Although the method name is "push_result"
+    // there is only a single register (either an octave_value or an
+    // octave_value_list) not a stack.
+
+    idx.clear ();
+    partial_expr_val = octave_value ();
+    base_expr_val = octave_value ();
+    val = octave_value ();
+
     push_result (retval);
   }
 
@@ -2490,44 +3613,12 @@
   {
     std::string nm = expr.name ();
 
-    octave_value fh = make_fcn_handle (nm);
+    octave_value fh = make_fcn_handle (m_interpreter, nm);
 
     push_result (fh);
   }
 
   void
-  tree_evaluator::visit_funcall (tree_funcall& expr)
-  {
-    octave_value_list retval;
-
-    octave_value fcn = expr.function ();
-
-    octave_value_list args = expr.arguments ();
-
-    int nargout = m_nargout_stack.top ();
-
-    retval = feval (fcn.function_value (), args, nargout);
-
-    if (retval.length () == 1 && retval(0).is_function ())
-      {
-        // The return object is a function.  We may need to re-index it
-        // using the same logic as for identifier.  This is primarily
-        // used for superclass references in classdef.
-
-        octave_value val = retval(0);
-        octave_function *f = val.function_value (true);
-
-        if (f && ! (expr.is_postfix_indexed ()
-                    && f->accepts_postfix_index (expr.postfix_index ())))
-          {
-            retval = f->call (*this, nargout);
-          }
-      }
-
-    push_result (retval);
-  }
-
-  void
   tree_evaluator::visit_parameter_list (tree_parameter_list&)
   {
     panic_impossible ();
@@ -2635,11 +3726,11 @@
 
     // Act like dbcont.
 
-    if (Vdebugging && m_call_stack.current_frame () == m_current_frame)
+    if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame)
       {
-        Vdebugging = false;
-
-        reset_debug_state ();
+        m_dbstep_flag = 0;
+
+        exit_debug_repl (true);
       }
     else if (m_statement_context == SC_FUNCTION
              || m_statement_context == SC_SCRIPT
@@ -2783,19 +3874,9 @@
                     bool do_bind_ans = false;
 
                     if (expr->is_identifier ())
-                      {
-                        symbol_scope scope = get_current_scope ();
-
-                        symbol_record::context_id context
-                          = scope.current_context ();
-
-                        tree_identifier *id
-                          = dynamic_cast<tree_identifier *> (expr);
-
-                        do_bind_ans = (! id->is_variable (context));
-                      }
+                      do_bind_ans = ! is_variable (expr);
                     else
-                      do_bind_ans = (! expr->is_assignment_expression ());
+                      do_bind_ans = ! expr->is_assignment_expression ();
 
                     if (do_bind_ans)
                       bind_ans (tmp_result, expr->print_result ()
@@ -2938,19 +4019,15 @@
         m_echo_file_pos = line + 1;
       }
 
+    error_system& es = m_interpreter.get_error_system ();
+
     bool execution_error = false;
 
     {
       // unwind frame before catch block
       unwind_protect frame;
 
-      frame.protect_var (buffer_error_messages);
-      frame.protect_var (Vdebug_on_error);
-      frame.protect_var (Vdebug_on_warning);
-
-      buffer_error_messages++;
-      Vdebug_on_error = false;
-      Vdebug_on_warning = false;
+      interpreter_try (frame);
 
       // The catch code is *not* added to unwind_protect stack;
       // it doesn't need to be run on interrupts.
@@ -2961,15 +4038,20 @@
         {
           try
             {
-              in_try_catch++;
+              unwind_protect inner_frame;
+
+              int itc = es.in_try_catch ();
+              inner_frame.add_method (es, &error_system::set_in_try_catch,
+                                      es.in_try_catch ());
+
+              es.in_try_catch (itc + 1);
+
               try_code->accept (*this);
-              in_try_catch--;
             }
           catch (const execution_exception&)
             {
               interpreter::recover_from_exception ();
 
-              in_try_catch--;          // must be restored before "catch" block
               execution_error = true;
             }
         }
@@ -2991,9 +4073,9 @@
 
                 octave_scalar_map err;
 
-                err.assign ("message", last_error_message ());
-                err.assign ("identifier", last_error_id ());
-                err.assign ("stack", last_error_stack ());
+                err.assign ("message", es.last_error_message ());
+                err.assign ("identifier", es.last_error_id ());
+                err.assign ("stack", es.last_error_stack ());
 
                 ult.assign (octave_value::op_asn_eq, err);
               }
@@ -3235,6 +4317,45 @@
       }
   }
 
+  void
+  tree_evaluator::visit_superclass_ref (tree_superclass_ref& expr)
+  {
+    std::string meth = expr.method_name ();
+    std::string cls = expr.class_name ();
+
+    octave_value tmp = octave_classdef::superclass_ref (meth, cls);
+
+    if (! expr.is_postfix_indexed ())
+      {
+        // There was no index, so this superclass_ref object is not
+        // part of an index expression.  It is also not an identifier in
+        // the syntax tree but we need to handle it as if it were.  So
+        // call the function here.
+
+        octave_function *f = tmp.function_value (true);
+
+        assert (f);
+
+        int nargout = m_nargout_stack.top ();
+
+        push_result (f->call (*this, nargout));
+        return;
+      }
+
+    // The superclass_ref function object will be indexed as part of the
+    // enclosing index expression.
+
+    push_result (tmp);
+  }
+
+  void
+  tree_evaluator::visit_metaclass_query (tree_metaclass_query& expr)
+  {
+    std::string cls = expr.class_name ();
+
+    push_result (octave_classdef::metaclass_query (cls));
+  }
+
   void tree_evaluator::bind_ans (const octave_value& val, bool print)
   {
     static std::string ans = "ans";
@@ -3250,9 +4371,7 @@
           }
         else
           {
-            symbol_scope scope = get_current_scope ();
-
-            scope.force_assign (ans, val);
+            assign (ans, val);
 
             if (print)
               {
@@ -3265,6 +4384,18 @@
   }
 
   void
+  tree_evaluator::evaluate_internal (tree_expression *expr, int nargout)
+  {
+    unwind_protect frame;
+
+    m_nargout_stack.push (nargout);
+
+    frame.add_method (m_nargout_stack, &value_stack<int>::pop);
+
+    expr->accept (*this);
+  }
+
+  void
   tree_evaluator::do_breakpoint (tree_statement& stmt)
   {
     do_breakpoint (stmt.is_active_breakpoint (*this),
@@ -3278,16 +4409,10 @@
     bool break_on_this_statement = false;
 
     if (is_breakpoint)
-      {
-        break_on_this_statement = true;
-
-        m_dbstep_flag = 0;
-
-        m_current_frame = m_call_stack.current_frame ();
-      }
+      break_on_this_statement = true;
     else if (m_dbstep_flag > 0)
       {
-        if (m_call_stack.current_frame () == m_current_frame)
+        if (m_call_stack.current_frame () == m_debug_frame)
           {
             if (m_dbstep_flag == 1 || is_end_of_fcn_or_script)
               {
@@ -3298,8 +4423,6 @@
                 // return to prompt.
 
                 break_on_this_statement = true;
-
-                m_dbstep_flag = 0;
               }
             else
               {
@@ -3310,15 +4433,13 @@
 
           }
         else if (m_dbstep_flag == 1
-                 && m_call_stack.current_frame () < m_current_frame)
+                 && m_call_stack.current_frame () < m_debug_frame)
           {
             // We stepped out from the end of a function.
 
-            m_current_frame = m_call_stack.current_frame ();
+            m_debug_frame = m_call_stack.current_frame ();
 
             break_on_this_statement = true;
-
-            m_dbstep_flag = 0;
           }
       }
     else if (m_dbstep_flag == -1)
@@ -3327,9 +4448,7 @@
 
         break_on_this_statement = true;
 
-        m_dbstep_flag = 0;
-
-        m_current_frame = m_call_stack.current_frame ();
+        m_debug_frame = m_call_stack.current_frame ();
       }
     else if (m_dbstep_flag == -2)
       {
@@ -3340,30 +4459,18 @@
         // that frame.
 
         if (is_end_of_fcn_or_script
-            && m_call_stack.current_frame () == m_current_frame)
+            && m_call_stack.current_frame () == m_debug_frame)
           m_dbstep_flag = -1;
       }
 
     if (break_on_this_statement)
       {
-        input_system& input_sys = m_interpreter.get_input_system ();
-
-        input_sys.keyboard ();
+        m_dbstep_flag = 0;
+
+        enter_debugger ();
       }
   }
 
-  // ARGS is currently unused, but since the do_keyboard function in
-  // input.cc accepts an argument list, we preserve it here so that the
-  // interface won't have to change if we decide to use it in the future.
-
-  octave_value
-  tree_evaluator::do_keyboard (const octave_value_list& args) const
-  {
-    input_system& input_sys = m_interpreter.get_input_system ();
-
-    return input_sys.keyboard (args);
-  }
-
   bool
   tree_evaluator::is_logically_true (tree_expression *expr,
                                      const char *warn_for)
@@ -3433,6 +4540,111 @@
                                   "max_recursion_depth", 0);
   }
 
+  symbol_info_list
+  tree_evaluator::glob_symbol_info (const std::string& pattern) const
+  {
+    return m_call_stack.glob_symbol_info (pattern);
+  }
+
+  symbol_info_list
+  tree_evaluator::regexp_symbol_info (const std::string& pattern) const
+  {
+    return m_call_stack.regexp_symbol_info (pattern);
+  }
+
+  symbol_info_list
+  tree_evaluator::get_symbol_info (void)
+  {
+    return m_call_stack.get_symbol_info ();
+  }
+
+  symbol_info_list
+  tree_evaluator::top_scope_symbol_info (void) const
+  {
+    return m_call_stack.top_scope_symbol_info ();
+  }
+
+  octave_map tree_evaluator::get_autoload_map (void) const
+  {
+    Cell func_names (dim_vector (m_autoload_map.size (), 1));
+    Cell file_names (dim_vector (m_autoload_map.size (), 1));
+
+    octave_idx_type i = 0;
+    for (const auto& fcn_fname : m_autoload_map)
+      {
+        func_names(i) = fcn_fname.first;
+        file_names(i) = fcn_fname.second;
+
+        i++;
+      }
+
+    octave_map m;
+
+    m.assign ("function", func_names);
+    m.assign ("file", file_names);
+
+    return m;
+  }
+
+  std::string tree_evaluator::lookup_autoload (const std::string& nm) const
+  {
+    std::string retval;
+
+    auto p = m_autoload_map.find (nm);
+
+    if (p != m_autoload_map.end ())
+      {
+        load_path& lp = m_interpreter.get_load_path ();
+
+        retval = lp.find_file (p->second);
+      }
+
+    return retval;
+  }
+
+  std::list<std::string> tree_evaluator::autoloaded_functions (void) const
+  {
+    std::list<std::string> names;
+
+    for (const auto& fcn_fname : m_autoload_map)
+      names.push_back (fcn_fname.first);
+
+    return names;
+  }
+
+  std::list<std::string>
+  tree_evaluator::reverse_lookup_autoload (const std::string& nm) const
+  {
+    std::list<std::string> names;
+
+    for (const auto& fcn_fname : m_autoload_map)
+      if (nm == fcn_fname.second)
+        names.push_back (fcn_fname.first);
+
+    return names;
+  }
+
+  void tree_evaluator::add_autoload (const std::string& fcn,
+                                     const std::string& nm)
+  {
+    std::string file_name = check_autoload_file (nm);
+
+    m_autoload_map[fcn] = file_name;
+  }
+
+  void tree_evaluator::remove_autoload (const std::string& fcn,
+                                        const std::string& nm)
+  {
+    check_autoload_file (nm);
+
+    // Remove function from symbol table and autoload map.
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    symtab.clear_dld_function (fcn);
+
+    m_autoload_map.erase (fcn);
+  }
+
   octave_value
   tree_evaluator::whos_line_format (const octave_value_list& args, int nargout)
   {
@@ -3465,10 +4677,7 @@
 
     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))
+    if (is_variable (expr))
       {
         std::string var = expr->name ();
 
@@ -3493,6 +4702,13 @@
     error_with_id (e.err_id (), "%s", msg.c_str ());
   }
 
+  octave_value
+  tree_evaluator::do_who (int argc, const string_vector& argv,
+                          bool return_list, bool verbose)
+  {
+    return m_call_stack.do_who (argc, argv, return_list, verbose);
+  }
+
   void
   tree_evaluator::push_echo_state (unwind_protect& frame, int type,
                                    const std::string& file_name,
@@ -3694,6 +4910,48 @@
     return octave_value ();
   }
 
+  bool tree_evaluator::in_debug_repl (void) const
+  {
+    return (m_debugger_stack.empty ()
+            ? false : m_debugger_stack.top()->in_debug_repl ());
+  }
+
+  bool tree_evaluator::in_debug_repl (bool flag)
+  {
+    if (! m_debugger_stack.empty ())
+      error ("attempt to set in_debug_repl without debugger object");
+
+    return m_debugger_stack.top()->in_debug_repl (flag);
+  }
+
+  bool tree_evaluator::exit_debug_repl (void) const
+  {
+    return (m_debugger_stack.empty ()
+            ? false : m_debugger_stack.top()->exit_debug_repl (true));
+  }
+
+  bool tree_evaluator::exit_debug_repl (bool flag)
+  {
+    if (m_debugger_stack.empty ())
+      error ("attempt to set exit_debug_repl without debugger object");
+
+    return m_debugger_stack.top()->exit_debug_repl (flag);
+  }
+
+  bool tree_evaluator::abort_debug_repl (void) const
+  {
+    return (m_debugger_stack.empty ()
+            ? false : m_debugger_stack.top()->abort_debug_repl ());
+  }
+
+  bool tree_evaluator::abort_debug_repl (bool flag)
+  {
+    if (m_debugger_stack.empty ())
+      error ("attempt to set abort_debug_repl without debugger object");
+
+    return m_debugger_stack.top()->abort_debug_repl (flag);
+  }
+
   octave_value
   tree_evaluator::PS4 (const octave_value_list& args, int nargout)
   {
@@ -3771,46 +5029,69 @@
     return quit;
   }
 
-  void tree_evaluator::bind_auto_fcn_vars (symbol_scope& scope,
-                                           const string_vector& arg_names,
+  void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,
                                            int nargin, int nargout,
                                            bool takes_varargs,
                                            const octave_value_list& va_args)
   {
-    scope.force_assign (".argn.", Cell (arg_names));
-    scope.mark_hidden (".argn.");
-    scope.mark_automatic (".argn.");
-
-    scope.force_assign (".ignored.", ignored_fcn_outputs ());
-    scope.mark_hidden (".ignored.");
-    scope.mark_automatic (".ignored.");
-
-    scope.force_assign (".nargin.", nargin);
-    scope.mark_hidden (".nargin.");
-    scope.mark_automatic (".nargin.");
-
-    scope.force_assign (".nargout.", nargout);
-    scope.mark_hidden (".nargout.");
-    scope.mark_automatic (".nargout.");
-
-    scope.force_assign (".saved_warning_states.", octave_value ());
-    scope.mark_hidden (".saved_warning_states.");
-    scope.mark_automatic (".saved_warning_states.");
-
-    if (! arg_names.empty ())
-      {
-        // It is better to save this in the hidden variable .argn. and
-        // then use that in the inputname function instead of using argn,
-        // which might be redefined in a function.  Keep the old argn name
-        // for backward compatibility of functions that use it directly.
-
-        charMatrix chm (arg_names, string_fill_char ());
-        scope.force_assign ("argn", chm);
-        scope.mark_automatic ("argn");
-      }
+    set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names));
+    set_auto_fcn_var (stack_frame::IGNORED, ignored_fcn_outputs ());
+    set_auto_fcn_var (stack_frame::NARGIN, nargin);
+    set_auto_fcn_var (stack_frame::NARGOUT, nargout);
+    set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ());
 
     if (takes_varargs)
-      scope.assign ("varargin", va_args.cell_value ());
+      assign ("varargin", va_args.cell_value ());
+  }
+
+  void tree_evaluator::init_local_fcn_vars (octave_user_function& user_fcn)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    const octave_user_function::local_vars_map& lviv
+      = user_fcn.local_var_init_vals ();
+
+    for (const auto& nm_ov : lviv)
+      frame.assign (nm_ov.first, nm_ov.second);
+  }
+
+  std::string
+  tree_evaluator::check_autoload_file (const std::string& nm) const
+  {
+    if (sys::env::absolute_pathname (nm))
+      return nm;
+
+    std::string full_name = nm;
+
+    octave_user_code *fcn = m_call_stack.current_user_code ();
+
+    bool found = false;
+
+    if (fcn)
+      {
+        std::string fname = fcn->fcn_file_name ();
+
+        if (! fname.empty ())
+          {
+            fname = sys::env::make_absolute (fname);
+            fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1);
+
+            sys::file_stat fs (fname + nm);
+
+            if (fs.exists ())
+              {
+                full_name = fname + nm;
+                found = true;
+              }
+          }
+      }
+
+    if (! found)
+      warning_with_id ("Octave:autoload-relative-file-name",
+                       "autoload: '%s' is not an absolute filename",
+                       nm.c_str ());
+
+    return full_name;
   }
 }
 
@@ -3867,8 +5148,7 @@
 
 @table @code
 @item %a
-Prints attributes of variables (g=global, p=persistent, f=formal parameter,
-a=automatic variable).
+Prints attributes of variables (g=global, p=persistent, f=formal parameter).
 
 @item %b
 Prints number of bytes occupied by variables.
--- a/libinterp/parse-tree/pt-eval.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-eval.h	Fri Jul 12 12:14:43 2019 -0400
@@ -25,6 +25,7 @@
 
 #include "octave-config.h"
 
+#include <iosfwd>
 #include <list>
 #include <set>
 #include <stack>
@@ -42,10 +43,12 @@
 
 namespace octave
 {
+  class symbol_info_list;
   class symbol_scope;
   class tree_decl_elt;
   class tree_expression;
 
+  class debugger;
   class interpreter;
   class unwind_protect;
 
@@ -129,17 +132,19 @@
       : 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_nargout_stack (), m_autoload_map (), m_bp_table (*this),
+        m_call_stack (*this), m_profiler (), m_debug_frame (0),
+        m_debug_mode (false), m_quiet_breakpoint_flag (false),
+        m_debugger_stack (), m_max_recursion_depth (256),
         m_whos_line_format ("  %a:4; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;\n"),
         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_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)
-    { }
+        m_indexed_object (nullptr), m_index_position (0),
+        m_num_indices (0)
+      { }
 
     // No copying!
 
@@ -149,10 +154,12 @@
 
     ~tree_evaluator (void) = default;
 
-    void reset (void);
+    bool at_top_level (void) const;
 
     int repl (bool interactive);
 
+    std::string mfilename (const std::string& opt = "") const;
+
     octave_value_list eval_string (const std::string& eval_str, bool silent,
                                    int& parse_status, int nargout);
 
@@ -162,6 +169,18 @@
     octave_value_list eval_string (const octave_value& arg, bool silent,
                                    int& parse_status, int nargout);
 
+    octave_value_list eval (const std::string& try_code, int nargout);
+
+    octave_value_list eval (const std::string& try_code,
+                            const std::string& catch_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code, int nargout);
+
+    octave_value_list evalin (const std::string& context,
+                              const std::string& try_code,
+                              const std::string& catch_code, int nargout);
+
     void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
     void visit_argument_list (tree_argument_list&);
@@ -197,8 +216,9 @@
     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);
+    execute_user_function (octave_user_function& user_function,
+                           int nargout, const octave_value_list& args,
+                           stack_frame *closure_frames = nullptr);
 
     void visit_octave_user_function_header (octave_user_function&);
 
@@ -228,8 +248,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
@@ -261,6 +279,9 @@
     void visit_while_command (tree_while_command&);
     void visit_do_until_command (tree_do_until_command&);
 
+    void visit_superclass_ref (tree_superclass_ref&);
+    void visit_metaclass_query (tree_metaclass_query&);
+
     void bind_ans (const octave_value& val, bool print);
 
     bool statement_printing_enabled (void);
@@ -269,7 +290,11 @@
 
     void reset_debug_state (bool mode);
 
-    void set_dbstep_flag (int step) { m_dbstep_flag = step; }
+    void enter_debugger (const std::string& prompt = "debug> ");
+
+    void keyboard (const std::string& prompt = "keyboard> ");
+
+    void dbupdown (int n, bool verbose = false);
 
     // Possible types of evaluation contexts.
     enum stmt_list_type
@@ -307,11 +332,7 @@
     {
       octave_value retval;
 
-      m_nargout_stack.push (nargout);
-
-      expr->accept (*this);
-
-      m_nargout_stack.pop ();
+      evaluate_internal (expr, nargout);
 
       switch (m_result_type)
         {
@@ -331,6 +352,8 @@
           break;
         }
 
+      m_result_type = RT_UNDEFINED;
+
       return retval;
     }
 
@@ -338,11 +361,7 @@
     {
       octave_value_list retval;
 
-      m_nargout_stack.push (nargout);
-
-      expr->accept (*this);
-
-      m_nargout_stack.pop ();
+      evaluate_internal (expr, nargout);
 
       switch (m_result_type)
         {
@@ -361,11 +380,62 @@
           break;
         }
 
+      m_result_type = RT_UNDEFINED;
+
       return retval;
     }
 
     octave_value evaluate (tree_decl_elt *);
 
+    void install_variable (const std::string& name,
+                           const octave_value& value, bool global);
+
+    octave_value global_varval (const std::string& name) const;
+
+    octave_value& global_varref (const std::string& name);
+
+    void global_assign (const std::string& name,
+                        const octave_value& val = octave_value ());
+
+    octave_value top_level_varval (const std::string& name) const;
+
+    void top_level_assign (const std::string& name,
+                           const octave_value& val = octave_value ());
+
+    bool is_variable (const std::string& name) const;
+
+    bool is_local_variable (const std::string& name) const;
+
+    bool is_variable (const tree_expression *expr) const;
+
+    bool is_defined (const tree_expression *expr) const;
+
+    bool is_variable (const symbol_record& sym) const;
+
+    bool is_defined (const symbol_record& sym) const;
+
+    bool is_global (const std::string& name) const;
+
+    octave_value varval (const symbol_record& sym) const;
+
+    octave_value varval (const std::string& name) const;
+
+    void assign (const std::string& name,
+                 const octave_value& val = octave_value ());
+
+    void assignin (const std::string& context, const std::string& name,
+                   const octave_value& val = octave_value ());
+
+    void source_file (const std::string& file_name,
+                      const std::string& context = "",
+                      bool verbose = false, bool require_file = true,
+                      const std::string& warn_for = "");
+
+    void set_auto_fcn_var (stack_frame::auto_var_type avt,
+                           const octave_value& val = octave_value ());
+
+    octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;
+
     void define_parameter_list_from_arg_vector
       (tree_parameter_list *param_list, const octave_value_list& args);
 
@@ -388,13 +458,162 @@
 
     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);
+    call_stack& get_call_stack (void) { return m_call_stack; }
+
+    void push_stack_frame (const symbol_scope& scope);
+
+    void push_stack_frame (octave_user_function *fcn,
+                           unwind_protect *up_frame,
+                           stack_frame *closure_frames = nullptr);
+
+    void push_stack_frame (octave_user_script *script,
+                           unwind_protect *up_frame);
+
+    void push_stack_frame (octave_function *fcn);
+
+    void pop_stack_frame (void);
+
+    const stack_frame& get_current_stack_frame (void) const
+    {
+      return m_call_stack.get_current_stack_frame ();
+    }
+
+    stack_frame& get_current_stack_frame (void)
+    {
+      return m_call_stack.get_current_stack_frame ();
+    }
+
+    stack_frame * current_user_frame (void) const
+    {
+      return m_call_stack.current_user_frame ();
+    }
+
+    // Current line in current function.
+    int current_line (void) const;
+
+    // Current column in current function.
+    int current_column (void) const;
+
+    // Line number in current function that we are debugging.
+    int debug_user_code_line (void) const;
+
+    // Column number in current function that we are debugging.
+    int debug_user_code_column (void) const;
+
+    void debug_where (std::ostream& os) const;
+
+    octave_user_code * current_user_code (void) const;
+
+    unwind_protect * curr_fcn_unwind_protect_frame (void) const;
+
+    // Current function that we are debugging.
+    octave_user_code * debug_user_code (void) const;
+
+    octave_function * current_function (void) const;
+
+    octave_function * caller_function (void) const;
+
+    bool goto_frame (size_t n = 0, bool verbose = false);
+
+    void goto_caller_frame (void);
+
+    void goto_base_frame (void);
+
+    void restore_frame (size_t n);
+
+    std::string get_dispatch_class (void) const;
+
+    void set_dispatch_class (const std::string& class_name);
+
+    bool is_class_method_executing (std::string& dispatch_class) const;
+
+    bool is_class_constructor_executing (std::string& dispatch_class) const;
+
+    std::list<stack_frame *>
+    backtrace_frames (octave_idx_type& curr_user_frame) const;
+
+    std::list<stack_frame *> backtrace_frames () const;
 
-    octave_user_code * get_user_code (const std::string& fname = "");
+    octave_map backtrace (octave_idx_type& curr_user_frame,
+                          bool print_subfn = true) const;
+
+    octave_map backtrace ();
+
+    octave_map empty_backtrace (void) const;
+
+    void push_dummy_scope (const std::string& name);
+    void pop_scope (void);
+
+    symbol_scope get_top_scope (void) const;
+    symbol_scope get_current_scope (void) const;
+
+    void mlock (void) const;
+
+    octave_value max_stack_depth (const octave_value_list& args, int nargout);
+
+    // Useful for debugging
+    void display_call_stack (void) const;
+
+    octave_value find (const std::string& name);
+
+    void clear_objects (void);
+
+    void clear_variable (const std::string& name);
+
+    void clear_variable_pattern (const std::string& pattern);
+
+    void clear_variable_regexp (const std::string& pattern);
+
+    void clear_variables (void);
+
+    void clear_global_variable (const std::string& name);
+
+    void clear_global_variable_pattern (const std::string& pattern);
+
+    void clear_global_variable_regexp (const std::string& pattern);
+
+    void clear_global_variables (void);
+
+    void clear_all (bool force = false);
+
+    void clear_symbol (const std::string& name);
+
+    void clear_symbol_pattern (const std::string& pattern);
+
+    void clear_symbol_regexp (const std::string& pattern);
+
+    std::list<std::string> global_variable_names (void) const;
+
+    std::list<std::string> variable_names (void) const;
+
+    octave_user_code * get_user_code (const std::string& fname = "",
+                                      const std::string& class_name = "");
+
+    std::string current_function_name (void) const;
+
+    bool in_user_code (void) const;
+
+    symbol_info_list glob_symbol_info (const std::string& pattern) const;
+
+    symbol_info_list regexp_symbol_info (const std::string& pattern) const;
+
+    symbol_info_list get_symbol_info (void);
+
+    symbol_info_list top_scope_symbol_info (void) const;
+
+    octave_map get_autoload_map (void) const;
+
+    std::string lookup_autoload (const std::string& nm) const;
+
+    std::list<std::string> autoloaded_functions (void) const;
+
+    std::list<std::string> reverse_lookup_autoload (const std::string& nm) const;
+
+    void add_autoload (const std::string& fcn, const std::string& nm);
+
+    void remove_autoload (const std::string& fcn, const std::string& nm);
 
     int max_recursion_depth (void) const { return m_max_recursion_depth; }
 
@@ -431,15 +650,20 @@
     octave_value
     silent_functions (const octave_value_list& args, int nargout);
 
-    size_t current_frame (void) const { return m_current_frame; }
+    size_t debug_frame (void) const { return m_debug_frame; }
 
-    size_t current_frame (size_t n)
+    size_t debug_frame (size_t n)
     {
-      size_t val = m_current_frame;
-      m_current_frame = n;
+      size_t val = m_debug_frame;
+      m_debug_frame = n;
       return val;
     }
 
+    size_t current_call_stack_frame_number (void) const
+    {
+      return m_call_stack.current_frame ();
+    }
+
     bool debug_mode (void) const { return m_debug_mode; }
 
     bool debug_mode (bool flag)
@@ -467,6 +691,16 @@
       return val;
     }
 
+    // The following functions are provided for convenience and forward
+    // to the corresponding functions in the debugger class for the
+    // current debugger (if any).
+    bool in_debug_repl (void) const;
+    bool in_debug_repl (bool flag);
+    bool exit_debug_repl (void) const;
+    bool exit_debug_repl (bool flag);
+    bool abort_debug_repl (void) const;
+    bool abort_debug_repl (bool flag);
+
     octave_value PS4 (const octave_value_list& args, int nargout);
 
     std::string PS4 (void) const { return m_PS4; }
@@ -514,6 +748,17 @@
       return val;
     }
 
+    int dbstep_flag (void) const { return m_dbstep_flag; }
+
+    int dbstep_flag (int val)
+    {
+      int old_val = m_dbstep_flag;
+      m_dbstep_flag = val;
+      return old_val;
+    }
+
+    void set_dbstep_flag (int step) { m_dbstep_flag = step; }
+
     octave_value echo (const octave_value_list& args, int nargout);
 
     int echo (void) const { return m_echo; }
@@ -530,6 +775,9 @@
 
     void final_index_error (index_exception& e, const tree_expression *expr);
 
+    octave_value do_who (int argc, const string_vector& argv,
+                         bool return_list, bool verbose = false);
+
     void push_echo_state (unwind_protect& frame, int type,
                           const std::string& file_name, size_t pos = 1);
 
@@ -543,14 +791,13 @@
 
     bool maybe_push_echo_state_cleanup (void);
 
+    void evaluate_internal (tree_expression *expr, int nargout);
+
     void do_breakpoint (tree_statement& stmt);
 
     void do_breakpoint (bool is_breakpoint,
                         bool is_end_of_fcn_or_script = false);
 
-    virtual octave_value
-    do_keyboard (const octave_value_list& args = octave_value_list ()) const;
-
     bool is_logically_true (tree_expression *expr, const char *warn_for);
 
     octave_value_list
@@ -570,11 +817,14 @@
 
     bool quit_loop_now (void);
 
-    void bind_auto_fcn_vars (symbol_scope& scope,
-                             const string_vector& arg_names, int nargin,
+    void bind_auto_fcn_vars (const string_vector& arg_names, int nargin,
                              int nargout, bool takes_varargs,
                              const octave_value_list& va_args);
 
+    void init_local_fcn_vars (octave_user_function& user_fcn);
+
+    std::string check_autoload_file (const std::string& nm) const;
+
     interpreter& m_interpreter;
 
     // The context for the current evaluation.
@@ -588,6 +838,9 @@
 
     value_stack<int> m_nargout_stack;
 
+    // List of autoloads (function -> file mapping).
+    std::map<std::string, std::string> m_autoload_map;
+
     bp_table m_bp_table;
 
     call_stack m_call_stack;
@@ -595,12 +848,19 @@
     profiler m_profiler;
 
     // The number of the stack frame we are currently debugging.
-    size_t m_current_frame;
+    size_t m_debug_frame;
 
     bool m_debug_mode;
 
     bool m_quiet_breakpoint_flag;
 
+    // When entering the debugger we push it on this stack.  Managing
+    // debugger invocations this way allows us to handle recursive
+    // debugger calls.  When we exit a debugger the object is popped
+    // from the stack and deleted and we resume working with the
+    // previous debugger (if any) that is now at the top of the stack.
+    std::stack<debugger *> m_debugger_stack;
+
     // Maximum nesting level for functions, scripts, or sourced files
     // called recursively.
     int m_max_recursion_depth;
@@ -662,11 +922,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_evaluator' instead")
-typedef octave::tree_evaluator tree_evaluator;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-except.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-except.h	Fri Jul 12 12:14:43 2019 -0400
@@ -168,14 +168,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_try_catch_command' instead")
-typedef octave::tree_try_catch_command tree_try_catch_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_unwind_protect_command' instead")
-typedef octave::tree_unwind_protect_command tree_unwind_protect_command;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-exp.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-exp.h	Fri Jul 12 12:14:43 2019 -0400
@@ -158,11 +158,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_expression' instead")
-typedef octave::tree_expression tree_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -70,21 +70,11 @@
     symbol_scope af_scope = m_scope;
     symbol_scope af_parent_scope = m_parent_scope;
 
-    symbol_table& symtab
-      = __get_symbol_table__ ("tree_anon_fcn_handle::dup");
-
     symbol_scope new_scope;
 
     if (af_scope)
       new_scope = af_scope.dup ();
 
-    // FIXME: why should we inherit from the current scope here?  That
-    // doesn't seem right, but with the way things work now it appears
-    // to be required for bug-31371.tst to pass.
-
-    if (new_scope)
-      symtab.inherit (new_scope);
-
     // FIXME: if new scope is nullptr, then we are in big trouble here...
 
     tree_anon_fcn_handle *new_afh = new
--- a/libinterp/parse-tree/pt-fcn-handle.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Fri Jul 12 12:14:43 2019 -0400
@@ -155,14 +155,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_fcn_handle' instead")
-typedef octave::tree_fcn_handle tree_fcn_handle;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_anon_fcn_handle' instead")
-typedef octave::tree_anon_fcn_handle tree_anon_fcn_handle;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-funcall.cc	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
-
-Copyright (C) 2012-2019 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 "ov-fcn.h"
-#include "pt-funcall.h"
-#include "pt-walk.h"
-
-namespace octave
-{
-  // Function call objects.
-
-  void
-  tree_funcall::print (std::ostream& os, bool pr_as_read_syntax,
-                       bool pr_orig_text)
-  {
-    print_raw (os, pr_as_read_syntax, pr_orig_text);
-  }
-
-  void
-  tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax,
-                           bool pr_orig_text)
-  {
-    if (pr_orig_text)
-      {
-        os << original_text ();
-      }
-    else
-      {
-        octave_function *fp = m_fcn.function_value ();
-        std::string nm = (fp ? fp->name () : "<invalid-function>");
-
-        os << nm << " (";
-
-        octave_idx_type n = m_args.length ();
-        for (octave_idx_type i = 0; i < n; i++)
-          {
-            m_args(i).print_raw (os, pr_as_read_syntax);
-
-            if (i < n - 1)
-              os << ", ";
-          }
-
-        os << ')';
-      }
-  }
-
-  tree_funcall *
-  tree_funcall::dup (symbol_scope&) const
-  {
-    tree_funcall *new_fc
-      = new tree_funcall (m_fcn, m_args, line (), column ());
-
-    new_fc->copy_base (*this);
-
-    return new_fc;
-  }
-}
--- a/libinterp/parse-tree/pt-funcall.h	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
-
-Copyright (C) 2012-2019 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_tree_funcall_h)
-#define octave_tree_funcall_h 1
-
-#include "octave-config.h"
-
-#include "ov.h"
-#include "ovl.h"
-#include "parse.h"
-#include "pt-exp.h"
-#include "pt-walk.h"
-
-namespace octave
-{
-  // Function call.  This class only represents function calls that have
-  // known functions (most useful for calls to built-in functions that
-  // are generated by the parser) and fixed argument lists, known at
-  // compile time.
-
-  class tree_funcall : public tree_expression
-  {
-  public:
-
-    tree_funcall (const octave_value& f, const octave_value_list& a,
-                  int l = -1, int c = -1)
-      : tree_expression (l, c), m_fcn (f), m_args (a)
-    {
-      if (! m_fcn.is_function ())
-        error ("tree_funcall: invalid function");
-    }
-
-    // No copying!
-
-    tree_funcall (const tree_funcall&) = delete;
-
-    tree_funcall& operator = (const tree_funcall&) = delete;
-
-    ~tree_funcall (void) = default;
-
-    bool has_magic_end (void) const { return false; }
-
-    void print (std::ostream& os, bool pr_as_read_syntax = false,
-                bool pr_orig_txt = true);
-
-    void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
-                    bool pr_orig_txt = true);
-
-    tree_funcall * dup (symbol_scope& scope) const;
-
-    octave_value function (void) const { return m_fcn; }
-
-    octave_value_list arguments (void) const { return m_args; }
-
-    void accept (tree_walker& tw)
-    {
-      tw.visit_funcall (*this);
-    }
-
-  private:
-
-    // Function to call.  Error if not a valid function at time of
-    // construction.
-    octave_value m_fcn;
-
-    // Argument list.
-    octave_value_list m_args;
-  };
-}
-
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_funcall' instead")
-typedef octave::tree_funcall tree_funcall;
-
-#endif
-
-#endif
--- a/libinterp/parse-tree/pt-id.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-id.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -38,15 +38,6 @@
 {
   // Symbols from the symbol table.
 
-  class tree_evaluator;
-
-  void tree_identifier::link_to_global (const symbol_scope& global_scope,
-                                        const symbol_record& global_sym)
-  {
-    if (! m_sym.is_global ())
-      m_sym.bind_fwd_rep (global_scope.get_rep (), global_sym);
-  }
-
   void
   tree_identifier::eval_undefined_error (void)
   {
@@ -70,9 +61,7 @@
     if (m_sym.is_added_static ())
       static_workspace_error ();
 
-    symbol_scope scope = tw.get_current_scope ();
-
-    return octave_lvalue (m_sym, scope.current_context ());
+    return octave_lvalue (m_sym, tw.get_current_stack_frame ());
   }
 
   tree_identifier *
@@ -90,4 +79,14 @@
 
     return new_id;
   }
+
+  octave_lvalue
+  tree_black_hole::lvalue (tree_evaluator& tw)
+  {
+    octave_lvalue retval (m_sym, tw.get_current_stack_frame ());
+
+    retval.mark_black_hole ();
+
+    return retval;
+  }
 }
--- a/libinterp/parse-tree/pt-id.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-id.h	Fri Jul 12 12:14:43 2019 -0400
@@ -71,53 +71,16 @@
 
     std::string name (void) const { return m_sym.name (); }
 
-    bool is_defined (symbol_record::context_id context)
-    {
-      return m_sym.is_defined (context);
-    }
-
-    virtual bool is_variable (symbol_record::context_id context) const
-    {
-      return m_sym.is_variable (context);
-    }
-
-    virtual bool is_black_hole (void) { return false; }
-
-    // Try to find a definition for an identifier.  Here's how:
-    //
-    //   * If the identifier is already defined and is a function defined
-    //     in an function file that has been modified since the last time
-    //     we parsed it, parse it again.
-    //
-    //   * If the identifier is not defined, try to find a builtin
-    //     variable or an already compiled function with the same name.
-    //
-    //   * If the identifier is still undefined, try looking for an
-    //     function file to parse.
-    //
-    //   * On systems that support dynamic linking, we prefer .oct files,
-    //     then .mex files, then .m files.
-
-    octave_value
-    do_lookup (symbol_record::context_id context,
-               const octave_value_list& args = octave_value_list ())
-    {
-      return m_sym.find (context, args);
-    }
-
-    void link_to_global (const symbol_scope& global_scope,
-                         const symbol_record& global_sym);
-
-    void mark_persistent (void) { m_sym.init_persistent (); }
+    virtual bool is_black_hole (void) const { return false; }
 
     void mark_as_formal_parameter (void) { m_sym.mark_formal (); }
 
-    // We really need to know whether this symbol referst to a variable
+    // We really need to know whether this symbol refers to a variable
     // or a function, but we may not know that yet.
 
     bool lvalue_ok (void) const { return true; }
 
-    octave_lvalue lvalue (tree_evaluator&);
+    octave_lvalue lvalue (tree_evaluator& tw);
 
     void eval_undefined_error (void);
 
@@ -136,7 +99,7 @@
 
     symbol_record symbol (void) const { return m_sym; }
 
-  private:
+  protected:
 
     // The symbol record that this identifier references.
     symbol_record m_sym;
@@ -151,32 +114,15 @@
 
     std::string name (void) const { return "~"; }
 
-    bool is_variable (symbol_record::context_id) const { return false; }
-
-    bool is_black_hole (void) { return true; }
+    bool is_black_hole (void) const { return true; }
 
     tree_black_hole * dup (symbol_scope&) const
     {
       return new tree_black_hole;
     }
 
-    octave_lvalue lvalue (tree_evaluator&)
-    {
-      octave_lvalue retval;
-      retval.mark_black_hole ();
-      return retval;
-    }
+    octave_lvalue lvalue (tree_evaluator& tw);
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_identifier' instead")
-typedef octave::tree_identifier tree_identifier;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_black_hole' instead")
-typedef octave::tree_black_hole tree_black_hole;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-idx.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -45,13 +45,13 @@
 
   tree_index_expression::tree_index_expression (int l, int c)
     : tree_expression (l, c), m_expr (nullptr), m_args (0), m_type (),
-      m_arg_nm (), m_dyn_field () { }
+      m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) { }
 
   tree_index_expression::tree_index_expression (tree_expression *e,
                                                 tree_argument_list *lst,
                                                 int l, int c, char t)
     : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-      m_arg_nm (), m_dyn_field ()
+      m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
   {
     append (lst, t);
   }
@@ -60,7 +60,7 @@
                                                 const std::string& n,
                                                 int l, int c)
     : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-      m_arg_nm (), m_dyn_field ()
+      m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
   {
     append (n);
   }
@@ -69,7 +69,7 @@
                                                 tree_expression *df,
                                                 int l, int c)
     : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-      m_arg_nm (), m_dyn_field ()
+      m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
   {
     append (df);
   }
@@ -197,8 +197,6 @@
   octave_lvalue
   tree_index_expression::lvalue (tree_evaluator& tw)
   {
-    octave_lvalue retval;
-
     std::list<octave_value_list> idx;
     std::string tmp_type;
 
@@ -208,7 +206,7 @@
     auto p_arg_nm = m_arg_nm.begin ();
     auto p_dyn_field = m_dyn_field.begin ();
 
-    retval = m_expr->lvalue (tw);
+    octave_lvalue retval = m_expr->lvalue (tw);
 
     octave_value tmp = retval.value ();
 
@@ -272,7 +270,7 @@
                   tmp = Cell ();
                 }
 
-              retval.numel (tmp.numel (tidx));
+              retval.numel (tmp.xnumel (tidx));
 
               idx.push_back (tidx);
               tmpidx.push_back (tidx);
@@ -304,7 +302,7 @@
                   else if (autoconv)
                     tmp = octave_map ();
 
-                  retval.numel (tmp.numel (pidx));
+                  retval.numel (tmp.xnumel (pidx));
 
                   tmpi = i-1;
                   tmpidx.push_back (tidx);
@@ -318,7 +316,7 @@
                     }
                   else
                     {
-                      retval.numel (tmp.numel (octave_value_list ()));
+                      retval.numel (tmp.xnumel (octave_value_list ()));
 
                       tmpi = i;
                       tmpidx.push_back (tidx);
--- a/libinterp/parse-tree/pt-idx.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-idx.h	Fri Jul 12 12:14:43 2019 -0400
@@ -89,6 +89,10 @@
 
     std::list<tree_expression *> dyn_fields (void) { return m_dyn_field; }
 
+    void mark_word_list_cmd (void) { m_word_list_cmd = true; }
+
+    bool is_word_list_cmd (void) const { return m_word_list_cmd; }
+
     bool lvalue_ok (void) const { return m_expr->lvalue_ok (); }
 
     bool rvalue_ok (void) const { return true; }
@@ -125,17 +129,13 @@
     // The list of dynamic field names, if any.
     std::list<tree_expression *> m_dyn_field;
 
+    // TRUE if this expression was parsed as a word list command.
+    bool m_word_list_cmd;
+
     tree_index_expression (int l, int c);
 
     octave_map make_arg_struct (void) const;
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_index_expression' instead")
-typedef octave::tree_index_expression tree_index_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-jit.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-jit.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -741,12 +741,6 @@
   }
 
   void
-  jit_convert::visit_funcall (tree_funcall&)
-  {
-    throw jit_fail_exception ();
-  }
-
-  void
   jit_convert::visit_parameter_list (tree_parameter_list&)
   {
     throw jit_fail_exception ("No visit_parameter_list implementation");
--- a/libinterp/parse-tree/pt-jit.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-jit.h	Fri Jul 12 12:14:43 2019 -0400
@@ -133,8 +133,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-jump.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-jump.h	Fri Jul 12 12:14:43 2019 -0400
@@ -100,17 +100,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_break_command' instead")
-typedef octave::tree_break_command tree_break_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_continue_command' instead")
-typedef octave::tree_continue_command tree_continue_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_return_command' instead")
-typedef octave::tree_return_command tree_return_command;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-loop.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-loop.h	Fri Jul 12 12:14:43 2019 -0400
@@ -322,20 +322,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_while_command' instead")
-typedef octave::tree_while_command tree_while_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_do_until_command' instead")
-typedef octave::tree_do_until_command tree_do_until_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_simple_for_command' instead")
-typedef octave::tree_simple_for_command tree_simple_for_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_complex_for_command' instead")
-typedef octave::tree_complex_for_command tree_complex_for_command;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-mat.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-mat.h	Fri Jul 12 12:14:43 2019 -0400
@@ -78,25 +78,4 @@
   maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_matrix' instead")
-typedef octave::tree_matrix tree_matrix;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::get_concat_class' instead")
-static inline std::string
-get_concat_class (const std::string& c1, const std::string& c2)
-{
-  return octave::get_concat_class (c1, c2);
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::maybe_warn_string_concat' instead")
-static inline void
-maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p)
-{
-  octave::maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
-}
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-misc.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-misc.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -59,30 +59,12 @@
     return retval;
   }
 
-  bool
-  tree_parameter_list::is_defined (symbol_record::context_id context)
-  {
-    bool status = true;
-
-    for (tree_decl_elt *elt : *this)
-      {
-        if (! elt->is_variable (context))
-          {
-            status = false;
-            break;
-          }
-      }
-
-    return status;
-  }
-
   tree_parameter_list *
   tree_parameter_list::dup (symbol_scope& scope) const
   {
     tree_parameter_list *new_list = new tree_parameter_list ();
 
-    if (takes_varargs ())
-      new_list->mark_varargs ();
+    new_list->m_marked_for_varargs = m_marked_for_varargs;
 
     for (const tree_decl_elt *elt : *this)
       new_list->append (elt->dup (scope));
--- a/libinterp/parse-tree/pt-misc.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-misc.h	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include "base-list.h"
 #include "pt-decl.h"
 #include "pt-walk.h"
-#include "symrec.h"
 
 namespace octave
 {
@@ -77,8 +76,6 @@
 
     bool varargs_only (void) { return (m_marked_for_varargs < 0); }
 
-    bool is_defined (symbol_record::context_id context);
-
     std::list<std::string> variable_names (void) const;
 
     tree_parameter_list * dup (symbol_scope& scope) const;
--- a/libinterp/parse-tree/pt-pr-code.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-pr-code.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -732,18 +732,6 @@
   }
 
   void
-  tree_print_code::visit_funcall (tree_funcall& fc)
-  {
-    indent ();
-
-    print_parens (fc, "(");
-
-    fc.print_raw (m_os, true, m_print_original_text);
-
-    print_parens (fc, ")");
-  }
-
-  void
   tree_print_code::visit_parameter_list (tree_parameter_list& lst)
   {
     auto p = lst.begin ();
@@ -1145,6 +1133,18 @@
   }
 
   void
+  tree_print_code::visit_superclass_ref (tree_superclass_ref& scr)
+  {
+    m_os << scr.method_name () << "@" << scr.class_name ();
+  }
+
+  void
+  tree_print_code::visit_metaclass_query (tree_metaclass_query& mcq)
+  {
+    m_os << "?" << mcq.class_name ();
+  }
+
+  void
   tree_print_code::print_fcn_handle_body (tree_expression *e)
   {
     if (e)
--- a/libinterp/parse-tree/pt-pr-code.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-pr-code.h	Fri Jul 12 12:14:43 2019 -0400
@@ -117,8 +117,6 @@
 
     void visit_fcn_handle (tree_fcn_handle&);
 
-    void visit_funcall (tree_funcall&);
-
     void visit_parameter_list (tree_parameter_list&);
 
     void visit_postfix_expression (tree_postfix_expression&);
@@ -149,6 +147,10 @@
 
     void visit_do_until_command (tree_do_until_command&);
 
+    void visit_superclass_ref (tree_superclass_ref&);
+
+    void visit_metaclass_query (tree_metaclass_query&);
+
     void print_fcn_handle_body (tree_expression *);
 
   private:
@@ -196,11 +198,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_print_code' instead")
-typedef octave::tree_print_code tree_print_code;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-select.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-select.h	Fri Jul 12 12:14:43 2019 -0400
@@ -292,24 +292,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_if_clause' instead")
-typedef octave::tree_if_clause tree_if_clause;
-
-// tree_if_command_list is derived from a template.
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_if_command' instead")
-typedef octave::tree_if_command tree_if_command;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_switch_case' instead")
-typedef octave::tree_switch_case tree_switch_case;
-
-// tree_switch_case_list is derived from a template.
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_switch_command' instead")
-typedef octave::tree_switch_command tree_switch_command;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-stmt.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-stmt.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -43,7 +43,6 @@
 #include "pt-jump.h"
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
-#include "pt-walk.h"
 #include "utils.h"
 #include "variables.h"
 
--- a/libinterp/parse-tree/pt-stmt.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-stmt.h	Fri Jul 12 12:14:43 2019 -0400
@@ -207,14 +207,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_statement' instead")
-typedef octave::tree_statement tree_statement;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_statement_list' instead")
-typedef octave::tree_statement_list tree_statement_list;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-tm-const.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-tm-const.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -463,8 +463,7 @@
     //
     // We might also start with a empty octave_value using
     //
-    //    ctmp = octave::type_info::lookup_type
-    //          (tmp.begin() -> begin() -> type_name());
+    //   ctmp = 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.
--- a/libinterp/parse-tree/pt-unop.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-unop.h	Fri Jul 12 12:14:43 2019 -0400
@@ -152,17 +152,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_unary_expression' instead")
-typedef octave::tree_unary_expression tree_unary_expression;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_prefix_expression' instead")
-typedef octave::tree_prefix_expression tree_prefix_expression;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_postfix_expression' instead")
-typedef octave::tree_postfix_expression tree_postfix_expression;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt-walk.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt-walk.h	Fri Jul 12 12:14:43 2019 -0400
@@ -65,7 +65,6 @@
   class tree_no_op_command;
   class tree_constant;
   class tree_fcn_handle;
-  class tree_funcall;
   class tree_parameter_list;
   class tree_postfix_expression;
   class tree_prefix_expression;
@@ -79,6 +78,8 @@
   class tree_while_command;
   class tree_do_until_command;
 
+  class tree_superclass_ref;
+  class tree_metaclass_query;
   class tree_classdef_attribute;
   class tree_classdef_attribute_list;
   class tree_classdef_superclass;
@@ -204,9 +205,6 @@
     visit_fcn_handle (tree_fcn_handle&) = 0;
 
     virtual void
-    visit_funcall (tree_funcall&) = 0;
-
-    virtual void
     visit_parameter_list (tree_parameter_list&) = 0;
 
     virtual void
@@ -243,6 +241,12 @@
     visit_do_until_command (tree_do_until_command&) = 0;
 
     virtual void
+    visit_superclass_ref (tree_superclass_ref&) { } /* = 0; */
+
+    virtual void
+    visit_metaclass_query (tree_metaclass_query&) { } /* = 0; */
+
+    virtual void
     visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */
 
     virtual void
@@ -295,11 +299,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree_walker' instead")
-typedef octave::tree_walker tree_walker;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/pt.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -27,6 +27,7 @@
 #include <sstream>
 #include <string>
 
+#include "interpreter.h"
 #include "ov-fcn.h"
 #include "pt.h"
 #include "pt-eval.h"
@@ -67,13 +68,8 @@
         int parse_status = 0;
 
         unwind_protect frame;
-        frame.protect_var (buffer_error_messages);
-        frame.protect_var (Vdebug_on_error);
-        frame.protect_var (Vdebug_on_warning);
 
-        buffer_error_messages++;
-        Vdebug_on_error = false;
-        Vdebug_on_warning = false;
+        interpreter_try (frame);
 
         retval = true;                // default to stopping if any error
         try
@@ -94,8 +90,13 @@
           }
         catch (const execution_exception& e)
           {
+            interpreter& interp = tw.get_interpreter ();
+            error_system& es = interp.get_error_system ();
+
+            std::string tmp = es.last_error_message ();
+
             warning ("Error evaluating breakpoint condition:\n    %s",
-                     last_error_message ().c_str ());
+                     tmp.c_str ());
           }
       }
     return retval;
--- a/libinterp/parse-tree/pt.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/pt.h	Fri Jul 12 12:14:43 2019 -0400
@@ -121,11 +121,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::tree' instead")
-typedef octave::tree tree;
-
 #endif
-
-#endif
--- a/libinterp/parse-tree/token.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/token.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -73,11 +73,11 @@
       m_orig_text ()
   { }
 
-  token::token (int tv, const std::string& method_nm,
-                const std::string& class_nm, int l, int c)
+  token::token (int tv, const std::string& meth, const std::string& cls,
+                int l, int c)
     : m_maybe_cmd (false), m_tspc (false), m_line_num (l), m_column_num (c),
       m_tok_val (tv), m_type_tag (scls_name_token),
-      m_tok_info (method_nm, class_nm), m_orig_text ()
+      m_tok_info (meth, cls), m_orig_text ()
   { }
 
   token::~token (void)
@@ -135,14 +135,14 @@
   token::superclass_method_name (void) const
   {
     assert (m_type_tag == scls_name_token);
-    return m_tok_info.m_superclass_info->m_method_nm;
+    return m_tok_info.m_superclass_info->m_method_name;
   }
 
   std::string
   token::superclass_class_name (void) const
   {
     assert (m_type_tag == scls_name_token);
-    return m_tok_info.m_superclass_info->m_class_nm;
+    return m_tok_info.m_superclass_info->m_class_name;
   }
 
   std::string
--- a/libinterp/parse-tree/token.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/parse-tree/token.h	Fri Jul 12 12:14:43 2019 -0400
@@ -155,8 +155,8 @@
         : m_sr (new symbol_record (sr))
       { }
 
-      tok_info (const std::string& method_nm, const std::string& class_nm)
-        : m_superclass_info (new superclass_info (method_nm, class_nm))
+      tok_info (const std::string& meth, const std::string& cls)
+        : m_superclass_info (new superclass_info (meth, cls))
       { }
 
       tok_info (const tok_info&) = delete;
@@ -177,9 +177,9 @@
       {
         superclass_info (void) = delete;
 
-        superclass_info (const std::string& method_nm,
-                         const std::string& class_nm)
-          : m_method_nm (method_nm), m_class_nm (class_nm)
+        superclass_info (const std::string& meth,
+                         const std::string& cls)
+          : m_method_name (meth), m_class_name (cls)
         { }
 
         superclass_info (const superclass_info&) = delete;
@@ -188,8 +188,13 @@
 
         ~superclass_info (void) = default;
 
-        std::string m_method_nm;
-        std::string m_class_nm;
+        // The name of the method to call.  This is the text before the
+        // "@" and may be of the form "object.method".
+        std::string m_method_name;
+
+        // The name of the superclass.  This is the text after the "@"
+        // and may be of the form "object.method".
+        std::string m_class_name;
       };
 
       superclass_info *m_superclass_info;
@@ -201,11 +206,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::token' instead")
-typedef octave::token token;
-
 #endif
-
-#endif
--- a/libinterp/template-inst/Array-tc.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/libinterp/template-inst/Array-tc.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -30,7 +30,8 @@
 #include "Array.cc"
 
 #include "ov.h"
-#include "ov-classdef.h"
+#include "cdef-class.h"
+#include "cdef-object.h"
 
 #include "oct-sort.cc"
 
@@ -53,5 +54,5 @@
 NO_INSTANTIATE_ARRAY_SORT (octave_value *);
 INSTANTIATE_ARRAY (octave_value *, OCTINTERP_API);
 
-NO_INSTANTIATE_ARRAY_SORT (cdef_object);
-INSTANTIATE_ARRAY (cdef_object, OCTINTERP_API);
+NO_INSTANTIATE_ARRAY_SORT (octave::cdef_object);
+INSTANTIATE_ARRAY (octave::cdef_object, OCTINTERP_API);
--- a/liboctave/array/Array.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/Array.h	Fri Jul 12 12:14:43 2019 -0400
@@ -103,8 +103,8 @@
 //!
 //! ### size_type
 //!
-//! Array::size_type is `octave_idx_type` which is a typedef for `int`
-//! or `long int`, depending whether Octave was configured for 64-bit
+//! Array::size_type is 'octave_idx_type' which is a typedef for 'int'
+//! or 'long int', depending whether Octave was configured for 64-bit
 //! indexing.
 //!
 //! This is a signed integer which may cause problems when mixed with
@@ -334,34 +334,6 @@
   void clear (octave_idx_type r, octave_idx_type c)
   { clear (dim_vector (r, c)); }
 
-  // Number of elements in the array.  These are all synonyms.
-  //@{
-  //! Number of elements in the array.
-  //! Synonymous with numel().
-  //! @note This method is deprecated in favour of numel().
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type capacity (void) const { return numel (); }
-
-  //! Number of elements in the array.
-  //!
-  //! Synonymous with numel().
-  //! @note This method is deprecated in favour of numel().
-  //!
-  //! @note
-  //! This is @em not the same as @c %length() at the Octave interpreter.
-  //! At the Octave interpreter, the function @c %length() returns the
-  //! length of the greatest dimension.  This method returns the total
-  //! number of elements.
-
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type length (void) const { return numel (); }
-
-  //! Number of elements in the array.
-  //! Synonymous with numel().
-  //! @note This method is deprecated in favour of numel().
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type nelem (void) const { return numel (); }
-
   //! Number of elements in the array.
   octave_idx_type numel (void) const { return slice_len; }
   //@}
@@ -426,7 +398,7 @@
   //! Dimensions beyond the Array number of dimensions return 1 as
   //! those are implicit singleton dimensions.
   //!
-  //! Equivalent to Octave's `size (A, DIM)`
+  //! Equivalent to Octave's 'size (A, DIM)'
 
   size_type size (const size_type d) const
   {
@@ -558,22 +530,10 @@
 
   bool issquare (void) const { return (dim1 () == dim2 ()); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'issquare' instead")
-  bool is_square (void) const
-  { return issquare (); }
-
   bool isempty (void) const { return numel () == 0; }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isempty' instead")
-  bool is_empty (void) const
-  { return isempty (); }
-
   bool isvector (void) const { return dimensions.isvector (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isvector' instead")
-  bool is_vector (void) const
-  { return isvector (); }
-
   bool is_nd_vector (void) const { return dimensions.is_nd_vector (); }
 
   Array<T> transpose (void) const;
@@ -712,10 +672,6 @@
   //! Ordering is auto-detected or can be specified.
   sortmode issorted (sortmode mode = UNSORTED) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
-  sortmode is_sorted (sortmode mode = UNSORTED) const
-  { return issorted (mode); }
-
   //! Sort by rows returns only indices.
   Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;
 
--- a/liboctave/array/CColVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CColVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/CDiagMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CDiagMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -316,15 +316,35 @@
   ComplexDiagMatrix retval (r, c);
 
   info = 0;
-  for (octave_idx_type i = 0; i < length (); i++)
+  octave_idx_type len = r;        // alias for readability
+  octave_idx_type z_count  = 0;   // zeros
+  octave_idx_type nz_count = 0;   // non-zeros
+  for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) == 0.0)
+      if (xelem (i, i) == 0.0)
         {
-          info = -1;
-          return *this;
+          z_count++;
+          if (nz_count > 0)
+            break;
         }
       else
-        retval.elem (i, i) = 1.0 / elem (i, i);
+        {
+          nz_count++;
+          if (z_count > 0)
+            break;
+          retval.elem (i, i) = 1.0 / xelem (i, i);
+        }
+    }
+  if (nz_count == 0)
+    {
+      (*current_liboctave_error_handler)
+        ("inverse of the null matrix not defined");
+    }
+  else if (z_count > 0)
+    {
+      info = -1;
+      element_type *data = retval.fortran_vec ();
+      std::fill (data, data + len, octave::numeric_limits<double>::Inf ());
     }
 
   return retval;
--- a/liboctave/array/CDiagMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CDiagMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -45,7 +45,13 @@
   typedef Complex complex_elt_type;
   typedef Complex element_type;
 
-  ComplexDiagMatrix (void) : MDiagArray2<Complex> () { }
+  ComplexDiagMatrix (void) = default;
+
+  ComplexDiagMatrix (const ComplexDiagMatrix& a) = default;
+
+  ComplexDiagMatrix& operator = (const ComplexDiagMatrix& a) = default;
+
+  ~ComplexDiagMatrix (void) = default;
 
   ComplexDiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<Complex> (r, c) { }
@@ -68,19 +74,10 @@
   ComplexDiagMatrix (const MDiagArray2<Complex>& a)
     : MDiagArray2<Complex> (a) { }
 
-  ComplexDiagMatrix (const ComplexDiagMatrix& a)
-    : MDiagArray2<Complex> (a) { }
-
   template <typename U>
   ComplexDiagMatrix (const DiagArray2<U>& a)
     : MDiagArray2<Complex> (a) { }
 
-  ComplexDiagMatrix& operator = (const ComplexDiagMatrix& a)
-  {
-    MDiagArray2<Complex>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const ComplexDiagMatrix& a) const;
   bool operator != (const ComplexDiagMatrix& a) const;
 
--- a/liboctave/array/CMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -44,7 +44,6 @@
 #include "dDiagMatrix.h"
 #include "dMatrix.h"
 #include "dRowVector.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
--- a/liboctave/array/CMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -57,7 +57,13 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  ComplexMatrix (void) : ComplexNDArray () { }
+  ComplexMatrix (void) = default;
+
+  ComplexMatrix (const ComplexMatrix& a) = default;
+
+  ComplexMatrix& operator = (const ComplexMatrix& a) = default;
+
+  ~ComplexMatrix (void) = default;
 
   ComplexMatrix (octave_idx_type r, octave_idx_type c)
     : ComplexNDArray (dim_vector (r, c)) { }
@@ -70,8 +76,6 @@
   ComplexMatrix (const dim_vector& dv, const Complex& val)
     : ComplexNDArray (dv.redim (2), val) { }
 
-  ComplexMatrix (const ComplexMatrix& a) : ComplexNDArray (a) { }
-
   template <typename U>
   ComplexMatrix (const MArray<U>& a) : ComplexNDArray (a.as_matrix ()) { }
 
@@ -111,10 +115,6 @@
 
   bool ishermitian (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'ishermitian' instead")
-  bool is_hermitian (void) const
-  { return ishermitian (); }
-
   // destructive insert/delete/reorder operations
 
   ComplexMatrix& insert (const Matrix& a, octave_idx_type r, octave_idx_type c);
--- a/liboctave/array/CNDArray.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CNDArray.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,6 @@
 #include "Array-util.h"
 #include "CNDArray.h"
 #include "f77-fcn.h"
-#include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "mx-base.h"
--- a/liboctave/array/CRowVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CRowVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/CSparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CSparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -49,7 +49,6 @@
 #include "CSparse.h"
 #include "boolSparse.h"
 #include "dSparse.h"
-#include "functor.h"
 #include "oct-spparms.h"
 #include "sparse-lu.h"
 #include "oct-sparse.h"
@@ -985,6 +984,12 @@
 SparseComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info,
                               double& rcond, bool, bool calc_cond) const
 {
+  if (nnz () == 0)
+    {
+      (*current_liboctave_error_handler)
+        ("inverse of the null matrix not defined");
+    }
+
   int typ = mattype.type (false);
   SparseComplexMatrix ret;
 
@@ -1035,6 +1040,18 @@
                                                              Qinit, Matrix (),
                                                              false, false);
           rcond = fact.rcond ();
+          if (rcond == 0.0)
+            {
+              // Return all Inf matrix with sparsity pattern of input.
+              octave_idx_type nz = nnz ();
+              ret = SparseComplexMatrix (rows (), cols (), nz);
+              std::fill (ret.xdata (), ret.xdata () + nz,
+                         octave::numeric_limits<double>::Inf ());
+              std::copy_n (ridx (), nz, ret.xridx ());
+              std::copy_n (cidx (), cols () + 1, ret.xcidx ());
+
+              return ret;
+            }
           double rcond2;
           SparseComplexMatrix InvL = fact.L ().transpose ().
                                      tinverse (tmp_typ, info, rcond2,
@@ -5707,7 +5724,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -5727,8 +5743,6 @@
           A->xtype = CHOLMOD_COMPLEX;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_dense Bstore;
           cholmod_dense *B = &Bstore;
@@ -5740,8 +5754,6 @@
           B->xtype = CHOLMOD_REAL;
 
           B->x = const_cast<double *>(b.fortran_vec ());
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -5959,7 +5971,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -5979,8 +5990,6 @@
           A->xtype = CHOLMOD_COMPLEX;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_sparse Bstore;
           cholmod_sparse *B = &Bstore;
@@ -6002,8 +6011,6 @@
           B->xtype = CHOLMOD_REAL;
 
           B->x = b.data ();
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -6262,7 +6269,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -6282,8 +6288,6 @@
           A->xtype = CHOLMOD_COMPLEX;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_dense Bstore;
           cholmod_dense *B = &Bstore;
@@ -6295,8 +6299,6 @@
           B->xtype = CHOLMOD_COMPLEX;
 
           B->x = const_cast<Complex *>(b.fortran_vec ());
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -6493,7 +6495,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -6513,8 +6514,6 @@
           A->xtype = CHOLMOD_COMPLEX;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_sparse Bstore;
           cholmod_sparse *B = &Bstore;
@@ -6536,8 +6535,6 @@
           B->xtype = CHOLMOD_COMPLEX;
 
           B->x = b.data ();
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
--- a/liboctave/array/CSparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/CSparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -113,10 +113,6 @@
 
   bool ishermitian (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'ishermitian' instead")
-  bool is_hermitian (void) const
-  { return ishermitian (); }
-
   SparseComplexMatrix max (int dim = -1) const;
   SparseComplexMatrix max (Array<octave_idx_type>& index, int dim = -1) const;
   SparseComplexMatrix min (int dim = -1) const;
--- a/liboctave/array/MatrixType.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/MatrixType.h	Fri Jul 12 12:14:43 2019 -0400
@@ -110,31 +110,15 @@
   bool isdiag (void) const
   { return (typ == Diagonal || typ == Permuted_Diagonal); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isdiag' instead")
-  bool is_diagonal (void) const
-  { return isdiag (); }
-
   bool istriu (void) const
   { return (typ == Upper || typ == Permuted_Upper); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'istriu' instead")
-  bool is_upper_triangular (void) const
-  { return istriu (); }
-
   bool istril (void) const
   { return (typ == Lower || typ == Permuted_Lower); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'istril' instead")
-  bool is_lower_triangular (void) const
-  { return istril (); }
-
   bool isbanded (void) const
   { return (typ == Banded || typ == Banded_Hermitian); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isbanded' instead")
-  bool is_banded (void) const
-  { return isbanded (); }
-
   bool is_tridiagonal (void) const
   { return (typ == Tridiagonal || typ == Tridiagonal_Hermitian); }
 
@@ -144,10 +128,6 @@
             || typ == Hermitian);
   }
 
-  OCTAVE_DEPRECATED (4.4, "use 'ishermitian' instead")
-  bool is_hermitian (void) const
-  { return ishermitian (); }
-
   bool is_rectangular (void) const { return (typ == Rectangular); }
 
   bool is_known (void) const { return (typ != Unknown); }
--- a/liboctave/array/PermMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/PermMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -35,14 +35,18 @@
 {
 public:
 
-  PermMatrix (void) : Array<octave_idx_type> () { }
+  PermMatrix (void) = default;
+
+  PermMatrix (const PermMatrix& m) = default;
+
+  PermMatrix& operator = (const PermMatrix& m) = default;
+
+  ~PermMatrix (void) = default;
 
   PermMatrix (octave_idx_type n);
 
   PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check = true);
 
-  PermMatrix (const PermMatrix& m) : Array<octave_idx_type> (m) { }
-
   PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n = 0);
 
   octave_idx_type dim1 (void) const
@@ -60,9 +64,6 @@
   octave_idx_type length (void) const
   { return perm_length (); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type nelem (void) const { return numel (); }
-
   octave_idx_type numel (void) const { return dim1 () * dim2 (); }
 
   size_t byte_size (void) const
--- a/liboctave/array/Range.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/Range.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,9 +39,11 @@
   Range (void)
     : rng_base (0), rng_limit (0), rng_inc (0), rng_numel (0), cache (1, 0) { }
 
-  Range (const Range& r)
-    : rng_base (r.rng_base), rng_limit (r.rng_limit), rng_inc (r.rng_inc),
-      rng_numel (r.rng_numel), cache (r.cache) { }
+  Range (const Range& r) = default;
+
+  Range& operator = (const Range& r) = default;
+
+  ~Range (void) = default;
 
   Range (double b, double l)
     : rng_base (b), rng_limit (l), rng_inc (1),
@@ -80,9 +82,6 @@
 
   octave_idx_type numel (void) const { return rng_numel; }
 
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type nelem (void) const { return numel (); }
-
   octave_idx_type rows (void) const { return 1; }
 
   octave_idx_type cols (void) const { return numel (); }
@@ -90,10 +89,6 @@
 
   bool isempty (void) const { return numel () == 0; }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isempty' instead")
-  bool is_empty (void) const
-  { return isempty (); }
-
   bool all_elements_are_ints (void) const;
 
   Matrix matrix_value (void) const;
@@ -112,10 +107,6 @@
 
   sortmode issorted (sortmode mode = ASCENDING) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
-  sortmode is_sorted (sortmode mode = ASCENDING) const
-  { return issorted (mode); }
-
   octave_idx_type nnz (void) const;
 
   // Support for single-index subscripting, without generating matrix cache.
--- a/liboctave/array/Sparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/Sparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -233,11 +233,6 @@
   //! This may differ from the actual number of elements, see nnz().
   octave_idx_type nzmax (void) const { return rep->length (); }
 
-  //! Amount of storage for nonzero elements.
-  //! Synonymous with nzmax().
-  OCTAVE_DEPRECATED (4.4, "use 'nzmax' instead")
-  octave_idx_type capacity (void) const { return nzmax (); }
-
   //! Actual number of nonzero terms.
   octave_idx_type nnz (void) const { return rep->nnz (); }
 
@@ -248,12 +243,6 @@
     return dimensions.safe_numel ();
   }
 
-  OCTAVE_DEPRECATED (4.4, "use 'nzmax' instead")
-  octave_idx_type nelem (void) const { return nzmax (); }
-
-  OCTAVE_DEPRECATED (4.4, "use 'numel' instead")
-  octave_idx_type length (void) const { return numel (); }
-
   octave_idx_type dim1 (void) const { return dimensions(0); }
   octave_idx_type dim2 (void) const { return dimensions(1); }
 
@@ -473,16 +462,8 @@
 
   bool issquare (void) const { return (dim1 () == dim2 ()); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'issquare' instead")
-  bool is_square (void) const
-  { return issquare (); }
-
   bool isempty (void) const { return (rows () < 1 || cols () < 1); }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isempty' instead")
-  bool is_empty (void) const
-  { return isempty (); }
-
   Sparse<T> transpose (void) const;
 
   T * data (void) { make_unique (); return rep->d; }
--- a/liboctave/array/boolMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/boolMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -37,7 +37,13 @@
 {
 public:
 
-  boolMatrix (void) : boolNDArray () { }
+  boolMatrix (void) = default;
+
+  boolMatrix (const boolMatrix& a) = default;
+
+  boolMatrix& operator = (const boolMatrix& a) = default;
+
+  ~boolMatrix (void) = default;
 
   boolMatrix (octave_idx_type r, octave_idx_type c)
     : boolNDArray (dim_vector (r, c)) { }
@@ -52,8 +58,6 @@
 
   boolMatrix (const Array<bool>& a) : boolNDArray (a.as_matrix ()) { }
 
-  boolMatrix (const boolMatrix& a) : boolNDArray (a) { }
-
   bool operator == (const boolMatrix& a) const;
   bool operator != (const boolMatrix& a) const;
 
--- a/liboctave/array/boolNDArray.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/boolNDArray.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -67,21 +67,6 @@
   return do_mx_red_op<bool, bool> (*this, dim, mx_inline_any);
 }
 
-NDArray
-boolNDArray::sum (int dim) const
-{
-  // NOTE: going via octave_idx_type is typically faster even though it
-  // requires a conversion.
-  return do_mx_red_op<octave_idx_type, bool> (*this, dim, mx_inline_count);
-}
-
-NDArray
-boolNDArray::cumsum (int dim) const
-{
-  // In this case, it's better to sum directly to doubles.
-  return do_mx_cum_op<double , bool> (*this, dim, mx_inline_cumcount);
-}
-
 boolNDArray
 boolNDArray::concat (const boolNDArray& rb,
                      const Array<octave_idx_type>& ra_idx)
--- a/liboctave/array/boolNDArray.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/boolNDArray.h	Fri Jul 12 12:14:43 2019 -0400
@@ -68,12 +68,6 @@
   boolNDArray all (int dim = -1) const;
   boolNDArray any (int dim = -1) const;
 
-  OCTAVE_DEPRECATED (4.4, "convert to and operate on numeric type instead")
-  NDArray sum (int dim = -1) const;
-
-  OCTAVE_DEPRECATED (4.4, "convert to and operate on numeric type instead")
-  NDArray cumsum (int dim = -1) const;
-
   boolNDArray concat (const boolNDArray& rb,
                       const Array<octave_idx_type>& ra_idx);
 
--- a/liboctave/array/chMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/chMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -42,7 +42,13 @@
 
 public:
 
-  charMatrix (void) : charNDArray () { }
+  charMatrix (void) = default;
+
+  charMatrix (const charMatrix& a) = default;
+
+  charMatrix& operator = (const charMatrix& a) = default;
+
+  ~charMatrix (void) = default;
 
   charMatrix (octave_idx_type r, octave_idx_type c)
     : charNDArray (dim_vector (r, c)) { }
@@ -57,8 +63,6 @@
 
   charMatrix (const Array<char>& a) : charNDArray (a.as_matrix ()) { }
 
-  charMatrix (const charMatrix& a) : charNDArray (a) { }
-
   charMatrix (char c) : charNDArray (c) { }
 
   charMatrix (const char *s) : charNDArray (s) { }
--- a/liboctave/array/dColVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dColVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/dDiagMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dDiagMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -233,19 +233,41 @@
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
-  octave_idx_type len = length ();
   if (r != c)
     (*current_liboctave_error_handler) ("inverse requires square matrix");
 
   DiagMatrix retval (r, c);
 
   info = 0;
+  octave_idx_type len = r;        // alias for readability
+  octave_idx_type z_count  = 0;   // zeros
+  octave_idx_type nz_count = 0;   // non-zeros
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) == 0.0)
-        retval.elem (i, i) = octave::numeric_limits<double>::Inf ();
+      if (xelem (i, i) == 0.0)
+        {
+          z_count++;
+          if (nz_count > 0)
+            break;
+        }
       else
-        retval.elem (i, i) = 1.0 / elem (i, i);
+        {
+          nz_count++;
+          if (z_count > 0)
+            break;
+          retval.elem (i, i) = 1.0 / xelem (i, i);
+        }
+    }
+  if (nz_count == 0)
+    {
+      (*current_liboctave_error_handler)
+        ("inverse of the null matrix not defined");
+    }
+  else if (z_count > 0)
+    {
+      info = -1;
+      element_type *data = retval.fortran_vec ();
+      std::fill (data, data + len, octave::numeric_limits<double>::Inf ());
     }
 
   return retval;
--- a/liboctave/array/dDiagMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dDiagMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,7 +39,13 @@
 
   typedef Matrix full_matrix_type;
 
-  DiagMatrix (void) : MDiagArray2<double> () { }
+  DiagMatrix (void) = default;
+
+  DiagMatrix (const DiagMatrix& a) = default;
+
+  DiagMatrix& operator = (const DiagMatrix& a) = default;
+
+  ~DiagMatrix (void) = default;
 
   DiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<double> (r, c) { }
@@ -47,8 +53,6 @@
   DiagMatrix (octave_idx_type r, octave_idx_type c, double val)
     : MDiagArray2<double> (r, c, val) { }
 
-  DiagMatrix (const DiagMatrix& a) : MDiagArray2<double> (a) { }
-
   DiagMatrix (const MDiagArray2<double>& a) : MDiagArray2<double> (a) { }
 
   template <typename U>
@@ -59,12 +63,6 @@
   DiagMatrix (const Array<double>& a, octave_idx_type r, octave_idx_type c)
     : MDiagArray2<double> (a, r, c) { }
 
-  DiagMatrix& operator = (const DiagMatrix& a)
-  {
-    MDiagArray2<double>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const DiagMatrix& a) const;
   bool operator != (const DiagMatrix& a) const;
 
--- a/liboctave/array/dMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -44,7 +44,6 @@
 #include "dDiagMatrix.h"
 #include "dMatrix.h"
 #include "dRowVector.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
--- a/liboctave/array/dMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -56,7 +56,13 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  Matrix (void) : NDArray () { }
+  Matrix (void) = default;
+
+  Matrix (const Matrix& a) = default;
+
+  Matrix& operator = (const Matrix& a) = default;
+
+  ~Matrix (void) = default;
 
   Matrix (octave_idx_type r, octave_idx_type c)
     : NDArray (dim_vector (r, c)) { }
@@ -69,8 +75,6 @@
   Matrix (const dim_vector& dv, double val)
     : NDArray (dv.redim (2), val) { }
 
-  Matrix (const Matrix& a) : NDArray (a) { }
-
   template <typename U>
   Matrix (const MArray<U>& a) : NDArray (a.as_matrix ()) { }
 
@@ -98,10 +102,6 @@
 
   bool issymmetric (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'issymmetric' instead")
-  bool is_symmetric (void) const
-  { return issymmetric (); }
-
   // destructive insert/delete/reorder operations
 
   Matrix& insert (const Matrix& a, octave_idx_type r, octave_idx_type c);
--- a/liboctave/array/dNDArray.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dNDArray.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,6 @@
 #include "Array-util.h"
 #include "dNDArray.h"
 #include "f77-fcn.h"
-#include "functor.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
--- a/liboctave/array/dRowVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dRowVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/dSparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dSparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -40,7 +40,6 @@
 #include "CSparse.h"
 #include "boolSparse.h"
 #include "dSparse.h"
-#include "functor.h"
 #include "oct-spparms.h"
 #include "sparse-lu.h"
 #include "MatrixType.h"
@@ -928,6 +927,12 @@
 SparseMatrix::inverse (MatrixType& mattype, octave_idx_type& info,
                        double& rcond, bool, bool calc_cond) const
 {
+  if (nnz () == 0)
+    {
+      (*current_liboctave_error_handler)
+        ("inverse of the null matrix not defined");
+    }
+
   int typ = mattype.type (false);
   SparseMatrix ret;
 
@@ -977,6 +982,19 @@
                                                       Qinit, Matrix (),
                                                       false, false);
           rcond = fact.rcond ();
+          if (rcond == 0.0)
+            {
+              // Return all Inf matrix with sparsity pattern of input.
+              octave_idx_type nz = nnz ();
+              ret = SparseMatrix (rows (), cols (), nz);
+              std::fill (ret.xdata (), ret.xdata () + nz,
+                         octave::numeric_limits<double>::Inf ());
+              std::copy_n (ridx (), nz, ret.xridx ());
+              std::copy_n (cidx (), cols () + 1, ret.xcidx ());
+
+              return ret;
+            }
+
           double rcond2;
           SparseMatrix InvL = fact.L ().transpose ().tinverse (tmp_typ,
                               info, rcond2, true, false);
@@ -5751,7 +5769,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -5771,8 +5788,6 @@
           A->xtype = CHOLMOD_REAL;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_dense Bstore;
           cholmod_dense *B = &Bstore;
@@ -5784,8 +5799,6 @@
           B->xtype = CHOLMOD_REAL;
 
           B->x = const_cast<double *>(b.fortran_vec ());
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -5976,7 +5989,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -5996,8 +6008,6 @@
           A->xtype = CHOLMOD_REAL;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_sparse Bstore;
           cholmod_sparse *B = &Bstore;
@@ -6019,8 +6029,6 @@
           B->xtype = CHOLMOD_REAL;
 
           B->x = b.data ();
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -6249,7 +6257,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -6269,8 +6276,6 @@
           A->xtype = CHOLMOD_REAL;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_dense Bstore;
           cholmod_dense *B = &Bstore;
@@ -6282,8 +6287,6 @@
           B->xtype = CHOLMOD_COMPLEX;
 
           B->x = const_cast<Complex *>(b.fortran_vec ());
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -6494,7 +6497,6 @@
 
           cholmod_sparse Astore;
           cholmod_sparse *A = &Astore;
-          double dummy;
           A->nrow = nr;
           A->ncol = nc;
 
@@ -6514,8 +6516,6 @@
           A->xtype = CHOLMOD_REAL;
 
           A->x = data ();
-          if (A->x == nullptr)
-            A->x = &dummy;
 
           cholmod_sparse Bstore;
           cholmod_sparse *B = &Bstore;
@@ -6537,8 +6537,6 @@
           B->xtype = CHOLMOD_COMPLEX;
 
           B->x = b.data ();
-          if (B->x == nullptr)
-            B->x = &dummy;
 
           cholmod_factor *L;
           BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
--- a/liboctave/array/dSparse.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dSparse.h	Fri Jul 12 12:14:43 2019 -0400
@@ -102,10 +102,6 @@
 
   bool issymmetric (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'issymmetric' instead")
-  bool is_symmetric (void) const
-  { return issymmetric (); }
-
   SparseMatrix max (int dim = -1) const;
   SparseMatrix max (Array<octave_idx_type>& index, int dim = -1) const;
   SparseMatrix min (int dim = -1) const;
--- a/liboctave/array/dim-vector.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/dim-vector.h	Fri Jul 12 12:14:43 2019 -0400
@@ -424,10 +424,6 @@
     return (ndims () == 2 && (xelem (0) == 1 || xelem (1) == 1));
   }
 
-  OCTAVE_DEPRECATED (4.4, "use 'isvector' instead")
-  bool is_vector (void) const
-  { return isvector (); }
-
   bool is_nd_vector (void) const
   {
     int num_non_one = 0;
--- a/liboctave/array/fCColVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCColVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/fCDiagMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCDiagMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -45,7 +45,13 @@
   typedef FloatComplex complex_elt_type;
   typedef FloatComplex element_type;
 
-  FloatComplexDiagMatrix (void) : MDiagArray2<FloatComplex> () { }
+  FloatComplexDiagMatrix (void) = default;
+
+  FloatComplexDiagMatrix (const FloatComplexDiagMatrix& a) = default;
+
+  FloatComplexDiagMatrix& operator = (const FloatComplexDiagMatrix& a) = default;
+
+  ~FloatComplexDiagMatrix (void) = default;
 
   FloatComplexDiagMatrix (octave_idx_type r,
                           octave_idx_type c)
@@ -70,19 +76,10 @@
   FloatComplexDiagMatrix (const MDiagArray2<FloatComplex>& a)
     : MDiagArray2<FloatComplex> (a) { }
 
-  FloatComplexDiagMatrix (const FloatComplexDiagMatrix& a)
-    : MDiagArray2<FloatComplex> (a) { }
-
   template <typename U>
   FloatComplexDiagMatrix (const DiagArray2<U>& a)
     : MDiagArray2<FloatComplex> (a) { }
 
-  FloatComplexDiagMatrix& operator = (const FloatComplexDiagMatrix& a)
-  {
-    MDiagArray2<FloatComplex>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const FloatComplexDiagMatrix& a) const;
   bool operator != (const FloatComplexDiagMatrix& a) const;
 
--- a/liboctave/array/fCMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -42,7 +42,6 @@
 #include "fCMatrix.h"
 #include "fCNDArray.h"
 #include "fCRowVector.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
--- a/liboctave/array/fCMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -57,7 +57,13 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatComplexMatrix (void) : FloatComplexNDArray () { }
+  FloatComplexMatrix (void) = default;
+
+  FloatComplexMatrix (const FloatComplexMatrix& a) = default;
+
+  FloatComplexMatrix& operator = (const FloatComplexMatrix& a) = default;
+
+  ~FloatComplexMatrix (void) = default;
 
   FloatComplexMatrix (octave_idx_type r, octave_idx_type c)
     : FloatComplexNDArray (dim_vector (r, c)) { }
@@ -72,9 +78,6 @@
   FloatComplexMatrix (const dim_vector& dv, const FloatComplex& val)
     : FloatComplexNDArray (dv.redim (2), val) { }
 
-  FloatComplexMatrix (const FloatComplexMatrix& a)
-    : FloatComplexNDArray (a) { }
-
   template <typename U>
   FloatComplexMatrix (const MArray<U>& a)
     : FloatComplexNDArray (a.as_matrix ()) { }
@@ -116,10 +119,6 @@
 
   bool ishermitian (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'ishermitian' instead")
-  bool is_hermitian (void) const
-  { return ishermitian (); }
-
   // destructive insert/delete/reorder operations
 
   FloatComplexMatrix& insert (const FloatMatrix& a,
--- a/liboctave/array/fCNDArray.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCNDArray.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,6 @@
 #include "Array-util.h"
 #include "f77-fcn.h"
 #include "fCNDArray.h"
-#include "functor.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "mx-base.h"
--- a/liboctave/array/fCRowVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fCRowVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/fColVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fColVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/fDiagMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fDiagMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,7 +39,13 @@
 
   typedef FloatMatrix full_matrix_type;
 
-  FloatDiagMatrix (void) : MDiagArray2<float> () { }
+  FloatDiagMatrix (void) = default;
+
+  FloatDiagMatrix (const FloatDiagMatrix& a) = default;
+
+  FloatDiagMatrix& operator = (const FloatDiagMatrix& a) = default;
+
+  ~FloatDiagMatrix (void) = default;
 
   FloatDiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<float> (r, c) { }
@@ -47,8 +53,6 @@
   FloatDiagMatrix (octave_idx_type r, octave_idx_type c, float val)
     : MDiagArray2<float> (r, c, val) { }
 
-  FloatDiagMatrix (const FloatDiagMatrix& a) : MDiagArray2<float> (a) { }
-
   FloatDiagMatrix (const MDiagArray2<float>& a) : MDiagArray2<float> (a) { }
 
   template <typename U>
@@ -59,12 +63,6 @@
   FloatDiagMatrix (const Array<float>& a, octave_idx_type r, octave_idx_type c)
     : MDiagArray2<float> (a, r, c) { }
 
-  FloatDiagMatrix& operator = (const FloatDiagMatrix& a)
-  {
-    MDiagArray2<float>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const FloatDiagMatrix& a) const;
   bool operator != (const FloatDiagMatrix& a) const;
 
--- a/liboctave/array/fMatrix.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fMatrix.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -46,7 +46,6 @@
 #include "fMatrix.h"
 #include "fNDArray.h"
 #include "fRowVector.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
--- a/liboctave/array/fMatrix.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fMatrix.h	Fri Jul 12 12:14:43 2019 -0400
@@ -56,7 +56,13 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatMatrix (void) : FloatNDArray () { }
+  FloatMatrix (void) = default;
+
+  FloatMatrix (const FloatMatrix& a) = default;
+
+  FloatMatrix& operator = (const FloatMatrix& a) = default;
+
+  ~FloatMatrix (void) = default;
 
   FloatMatrix (octave_idx_type r, octave_idx_type c)
     : FloatNDArray (dim_vector (r, c)) { }
@@ -69,8 +75,6 @@
   FloatMatrix (const dim_vector& dv, float val)
     : FloatNDArray (dv.redim (2), val) { }
 
-  FloatMatrix (const FloatMatrix& a) : FloatNDArray (a) { }
-
   template <typename U>
   FloatMatrix (const MArray<U>& a) : FloatNDArray (a.as_matrix ()) { }
 
@@ -98,10 +102,6 @@
 
   bool issymmetric (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'issymmetric' instead")
-  bool is_symmetric (void) const
-  { return issymmetric (); }
-
   // destructive insert/delete/reorder operations
 
   FloatMatrix& insert (const FloatMatrix& a,
--- a/liboctave/array/fNDArray.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fNDArray.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,7 +32,6 @@
 #include "Array-util.h"
 #include "f77-fcn.h"
 #include "fNDArray.h"
-#include "functor.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
--- a/liboctave/array/fRowVector.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/fRowVector.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,6 @@
 #include <ostream>
 
 #include "Array-util.h"
-#include "functor.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
 #include "mx-base.h"
--- a/liboctave/array/idx-vector.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/idx-vector.h	Fri Jul 12 12:14:43 2019 -0400
@@ -1023,10 +1023,6 @@
 
   bool isvector (void) const;
 
-  OCTAVE_DEPRECATED (4.4, "use 'isvector' instead")
-  bool is_vector (void) const
-  { return isvector (); }
-
   // FIXME: these are here for compatibility.  They should be removed
   // when no longer in use.
 
--- a/liboctave/array/intNDArray.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/array/intNDArray.h	Fri Jul 12 12:14:43 2019 -0400
@@ -38,7 +38,13 @@
 
   using typename MArray<T>::element_type;
 
-  intNDArray (void) : MArray<T> () { }
+  intNDArray (void) = default;
+
+  intNDArray (const intNDArray<T>& a) = default;
+
+  intNDArray& operator = (const intNDArray<T>& a) = default;
+
+  ~intNDArray (void) = default;
 
   intNDArray (T val) : MArray<T> (dim_vector (1, 1), val) { }
 
@@ -56,12 +62,6 @@
   template <typename U>
   intNDArray (const intNDArray<U>& a) : MArray<T> (a) { }
 
-  intNDArray& operator = (const intNDArray<T>& a)
-  {
-    MArray<T>::operator = (a);
-    return *this;
-  }
-
   boolNDArray operator ! (void) const;
 
   bool any_element_is_nan (void) const { return false; }
--- a/liboctave/external/odepack/sintdy.f	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/external/odepack/sintdy.f	Fri Jul 12 12:14:43 2019 -0400
@@ -97,14 +97,14 @@
       RETURN
 C
  80   CALL XERRWD('SINTDY-  K (=I1) illegal      ',
-     1     30, 51, 0, 1, K, 0, 0, 0.0E0, 0.0E0)
+     1     30, 51, 0, 1, K, 0, 0, 0.0D0, 0.0D0)
       IFLAG = -1
       RETURN
  90   CALL XERRWD('SINTDY-  T (=R1) illegal      ',
-     1     30, 52, 0, 0, 0, 0, 1, T, 0.0E0)
+     1     30, 52, 0, 0, 0, 0, 1, DBLE (T), 0.0D0)
       CALL XERRWD(
      1   '      T not in interval TCUR - HU (= R1) to TCUR (=R2)      ',
-     1    60, 52, 0, 0, 0, 0, 2, TP, TN)
+     1    60, 52, 0, 0, 0, 0, 2, DBLE (TP), TN)
       IFLAG = -2
       RETURN
 C----------------------- END OF SUBROUTINE SINTDY ----------------------
--- a/liboctave/external/odepack/slsode.f	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/external/odepack/slsode.f	Fri Jul 12 12:14:43 2019 -0400
@@ -1508,17 +1508,17 @@
       NHNIL = NHNIL + 1
       IF (NHNIL .GT. MXHNIL) GO TO 290
       CALL XERRWD('SLSODE-  Warning..internal T (=R1) and H (=R2) are',
-     1     50, 101, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 101, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD(
      1  '      such that in the machine, T + H = T on the next step  ',
-     1     60, 101, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     60, 101, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      (H = step size). Solver will continue anyway',
-     1     50, 101, 0, 0, 0, 0, 2, TN, H)
+     1     50, 101, 0, 0, 0, 0, 2, DBLE (TN), DBLE (H))
       IF (NHNIL .LT. MXHNIL) GO TO 290
       CALL XERRWD('SLSODE-  Above warning has been issued I1 times.  ',
-     1     50, 102, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 102, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      It will not be issued again for this problem',
-     1     50, 102, 0, 1, MXHNIL, 0, 0, 0.0E0, 0.0E0)
+     1     50, 102, 0, 1, MXHNIL, 0, 0, 0.0D0, 0.0D0)
  290  CONTINUE
 C-----------------------------------------------------------------------
 C  CALL SSTODE(NEQ,Y,YH,NYH,YH,EWT,SAVF,ACOR,WM,IWM,F,JAC,SPREPJ,SSOLSY)
@@ -1591,39 +1591,39 @@
 C-----------------------------------------------------------------------
 C The maximum number of steps was taken before reaching TOUT. ----------
  500  CALL XERRWD('SLSODE-  At current T (=R1), MXSTEP (=I1) steps   ',
-     1 50, 201, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1 50, 201, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      taken on this call before reaching TOUT     ',
-     1     50, 201, 0, 1, MXSTEP, 0, 1, TN, 0.0E0)
+     1     50, 201, 0, 1, MXSTEP, 0, 1, DBLE (TN), 0.0D0)
       ISTATE = -1
       GO TO 580
 C EWT(I) .LE. 0.0 for some I (not at start of problem). ----------------
  510  EWTI = RWORK(LEWT+I-1)
       CALL XERRWD('SLSODE-  At T (=R1), EWT(I1) has become R2 .LE. 0.',
-     1 50, 202, 0, 1, I, 0, 2, TN, EWTI)
+     1 50, 202, 0, 1, I, 0, 2, DBLE (TN), DBLE (EWTI))
       ISTATE = -6
       GO TO 580
 C Too much accuracy requested for machine precision. -------------------
  520  CALL XERRWD('SLSODE-  At T (=R1), too much accuracy requested  ',
-     1     50, 203, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 203, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      for precision of machine..  see TOLSF (=R2) ',
-     1     50, 203, 0, 0, 0, 0, 2, TN, TOLSF)
+     1     50, 203, 0, 0, 0, 0, 2, DBLE (TN), DBLE (TOLSF))
       RWORK(14) = TOLSF
       ISTATE = -2
       GO TO 580
 C KFLAG = -1.  Error test failed repeatedly or with ABS(H) = HMIN. -----
  530  CALL XERRWD('SLSODE-  At T(=R1) and step size H(=R2), the error',
-     1     50, 204, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 204, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      test failed repeatedly or with ABS(H) = HMIN',
-     1     50, 204, 0, 0, 0, 0, 2, TN, H)
+     1     50, 204, 0, 0, 0, 0, 2, DBLE (TN), DBLE (H))
       ISTATE = -4
       GO TO 560
 C KFLAG = -2.  Convergence failed repeatedly or with ABS(H) = HMIN. ----
  540  CALL XERRWD('SLSODE-  At T (=R1) and step size H (=R2), the    ',
-     1     50, 205, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 205, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      corrector convergence failed repeatedly     ',
-     1     50, 205, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 205, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD('      or with ABS(H) = HMIN   ',
-     1     30, 205, 0, 0, 0, 0, 2, TN, H)
+     1     30, 205, 0, 0, 0, 0, 2, DBLE (TN), DBLE (H))
       ISTATE = -5
 C Compute IMXER if relevant. -------------------------------------------
  560  BIG = 0.0E0
@@ -1656,105 +1656,105 @@
 C is a negative ISTATE, the run is aborted (apparent infinite loop).
 C-----------------------------------------------------------------------
  601  CALL XERRWD('SLSODE-  ISTATE (=I1) illegal ',
-     1     30, 1, 0, 1, ISTATE, 0, 0, 0.0E0, 0.0E0)
+     1     30, 1, 0, 1, ISTATE, 0, 0, 0.0D0, 0.0D0)
       IF (ISTATE .LT. 0) GO TO 800
       GO TO 700
  602  CALL XERRWD('SLSODE-  ITASK (=I1) illegal  ',
-     1     30, 2, 0, 1, ITASK, 0, 0, 0.0E0, 0.0E0)
+     1     30, 2, 0, 1, ITASK, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  603  CALL XERRWD('SLSODE-  ISTATE .GT. 1 but SLSODE not initialized ',
-     1     50, 3, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 3, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  604  CALL XERRWD('SLSODE-  NEQ (=I1) .LT. 1     ',
-     1     30, 4, 0, 1, NEQ(1), 0, 0, 0.0E0, 0.0E0)
+     1     30, 4, 0, 1, NEQ(1), 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  605  CALL XERRWD('SLSODE-  ISTATE = 3 and NEQ increased (I1 to I2)  ',
-     1     50, 5, 0, 2, N, NEQ(1), 0, 0.0E0, 0.0E0)
+     1     50, 5, 0, 2, N, NEQ(1), 0, 0.0D0, 0.0D0)
       GO TO 700
  606  CALL XERRWD('SLSODE-  ITOL (=I1) illegal   ',
-     1     30, 6, 0, 1, ITOL, 0, 0, 0.0E0, 0.0E0)
+     1     30, 6, 0, 1, ITOL, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  607  CALL XERRWD('SLSODE-  IOPT (=I1) illegal   ',
-     1     30, 7, 0, 1, IOPT, 0, 0, 0.0E0, 0.0E0)
+     1     30, 7, 0, 1, IOPT, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  608  CALL XERRWD('SLSODE-  MF (=I1) illegal     ',
-     1     30, 8, 0, 1, MF, 0, 0, 0.0E0, 0.0E0)
+     1     30, 8, 0, 1, MF, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  609  CALL XERRWD('SLSODE-  ML (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)',
-     1     50, 9, 0, 2, ML, NEQ(1), 0, 0.0E0, 0.0E0)
+     1     50, 9, 0, 2, ML, NEQ(1), 0, 0.0D0, 0.0D0)
       GO TO 700
  610  CALL XERRWD('SLSODE-  MU (=I1) illegal.. .LT.0 or .GE.NEQ (=I2)',
-     1     50, 10, 0, 2, MU, NEQ(1), 0, 0.0E0, 0.0E0)
+     1     50, 10, 0, 2, MU, NEQ(1), 0, 0.0D0, 0.0D0)
       GO TO 700
  611  CALL XERRWD('SLSODE-  MAXORD (=I1) .LT. 0  ',
-     1     30, 11, 0, 1, MAXORD, 0, 0, 0.0E0, 0.0E0)
+     1     30, 11, 0, 1, MAXORD, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  612  CALL XERRWD('SLSODE-  MXSTEP (=I1) .LT. 0  ',
-     1 30, 12, 0, 1, MXSTEP, 0, 0, 0.0E0, 0.0E0)
+     1 30, 12, 0, 1, MXSTEP, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  613  CALL XERRWD('SLSODE-  MXHNIL (=I1) .LT. 0  ',
-     1     30, 13, 0, 1, MXHNIL, 0, 0, 0.0E0, 0.0E0)
+     1     30, 13, 0, 1, MXHNIL, 0, 0, 0.0D0, 0.0D0)
       GO TO 700
  614  CALL XERRWD('SLSODE-  TOUT (=R1) behind T (=R2)      ',
-     1     40, 14, 0, 0, 0, 0, 2, TOUT, T)
+     1     40, 14, 0, 0, 0, 0, 2, DBLE (TOUT), DBLE (T))
       CALL XERRWD('      Integration direction is given by H0 (=R1)  ',
-     1     50, 14, 0, 0, 0, 0, 1, H0, 0.0E0)
+     1     50, 14, 0, 0, 0, 0, 1, DBLE (H0), 0.0D0)
       GO TO 700
  615  CALL XERRWD('SLSODE-  HMAX (=R1) .LT. 0.0  ',
-     1     30, 15, 0, 0, 0, 0, 1, HMAX, 0.0E0)
+     1     30, 15, 0, 0, 0, 0, 1, DBLE (HMAX), 0.0D0)
       GO TO 700
  616  CALL XERRWD('SLSODE-  HMIN (=R1) .LT. 0.0  ',
-     1     30, 16, 0, 0, 0, 0, 1, HMIN, 0.0E0)
+     1     30, 16, 0, 0, 0, 0, 1, DBLE (HMIN), 0.0D0)
       GO TO 700
  617  CALL XERRWD(
      1  'SLSODE-  RWORK length needed, LENRW (=I1), exceeds LRW (=I2)',
-     1   60, 17, 0, 2, LENRW, LRW, 0, 0.0E0, 0.0E0)
+     1   60, 17, 0, 2, LENRW, LRW, 0, 0.0D0, 0.0D0)
       GO TO 700
  618  CALL XERRWD(
      1   'SLSODE-  IWORK length needed, LENIW (=I1), exceeds LIW (=I2)',
-     1    60, 18, 0, 2, LENIW, LIW, 0, 0.0E0, 0.0E0)
+     1    60, 18, 0, 2, LENIW, LIW, 0, 0.0D0, 0.0D0)
       GO TO 700
  619  CALL XERRWD('SLSODE-  RTOL(I1) is R1 .LT. 0.0        ',
-     1     40, 19, 0, 1, I, 0, 1, RTOLI, 0.0E0)
+     1     40, 19, 0, 1, I, 0, 1, DBLE (RTOLI), 0.0D0)
       GO TO 700
  620  CALL XERRWD('SLSODE-  ATOL(I1) is R1 .LT. 0.0        ',
-     1     40, 20, 0, 1, I, 0, 1, ATOLI, 0.0E0)
+     1     40, 20, 0, 1, I, 0, 1, DBLE (ATOLI), 0.0D0)
       GO TO 700
  621  EWTI = RWORK(LEWT+I-1)
       CALL XERRWD('SLSODE-  EWT(I1) is R1 .LE. 0.0         ',
-     1     40, 21, 0, 1, I, 0, 1, EWTI, 0.0E0)
+     1     40, 21, 0, 1, I, 0, 1, DBLE (EWTI), 0.0D0)
       GO TO 700
  622  CALL XERRWD(
      1   'SLSODE-  TOUT (=R1) too close to T(=R2) to start integration',
-     1     60, 22, 0, 0, 0, 0, 2, TOUT, T)
+     1     60, 22, 0, 0, 0, 0, 2, DBLE (TOUT), DBLE (T))
       GO TO 700
  623  CALL XERRWD(
      1 'SLSODE-  ITASK = I1 and TOUT (=R1) behind TCUR - HU (= R2)  ',
-     1     60, 23, 0, 1, ITASK, 0, 2, TOUT, TP)
+     1     60, 23, 0, 1, ITASK, 0, 2, DBLE (TOUT), DBLE (TP))
       GO TO 700
  624  CALL XERRWD(
      1   'SLSODE-  ITASK = 4 OR 5 and TCRIT (=R1) behind TCUR (=R2)   ',
-     1    60, 24, 0, 0, 0, 0, 2, TCRIT, TN)
+     1    60, 24, 0, 0, 0, 0, 2, DBLE (TCRIT), DBLE (TN))
       GO TO 700
  625  CALL XERRWD(
      1  'SLSODE-  ITASK = 4 or 5 and TCRIT (=R1) behind TOUT (=R2)   ',
-     1   60, 25, 0, 0, 0, 0, 2, TCRIT, TOUT)
+     1   60, 25, 0, 0, 0, 0, 2, DBLE (TCRIT), DBLE (TOUT))
       GO TO 700
  626  CALL XERRWD('SLSODE-  At start of problem, too much accuracy   ',
-     1     50, 26, 0, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 26, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
       CALL XERRWD(
      1   '      requested for precision of machine..  See TOLSF (=R1) ',
-     1    60, 26, 0, 0, 0, 0, 1, TOLSF, 0.0E0)
+     1    60, 26, 0, 0, 0, 0, 1, DBLE (TOLSF), 0.0D0)
       RWORK(14) = TOLSF
       GO TO 700
  627  CALL XERRWD('SLSODE-  Trouble in SINTDY.  ITASK = I1, TOUT = R1',
-     1     50, 27, 0, 1, ITASK, 0, 1, TOUT, 0.0E0)
+     1     50, 27, 0, 1, ITASK, 0, 1, DBLE (TOUT), 0.0D0)
 C
  700  ISTATE = -3
       RETURN
 C
  800  CALL XERRWD('SLSODE-  Run aborted.. apparent infinite loop     ',
-     1     50, 303, 2, 0, 0, 0, 0, 0.0E0, 0.0E0)
+     1     50, 303, 2, 0, 0, 0, 0, 0.0D0, 0.0D0)
       RETURN
 C----------------------- END OF SUBROUTINE SLSODE ----------------------
       END
--- a/liboctave/external/quadpack/xerror.f	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/external/quadpack/xerror.f	Fri Jul 12 12:14:43 2019 -0400
@@ -33,7 +33,8 @@
 C     WRITTEN BY RON JONES, WITH SLATEC COMMON MATH LIBRARY SUBCOMMITTEE
 C     LATEST REVISION ---  7 FEB 1979
 C
-      DIMENSION MESSG(NMESSG)
-      CALL XERRWD(MESSG,NMESSG,NERR,LEVEL,0,0,0,0,0.,0.)
+      CHARACTER*(*) MESSG
+      INTEGER NMESSG, NERR, LEVEL
+      CALL XERRWD(MESSG,NMESSG,NERR,LEVEL,0,0,0,0,0.0D0,0.0D0)
       RETURN
       END
--- a/liboctave/numeric/DASPK.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/DASPK.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -66,8 +66,6 @@
 ddaspk_f (const double& time, const double *state, const double *deriv,
           const double&, double *delta, F77_INT& ires, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   ColumnVector tmp_deriv (nn);
   ColumnVector tmp_state (nn);
   ColumnVector tmp_delta (nn);
@@ -95,8 +93,6 @@
         }
     }
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -109,12 +105,8 @@
              const double *, double *, F77_INT *, double *,
              const double&, F77_INT&, double *, F77_INT*)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   (*current_liboctave_error_handler) ("daspk: PSOL is not implemented");
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -122,8 +114,6 @@
 ddaspk_j (const double& time, const double *state, const double *deriv,
           double *pd, const double& cj, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   // FIXME: would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -141,8 +131,6 @@
     for (F77_INT i = 0; i < nn; i++)
       pd[nn * j + i] = tmp_pd.elem (i, j);
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
--- a/liboctave/numeric/DASRT.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/DASRT.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -64,8 +64,6 @@
 ddasrt_f (const double& t, const double *state, const double *deriv,
           double *delta, F77_INT& ires, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   ColumnVector tmp_state (nn);
   ColumnVector tmp_deriv (nn);
 
@@ -89,8 +87,6 @@
         delta[i] = tmp_fval(i);
     }
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -98,8 +94,6 @@
 ddasrt_j (const double& time, const double *state, const double *deriv,
           double *pd, const double& cj, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   // FIXME: would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -117,8 +111,6 @@
     for (F77_INT i = 0; i < nn; i++)
       pd[nn * j + i] = tmp_pd.elem (i, j);
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -126,8 +118,6 @@
 ddasrt_g (const F77_INT& neq, const double& t, const double *state,
           const F77_INT& ng, double *gout, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   F77_INT n = neq;
 
   ColumnVector tmp_state (n);
@@ -139,8 +129,6 @@
   for (F77_INT i = 0; i < ng; i++)
     gout[i] = tmp_fval(i);
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
--- a/liboctave/numeric/DASSL.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/DASSL.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -61,8 +61,6 @@
 ddassl_f (const double& time, const double *state, const double *deriv,
           double *delta, F77_INT& ires, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   // FIXME: would be nice to avoid copying the data.
 
   ColumnVector tmp_deriv (nn);
@@ -92,8 +90,6 @@
         }
     }
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -101,8 +97,6 @@
 ddassl_j (const double& time, const double *state, const double *deriv,
           double *pd, const double& cj, double *, F77_INT *)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   // FIXME: would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -120,8 +114,6 @@
     for (F77_INT i = 0; i < nn; i++)
       pd[nn * j + i] = tmp_pd.elem (i, j);
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
--- a/liboctave/numeric/LSODE.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/LSODE.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -57,8 +57,6 @@
 lsode_f (const F77_INT& neq, const double& time, double *, double *deriv,
          F77_INT& ierr)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   ColumnVector tmp_deriv;
 
   // NOTE: this won't work if LSODE passes copies of the state vector.
@@ -75,8 +73,6 @@
         deriv[i] = tmp_deriv.elem (i);
     }
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
@@ -84,8 +80,6 @@
 lsode_j (const F77_INT& neq, const double& time, double *, const F77_INT&,
          const F77_INT&, double *pd, const F77_INT& nrowpd)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
   Matrix tmp_jac (neq, neq);
 
   // NOTE: this won't work if LSODE passes copies of the state vector.
@@ -98,8 +92,6 @@
     for (F77_INT i = 0; i < neq; i++)
       pd[nrowpd * j + i] = tmp_jac (i, j);
 
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
--- a/liboctave/numeric/Quad.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/Quad.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -35,11 +35,6 @@
 static integrand_fcn user_fcn;
 static float_integrand_fcn float_user_fcn;
 
-// FIXME: would be nice to not have to have this global variable.
-// Nonzero means an error occurred in the calculation of the integrand
-// function, and the user wants us to quit.
-int quad_integration_error = 0;
-
 typedef F77_INT (*quad_fcn_ptr) (const double&, int&, double&);
 typedef F77_INT (*quad_float_fcn_ptr) (const float&, int&, float&);
 
@@ -79,36 +74,18 @@
 }
 
 static F77_INT
-user_function (const double& x, int& ierr, double& result)
+user_function (const double& x, int&, double& result)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
-  quad_integration_error = 0;
-
   result = (*user_fcn) (x);
 
-  if (quad_integration_error)
-    ierr = -1;
-
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
 static F77_INT
-float_user_function (const float& x, int& ierr, float& result)
+float_user_function (const float& x, int&, float& result)
 {
-  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
-
-  quad_integration_error = 0;
-
   result = (*float_user_fcn) (x);
 
-  if (quad_integration_error)
-    ierr = -1;
-
-  END_INTERRUPT_WITH_EXCEPTIONS;
-
   return 0;
 }
 
--- a/liboctave/numeric/Quad.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/Quad.h	Fri Jul 12 12:14:43 2019 -0400
@@ -31,11 +31,6 @@
 typedef double (*integrand_fcn) (double x);
 typedef float (*float_integrand_fcn) (float x);
 
-// FIXME: would be nice to not have to have this global variable.
-// Nonzero means an error occurred in the calculation of the integrand
-// function, and the user wants us to quit.
-extern OCTAVE_API int quad_integration_error;
-
 #include "Quad-opts.h"
 
 class
--- a/liboctave/numeric/aepbalance.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/aepbalance.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -35,14 +35,14 @@
 #include "lo-error.h"
 #include "lo-lapack-proto.h"
 
-static inline char
-get_job (bool noperm, bool noscal)
-{
-  return noperm ? (noscal ? 'N' : 'S') : (noscal ? 'P' : 'B');
-}
-
 namespace octave
 {
+  static inline char
+  get_job (bool noperm, bool noscal)
+  {
+    return noperm ? (noscal ? 'N' : 'S') : (noscal ? 'P' : 'B');
+  }
+
   namespace math
   {
     template <>
--- a/liboctave/numeric/bsxfun.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/bsxfun.h	Fri Jul 12 12:14:43 2019 -0400
@@ -48,7 +48,7 @@
     }
 
   (*current_liboctave_warning_with_id_handler)
-    ("Octave:language-extension", "performing `%s' automatic broadcasting",
+    ("Octave:language-extension", "performing '%s' automatic broadcasting",
      name.c_str ());
 
   return true;
@@ -78,7 +78,7 @@
     }
 
   (*current_liboctave_warning_with_id_handler)
-    ("Octave:language-extension", "performing `%s' automatic broadcasting",
+    ("Octave:language-extension", "performing '%s' automatic broadcasting",
      name.c_str ());
 
   return true;
--- a/liboctave/numeric/chol.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/chol.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -45,194 +45,194 @@
 #  include "qr.h"
 #endif
 
-static Matrix
-chol2inv_internal (const Matrix& r, bool is_upper = true)
-{
-  Matrix retval;
-
-  octave_idx_type r_nr = r.rows ();
-  octave_idx_type r_nc = r.cols ();
-
-  if (r_nr != r_nc)
-    (*current_liboctave_error_handler) ("chol2inv requires square matrix");
-
-  F77_INT n = octave::to_f77_int (r_nc);
-  F77_INT info;
-
-  Matrix tmp = r;
-  double *v = tmp.fortran_vec ();
-
-  if (is_upper)
-    F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               v, n, info
-                               F77_CHAR_ARG_LEN (1)));
-  else
-    F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               v, n, info
-                               F77_CHAR_ARG_LEN (1)));
-
-  // FIXME: Should we check info exit value and possible report an error?
-
-  // If someone thinks of a more graceful way of doing this
-  // (or faster for that matter :-)), please let me know!
-
-  if (n > 1)
-    {
-      if (is_upper)
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (i, j) = tmp.xelem (j, i);
-      else
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (j, i) = tmp.xelem (i, j);
-    }
-
-  retval = tmp;
-
-  return retval;
-}
-
-static FloatMatrix
-chol2inv_internal (const FloatMatrix& r, bool is_upper = true)
-{
-  FloatMatrix retval;
-
-  octave_idx_type r_nr = r.rows ();
-  octave_idx_type r_nc = r.cols ();
-
-  if (r_nr != r_nc)
-    (*current_liboctave_error_handler) ("chol2inv requires square matrix");
-
-  F77_INT n = octave::to_f77_int (r_nc);
-  F77_INT info;
-
-  FloatMatrix tmp = r;
-  float *v = tmp.fortran_vec ();
-
-  if (is_upper)
-    F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               v, n, info
-                               F77_CHAR_ARG_LEN (1)));
-  else
-    F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               v, n, info
-                               F77_CHAR_ARG_LEN (1)));
-
-  // FIXME: Should we check info exit value and possible report an error?
-
-  // If someone thinks of a more graceful way of doing this (or
-  // faster for that matter :-)), please let me know!
-
-  if (n > 1)
-    {
-      if (is_upper)
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (i, j) = tmp.xelem (j, i);
-      else
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (j, i) = tmp.xelem (i, j);
-    }
-
-  retval = tmp;
-
-  return retval;
-}
-
-static ComplexMatrix
-chol2inv_internal (const ComplexMatrix& r, bool is_upper = true)
-{
-  ComplexMatrix retval;
-
-  octave_idx_type r_nr = r.rows ();
-  octave_idx_type r_nc = r.cols ();
-
-  if (r_nr != r_nc)
-    (*current_liboctave_error_handler) ("chol2inv requires square matrix");
-
-  F77_INT n = octave::to_f77_int (r_nc);
-  F77_INT info;
-
-  ComplexMatrix tmp = r;
-
-  if (is_upper)
-    F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
-                               F77_CHAR_ARG_LEN (1)));
-  else
-    F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
-                               F77_CHAR_ARG_LEN (1)));
-
-  // If someone thinks of a more graceful way of doing this (or
-  // faster for that matter :-)), please let me know!
-
-  if (n > 1)
-    {
-      if (is_upper)
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (i, j) = std::conj (tmp.xelem (j, i));
-      else
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (j, i) = std::conj (tmp.xelem (i, j));
-    }
-
-  retval = tmp;
-
-  return retval;
-}
-
-static FloatComplexMatrix
-chol2inv_internal (const FloatComplexMatrix& r, bool is_upper = true)
-{
-  FloatComplexMatrix retval;
-
-  octave_idx_type r_nr = r.rows ();
-  octave_idx_type r_nc = r.cols ();
-
-  if (r_nr != r_nc)
-    (*current_liboctave_error_handler) ("chol2inv requires square matrix");
-
-  F77_INT n = octave::to_f77_int (r_nc);
-  F77_INT info;
-
-  FloatComplexMatrix tmp = r;
-
-  if (is_upper)
-    F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
-                               F77_CHAR_ARG_LEN (1)));
-  else
-    F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
-                               F77_CHAR_ARG_LEN (1)));
-
-  // If someone thinks of a more graceful way of doing this (or
-  // faster for that matter :-)), please let me know!
-
-  if (n > 1)
-    {
-      if (is_upper)
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (i, j) = std::conj (tmp.xelem (j, i));
-      else
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (j, i) = std::conj (tmp.xelem (i, j));
-    }
-
-  retval = tmp;
-
-  return retval;
-}
-
 namespace octave
 {
+  static Matrix
+  chol2inv_internal (const Matrix& r, bool is_upper = true)
+  {
+    Matrix retval;
+
+    octave_idx_type r_nr = r.rows ();
+    octave_idx_type r_nc = r.cols ();
+
+    if (r_nr != r_nc)
+      (*current_liboctave_error_handler) ("chol2inv requires square matrix");
+
+    F77_INT n = to_f77_int (r_nc);
+    F77_INT info;
+
+    Matrix tmp = r;
+    double *v = tmp.fortran_vec ();
+
+    if (is_upper)
+      F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
+                                 v, n, info
+                                 F77_CHAR_ARG_LEN (1)));
+    else
+      F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
+                                 v, n, info
+                                 F77_CHAR_ARG_LEN (1)));
+
+    // FIXME: Should we check info exit value and possibly report an error?
+
+    // If someone thinks of a more graceful way of doing this
+    // (or faster for that matter :-)), please let me know!
+
+    if (n > 1)
+      {
+        if (is_upper)
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (i, j) = tmp.xelem (j, i);
+        else
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (j, i) = tmp.xelem (i, j);
+      }
+
+    retval = tmp;
+
+    return retval;
+  }
+
+  static FloatMatrix
+  chol2inv_internal (const FloatMatrix& r, bool is_upper = true)
+  {
+    FloatMatrix retval;
+
+    octave_idx_type r_nr = r.rows ();
+    octave_idx_type r_nc = r.cols ();
+
+    if (r_nr != r_nc)
+      (*current_liboctave_error_handler) ("chol2inv requires square matrix");
+
+    F77_INT n = to_f77_int (r_nc);
+    F77_INT info;
+
+    FloatMatrix tmp = r;
+    float *v = tmp.fortran_vec ();
+
+    if (is_upper)
+      F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
+                                 v, n, info
+                                 F77_CHAR_ARG_LEN (1)));
+    else
+      F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
+                                 v, n, info
+                                 F77_CHAR_ARG_LEN (1)));
+
+    // FIXME: Should we check info exit value and possibly report an error?
+
+    // If someone thinks of a more graceful way of doing this (or
+    // faster for that matter :-)), please let me know!
+
+    if (n > 1)
+      {
+        if (is_upper)
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (i, j) = tmp.xelem (j, i);
+        else
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (j, i) = tmp.xelem (i, j);
+      }
+
+    retval = tmp;
+
+    return retval;
+  }
+
+  static ComplexMatrix
+  chol2inv_internal (const ComplexMatrix& r, bool is_upper = true)
+  {
+    ComplexMatrix retval;
+
+    octave_idx_type r_nr = r.rows ();
+    octave_idx_type r_nc = r.cols ();
+
+    if (r_nr != r_nc)
+      (*current_liboctave_error_handler) ("chol2inv requires square matrix");
+
+    F77_INT n = to_f77_int (r_nc);
+    F77_INT info;
+
+    ComplexMatrix tmp = r;
+
+    if (is_upper)
+      F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
+                                 F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                                 F77_CHAR_ARG_LEN (1)));
+    else
+      F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
+                                 F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                                 F77_CHAR_ARG_LEN (1)));
+
+    // If someone thinks of a more graceful way of doing this (or
+    // faster for that matter :-)), please let me know!
+
+    if (n > 1)
+      {
+        if (is_upper)
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (i, j) = std::conj (tmp.xelem (j, i));
+        else
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (j, i) = std::conj (tmp.xelem (i, j));
+      }
+
+    retval = tmp;
+
+    return retval;
+  }
+
+  static FloatComplexMatrix
+  chol2inv_internal (const FloatComplexMatrix& r, bool is_upper = true)
+  {
+    FloatComplexMatrix retval;
+
+    octave_idx_type r_nr = r.rows ();
+    octave_idx_type r_nc = r.cols ();
+
+    if (r_nr != r_nc)
+      (*current_liboctave_error_handler) ("chol2inv requires square matrix");
+
+    F77_INT n = to_f77_int (r_nc);
+    F77_INT info;
+
+    FloatComplexMatrix tmp = r;
+
+    if (is_upper)
+      F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
+                                 F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                                 F77_CHAR_ARG_LEN (1)));
+    else
+      F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
+                                 F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                                 F77_CHAR_ARG_LEN (1)));
+
+    // If someone thinks of a more graceful way of doing this (or
+    // faster for that matter :-)), please let me know!
+
+    if (n > 1)
+      {
+        if (is_upper)
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (i, j) = std::conj (tmp.xelem (j, i));
+        else
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (j, i) = std::conj (tmp.xelem (i, j));
+      }
+
+    retval = tmp;
+
+    return retval;
+  }
+
   namespace math
   {
     template <typename T>
--- a/liboctave/numeric/chol.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/chol.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,7 +39,7 @@
       typedef typename T::column_vector_type VT;
       typedef typename T::real_elt_type COND_T;
 
-      chol (void) : chol_mat (), xrcond (0) { }
+      chol (void) : chol_mat (), xrcond (0), is_upper (true) { }
 
       chol (const T& a, bool upper = true, bool calc_cond = false)
         : chol_mat (), xrcond (0)
@@ -55,7 +55,7 @@
       }
 
       chol (const chol& a)
-        : chol_mat (a.chol_mat), xrcond (a.xrcond) { }
+        : chol_mat (a.chol_mat), xrcond (a.xrcond), is_upper (a.is_upper) { }
 
       chol& operator = (const chol& a)
       {
@@ -63,6 +63,7 @@
           {
             chol_mat = a.chol_mat;
             xrcond = a.xrcond;
+            is_upper = a.is_upper;
           }
 
         return *this;
--- a/liboctave/numeric/gsvd.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/gsvd.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -39,52 +39,54 @@
 #include "lo-lapack-proto.h"
 #include "oct-shlib.h"
 
-static std::map<std::string, void *> gsvd_fcn;
+namespace octave
+{
+  static std::map<std::string, void *> gsvd_fcn;
 
-static bool have_DGGSVD3 = false;
-static bool gsvd_initialized = false;
+  static bool have_DGGSVD3 = false;
+  static bool gsvd_initialized = false;
 
-/* Hack to stringize macro results. */
+  /* Hack to stringize macro results. */
 #define xSTRINGIZE(x) #x
 #define STRINGIZE(x) xSTRINGIZE(x)
 
-void initialize_gsvd (void)
-{
-  if (gsvd_initialized)
-    return;
+  static void initialize_gsvd (void)
+  {
+    if (gsvd_initialized)
+      return;
 
-  octave::dynamic_library libs ("");
-  if (! libs)
-    {
-      // FIXME: Should we throw an error if we cannot check the libraries?
-      have_DGGSVD3 = false;
-      return;
-    }
+    dynamic_library libs ("");
+    if (! libs)
+      {
+        // FIXME: Should we throw an error if we cannot check the libraries?
+        have_DGGSVD3 = false;
+        return;
+      }
 
-  have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)))
-                  != nullptr);
+    have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)))
+                    != nullptr);
 
-  if (have_DGGSVD3)
-    {
-      gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)));
-      gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3)));
-      gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3)));
-      gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3)));
-    }
-  else
-    {
-      gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD)));
-      gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD)));
-      gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD)));
-      gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD)));
-    }
-  gsvd_initialized = true;
-}
+    if (have_DGGSVD3)
+      {
+        gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)));
+        gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3)));
+        gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3)));
+        gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3)));
+      }
+    else
+      {
+        gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD)));
+        gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD)));
+        gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD)));
+        gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD)));
+      }
+    gsvd_initialized = true;
+  }
 
-template<class T1>
-struct real_ggsvd_ptr
-{
-  typedef F77_RET_T (*type)
+  template<class T1>
+  struct real_ggsvd_ptr
+  {
+    typedef F77_RET_T (*type)
     (F77_CONST_CHAR_ARG_DECL,   // JOBU
      F77_CONST_CHAR_ARG_DECL,   // JOBV
      F77_CONST_CHAR_ARG_DECL,   // JOBQ
@@ -111,12 +113,12 @@
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL);
-};
+  };
 
-template<class T1>
-struct real_ggsvd3_ptr
-{
-  typedef F77_RET_T (*type)
+  template<class T1>
+  struct real_ggsvd3_ptr
+  {
+    typedef F77_RET_T (*type)
     (F77_CONST_CHAR_ARG_DECL,   // JOBU
      F77_CONST_CHAR_ARG_DECL,   // JOBV
      F77_CONST_CHAR_ARG_DECL,   // JOBQ
@@ -144,12 +146,12 @@
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL);
-};
+  };
 
-template<class T1, class T2>
-struct comp_ggsvd_ptr
-{
-  typedef F77_RET_T (*type)
+  template<class T1, class T2>
+  struct comp_ggsvd_ptr
+  {
+    typedef F77_RET_T (*type)
     (F77_CONST_CHAR_ARG_DECL,   // JOBU
      F77_CONST_CHAR_ARG_DECL,   // JOBV
      F77_CONST_CHAR_ARG_DECL,   // JOBQ
@@ -177,12 +179,12 @@
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL);
-};
+  };
 
-template<class T1, class T2>
-struct comp_ggsvd3_ptr
-{
-  typedef F77_RET_T (*type)
+  template<class T1, class T2>
+  struct comp_ggsvd3_ptr
+  {
+    typedef F77_RET_T (*type)
     (F77_CONST_CHAR_ARG_DECL,   // JOBU
      F77_CONST_CHAR_ARG_DECL,   // JOBV
      F77_CONST_CHAR_ARG_DECL,   // JOBQ
@@ -211,20 +213,18 @@
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL
      F77_CHAR_ARG_LEN_DECL);
-};
+  };
 
-// template specializations
-typedef real_ggsvd3_ptr<F77_DBLE>::type dggsvd3_type;
-typedef real_ggsvd_ptr<F77_DBLE>::type dggsvd_type;
-typedef real_ggsvd3_ptr<F77_REAL>::type sggsvd3_type;
-typedef real_ggsvd_ptr<F77_REAL>::type sggsvd_type;
-typedef comp_ggsvd3_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd3_type;
-typedef comp_ggsvd_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd_type;
-typedef comp_ggsvd3_ptr<F77_CMPLX, F77_REAL>::type cggsvd3_type;
-typedef comp_ggsvd_ptr<F77_CMPLX, F77_REAL>::type cggsvd_type;
+  // template specializations
+  typedef real_ggsvd3_ptr<F77_DBLE>::type dggsvd3_type;
+  typedef real_ggsvd_ptr<F77_DBLE>::type dggsvd_type;
+  typedef real_ggsvd3_ptr<F77_REAL>::type sggsvd3_type;
+  typedef real_ggsvd_ptr<F77_REAL>::type sggsvd_type;
+  typedef comp_ggsvd3_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd3_type;
+  typedef comp_ggsvd_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd_type;
+  typedef comp_ggsvd3_ptr<F77_CMPLX, F77_REAL>::type cggsvd3_type;
+  typedef comp_ggsvd_ptr<F77_CMPLX, F77_REAL>::type cggsvd_type;
 
-namespace octave
-{
   namespace math
   {
     template <>
--- a/liboctave/numeric/lo-mappers.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/lo-mappers.h	Fri Jul 12 12:14:43 2019 -0400
@@ -39,20 +39,9 @@
   namespace math
   {
     extern OCTAVE_API bool isna (double x);
-    OCTAVE_DEPRECATED (4.4, "use 'math::isna' instead")
-    inline bool is_NA (double x) { return math::isna (x); }
-
     extern OCTAVE_API bool isna (float x);
-    OCTAVE_DEPRECATED (4.4, "use 'math::isna' instead")
-    inline bool is_NA (float x) { return math::isna (x); }
-
     extern OCTAVE_API bool isna (const Complex& x);
-    OCTAVE_DEPRECATED (4.4, "use 'math::isna' instead")
-    inline bool is_NA (const Complex& x) { return math::isna (x); }
-
     extern OCTAVE_API bool isna (const FloatComplex& x);
-    OCTAVE_DEPRECATED (4.4, "use 'math::isna' instead")
-    inline bool is_NA (const FloatComplex& x) { return math::isna (x); }
 
     extern OCTAVE_API bool is_NaN_or_NA (const Complex& x);
     extern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x);
@@ -209,19 +198,6 @@
       return (isfinite (std::real (x)) && isfinite (std::imag (x)));
     }
 
-    OCTAVE_DEPRECATED (4.4, "use 'math::isfinite' instead")
-    inline bool finite (double x) { return math::isfinite (x); }
-    OCTAVE_DEPRECATED (4.4, "use 'math::isfinite' instead")
-    inline bool finite (float x) { return math::isfinite (x); }
-
-    template <typename T>
-    OCTAVE_DEPRECATED (4.4, "use 'math::isfinite' instead")
-    bool
-    finite (const std::complex<T>& x)
-    {
-      return math::isfinite (x);
-    }
-
     inline bool isinf (double x) { return std::isinf (x); }
     inline bool isinf (float x) { return std::isinf (x); }
 
@@ -479,21 +455,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-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")
-inline bool xfinite (float x) { return octave::math::isfinite (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.4, "use 'octave::math::isfinite' instead")
-bool
-xfinite (const std::complex<T>& x)
-{
-  return octave::math::isfinite (x);
-}
-
 #endif
-
-#endif
--- a/liboctave/numeric/oct-fftw.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/oct-fftw.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -79,7 +79,7 @@
 
     // Use number of processors available to the current process
     // This can be later changed with fftw ("threads", nthreads).
-    nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT);
+    nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE);
     fftw_plan_with_nthreads (nthreads);
 #endif
 
@@ -112,15 +112,9 @@
     if (! instance)
       {
         instance = new fftw_planner ();
-
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
+        singleton_cleanup_list::add (cleanup_instance);
       }
 
-    if (! instance)
-      (*current_liboctave_error_handler)
-        ("unable to create fftw_planner object!");
-
     return retval;
   }
 
@@ -439,7 +433,7 @@
 
     // Use number of processors available to the current process
     // This can be later changed with fftw ("threads", nthreads).
-    nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT);
+    nthreads = octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE);
     fftwf_plan_with_nthreads (nthreads);
 #endif
 
@@ -472,15 +466,9 @@
     if (! instance)
       {
         instance = new float_fftw_planner ();
-
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
+        singleton_cleanup_list::add (cleanup_instance);
       }
 
-    if (! instance)
-      (*current_liboctave_error_handler)
-        ("unable to create fftw_planner object!");
-
     return retval;
   }
 
--- a/liboctave/numeric/oct-fftw.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/oct-fftw.h	Fri Jul 12 12:14:43 2019 -0400
@@ -376,31 +376,4 @@
   extern OCTAVE_API std::string fftwf_version (void);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::fftw_version' instead")
-static inline std::string
-octave_fftw_version (void)
-{
-  return octave::fftw_version ();
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::fftwf_version' instead")
-static inline std::string
-octave_fftwf_version (void)
-{
-  return octave::fftwf_version ();
-}
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::fftw_planner' instead")
-typedef octave::fftw_planner octave_fftw_planner;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::float_fftw_planner' instead")
-typedef octave::float_fftw_planner octave_float_fftw_planner;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::fftw' instead")
-typedef octave::fftw octave_fftw;
-
 #endif
-
-#endif
--- a/liboctave/numeric/oct-rand.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/oct-rand.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -63,15 +63,9 @@
     if (! instance)
       {
         instance = new rand ();
-
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
+        singleton_cleanup_list::add (cleanup_instance);
       }
 
-    if (! instance)
-      (*current_liboctave_error_handler)
-        ("unable to create rand object!");
-
     return retval;
   }
 
@@ -301,7 +295,7 @@
     if (use_old_generators)
       F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval);
     else
-      retval = octave::rand_uniform<double> ();
+      retval = rand_uniform<double> ();
 
     return retval;
   }
@@ -314,7 +308,7 @@
     if (use_old_generators)
       F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval);
     else
-      retval = octave::rand_normal<double> ();
+      retval = rand_normal<double> ();
 
     return retval;
   }
@@ -327,7 +321,7 @@
     if (use_old_generators)
       F77_FUNC (dgenexp, DGENEXP) (1.0, retval);
     else
-      retval = octave::rand_exponential<double> ();
+      retval = rand_exponential<double> ();
 
     return retval;
   }
@@ -349,7 +343,7 @@
           }
       }
     else
-      retval = octave::rand_poisson<double> (a);
+      retval = rand_poisson<double> (a);
 
     return retval;
   }
@@ -367,7 +361,7 @@
           F77_FUNC (dgengam, DGENGAM) (1.0, a, retval);
       }
     else
-      retval = octave::rand_gamma<double> (a);
+      retval = rand_gamma<double> (a);
 
     return retval;
   }
@@ -380,7 +374,7 @@
     if (use_old_generators)
       F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval);
     else
-      retval = octave::rand_uniform<float> ();
+      retval = rand_uniform<float> ();
 
     return retval;
   }
@@ -393,7 +387,7 @@
     if (use_old_generators)
       F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval);
     else
-      retval = octave::rand_normal<float> ();
+      retval = rand_normal<float> ();
 
     return retval;
   }
@@ -406,7 +400,7 @@
     if (use_old_generators)
       F77_FUNC (fgenexp, FGENEXP) (1.0f, retval);
     else
-      retval = octave::rand_exponential<float> ();
+      retval = rand_exponential<float> ();
 
     return retval;
   }
@@ -430,7 +424,7 @@
     else
       {
         // Keep poisson distribution in double precision for accuracy
-        retval = octave::rand_poisson<double> (a);
+        retval = rand_poisson<double> (a);
       }
 
     return retval;
@@ -449,7 +443,7 @@
           F77_FUNC (fgengam, FGENGAM) (1.0f, a, retval);
       }
     else
-      retval = octave::rand_gamma<float> (a);
+      retval = rand_gamma<float> (a);
 
     return retval;
   }
@@ -735,21 +729,21 @@
         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);
+          rand_uniform<float> (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
-          octave::rand_normal<float> (len, v);
+          rand_normal<float> (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
-          octave::rand_exponential<float> (len, v);
+          rand_exponential<float> (len, v);
         break;
 
       case poisson_dist:
@@ -766,7 +760,7 @@
               }
           }
         else
-          octave::rand_poisson<float> (a, len, v);
+          rand_poisson<float> (a, len, v);
         break;
 
       case gamma_dist:
@@ -778,7 +772,7 @@
               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);
+          rand_gamma<float> (a, len, v);
         break;
 
       default:
--- a/liboctave/numeric/oct-rand.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/oct-rand.h	Fri Jul 12 12:14:43 2019 -0400
@@ -53,8 +53,8 @@
     // Return the current seed.
     static double seed (void)
     {
-      return instance_ok () ? instance->do_seed ()
-        : octave::numeric_limits<double>::NaN ();
+      return (instance_ok ()
+              ? instance->do_seed () : numeric_limits<double>::NaN ());
     }
 
     // Set the seed.
@@ -139,15 +139,15 @@
     // 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 (instance_ok ()
+              ? instance->do_scalar (a) : numeric_limits<double>::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 (instance_ok ()
+              ? instance->do_scalar (a) : numeric_limits<float>::NaN ());
     }
 
     // Return an array of numbers from the sequence.
@@ -173,8 +173,8 @@
     // 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 (instance_ok ()
+              ? instance->do_float_nd_array (dims, a) : FloatNDArray ());
     }
 
   private:
@@ -287,11 +287,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::rand' instead")
-typedef octave::rand octave_rand;
-
 #endif
-
-#endif
--- a/liboctave/numeric/oct-spparms.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/oct-spparms.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -43,15 +43,9 @@
   if (! instance)
     {
       instance = new octave_sparse_params ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
+      singleton_cleanup_list::add (cleanup_instance);
     }
 
-  if (! instance)
-    (*current_liboctave_error_handler)
-      ("unable to create octave_sparse_params object!");
-
   return retval;
 }
 
--- a/liboctave/numeric/randgamma.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/randgamma.h	Fri Jul 12 12:14:43 2019 -0400
@@ -44,32 +44,4 @@
   }
 }
 
-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	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/randmtzig.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -273,7 +273,7 @@
 
     /* If there isn't enough entropy, gather some from various sources */
 
-    octave::sys::time now;
+    sys::time now;
 
     if (n < MT_N)
       entropy[n++] = now.unix_time (); /* Current time in seconds */
--- a/liboctave/numeric/randmtzig.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/randmtzig.h	Fri Jul 12 12:14:43 2019 -0400
@@ -115,123 +115,4 @@
   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);
-}
-
-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);
-}
-
-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> ();
-}
-
-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	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/randpoisson.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -178,7 +178,7 @@
       {
         /* generate uniform number U -- U(0, p6)                           */
         /* case distinction corresponding to U                             */
-        if ((U = octave::rand_uniform<double> () * p6) < p2)
+        if ((U = rand_uniform<double> () * p6) < p2)
           {                                            /* centre left      */
 
             /* immediate acceptance region
@@ -190,7 +190,7 @@
 
             /* 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;
+            Dk = std::floor (dl * rand_uniform<double> ()) + 1.0;
             if (W <= f2 - Dk * (f2 - f2/r2))
               {                                        /* quick accept of  */
                 return (k2 - Dk);                      /* X = k2 - Dk      */
@@ -217,7 +217,7 @@
 
             /* 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;
+            Dk = std::floor (dr * rand_uniform<double> ()) + 1.0;
             if (W <= f4 - Dk * (f4 - f4*r4))
               {                                        /* quick accept of  */
                 return (k4 + Dk);                      /* X = k4 + Dk      */
@@ -235,7 +235,7 @@
           }
         else
           {
-            W = octave::rand_uniform<double> ();
+            W = rand_uniform<double> ();
             if (U < p5)
               {                                        /* expon. tail left */
                 Dk = std::floor (1.0 - std::log (W)/ll);
@@ -299,7 +299,7 @@
 
     while (i-- > 0)
       {
-        double u = octave::rand_uniform<double> ();
+        double u = rand_uniform<double> ();
 
         /* If u > 0.458 we know we can jump to floor(lambda) before
          * comparing (this observation is based on Stadlober's winrand
@@ -358,12 +358,12 @@
           {
             do
               {
-                y = tan (M_PI*octave::rand_uniform<double> ());
+                y = tan (M_PI*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);
+          } while (rand_uniform<double> () > t);
         p[i] = em;
       }
   }
--- a/liboctave/numeric/randpoisson.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/randpoisson.h	Fri Jul 12 12:14:43 2019 -0400
@@ -35,32 +35,4 @@
   template <typename T> T rand_poisson (T L);
 }
 
-OCTAVE_DEPRECATED (4.4, "use 'octave::rand_poisson<double>' instead")
-inline double
-oct_randp (double L)
-{
-  return octave::rand_poisson (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);
-}
-
-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/svd.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/numeric/svd.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -385,6 +385,13 @@
       else
         (*current_liboctave_error_handler) ("svd: unknown driver");
 
+      // LAPACK can return -0 which is a small problem (bug #55710).
+      for (octave_idx_type i = 0; i < sigma.diag_length (); i++)
+        {
+          if (! sigma.dgxelem (i))
+            sigma.dgxelem (i) = DM_P (0);
+        }
+
       if (! (jobv == 'N' || jobv == 'O'))
         right_sm = right_sm.hermitian ();
     }
--- a/liboctave/system/file-ops.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/system/file-ops.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -50,164 +50,164 @@
 #include "str-vec.h"
 #include "unistd-wrappers.h"
 
-// The following tilde-expansion code was stolen and adapted from
-// readline.
-
-// The default value of tilde_additional_prefixes.  This is set to
-// whitespace preceding a tilde so that simple programs which do not
-// perform any word separation get desired behavior.
-static const char *default_prefixes[] = { " ~", "\t~", ":~", nullptr };
-
-// The default value of tilde_additional_suffixes.  This is set to
-// whitespace or newline so that simple programs which do not perform
-// any word separation get desired behavior.
-static const char *default_suffixes[] = { " ", "\n", ":", nullptr };
-
-static size_t
-tilde_find_prefix (const std::string& s, size_t& len)
-{
-  len = 0;
-
-  size_t s_len = s.length ();
-
-  if (s_len == 0 || s[0] == '~')
-    return 0;
-
-  string_vector prefixes = octave::sys::file_ops::tilde_additional_prefixes;
-
-  if (! prefixes.empty ())
-    {
-      for (size_t i = 0; i < s_len; i++)
-        {
-          for (int j = 0; j < prefixes.numel (); j++)
-            {
-              size_t pfx_len = prefixes[j].length ();
-
-              if (prefixes[j] == s.substr (i, pfx_len))
-                {
-                  len = pfx_len - 1;
-                  return i + len;
-                }
-            }
-        }
-    }
-
-  return s_len;
-}
-
-// Find the end of a tilde expansion in S, and return the index
-// of the character which ends the tilde definition.
-
-static size_t
-tilde_find_suffix (const std::string& s)
-{
-  size_t s_len = s.length ();
-
-  string_vector suffixes = octave::sys::file_ops::tilde_additional_suffixes;
-
-  size_t i = 0;
-
-  for ( ; i < s_len; i++)
-    {
-      if (octave::sys::file_ops::is_dir_sep (s[i]))
-        break;
-
-      if (! suffixes.empty ())
-        {
-          for (int j = 0; j < suffixes.numel (); j++)
-            {
-              size_t sfx_len = suffixes[j].length ();
-
-              if (suffixes[j] == s.substr (i, sfx_len))
-                return i;
-            }
-        }
-    }
-
-  return i;
-}
-
-// Take FNAME and return the tilde prefix we want expanded.
-
-static std::string
-isolate_tilde_prefix (const std::string& fname)
-{
-  size_t f_len = fname.length ();
-
-  size_t len = 1;
-
-  while (len < f_len && ! octave::sys::file_ops::is_dir_sep (fname[len]))
-    len++;
-
-  return fname.substr (1, len);
-}
-
-// Do the work of tilde expansion on FILENAME.  FILENAME starts with a
-// tilde.
-
-static std::string
-tilde_expand_word (const std::string& filename)
-{
-  size_t f_len = filename.length ();
-
-  if (f_len == 0 || filename[0] != '~')
-    return std::string (filename);
-
-  // A leading '~/' or a bare '~' is *always* translated to the value
-  // of $HOME or the home directory of the current user, regardless of
-  // any preexpansion hook.
-
-  if (f_len == 1 || octave::sys::file_ops::is_dir_sep (filename[1]))
-    return octave::sys::env::get_home_directory () + filename.substr (1);
-
-  std::string username = isolate_tilde_prefix (filename);
-
-  size_t user_len = username.length ();
-
-  std::string dirname;
-
-  if (octave::sys::file_ops::tilde_expansion_preexpansion_hook)
-    {
-      std::string expansion
-        = octave::sys::file_ops::tilde_expansion_preexpansion_hook (username);
-
-      if (! expansion.empty ())
-        return expansion + filename.substr (user_len+1);
-    }
-
-  // No preexpansion hook, or the preexpansion hook failed.  Look in the
-  // password database.
-
-  octave::sys::password pw = octave::sys::password::getpwnam (username);
-
-  if (! pw)
-    {
-      // If the calling program has a special syntax for expanding tildes,
-      // and we couldn't find a standard expansion, then let them try.
-
-      if (octave::sys::file_ops::tilde_expansion_failure_hook)
-        {
-          std::string expansion
-            = octave::sys::file_ops::tilde_expansion_failure_hook (username);
-
-          if (! expansion.empty ())
-            dirname = expansion + filename.substr (user_len+1);
-        }
-
-      // If we don't have a failure hook, or if the failure hook did not
-      // expand the tilde, return a copy of what we were passed.
-
-      if (dirname.empty ())
-        dirname = filename;
-    }
-  else
-    dirname = pw.dir () + filename.substr (user_len+1);
-
-  return dirname;
-}
-
 namespace octave
 {
+  // The following tilde-expansion code was stolen and adapted from
+  // readline.
+
+  // The default value of tilde_additional_prefixes.  This is set to
+  // whitespace preceding a tilde so that simple programs which do not
+  // perform any word separation get desired behavior.
+  static const char *default_prefixes[] = { " ~", "\t~", ":~", nullptr };
+
+  // The default value of tilde_additional_suffixes.  This is set to
+  // whitespace or newline so that simple programs which do not perform
+  // any word separation get desired behavior.
+  static const char *default_suffixes[] = { " ", "\n", ":", nullptr };
+
+  static size_t
+  tilde_find_prefix (const std::string& s, size_t& len)
+  {
+    len = 0;
+
+    size_t s_len = s.length ();
+
+    if (s_len == 0 || s[0] == '~')
+      return 0;
+
+    string_vector prefixes = sys::file_ops::tilde_additional_prefixes;
+
+    if (! prefixes.empty ())
+      {
+        for (size_t i = 0; i < s_len; i++)
+          {
+            for (int j = 0; j < prefixes.numel (); j++)
+              {
+                size_t pfx_len = prefixes[j].length ();
+
+                if (prefixes[j] == s.substr (i, pfx_len))
+                  {
+                    len = pfx_len - 1;
+                    return i + len;
+                  }
+              }
+          }
+      }
+
+    return s_len;
+  }
+
+  // Find the end of a tilde expansion in S, and return the index
+  // of the character which ends the tilde definition.
+
+  static size_t
+  tilde_find_suffix (const std::string& s)
+  {
+    size_t s_len = s.length ();
+
+    string_vector suffixes = sys::file_ops::tilde_additional_suffixes;
+
+    size_t i = 0;
+
+    for ( ; i < s_len; i++)
+      {
+        if (sys::file_ops::is_dir_sep (s[i]))
+          break;
+
+        if (! suffixes.empty ())
+          {
+            for (int j = 0; j < suffixes.numel (); j++)
+              {
+                size_t sfx_len = suffixes[j].length ();
+
+                if (suffixes[j] == s.substr (i, sfx_len))
+                  return i;
+              }
+          }
+      }
+
+    return i;
+  }
+
+  // Take FNAME and return the tilde prefix we want expanded.
+
+  static std::string
+  isolate_tilde_prefix (const std::string& fname)
+  {
+    size_t f_len = fname.length ();
+
+    size_t len = 1;
+
+    while (len < f_len && ! sys::file_ops::is_dir_sep (fname[len]))
+      len++;
+
+    return fname.substr (1, len);
+  }
+
+  // Do the work of tilde expansion on FILENAME.  FILENAME starts with a
+  // tilde.
+
+  static std::string
+  tilde_expand_word (const std::string& filename)
+  {
+    size_t f_len = filename.length ();
+
+    if (f_len == 0 || filename[0] != '~')
+      return std::string (filename);
+
+    // A leading '~/' or a bare '~' is *always* translated to the value
+    // of $HOME or the home directory of the current user, regardless of
+    // any preexpansion hook.
+
+    if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1]))
+      return sys::env::get_home_directory () + filename.substr (1);
+
+    std::string username = isolate_tilde_prefix (filename);
+
+    size_t user_len = username.length ();
+
+    std::string dirname;
+
+    if (sys::file_ops::tilde_expansion_preexpansion_hook)
+      {
+        std::string expansion
+          = sys::file_ops::tilde_expansion_preexpansion_hook (username);
+
+        if (! expansion.empty ())
+          return expansion + filename.substr (user_len+1);
+      }
+
+    // No preexpansion hook, or the preexpansion hook failed.  Look in the
+    // password database.
+
+    sys::password pw = sys::password::getpwnam (username);
+
+    if (! pw)
+      {
+        // If the calling program has a special syntax for expanding tildes,
+        // and we couldn't find a standard expansion, then let them try.
+
+        if (sys::file_ops::tilde_expansion_failure_hook)
+          {
+            std::string expansion
+              = sys::file_ops::tilde_expansion_failure_hook (username);
+
+            if (! expansion.empty ())
+              dirname = expansion + filename.substr (user_len+1);
+          }
+
+        // If we don't have a failure hook, or if the failure hook did not
+        // expand the tilde, return a copy of what we were passed.
+
+        if (dirname.empty ())
+          dirname = filename;
+      }
+    else
+      dirname = pw.dir () + filename.substr (user_len+1);
+
+    return dirname;
+  }
+
   namespace sys
   {
     namespace file_ops
--- a/liboctave/system/lo-sysdep.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/system/lo-sysdep.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -179,7 +179,7 @@
 
 #if defined (OCTAVE_USE_WINDOWS_API)
       wchar_t *wnew_item = u8_to_wchar (new_item);
-      octave::unwind_protect frame;
+      unwind_protect frame;
       frame.add_fcn (std::free, static_cast<void *> (new_item));
       if (_wputenv (wnew_item) < 0)
         (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
@@ -374,7 +374,7 @@
       if (test_dir.empty ())
       {
         std::string msg;
-        int status = octave::sys::mkdir (oct_ascii_dir, 0777, msg);
+        int status = sys::mkdir (oct_ascii_dir, 0777, msg);
 
         if (status < 0)
           return orig_file_name;
@@ -386,12 +386,12 @@
       // 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));
+           + crypto::hash ("SHA1", orig_file_name));
 
       std::string abs_filename_hash = canonicalize_file_name (filename_hash);
 
       if (! abs_filename_hash.empty ())
-        octave::sys::unlink (filename_hash);
+        sys::unlink (filename_hash);
 
       wchar_t w_filename_hash[filename_hash.length ()+1] = {0};
 
--- a/liboctave/system/mach-info.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/system/mach-info.h	Fri Jul 12 12:14:43 2019 -0400
@@ -53,45 +53,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-class oct_mach_info
-{
-public:
-
-  typedef octave::mach_info::float_format float_format;
-
-  OCTAVE_DEPRECATED (4.4, "use 'octave::mach_info::native_float_format' instead")
-  static float_format native_float_format (void)
-  {
-    return octave::mach_info::native_float_format ();
-  }
-
-  OCTAVE_DEPRECATED (4.4, "use 'octave::mach_info::words_big_endian' instead")
-  static bool words_big_endian (void)
-  {
-    return octave::mach_info::words_big_endian ();
-  }
-
-  OCTAVE_DEPRECATED (4.4, "use 'octave::mach_info::words_little_endian' instead")
-  static bool words_little_endian (void)
-  {
-    return octave::mach_info::words_little_endian ();
-  }
-
-  OCTAVE_DEPRECATED (4.4, "use 'octave::mach_info::string_to_float_format' instead")
-  static float_format string_to_float_format (const std::string& str)
-  {
-    return octave::mach_info::string_to_float_format (str);
-  }
-
-  OCTAVE_DEPRECATED (4.4, "use 'octave::mach_info::float_format_as_string' instead")
-  static std::string float_format_as_string (float_format ff)
-  {
-    return octave::mach_info::float_format_as_string (ff);
-  }
-};
-
 #endif
-
-#endif
--- a/liboctave/system/oct-env.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/system/oct-env.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -85,15 +85,9 @@
       if (! instance)
         {
           instance = new env ();
-
-          if (instance)
-            singleton_cleanup_list::add (cleanup_instance);
+          singleton_cleanup_list::add (cleanup_instance);
         }
 
-      if (! instance)
-        (*current_liboctave_error_handler)
-          ("unable to create current working directory object!");
-
       return retval;
     }
 
@@ -585,6 +579,16 @@
           while (sys::file_ops::is_dir_sep (path[i]) && i > 0)
             i--;
 
+#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
+          // Don't strip file letter part.
+          if (i == 1 && path[i] == ':')
+            {
+              // Keep path separator if present.
+              i = std::min (i+2, path.length ());
+              break;
+            }
+#endif
+
           while (! sys::file_ops::is_dir_sep (path[i]) && i > 0)
             i--;
 
--- a/liboctave/util/action-container.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/action-container.h	Fri Jul 12 12:14:43 2019 -0400
@@ -88,7 +88,7 @@
     public:
 
       restore_var_elem (T& ref, const T& val)
-        : e_ptr (&ref), e_val (val) { }
+        : m_ptr (&ref), m_val (val) { }
 
       // No copying!
 
@@ -96,11 +96,11 @@
 
       restore_var_elem& operator = (const restore_var_elem&) = delete;
 
-      void run (void) { *e_ptr = e_val; }
+      void run (void) { *m_ptr = m_val; }
 
     private:
 
-      T *e_ptr, e_val;
+      T *m_ptr, m_val;
     };
 
     // Deletes a class allocated using new.
@@ -111,7 +111,7 @@
     public:
 
       delete_ptr_elem (T *ptr)
-        : e_ptr (ptr) { }
+        : m_ptr (ptr) { }
 
       // No copying!
 
@@ -119,11 +119,11 @@
 
       delete_ptr_elem operator = (const delete_ptr_elem&) = delete;
 
-      void run (void) { delete e_ptr; }
+      void run (void) { delete m_ptr; }
 
     private:
 
-      T *e_ptr;
+      T *m_ptr;
     };
 
     action_container (void) { }
@@ -225,11 +225,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::action_container' instead")
-typedef octave::action_container action_container;
-
 #endif
-
-#endif
--- a/liboctave/util/cmd-edit.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/cmd-edit.h	Fri Jul 12 12:14:43 2019 -0400
@@ -41,7 +41,9 @@
   protected:
 
     command_editor (void)
-      : command_number (0), interrupted (false), initial_input () { }
+      : command_number (0), m_rows (24), m_cols (80), interrupted (false),
+        initial_input ()
+      { }
 
   public:
 
@@ -249,15 +251,19 @@
 
     virtual void do_redisplay (void) { }
 
-    virtual int do_terminal_rows (void) { return 24; }
+    virtual int do_terminal_rows (void) { return m_rows; }
 
-    virtual int do_terminal_cols (void) { return 80; }
+    virtual int do_terminal_cols (void) { return m_cols; }
 
     virtual void do_clear_screen (bool) { }
 
     virtual void do_resize_terminal (void) { }
 
-    virtual void do_set_screen_size (int, int) { }
+    virtual void do_set_screen_size (int ht, int wd)
+    {
+      m_rows = ht;
+      m_cols = wd;
+    }
 
     virtual std::string do_decode_prompt_string (const std::string&);
 
@@ -365,6 +371,9 @@
     // The current command number.
     int command_number;
 
+    int m_rows;
+    int m_cols;
+
     bool interrupted;
 
     std::string initial_input;
--- a/liboctave/util/f77-fcn.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/f77-fcn.h	Fri Jul 12 12:14:43 2019 -0400
@@ -45,9 +45,6 @@
 #  define F77_FCN(f, F) F77_FUNC (f, F)
 #endif
 
-OCTAVE_DEPRECATED (4.4, "this variable is obsolete and should not be needed")
-static const int f77_exception_encountered = 0;
-
 /*
 
 The following macros are used for handling Fortran <-> C calling
--- a/liboctave/util/file-info.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/file-info.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -81,7 +81,7 @@
 
     size_t sz = fs.size ();
 
-    std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+    std::string ascii_fname = sys::get_ASCII_filename (fname);
 
     std::ifstream file (ascii_fname.c_str (), std::ios::in | std::ios::binary);
 
--- a/liboctave/util/functor.h	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
-
-Copyright (C) 2008-2019 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_functor_h)
-#define octave_functor_h 1
-
-#include "octave-config.h"
-
-template <typename RT, typename PT>
-class fcn_ptr
-{
-public:
-  typedef RT (*TYPE) (PT);
-};
-
-template <typename RT, typename PT>
-class functor
-{
-private:
-  typedef typename fcn_ptr<RT, PT>::TYPE fcn_ptr_type;
-  fcn_ptr_type fptr;
-
-public:
-
-  functor (fcn_ptr_type p) : fptr (p) { }
-
-  RT operator () (PT arg) { return fptr (arg); }
-};
-
-template <typename CT, typename RT, typename PT>
-class functor_with_conversion
-{
-private:
-  typedef typename fcn_ptr<RT, PT>::TYPE fcn_ptr_type;
-  fcn_ptr_type fptr;
-
-public:
-
-  functor_with_conversion (fcn_ptr_type p) : fptr (p) { }
-
-  CT operator () (PT arg) { return CT (fptr (arg)); }
-};
-
-template <typename RT, typename PT>
-functor<RT, PT>
-func_ptr (RT (*f) (PT))
-{
-  return functor<RT, PT> (f);
-}
-
-template <typename CT, typename RT, typename PT>
-functor_with_conversion<CT, RT, PT>
-func_ptr_with_conversion (RT (*f) (PT))
-{
-  return functor_with_conversion<CT, RT, PT> (f);
-}
-
-#endif
--- a/liboctave/util/lo-array-errwarn.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/lo-array-errwarn.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -32,20 +32,23 @@
 #include "lo-array-errwarn.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";
-
 namespace octave
 {
+  // 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
   err_nan_to_logical_conversion (void)
   {
--- a/liboctave/util/lo-regexp.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/lo-regexp.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -45,20 +45,20 @@
 #include "lo-regexp.h"
 #include "str-vec.h"
 
-// Define the maximum number of retries for a pattern
-// that possibly results in an infinite recursion.
+namespace octave
+{
+  // Define the maximum number of retries for a pattern
+  // that possibly results in an infinite recursion.
 #define PCRE_MATCHLIMIT_MAX 10
 
-// FIXME: should this be configurable?
+  // FIXME: should this be configurable?
 #define MAXLOOKBEHIND 10
 
-static bool lookbehind_warned = false;
+  static bool lookbehind_warned = false;
 
-// FIXME: don't bother collecting and composing return values
-//        the user doesn't want.
+  // FIXME: don't bother collecting and composing return values
+  //        the user doesn't want.
 
-namespace octave
-{
   void
   regexp::free (void)
   {
--- a/liboctave/util/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -7,7 +7,6 @@
   %reldir%/cmd-hist.h \
   %reldir%/data-conv.h \
   %reldir%/file-info.h \
-  %reldir%/functor.h \
   %reldir%/glob-match.h \
   %reldir%/lo-array-errwarn.h \
   %reldir%/lo-cutils.h \
--- a/liboctave/util/oct-base64.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-base64.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -92,23 +92,3 @@
     return retval;
   }
 }
-
-// Always define these functions.  The macro is intended to allow the
-// declarations to be hidden, not so that Octave will not provide the
-// functions if they are requested.
-
-// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-bool
-octave_base64_encode (const char *inc, const size_t inlen, char **out)
-{
-  return octave::base64_encode (inc, inlen, out);
-}
-
-Array<double>
-octave_base64_decode (const std::string& str)
-{
-  return octave::base64_decode (str);
-}
-
-// #endif
--- a/liboctave/util/oct-base64.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-base64.h	Fri Jul 12 12:14:43 2019 -0400
@@ -38,16 +38,4 @@
   base64_decode (const std::string& str);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::base_64_encode' instead")
-extern bool
-octave_base64_encode (const char *inc, const size_t inlen, char **out);
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::base_64_decode' instead")
-extern Array<double>
-octave_base64_decode (const std::string& str);
-
 #endif
-
-#endif
--- a/liboctave/util/oct-binmap.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-binmap.h	Fri Jul 12 12:14:43 2019 -0400
@@ -66,40 +66,42 @@
 class bsxfun_wrapper
 {
 private:
-  static F f;
+
+  static F s_fcn;
 
 public:
+
   static void
   set_f (const F& f_in)
   {
-    f = f_in;
+    s_fcn = f_in;
   }
 
   static void
   op_mm (size_t n, R *r, const X *x , const Y *y)
   {
     for (size_t i = 0; i < n; i++)
-      r[i] = f (x[i], y[i]);
+      r[i] = s_fcn (x[i], y[i]);
   }
 
   static void
   op_sm (size_t n, R *r, X x, const Y *y)
   {
     for (size_t i = 0; i < n; i++)
-      r[i] = f (x, y[i]);
+      r[i] = s_fcn (x, y[i]);
   }
 
   static void
   op_ms (size_t n , R *r, const X *x, Y y)
   {
     for (size_t i = 0; i < n; i++)
-      r[i] = f (x[i], y);
+      r[i] = s_fcn (x[i], y);
   }
 };
 
 // Static init
 template <typename R, typename X, typename Y, typename F>
-F bsxfun_wrapper<R, X, Y, F>::f;
+F bsxfun_wrapper<R, X, Y, F>::s_fcn;
 
 // scalar-Array
 template <typename U, typename T, typename R, typename F>
--- a/liboctave/util/oct-glob.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-glob.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -39,16 +39,16 @@
 // transforms the glob_match::glob function to be glob_match::rpl_glob,
 // which is not what we want...
 
-static bool
-single_match_exists (const std::string& file)
-{
-  octave::sys::file_stat s (file);
-
-  return s.exists ();
-}
-
 namespace octave
 {
+  static bool
+  single_match_exists (const std::string& file)
+  {
+    sys::file_stat s (file);
+
+    return s.exists ();
+  }
+
   namespace sys
   {
     bool
--- a/liboctave/util/oct-mutex.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-mutex.h	Fri Jul 12 12:14:43 2019 -0400
@@ -152,26 +152,7 @@
     static void init (void);
 
     static bool is_thread (void);
-
-    OCTAVE_DEPRECATED (4.4, "use 'is_thread' instead")
-    static bool is_octave_thread (void) { return is_thread (); }
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::mutex' instead")
-typedef octave::mutex octave_mutex;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::base_mutex' instead")
-typedef octave::base_mutex octave_base_mutex;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::autolock' instead")
-typedef octave::autolock octave_autolock;
-
-OCTAVE_DEPRECATED (4.4, "use 'octave::thread' instead")
-typedef octave::thread octave_thread;
-
 #endif
-
-#endif
--- a/liboctave/util/oct-refcount.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-refcount.h	Fri Jul 12 12:14:43 2019 -0400
@@ -77,33 +77,33 @@
     typedef T count_type;
 
     refcount (count_type initial_count)
-      : count (initial_count)
+      : m_count (initial_count)
     { }
 
     // Increment/Decrement.  int is postfix.
     count_type operator++ (void)
     {
-      return OCTAVE_ATOMIC_INCREMENT (&count);
+      return OCTAVE_ATOMIC_INCREMENT (&m_count);
     }
 
     count_type operator++ (int)
     {
-      return OCTAVE_ATOMIC_POST_INCREMENT (&count);
+      return OCTAVE_ATOMIC_POST_INCREMENT (&m_count);
     }
 
     count_type operator-- (void)
     {
-      return OCTAVE_ATOMIC_DECREMENT (&count);
+      return OCTAVE_ATOMIC_DECREMENT (&m_count);
     }
 
     count_type operator-- (int)
     {
-      return OCTAVE_ATOMIC_POST_DECREMENT (&count);
+      return OCTAVE_ATOMIC_POST_DECREMENT (&m_count);
     }
 
     count_type value (void) const
     {
-      return static_cast<count_type const volatile&> (count);
+      return static_cast<count_type const volatile&> (m_count);
     }
 
     operator count_type (void) const
@@ -113,16 +113,13 @@
 
     count_type * get (void)
     {
-      return &count;
+      return &m_count;
     }
 
   private:
 
-    count_type count;
+    count_type m_count;
   };
 }
 
-template <typename T>
-using octave_refcount OCTAVE_DEPRECATED (4.4, "use 'octave::refcount' instead") = octave::refcount<T>;
-
 #endif
--- a/liboctave/util/oct-rl-hist.c	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-rl-hist.c	Fri Jul 12 12:14:43 2019 -0400
@@ -70,7 +70,7 @@
 }
 
 /* Remove all entries matching LINE from the history list.  Triggered when
-   HISTCONTROL includes `erasedups'.  */
+   HISTCONTROL includes 'erasedups'.  */
 
 static void
 hc_erasedups (const char *line)
--- a/liboctave/util/oct-shlib.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-shlib.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -27,15 +27,6 @@
 
 #include <map>
 
-#if defined (HAVE_SHL_LOAD_API)
-#  include <cerrno>
-#  include <cstring>
-#endif
-
-#if defined (HAVE_DYLD_API)
-#  include <mach-o/dyld.h>
-#endif
-
 extern "C"
 {
 #if defined (HAVE_DLOPEN_API)
@@ -47,8 +38,6 @@
 extern void * dlsym (void *, const char *);
 extern int dlclose (void *);
 #  endif
-#elif defined (HAVE_SHL_LOAD_API)
-#  include <dl.h>
 #elif defined (HAVE_LOADLIBRARY_API)
 #  define WIN32_LEAN_AND_MEAN 1
 #  include <windows.h>
@@ -265,84 +254,6 @@
     return function;
   }
 
-#elif defined (HAVE_SHL_LOAD_API)
-
-  class
-  octave_shl_load_shlib : public dynamic_library::dynlib_rep
-  {
-  public:
-
-    octave_shl_load_shlib (const std::string& f);
-
-    // No copying!
-
-    octave_shl_load_shlib (const octave_shl_load_shlib&) = delete;
-
-    octave_shl_load_shlib& operator = (const octave_shl_load_shlib&) = delete;
-
-    ~octave_shl_load_shlib (void);
-
-    void * search (const std::string& name,
-                   dynamic_library::name_mangler mangler = 0);
-
-    bool is_open (void) const { return (search_all_loaded || library != 0); }
-
-  private:
-
-    shl_t library;
-  };
-
-  octave_shl_load_shlib::octave_shl_load_shlib (const std::string& f)
-    : dynamic_library::dynlib_rep (f), library (0)
-  {
-    file = f;
-
-    if (file.empty())
-      {
-        search_all_loaded = true;
-        return;
-      }
-
-    library = shl_load (file.c_str (), BIND_IMMEDIATE, 0L);
-
-    if (! library)
-      {
-        using namespace std;  // FIXME: Why have this line?
-        (*current_liboctave_error_handler) ("%s", std::strerror (errno));
-      }
-  }
-
-  octave_shl_load_shlib::~octave_shl_load_shlib (void)
-  {
-    if (library)
-      shl_unload (library);
-  }
-
-  void *
-  octave_shl_load_shlib::search (const std::string& name,
-                                 dynamic_library::name_mangler mangler)
-  {
-    void *function = nullptr;
-
-    if (! is_open ())
-      (*current_liboctave_error_handler)
-        ("shared library %s is not open", file.c_str ());
-
-    std::string sym_name = name;
-
-    if (mangler)
-      sym_name = mangler (name);
-
-    if (search_all_loaded)
-      int status = shl_findsym (nullptr, sym_name.c_str (),
-                                TYPE_UNDEFINED, &function);
-    else
-      int status = shl_findsym (&library, sym_name.c_str (),
-                                TYPE_UNDEFINED, &function);
-
-    return function;
-  }
-
 #elif defined (HAVE_LOADLIBRARY_API)
 
   class
@@ -503,108 +414,6 @@
     return function;
   }
 
-#elif defined (HAVE_DYLD_API)
-
-  class
-  octave_dyld_shlib : public dynamic_library::dynlib_rep
-  {
-  public:
-
-    octave_dyld_shlib (void);
-
-    // No copying!
-
-    octave_dyld_shlib (const octave_dyld_shlib&) = delete;
-
-    octave_dyld_shlib& operator = (const octave_dyld_shlib&) = delete;
-
-    ~octave_dyld_shlib (void);
-
-    void open (const std::string& f);
-
-    void * search (const std::string& name,
-                   dynamic_library::name_mangler mangler = nullptr);
-
-    void close (void);
-
-    bool is_open (void) const { return (search_all_loaded || handle != 0); }
-
-  private:
-
-    NSObjectFileImage img;
-    NSModule handle;
-  };
-
-  octave_dyld_shlib::octave_dyld_shlib (const std::string& f)
-    : dynamic_library::dynlib_rep (f), handle (0)
-  {
-    if (f.empty ())
-      (*current_liboctave_error_handler)
-        ("global search is not implemented for DYLD_API");
-
-    int returnCode = NSCreateObjectFileImageFromFile (file.c_str (), &img);
-
-    if (NSObjectFileImageSuccess != returnCode)
-      {
-        (*current_liboctave_error_handler)
-          ("got NSObjectFileImageReturnCode %d", returnCode);
-
-        // FIXME: should use NSLinkEditError () to get
-        //        more info on what went wrong.
-      }
-
-    handle = NSLinkModule (img, file.c_str (),
-                           (NSLINKMODULE_OPTION_RETURN_ON_ERROR
-                            | NSLINKMODULE_OPTION_PRIVATE));
-    if (! handle)
-      {
-        NSLinkEditErrors ler;
-        int lerno;
-        const char *file2;
-        const char *errstr = nullptr;
-
-        NSLinkEditError (&ler, &lerno, &file2, &errstr);
-
-        if (! errstr)
-          errstr = "unspecified error";
-
-        (*current_liboctave_error_handler) ("%s: %s", file.c_str (), errstr);
-      }
-  }
-
-  octave_dyld_shlib::~octave_dyld_shlib (void)
-  {
-    if (handle)
-      NSUnLinkModule (handle, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
-
-    NSDestroyObjectFileImage (img);
-  }
-
-  void *
-  octave_dyld_shlib::search (const std::string& name,
-                             dynamic_library::name_mangler mangler)
-  {
-    void *function = nullptr;
-
-    if (! is_open ())
-      (*current_liboctave_error_handler)
-        ("bundle %s is not open", file.c_str ());
-
-    std::string sym_name = name;
-
-    if (mangler)
-      sym_name = mangler (name);
-
-    NSSymbol symbol = NSLookupSymbolInModule (handle, sym_name.c_str ());
-
-    if (symbol)
-      {
-        function = NSAddressOfSymbol (symbol);
-      }
-
-    return function;
-  }
-
 #endif
 
   dynamic_library::dynlib_rep *
@@ -612,12 +421,8 @@
   {
 #if defined (HAVE_DLOPEN_API)
     return new octave_dlopen_shlib (f);
-#elif defined (HAVE_SHL_LOAD_API)
-    return new octave_shl_load_shlib (f);
 #elif defined (HAVE_LOADLIBRARY_API)
     return new octave_w32_shlib (f);
-#elif defined (HAVE_DYLD_API)
-    return new octave_dyld_shlib (f);
 #else
     (*current_liboctave_error_handler)
       ("support for dynamically loaded libraries was unavailable or disabled when liboctave was built");
--- a/liboctave/util/oct-sort.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-sort.h	Fri Jul 12 12:14:43 2019 -0400
@@ -124,10 +124,6 @@
   // Check whether an array is sorted.
   bool issorted (const T *data, octave_idx_type nel);
 
-  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
-  bool is_sorted (const T *data, octave_idx_type nel)
-  { return issorted (data, nel); }
-
   // Sort a matrix by rows, return a permutation
   // vector.
   void sort_rows (const T *data, octave_idx_type *idx,
@@ -312,11 +308,6 @@
   bool issorted (const T *data, octave_idx_type nel, Comp comp);
 
   template <typename Comp>
-  OCTAVE_DEPRECATED (4.4, "use 'issorted' instead")
-  bool is_sorted (const T *data, octave_idx_type nel, Comp comp)
-  { return issorted (data, nel, comp); }
-
-  template <typename Comp>
   void sort_rows (const T *data, octave_idx_type *idx,
                   octave_idx_type rows, octave_idx_type cols,
                   Comp comp);
--- a/liboctave/util/oct-sparse.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-sparse.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -31,19 +31,19 @@
      || defined (HAVE_CHOLMOD) || defined (HAVE_COLAMD)         \
      || defined (HAVE_CXSPARSE) || defined (HAVE_UMFPACK))
 
-static inline void
-check_suitesparse_integer_size (void)
-{
-  // FIXME: maybe it would be better to make this a configure check and
-  // disable suitesparse if it fails?
-
-  if (sizeof (octave::suitesparse_integer) != sizeof (octave_idx_type))
-    (*current_liboctave_error_handler)
-      ("size of suitesparse integer does not match octave_idx_type!");
-}
-
 namespace octave
 {
+  static inline void
+  check_suitesparse_integer_size (void)
+  {
+    // FIXME: maybe it would be better to make this a configure check and
+    // disable suitesparse if it fails?
+
+    if (sizeof (suitesparse_integer) != sizeof (octave_idx_type))
+      (*current_liboctave_error_handler)
+        ("size of suitesparse integer does not match octave_idx_type!");
+  }
+
   suitesparse_integer *
   to_suitesparse_intptr (octave_idx_type *i)
   {
--- a/liboctave/util/oct-string.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-string.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -34,6 +34,8 @@
 #include "Array.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
+#include "uniconv-wrappers.h"
+#include "unwind-prot.h"
 
 template <typename T>
 static bool
@@ -484,6 +486,70 @@
   return val;
 }
 
+std::string
+octave::string::u8_to_encoding (const std::string& who,
+                                const std::string& u8_string,
+                                const std::string& encoding)
+{
+  const uint8_t *src = reinterpret_cast<const uint8_t *>
+                       (u8_string.c_str ());
+  size_t srclen = u8_string.length ();
+
+  size_t length;
+  char *native_str = octave_u8_conv_to_encoding (encoding.c_str (), src,
+                                                 srclen, &length);
+
+  if (! native_str)
+    {
+      if (errno == ENOSYS)
+        (*current_liboctave_error_handler)
+          ("%s: iconv() is not supported. Installing GNU libiconv and then "
+           "re-compiling Octave could fix this.", who.c_str ());
+      else
+        (*current_liboctave_error_handler)
+          ("%s: converting from UTF-8 to codepage '%s' failed: %s",
+           who.c_str (), encoding.c_str (), std::strerror (errno));
+    }
+
+  octave::unwind_protect frame;
+  frame.add_fcn (::free, static_cast<void *> (native_str));
+
+  std::string retval = std::string (native_str, length);
+
+  return retval;
+}
+
+std::string
+octave::string::u8_from_encoding (const std::string& who,
+                                  const std::string& native_string,
+                                  const std::string& encoding)
+{
+  const char *src = native_string.c_str ();
+  size_t srclen = native_string.length ();
+
+  size_t length;
+  uint8_t *utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src,
+                                                    srclen, &length);
+  if (! utf8_str)
+    {
+      if (errno == ENOSYS)
+        (*current_liboctave_error_handler)
+          ("%s: iconv() is not supported. Installing GNU libiconv and then "
+           "re-compiling Octave could fix this.", who.c_str ());
+      else
+        (*current_liboctave_error_handler)
+          ("%s: converting from codepage '%s' to UTF-8 failed: %s",
+           who.c_str (), encoding.c_str (), std::strerror (errno));
+    }
+
+  octave::unwind_protect frame;
+  frame.add_fcn (::free, static_cast<void *> (utf8_str));
+
+  std::string retval = std::string (reinterpret_cast<char *> (utf8_str), length);
+
+  return retval;
+}
+
 template <typename T>
 std::string
 rational_approx (T val, int len)
--- a/liboctave/util/oct-string.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/oct-string.h	Fri Jul 12 12:14:43 2019 -0400
@@ -125,6 +125,14 @@
 
     extern OCTAVE_API Complex
     str2double (const std::string& str_arg);
+
+    extern OCTAVE_API std::string
+    u8_to_encoding (const std::string& who, const std::string& u8_string,
+                    const std::string& encoding);
+
+    extern OCTAVE_API std::string
+    u8_from_encoding (const std::string& who, const std::string& native_string,
+                      const std::string& encoding);
   }
 }
 
--- a/liboctave/util/singleton-cleanup.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/singleton-cleanup.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -45,9 +45,5 @@
   if (! instance)
     instance = new singleton_cleanup_list ();
 
-  if (! instance)
-    (*current_liboctave_error_handler)
-      ("unable to create singleton_cleanup_list object!");
-
   return retval;
 }
--- a/liboctave/util/sparse-sort.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/sparse-sort.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -42,11 +42,13 @@
                           octave_sparse_sort_idxl *j)
 {
   octave_idx_type tmp = i->c - j->c;
+
   if (tmp < 0)
     return true;
   else if (tmp > 0)
     return false;
-  return  (i->r < j->r);
+
+  return (i->r < j->r);
 }
 
 template class octave_sort<octave_sparse_sort_idxl *>;
--- a/liboctave/util/sparse-sort.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/sparse-sort.h	Fri Jul 12 12:14:43 2019 -0400
@@ -32,6 +32,7 @@
 octave_sparse_sort_idxl
 {
 public:
+
   octave_idx_type r;
   octave_idx_type c;
   octave_idx_type idx;
@@ -44,6 +45,7 @@
 octave_idx_vector_sort
 {
 public:
+
   octave_idx_type i;
   octave_idx_type idx;
 };
--- a/liboctave/util/str-vec.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/str-vec.h	Fri Jul 12 12:14:43 2019 -0400
@@ -100,10 +100,14 @@
   }
 
   std::string& operator[] (octave_idx_type i)
-  { return Array<std::string>::elem (i); }
+  {
+    return Array<std::string>::elem (i);
+  }
 
   std::string operator[] (octave_idx_type i) const
-  { return Array<std::string>::elem (i); }
+  {
+    return Array<std::string>::elem (i);
+  }
 
   string_vector& sort (bool make_uniq = false);
 
--- a/liboctave/util/unwind-prot.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/unwind-prot.h	Fri Jul 12 12:14:43 2019 -0400
@@ -41,7 +41,7 @@
   {
   public:
 
-    unwind_protect (void) : lifo () { }
+    unwind_protect (void) : m_lifo () { }
 
     // No copying!
 
@@ -62,8 +62,8 @@
       if (! empty ())
         {
           // No leak on exception!
-          std::unique_ptr<elem> ptr (lifo.top ());
-          lifo.pop ();
+          std::unique_ptr<elem> ptr (m_lifo.top ());
+          m_lifo.pop ();
           ptr->run ();
         }
     }
@@ -72,22 +72,22 @@
     {
       if (! empty ())
         {
-          elem *ptr = lifo.top ();
-          lifo.pop ();
+          elem *ptr = m_lifo.top ();
+          m_lifo.pop ();
           delete ptr;
         }
     }
 
-    size_t size (void) const { return lifo.size (); }
+    size_t size (void) const { return m_lifo.size (); }
 
   protected:
 
     virtual void add_action (elem *new_elem)
     {
-      lifo.push (new_elem);
+      m_lifo.push (new_elem);
     }
 
-    std::stack<elem *> lifo;
+    std::stack<elem *> m_lifo;
   };
 
   // Like unwind_protect, but this one will guard against the possibility
--- a/liboctave/util/url-transfer.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/url-transfer.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -40,6 +40,7 @@
 #include "oct-env.h"
 #include "unwind-prot.h"
 #include "url-transfer.h"
+#include "version.h"
 
 #if defined (HAVE_CURL)
 #  include <curl/curl.h>
@@ -50,23 +51,26 @@
 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) { }
+    : m_host_or_url (), m_valid (false), m_ftp (false),
+      m_ascii_mode (false), m_ok (true), m_errmsg (),
+      m_curr_istream (&std::cin), m_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) { }
+    : m_host_or_url (host), m_valid (false), m_ftp (true),
+      m_ascii_mode (false), m_ok (true), m_errmsg (),
+      m_curr_istream (&std::cin), m_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) { }
+    : m_host_or_url (url), m_valid (false), m_ftp (false),
+      m_ascii_mode (false), m_ok (true), m_errmsg (),
+      m_curr_istream (&std::cin), m_curr_ostream (&os)
+  { }
 
   void
   base_url_transfer::delete_file (const std::string& file)
@@ -88,8 +92,8 @@
 
         if (status < 0)
           {
-            ok = false;
-            errmsg = "__ftp_mget__: can not create directory '"
+            m_ok = false;
+            m_errmsg = "__ftp_mget__: can not create directory '"
                      + target + sep + directory + "': " + msg;
             return;
           }
@@ -124,8 +128,8 @@
 
                 if (! ofile.is_open ())
                   {
-                    ok = false;
-                    errmsg = "__ftp_mget__: unable to open file";
+                    m_ok = false;
+                    m_errmsg = "__ftp_mget__: unable to open file";
                     break;
                   }
 
@@ -181,13 +185,15 @@
               if (file == "." || file == "..")
                 continue;
 
-              std::string realfile = realdir + sys::file_ops::dir_sep_str () + file;
+              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
+                  m_ok = false;
+                  m_errmsg = "__ftp__mput: file '" + realfile
                            + "' does not exist";
                   break;
                 }
@@ -202,16 +208,15 @@
               else
                 {
                   // FIXME: Does ascii mode need to be flagged here?
-                  std::string ascii_fname
-                    = octave::sys::get_ASCII_filename (realfile);
+                  std::string ascii_fname = sys::get_ASCII_filename (realfile);
 
                   std::ifstream ifile (ascii_fname.c_str (),
                                        std::ios::in | std::ios::binary);
 
                   if (! ifile.is_open ())
                     {
-                      ok = false;
-                      errmsg = "__ftp_mput__: unable to open file '"
+                      m_ok = false;
+                      m_errmsg = "__ftp_mput__: unable to open file '"
                                + realfile + "'";
                       break;
                     }
@@ -228,8 +233,8 @@
             }
         else
           {
-            ok = false;
-            errmsg = "__ftp_mput__: can not read the directory '"
+            m_ok = false;
+            m_errmsg = "__ftp_mput__: can not read the directory '"
                      + realdir + "'";
           }
       }
@@ -270,11 +275,11 @@
 #define SETOPT(option, parameter)                                       \
   do                                                                    \
     {                                                                   \
-      CURLcode res = curl_easy_setopt (curl, option, parameter);        \
+      CURLcode res = curl_easy_setopt (m_curl, option, parameter);      \
       if (res != CURLE_OK)                                              \
         {                                                               \
-          ok = false;                                                   \
-          errmsg = curl_easy_strerror (res);                            \
+          m_ok = false;                                                 \
+          m_errmsg = curl_easy_strerror (res);                          \
           return;                                                       \
         }                                                               \
     }                                                                   \
@@ -284,11 +289,11 @@
 #define SETOPTR(option, parameter)                                      \
   do                                                                    \
     {                                                                   \
-      CURLcode res = curl_easy_setopt (curl, option, parameter);        \
+      CURLcode res = curl_easy_setopt (m_curl, option, parameter);      \
       if (res != CURLE_OK)                                              \
         {                                                               \
-          ok = false;                                                   \
-          errmsg = curl_easy_strerror (res);                            \
+          m_ok = false;                                                 \
+          m_errmsg = curl_easy_strerror (res);                          \
           return retval;                                                \
         }                                                               \
     }                                                                   \
@@ -299,46 +304,46 @@
   public:
 
     curl_transfer (void)
-      : base_url_transfer (), curl (curl_easy_init ()), errnum (), url (),
-        userpwd ()
+      : base_url_transfer (), m_curl (curl_easy_init ()), m_errnum (), m_url (),
+        m_userpwd ()
     {
-      if (curl)
-        valid = true;
+      if (m_curl)
+        m_valid = true;
       else
-        errmsg = "can not create curl object";
+        m_errmsg = "can not create curl object";
     }
 
     curl_transfer (const std::string& host, const std::string& user_arg,
                    const std::string& passwd, std::ostream& os)
       : base_url_transfer (host, user_arg, passwd, os),
-        curl (curl_easy_init ()), errnum (), url (), userpwd ()
+        m_curl (curl_easy_init ()), m_errnum (), m_url (), m_userpwd ()
     {
-      if (curl)
-        valid = true;
+      if (m_curl)
+        m_valid = true;
       else
         {
-          errmsg = "can not create curl object";
+          m_errmsg = "can not create curl object";
           return;
         }
 
       init (user_arg, passwd, std::cin, os);
 
-      url = "ftp://" + host;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + host;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
 
       // Set up the link, with no transfer.
       perform ();
     }
 
     curl_transfer (const std::string& url_str, std::ostream& os)
-      : base_url_transfer (url_str, os), curl (curl_easy_init ()), errnum (),
-        url (), userpwd ()
+      : base_url_transfer (url_str, os), m_curl (curl_easy_init ()),
+        m_errnum (), m_url (), m_userpwd ()
     {
-      if (curl)
-        valid = true;
+      if (m_curl)
+        m_valid = true;
       else
         {
-          errmsg = "can not create curl object";
+          m_errmsg = "can not create curl object";
           return;
         }
 
@@ -369,20 +374,20 @@
 
     ~curl_transfer (void)
     {
-      if (curl)
-        curl_easy_cleanup (curl);
+      if (m_curl)
+        curl_easy_cleanup (m_curl);
     }
 
     void perform (void)
     {
       BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-      errnum = curl_easy_perform (curl);
+      m_errnum = curl_easy_perform (m_curl);
 
-      if (errnum != CURLE_OK)
+      if (m_errnum != CURLE_OK)
         {
-          ok = false;
-          errmsg = curl_easy_strerror (errnum);
+          m_ok = false;
+          m_errmsg = curl_easy_strerror (m_errnum);
         }
 
       END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
@@ -390,34 +395,34 @@
 
     std::string lasterror (void) const
     {
-      return std::string (curl_easy_strerror (errnum));
+      return std::string (curl_easy_strerror (m_errnum));
     }
 
     std::ostream& set_ostream (std::ostream& os)
     {
-      std::ostream& retval = *curr_ostream;
-      curr_ostream = &os;
-      SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (curr_ostream));
+      std::ostream& retval = *m_curr_ostream;
+      m_curr_ostream = &os;
+      SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (m_curr_ostream));
       return retval;
     }
 
     std::istream& set_istream (std::istream& is)
     {
-      std::istream& retval = *curr_istream;
-      curr_istream = &is;
-      SETOPTR (CURLOPT_READDATA, static_cast<void *> (curr_istream));
+      std::istream& retval = *m_curr_istream;
+      m_curr_istream = &is;
+      SETOPTR (CURLOPT_READDATA, static_cast<void *> (m_curr_istream));
       return retval;
     }
 
     void ascii (void)
     {
-      ascii_mode = true;
+      m_ascii_mode = true;
       SETOPT (CURLOPT_TRANSFERTEXT, 1);
     }
 
     void binary (void)
     {
-      ascii_mode = false;
+      m_ascii_mode = false;
       SETOPT (CURLOPT_TRANSFERTEXT, 0);
     }
 
@@ -463,8 +468,8 @@
 
     void put (const std::string& file, std::istream& is)
     {
-      url = "ftp://" + host_or_url + '/' + file;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url + '/' + file;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
       SETOPT (CURLOPT_UPLOAD, 1);
       SETOPT (CURLOPT_NOBODY, 0);
       std::istream& old_is = set_istream (is);
@@ -476,14 +481,14 @@
       set_istream (old_is);
       SETOPT (CURLOPT_NOBODY, 1);
       SETOPT (CURLOPT_UPLOAD, 0);
-      url = "ftp://" + host_or_url;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
     }
 
     void get (const std::string& file, std::ostream& os)
     {
-      url = "ftp://" + host_or_url + '/' + file;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url + '/' + file;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
       SETOPT (CURLOPT_NOBODY, 0);
       std::ostream& old_os = set_ostream (os);
 
@@ -493,14 +498,14 @@
 
       set_ostream (old_os);
       SETOPT (CURLOPT_NOBODY, 1);
-      url = "ftp://" + host_or_url;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
     }
 
     void dir (void)
     {
-      url = "ftp://" + host_or_url + '/';
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url + '/';
+      SETOPT (CURLOPT_URL, m_url.c_str ());
       SETOPT (CURLOPT_NOBODY, 0);
 
       perform ();
@@ -508,8 +513,8 @@
         return;
 
       SETOPT (CURLOPT_NOBODY, 1);
-      url = "ftp://" + host_or_url;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
     }
 
     string_vector list (void)
@@ -517,9 +522,9 @@
       string_vector retval;
 
       std::ostringstream buf;
-      url = "ftp://" + host_or_url + '/';
+      m_url = "ftp://" + m_host_or_url + '/';
       SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (&buf));
-      SETOPTR (CURLOPT_URL, url.c_str ());
+      SETOPTR (CURLOPT_URL, m_url.c_str ());
       SETOPTR (CURLOPT_DIRLISTONLY, 1);
       SETOPTR (CURLOPT_NOBODY, 0);
 
@@ -528,10 +533,10 @@
         return retval;
 
       SETOPTR (CURLOPT_NOBODY, 1);
-      url = "ftp://" + host_or_url;
-      SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (curr_ostream));
+      m_url = "ftp://" + m_host_or_url;
+      SETOPTR (CURLOPT_WRITEDATA, static_cast<void *> (m_curr_ostream));
       SETOPTR (CURLOPT_DIRLISTONLY, 0);
-      SETOPTR (CURLOPT_URL, url.c_str ());
+      SETOPTR (CURLOPT_URL, m_url.c_str ());
 
       // Count number of directory entries
       std::string str = buf.str ();
@@ -565,8 +570,8 @@
     {
       std::string path = pwd ();
 
-      url = "ftp://" + host_or_url + '/' + path + '/' + filename;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url + '/' + path + '/' + filename;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
       SETOPT (CURLOPT_FILETIME, 1);
       SETOPT (CURLOPT_HEADERFUNCTION, throw_away);
       SETOPT (CURLOPT_WRITEFUNCTION, throw_away);
@@ -588,17 +593,17 @@
 
       fileisdir = false;
       time_t ft;
-      curl_easy_getinfo (curl, CURLINFO_FILETIME, &ft);
+      curl_easy_getinfo (m_curl, CURLINFO_FILETIME, &ft);
       filetime = ft;
       double fs;
-      curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs);
+      curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs);
       filesize = fs;
 
       SETOPT (CURLOPT_WRITEFUNCTION, write_data);
       SETOPT (CURLOPT_HEADERFUNCTION, 0);
       SETOPT (CURLOPT_FILETIME, 0);
-      url = "ftp://" + host_or_url;
-      SETOPT (CURLOPT_URL, url.c_str ());
+      m_url = "ftp://" + m_host_or_url;
+      SETOPT (CURLOPT_URL, m_url.c_str ());
 
       // The MDTM command seems to reset the path to the root with the
       // servers I tested with, so cd again into the correct path.  Make
@@ -643,49 +648,168 @@
 
     void http_get (const Array<std::string>& param)
     {
-      url = host_or_url;
-
-      std::string query_string = form_query_string (param);
-
-      if (! query_string.empty ())
-        url += '?' + query_string;
-
-      SETOPT (CURLOPT_URL, url.c_str ());
-
-      perform ();
+      http_action (param, "get");
     }
 
     void http_post (const Array<std::string>& param)
     {
-      SETOPT (CURLOPT_URL, host_or_url.c_str ());
+      http_action (param, "post");
+    }
+
+    void http_action (const Array<std::string>& param, const std::string& action)
+    {
+      m_url = m_host_or_url;
+
+      std::string query_string;
+
+      query_string = form_query_string (param);
+
+      if (action.empty () || action == "get")
+        {
+          if (! query_string.empty ())
+            m_url += '?' + query_string;
+
+          SETOPT (CURLOPT_URL, m_url.c_str ());
+        }
+      else if (action == "post" || action == "put" || action == "delete")
+        {
+          SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ());
+
+          if (action == "put")
+            {
+              SETOPT (CURLOPT_CUSTOMREQUEST, "PUT");
+            }
+
+          if (action == "delete")
+            {
+              SETOPT (CURLOPT_CUSTOMREQUEST, "DELETE");
+            }
+
+          SETOPT (CURLOPT_URL, m_url.c_str ());
+        }
+      else
+        {
+          m_ok = false;
+          m_errmsg = "curl_transfer: unknown http action";
+        }
+
+      if (m_ok)
+        perform ();
+    }
+
+    void cookie_jar (const std::string& filename)
+    {
+      SETOPT (CURLOPT_COOKIEJAR, filename.c_str ());
+
+      SETOPT (CURLOPT_COOKIEFILE, filename.c_str ());
+    }
 
-      std::string query_string = form_query_string (param);
+    // Sets the header fields in a transfer. Input should be in the form
+    // of an array of strings with pairs of keys and values together
+    void set_header_fields (const Array<std::string>& param)
+    {
+      struct curl_slist *slist = nullptr;
+
+      unwind_protect frame;
+
+      frame.add_fcn (curl_slist_free_all, slist);
+
+      if (param.numel () >= 2)
+      {
+        for (int i = 0; i < param.numel (); i += 2)
+        {
+          std::string header = param(i) + ": " + param(i+1);
+
+          slist = curl_slist_append (slist, header.c_str ());
+        }
+
+        SETOPT (CURLOPT_HTTPHEADER, slist);
+      }
+    }
 
-      SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ());
+    // Sets and sends the form data associated with a transfer.
+    // Input should be an array of strings with each pair of strings
+    // corresponding to the fieldname and it's value.
+    // To attach a file, you should use 'file' as the fieldname with the
+    // path of the file as its value.
+    void form_data_post (const Array<std::string>& param)
+    {
+      struct curl_httppost *post = NULL, *last = NULL;
+
+      SETOPT (CURLOPT_URL, m_host_or_url.c_str ());
+
+      unwind_protect frame;
+
+      frame.add_fcn (curl_formfree, post);
+
+      if (param.numel () >= 2)
+      {
+        for (int i = 0; i < param.numel (); i += 2)
+          {
+            std::string name = param(i);
+            std::string data = param(i+1);
+
+            if (name == "file")
+               curl_formadd (&post, &last, CURLFORM_COPYNAME, name.c_str (),
+                             CURLFORM_FILE, data.c_str (), CURLFORM_END);
+            else
+               curl_formadd(&post, &last, CURLFORM_COPYNAME, name.c_str (),
+                            CURLFORM_COPYCONTENTS, data.c_str (), CURLFORM_END);
+          }
+
+        SETOPT (CURLOPT_HTTPPOST, post);
+      }
 
       perform ();
     }
 
-    void http_action (const Array<std::string>& param, const std::string& action)
+    // Sets the various options specified by weboptions object.
+    void set_weboptions (const struct weboptions& options)
     {
-      if (action.empty () || action == "get")
-        http_get (param);
-      else if (action == "post")
-        http_post (param);
-      else
-        {
-          ok = false;
-          errmsg = "curl_transfer: unknown http action";
-        }
+      // Remove this after completing fixmes.
+      std::string temp = "";
+
+      set_header_fields (options.HeaderFields);
+
+      SETOPT (CURLOPT_TIMEOUT, options.Timeout);
+
+      if (! options.UserAgent.empty ())
+        SETOPT (CURLOPT_USERAGENT, options.UserAgent.c_str ());
+
+      if (! options.Username.empty ())
+      {
+        if (! options.Password.empty ())
+          {
+            std::string tmp = options.Username + ":" + options.Password;
+            SETOPT (CURLOPT_USERPWD, tmp.c_str ());
+          }
+        else
+          {
+            std::string tmp = options.Username + ":";
+            SETOPT (CURLOPT_USERPWD, tmp.c_str ());
+          }
+      }
+
+      // Unimplemented. Only for MATLAB complatiblity.
+      if (! options.ContentReader.empty ())
+        temp = options.ContentReader;
+
+      // Unimplemented. Only for MATLAB complatiblity.
+      if (! options.ArrayFormat.empty ())
+        temp = options.ArrayFormat;
+
+      // Unimplemented. Only for MATLAB complatiblity.
+      if (! options.CertificateFilename.empty ())
+        temp = options.CertificateFilename;
     }
 
   private:
 
     // Pointer to cURL object.
-    CURL *curl;
+    CURL *m_curl;
 
     // cURL error code.
-    CURLcode errnum;
+    CURLcode m_errnum;
 
     // The cURL library changed the curl_easy_setopt call to make an
     // internal copy of string parameters in version 7.17.0.  Prior
@@ -700,8 +824,8 @@
     // the handle is released.  The curl_handle::curl_handle_rep class
     // contains the pointer to the CURL handle and so is the best
     // candidate for storing the strings as well. (bug #36717)
-    std::string url;
-    std::string userpwd;
+    std::string m_url;
+    std::string m_userpwd;
 
     void init (const std::string& user, const std::string& passwd,
                std::istream& is, std::ostream& os)
@@ -710,11 +834,11 @@
       SETOPT (CURLOPT_NOBODY, 1);
 
       // Set the username and password
-      userpwd = user;
+      m_userpwd = user;
       if (! passwd.empty ())
-        userpwd += ':' + passwd;
-      if (! userpwd.empty ())
-        SETOPT (CURLOPT_USERPWD, userpwd.c_str ());
+        m_userpwd += ':' + passwd;
+      if (! m_userpwd.empty ())
+        SETOPT (CURLOPT_USERPWD, m_userpwd.c_str ());
 
       // Define our callback to get called when there's data to be written.
       SETOPT (CURLOPT_WRITEFUNCTION, write_data);
@@ -736,6 +860,17 @@
       // instead.
       SETOPT (CURLOPT_FTP_USE_EPSV, false);
 
+      // Set the user agent for the curl request
+      // Needed by mediaWiki API.
+      curl_version_info_data * data = curl_version_info(CURLVERSION_NOW);
+      const char *lib_ver = data->version;
+      std::string user_agent =
+          "GNU Octave/" + std::string (OCTAVE_VERSION) +
+          " (https://www.gnu.org/software/octave/ ; help@octave.org) libcurl/"
+          + std::string (lib_ver);
+
+      SETOPT (CURLOPT_USERAGENT, user_agent.c_str ());
+
       SETOPT (CURLOPT_NOPROGRESS, true);
       SETOPT (CURLOPT_FAILONERROR, true);
 
@@ -747,25 +882,26 @@
     {
       std::ostringstream query;
 
-      for (int i = 0; i < param.numel (); i += 2)
-        {
-          std::string name = param(i);
-          std::string text = param(i+1);
+      if (param.numel () >= 2)
+        for (int i = 0; i < param.numel (); i += 2)
+          {
+            std::string name = param(i);
+            std::string text = param(i+1);
 
-          // Encode strings.
-          char *enc_name = curl_easy_escape (curl, name.c_str (),
-                                             name.length ());
-          char *enc_text = curl_easy_escape (curl, text.c_str (),
-                                             text.length ());
+            // Encode strings.
+            char *enc_name = curl_easy_escape (m_curl, name.c_str (),
+                                               name.length ());
+            char *enc_text = curl_easy_escape (m_curl, text.c_str (),
+                                               text.length ());
 
-          query << enc_name << '=' << enc_text;
+            query << enc_name << '=' << enc_text;
 
-          curl_free (enc_name);
-          curl_free (enc_text);
+            curl_free (enc_name);
+            curl_free (enc_text);
 
-          if (i < param.numel ()-1)
-            query << '&';
-        }
+            if (i < param.numel ()-2)
+              query << '&';
+          }
 
       query.flush ();
 
@@ -806,16 +942,16 @@
 #  define REP_CLASS base_url_transfer
 #endif
 
-  url_transfer::url_transfer (void) : rep (new REP_CLASS ())
+  url_transfer::url_transfer (void) : m_rep (new REP_CLASS ())
   { }
 
   url_transfer::url_transfer (const std::string& host, const std::string& user,
                               const std::string& passwd, std::ostream& os)
-    : rep (new REP_CLASS (host, user, passwd, os))
+    : m_rep (new REP_CLASS (host, user, passwd, os))
   { }
 
   url_transfer::url_transfer (const std::string& url, std::ostream& os)
-    : rep (new REP_CLASS (url, os))
+    : m_rep (new REP_CLASS (url, os))
   { }
 
 #undef REP_CLASS
--- a/liboctave/util/url-transfer.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/liboctave/util/url-transfer.h	Fri Jul 12 12:14:43 2019 -0400
@@ -41,6 +41,19 @@
 
 namespace octave
 {
+  struct weboptions
+  {
+    std::string UserAgent;
+    long Timeout;
+    std::string Username;
+    std::string Password;
+    Array<std::string> HeaderFields;
+    std::string ContentReader;
+    std::string RequestMethod;
+    std::string ArrayFormat;
+    std::string CertificateFilename;
+  };
+
   class
   OCTAVE_API
   base_url_transfer
@@ -75,31 +88,31 @@
 
     virtual ~base_url_transfer (void) = default;
 
-    bool is_valid (void) const { return valid; }
+    bool is_valid (void) const { return m_valid; }
 
-    bool good (void) const { return valid && ok; }
+    bool good (void) const { return m_valid && m_ok; }
 
     virtual void perform (void) { }
 
-    virtual std::string lasterror (void) const { return errmsg; }
+    virtual std::string lasterror (void) const { return m_errmsg; }
 
     virtual std::ostream& set_ostream (std::ostream& /* os */)
     {
-      return *curr_ostream;
+      return *m_curr_ostream;
     }
 
     virtual std::istream& set_istream (std::istream& /* is */)
     {
-      return *curr_istream;
+      return *m_curr_istream;
     }
 
     virtual void ascii (void) { }
 
     virtual void binary (void) { }
 
-    bool is_ascii (void) const { return ascii_mode; }
+    bool is_ascii (void) const { return m_ascii_mode; }
 
-    bool is_binary (void) const { return ! ascii_mode; }
+    bool is_binary (void) const { return ! m_ascii_mode; }
 
     virtual void cwd (const std::string& /* path */) { }
 
@@ -142,17 +155,25 @@
     virtual void http_action (const Array<std::string>& /* param */,
                               const std::string& /* action */) { }
 
+    virtual void cookie_jar (const std::string& /* filename */) { }
+
+    virtual void set_header_fields (const Array<std::string>& /* param */) { }
+
+    virtual void form_data_post (const Array<std::string>& /* param */) { }
+
+    virtual void set_weboptions (const struct weboptions& /* param */) { }
+
   protected:
 
     // Host for ftp transfers or full URL for http requests.
-    std::string host_or_url;
-    bool valid;
-    bool ftp;
-    bool ascii_mode;
-    bool ok;
-    std::string errmsg;
-    std::istream *curr_istream;
-    std::ostream *curr_ostream;
+    std::string m_host_or_url;
+    bool m_valid;
+    bool m_ftp;
+    bool m_ascii_mode;
+    bool m_ok;
+    std::string m_errmsg;
+    std::istream *m_curr_istream;
+    std::ostream *m_curr_ostream;
   };
 
   class
@@ -174,90 +195,116 @@
 
     ~url_transfer (void) = default;
 
-    bool is_valid (void) const { return rep->is_valid (); }
+    bool is_valid (void) const { return m_rep->is_valid (); }
 
-    bool good (void) const { return rep->good (); }
+    bool good (void) const { return m_rep->good (); }
 
-    std::string lasterror (void) const { return rep->lasterror (); }
+    std::string lasterror (void) const { return m_rep->lasterror (); }
 
     std::ostream& set_ostream (std::ostream& os)
     {
-      return rep->set_ostream (os);
+      return m_rep->set_ostream (os);
     }
 
     std::istream& set_istream (std::istream& is)
     {
-      return rep->set_istream (is);
+      return m_rep->set_istream (is);
     }
 
-    void ascii (void) { rep->ascii (); }
+    void ascii (void) { m_rep->ascii (); }
 
-    void binary (void) { rep->binary (); }
+    void binary (void) { m_rep->binary (); }
 
-    bool is_ascii (void) const { return rep->is_ascii (); }
+    bool is_ascii (void) const { return m_rep->is_ascii (); }
 
-    bool is_binary (void) const { return rep->is_binary (); }
+    bool is_binary (void) const { return m_rep->is_binary (); }
 
-    void cwd (const std::string& path) { rep->cwd (path); }
+    void cwd (const std::string& path) { m_rep->cwd (path); }
 
-    void del (const std::string& file) { rep->del (file); }
+    void del (const std::string& file) { m_rep->del (file); }
 
-    void rmdir (const std::string& path) { rep->rmdir (path); }
+    void rmdir (const std::string& path) { m_rep->rmdir (path); }
 
-    void mkdir (const std::string& path) { rep->mkdir (path); }
+    void mkdir (const std::string& path) { m_rep->mkdir (path); }
 
     void rename (const std::string& oldname, const std::string& newname)
     {
-      rep->rename (oldname, newname);
+      m_rep->rename (oldname, newname);
     }
 
     void put (const std::string& file, std::istream& is)
     {
-      rep->put (file, is);
+      m_rep->put (file, is);
     }
 
     void get (const std::string& file, std::ostream& os)
     {
-      rep->get (file, os);
+      m_rep->get (file, os);
     }
 
     void mget_directory (const std::string& directory,
                          const std::string& target)
     {
-      rep->mget_directory (directory, target);
+      m_rep->mget_directory (directory, target);
     }
 
     string_vector mput_directory (const std::string& base,
                                   const std::string& directory)
     {
-      return rep->mput_directory (base, directory);
+      return m_rep->mput_directory (base, directory);
     }
 
-    void dir (void) { rep->dir (); }
+    void dir (void) { m_rep->dir (); }
 
-    string_vector list (void) { return rep->list (); }
+    string_vector list (void) { return m_rep->list (); }
 
     void get_fileinfo (const std::string& filename, double& filesize,
                        time_t& filetime, bool& fileisdir)
     {
-      rep->get_fileinfo (filename, filesize, filetime, fileisdir);
+      m_rep->get_fileinfo (filename, filesize, filetime, fileisdir);
     }
 
-    std::string pwd (void) { return rep->pwd (); }
+    std::string pwd (void) { return m_rep->pwd (); }
 
-    void http_get (const Array<std::string>& param) { rep->http_get (param); }
+    void http_get (const Array<std::string>& param)
+    {
+      m_rep->http_get (param);
+    }
 
-    void http_post (const Array<std::string>& param) { rep->http_post (param); }
+    void http_post (const Array<std::string>& param)
+    {
+      m_rep->http_post (param);
+    }
 
     void http_action (const Array<std::string>& param,
                       const std::string& action)
     {
-      rep->http_action (param, action);
+      m_rep->http_action (param, action);
+    }
+
+    void cookie_jar (const std::string& filename)
+    {
+      m_rep->cookie_jar (filename);
+    }
+
+    void set_header_fields (const Array<std::string>& param)
+    {
+      m_rep->set_header_fields (param);
+    }
+
+    void form_data_post (const Array<std::string>& param)
+    {
+      m_rep->form_data_post (param);
+    }
+
+    void set_weboptions (const struct weboptions& param)
+    {
+      m_rep->set_weboptions (param);
     }
 
   private:
 
-    std::shared_ptr<base_url_transfer> rep;
+    std::shared_ptr<base_url_transfer> m_rep;
   };
 }
 
--- a/m4/acinclude.m4	Wed Jul 10 20:02:44 2019 -0700
+++ b/m4/acinclude.m4	Fri Jul 12 12:14:43 2019 -0400
@@ -592,46 +592,6 @@
   fi
 ])
 dnl
-dnl Check whether the QScintilla class QsciScintilla has the
-dnl findFirstInSelection member function.  This member function was introduced
-dnl in QScintilla 2.7.
-dnl
-dnl FIXME: Delete this entirely when we can safely assume that QScintilla 2.7
-dnl or later is in use everywhere, or when we drop support for Qt 4 (Qt 5 only
-dnl works with QScintilla 2.7.1 or later).
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QSCI_FINDSELECTION], [
-  AC_CACHE_CHECK([for QsciScintilla::findFirstInSelection in <Qsci/qsciscintilla.h>],
-    [octave_cv_func_qsci_findfirstinselection],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <Qsci/qsciscintilla.h>
-        class qsci : public QsciScintilla
-        {
-        public:
-          qsci (QWidget *parent = 0) : QsciScintilla (parent)
-          { this->findFirstInSelection (QString ("x"),true,true,true,true,true); }
-          ~qsci () {}
-        };
-        ]], [[
-        qsci edit;
-        ]])],
-      octave_cv_func_qsci_findfirstinselection=yes,
-      octave_cv_func_qsci_findfirstinselection=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qsci_findfirstinselection = yes; then
-    AC_DEFINE(HAVE_QSCI_FINDSELECTION, 1,
-      [Define to 1 if you have the `QsciScintilla::findFirstInSelection' member function.])
-  fi
-])
-dnl
 dnl Check whether QObject::findChildren accepts Qt::FindChildOptions
 dnl argument.
 dnl
@@ -733,6 +693,42 @@
   fi
 ])
 dnl
+dnl Check whether the Qt class QWheelEvent has the angleDelta member function.
+dnl This member function was introduced in Qt 5.
+dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 4.
+dnl
+AC_DEFUN([OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA], [
+  AC_CACHE_CHECK([for QWheelEvent::angleDelta in <QWheelEvent>],
+    [octave_cv_func_qwheelevent_angledelta],
+    [AC_LANG_PUSH(C++)
+    ac_octave_save_CPPFLAGS="$CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #include <QWheelEvent>
+        class wheel_event : public QWheelEvent
+        {
+        public:
+          wheel_event (QWidget *parent = 0) : QWheelEvent (parent) { this->angleDelta (); }
+          ~wheel_event () {}
+        };
+        ]], [[
+        wheel_event tw;
+        ]])],
+      octave_cv_func_qwheelevent_angledelta=yes,
+      octave_cv_func_qwheelevent_angledelta=no)
+    CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_func_qwheelevent_angledelta = yes; then
+    AC_DEFINE(HAVE_QWHEELEVENT_ANGLEDELTA, 1,
+      [Define to 1 if you have the `QWheelEvent::angleDelta' member function.])
+  fi
+])
+dnl
 dnl Check whether Qt message handler function accepts QMessageLogContext
 dnl argument.  This change was introduced in Qt 5.
 dnl
@@ -2147,6 +2143,7 @@
     OCTAVE_CHECK_FUNC_QSCREEN_DEVICEPIXELRATIO
     OCTAVE_CHECK_FUNC_QTABWIDGET_SETMOVABLE
     OCTAVE_CHECK_FUNC_QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT
+    OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA
     OCTAVE_CHECK_MEMBER_QFONT_FORCE_INTEGER_METRICS
     OCTAVE_CHECK_MEMBER_QFONT_MONOSPACE
     OCTAVE_HAVE_QGUIAPPLICATION
@@ -2211,18 +2208,51 @@
   ])
 ])
 dnl
+dnl Check whether SUNDIALS libraries provide a compatible interface.
+dnl The current recommended interface was introduced in SUNDIALS version 4.
+dnl The deprecated interface that Octave currently works to be compatible with
+dnl was introduced in SUNDIALS version 3.
+dnl
+AC_DEFUN([OCTAVE_CHECK_SUNDIALS_COMPATIBLE_API], [
+  ac_octave_save_LIBS=$LIBS
+  LIBS="$SUNDIALS_IDA_LIBS $SUNDIALS_NVECSERIAL_LIBS $LIBS"
+  dnl Current API functions present in SUNDIALS version 4
+  AC_CHECK_FUNCS([IDASetJacFn IDASetLinearSolver SUNLinSol_Dense])
+  dnl FIXME: The purpose of the following tests is to detect the deprecated
+  dnl API from SUNDIALS version 3, which should only be used if the current
+  dnl API tests above failed. For now, always test for ida_direct.h.
+  AC_CHECK_HEADERS([ida/ida_direct.h ida_direct.h])
+  dnl Each of these is a deprecated analog to the functions listed above.
+  AC_CHECK_FUNCS([IDADlsSetJacFn IDADlsSetLinearSolver SUNDenseLinearSolver])
+  LIBS=$ac_octave_save_LIBS
+  AC_MSG_CHECKING([whether SUNDIALS API provides the necessary functions])
+  if test "x$ac_cv_func_IDASetJacFn" = xyes \
+     && test "x$ac_cv_func_IDASetLinearSolver" = xyes \
+     && test "x$ac_cv_func_SUNLinSol_Dense" = xyes; then
+    octave_have_sundials_compatible_api=yes
+  elif test "x$ac_cv_func_IDADlsSetJacFn" = xyes \
+     && test "x$ac_cv_func_IDADlsSetLinearSolver" = xyes \
+     && test "x$ac_cv_func_SUNDenseLinearSolver" = xyes; then
+    octave_have_sundials_compatible_api=yes
+  else
+    octave_have_sundials_compatible_api=no
+  fi
+  AC_MSG_RESULT([$octave_have_sundials_compatible_api])
+  if test $octave_have_sundials_compatible_api = no; then
+    warn_sundials_disabled="SUNDIALS libraries do not provide an API that is compatible with Octave.  The solvers ode15i and ode15s will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
+  fi
+])
+dnl
 dnl Check whether SUNDIALS IDA library is configured with double
 dnl precision realtype.
 dnl
 AC_DEFUN([OCTAVE_CHECK_SUNDIALS_SIZEOF_REALTYPE], [
-  AC_CHECK_HEADERS([ida/ida.h ida.h])
   AC_CACHE_CHECK([whether SUNDIALS IDA is configured with double precision realtype],
     [octave_cv_sundials_realtype_is_double],
     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #if defined (HAVE_IDA_IDA_H)
-        #include <ida/ida.h>
-        #else
-        #include <ida.h>
+        #  include <ida/ida.h>
         #endif
         #include <assert.h>
         ]], [[
@@ -2233,66 +2263,100 @@
       octave_cv_sundials_realtype_is_double=no)
   ])
   if test $octave_cv_sundials_realtype_is_double = no; then
-    warn_sundials_realtype="SUNDIALS IDA library not configured with double precision realtype, ode15i and ode15s will be disabled"
-    OCTAVE_CONFIGURE_WARNING([warn_sundials_realtype])
+    warn_sundials_disabled="SUNDIALS IDA library not configured with double precision realtype.  The solvers ode15i and ode15s will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
   fi
 ])
 dnl
-dnl Check whether SUNDIALS IDA library is configured with IDAKLU
+dnl Check whether SUNDIALS IDA library is configured with SUNLINSOL_KLU
 dnl enabled.
 dnl
-AC_DEFUN([OCTAVE_CHECK_SUNDIALS_IDAKLU], [
-  AC_CHECK_HEADERS([ida/ida_klu.h ida_klu.h])
-  AC_CACHE_CHECK([whether SUNDIALS IDA is configured with IDAKLU enabled],
-    [octave_cv_sundials_idaklu],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-         #if defined (HAVE_IDA_IDA_KLU_H)
-         #include <ida/ida_klu.h>
-         #else
-         #include <ida_klu.h>
+AC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU], [
+  ## Including <sunlinsol/sunlinsol_klu.h> may depend on including klu.h
+  ## first.  So perform the check as follows using several different
+  ## possible locations for klu.h instead of using OCTAVE_CHECK_LIB to
+  ## check for sunlinsol_klu.h.
+  AC_CHECK_HEADERS([klu.h klu/klu.h suitesparse/klu.h ufsparse/klu.h])
+  AC_CHECK_HEADERS([sunlinsol/sunlinsol_klu.h], [], [],
+    [#if defined (HAVE_KLU_H)
+     #  include <klu.h>
+     #elif  defined (HAVE_KLU_KLU_H)
+     #  include <klu/klu.h>
+     #elif  defined (HAVE_SUITESPARSE_KLU_H)
+     #  include <suitesparse/klu.h>
+     #elif  defined (HAVE_UFSPARSE_KLU_H)
+     #  include <ufsparse/klu.h>
+     #endif
+    ])
+  OCTAVE_CHECK_LIB(sundials_sunlinsolklu, SUNLINSOL_KLU, [],
+    [], [SUNKLU], [],
+    [don't use SUNDIALS SUNLINSOL_KLU library, disable ode15i and ode15s sparse Jacobian],
+    [AC_CHECK_FUNCS([SUNLinSol_KLU SUNKLU])
+     AC_CACHE_CHECK([whether compiling a program that calls SUNKLU works],
+      [octave_cv_sundials_sunlinsol_klu],
+      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+         #if defined (HAVE_IDA_IDA_H)
+         #include <ida/ida.h>
+         #endif
+         #if defined (HAVE_KLU_H)
+         #include <klu.h>
+         #endif
+         #if defined (HAVE_KLU_KLU_H)
+         #include <klu/klu.h>
+         #endif
+         #if defined (HAVE_SUITESPARSE_KLU_H)
+         #include <suitesparse/klu.h>
+         #endif
+         #if defined (HAVE_UFPARSE_KLU_H)
+         #include <ufsparse/klu.h>
+         #endif
+         #if defined (HAVE_SUNLINSOL_SUNLINSOL_KLU_H)
+         #include <sunlinsol/sunlinsol_klu.h>
          #endif
          ]], [[
-         IDAKLU (0, 0, 0, 0);
+         SUNKLU (0, 0);
       ]])],
-      octave_cv_sundials_idaklu=yes,
-      octave_cv_sundials_idaklu=no)
-    ])
-  if test $octave_cv_sundials_idaklu = yes; then
-    AC_DEFINE(HAVE_SUNDIALS_IDAKLU, 1,
-      [Define to 1 if SUNDIALS IDA is configured with IDAKLU enabled.])
+      octave_cv_sundials_sunlinsol_klu=yes,
+      octave_cv_sundials_sunlinsol_klu=no)
+    ])])
+  if test "x$ac_cv_header_sunlinsol_sunlinsol_klu_h" = xyes \
+     && test "x$octave_cv_sundials_sunlinsol_klu" = xyes; then
+    AC_DEFINE(HAVE_SUNDIALS_SUNLINSOL_KLU, 1,
+      [Define to 1 if SUNDIALS IDA is configured with SUNLINSOL_KLU enabled.])
   else
-    warn_sundials_idaklu="SUNDIALS IDA library not configured with IDAKLU, ode15i and ode15s will not support the sparse Jacobian feature"
-    OCTAVE_CONFIGURE_WARNING([warn_sundials_idaklu])
+    warn_sundials_sunlinsol_klu="SUNDIALS IDA library not configured with SUNLINSOL_KLU or sunlinksol_klu.h is not usable.  The solvers ode15i and ode15s will not support the sparse Jacobian feature."
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_sunlinsol_klu])
   fi
 ])
 dnl
-dnl Check whether SUNDIALS IDA library has the IDADENSE linear solver.
+dnl Check whether SUNDIALS IDA library has the SUNLINSOL_DENSE linear solver.
 dnl The IDADENSE API was removed in SUNDIALS version 3.0.0.
 dnl
-AC_DEFUN([OCTAVE_CHECK_SUNDIALS_IDA_DENSE], [
-  AC_CHECK_HEADERS([ida/ida_dense.h ida_dense.h])
-  AC_CACHE_CHECK([whether SUNDIALS IDA includes the IDADENSE linear solver],
-    [octave_cv_sundials_ida_dense],
+AC_DEFUN([OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE], [
+  AC_CHECK_HEADERS([sunlinsol/sunlinsol_dense.h])
+  AC_CACHE_CHECK([whether SUNDIALS IDA includes the SUNLINSOL_DENSE linear solver],
+    [octave_cv_sundials_sunlinsol_dense],
     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-         #if defined (HAVE_IDA_IDA_DENSE_H)
-         #include <ida/ida_dense.h>
-         #else
-         #include <ida_dense.h>
+         #if defined (HAVE_IDA_IDA_H)
+         #  include <ida/ida.h>
+         #endif
+         #if defined (HAVE_SUNLINSOL_SUNLINSOL_DENSE_H)
+         #  include <sunlinsol/sunlinsol_dense.h>
          #endif
          ]], [[
          void *mem = 0;
          long int num = 0;
          IDADense (mem, num);
       ]])],
-      octave_cv_sundials_ida_dense=yes,
-      octave_cv_sundials_ida_dense=no)
+      octave_cv_sundials_sunlinsol_dense=yes,
+      octave_cv_sundials_sunlinsol_dense=no)
     ])
-  if test $octave_cv_sundials_ida_dense = yes; then
-    AC_DEFINE(HAVE_SUNDIALS_IDADENSE, 1,
-      [Define to 1 if SUNDIALS IDA includes the IDADENSE linear solver.])
+  if test $octave_cv_sundials_sunlinsol_dense = yes; then
+    AC_DEFINE(HAVE_SUNDIALS_SUNLINSOL_DENSE, 1,
+      [Define to 1 if SUNDIALS IDA includes the SUNLINSOL_DENSE linear solver.])
   else
-    warn_sundials_ida_dense="SUNDIALS IDA library does not include the IDADENSE linear solver, ode15i and ode15s will be disabled"
-    OCTAVE_CONFIGURE_WARNING([warn_sundials_ida_dense])
+    warn_sundials_disabled="SUNDIALS IDA library does not include the SUNLINSOL_DENSE linear solver.  The solvers ode15i and ode15s will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
   fi
 ])
 dnl
--- a/oct-conf-post.in.h	Wed Jul 10 20:02:44 2019 -0700
+++ b/oct-conf-post.in.h	Fri Jul 12 12:14:43 2019 -0400
@@ -124,6 +124,11 @@
 #  define OCTAVE_USE_OS_X_API 1
 #endif
 
+/* Silence deprecated API warning from Apple OS > 10.14 */
+#if defined (__APPLE__) && defined (__MACH__) && defined (HAVE_OPENGL)
+#  define GL_SILENCE_DEPRECATION 1
+#endif
+
 /* Define to 1 if we expect to have <windows.h>, Sleep, etc. */
 #if defined (__WIN32__) && ! defined (__CYGWIN__)
 #  define OCTAVE_USE_WINDOWS_API 1
--- a/scripts/+containers/Map.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/+containers/Map.m	Fri Jul 12 12:14:43 2019 -0400
@@ -376,6 +376,9 @@
             otherwise
               error ("containers.Map: unknown property '%s'", s(1).subs);
           endswitch
+          if (numel (s) > 1 && strcmp (s(2).type, "()") && isempty (s(2).subs))
+            s(1) = [];
+          endif
         case "()"
           if (isempty (s(1).subs))
             error ("containers.Map: no key specified");
@@ -785,9 +788,16 @@
 %!error <specified key .b. does not exist>
 %! m = containers.Map ("a", 1);
 %! m("b");
-%!error <specified key .2. does not exist>
-%! m = containers.Map (1, 1);
-%! m(2);
+%!test
+%! [old_fmt, old_spacing] = format ();
+%! unwind_protect
+%!   format short;
+%!   m = containers.Map (1, 1);
+%!   fail ("m(2)", "specified key <2> does not exist");
+%! unwind_protect_cleanup
+%!   format (old_fmt);
+%!   format (old_spacing);
+%! end_unwind_protect
 %!error <only '\(\)' indexing is supported>
 %! m = containers.Map ("a", 1);
 %! m{1};
--- a/scripts/deprecated/chop.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-## Copyright (C) 2010-2019 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 {} {} chop (@var{x}, @var{ndigits}, @var{base})
-##
-## @code{chop} is deprecated and will be removed in Octave version 6.
-##
-## Truncate elements of @var{x} to a length of @var{ndigits} such that the
-## resulting numbers are exactly divisible by @var{base}.
-##
-## If @var{base} is not specified it defaults to 10.
-##
-## @example
-## @group
-## format long
-## chop (-pi, 5, 10)
-##    @result{} -3.14200000000000
-## chop (-pi, 5, 5)
-##    @result{} -3.14150000000000
-## @end group
-## @end example
-## @end deftypefn
-
-## Deprecated in version 4.4
-
-function retval = chop (x, ndigits, base = 10)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "chop is obsolete and will be removed from a future version of Octave");
-  endif
-
-  if (nargin == 2 || nargin == 3)
-    tmp = abs (x);
-
-    ## Avoid computing log (0).
-    tmp(x == 0) = 1;
-
-    ## Digits to the left of the decimal.
-    tmp = floor (log10 (tmp) + 1);
-
-    ## The expression
-    ##
-    ##   round (x .* inflate)
-    ##
-    ## produces an integer that contains the digits we want to keep.
-    ## Multiplying by deflate puts the decimal back where it belngs.
-    ##
-    ## Further scaling and rounding with the base factor produces a
-    ## value with ndigits exactly divisible by base.  We skip that step
-    ## unless base was explicitly provided.
-
-    inflate = 10 .^ (ndigits - tmp);
-    deflate = 1 ./ inflate;
-    if (nargin == 2)
-      retval = deflate .* round (x .* inflate);
-    else
-      retval = base .* deflate .* round (round (x .* inflate) ./ base);
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-
-## First test is necessary to provoke 1-time legacy warning
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! chop (0, 1);
-
-%!assert (chop (e, 3), 2.72)
-%!assert (chop (e, 4), 2.718)
-%!assert (chop (e, 4, 5), 2.72)
-%!assert (chop (e, 4, 7), 2.716)
-%!assert (chop (-e, 3), -2.72)
-%!assert (chop (-e, 4), -2.718)
-%!assert (chop (-e, 4, 5), -2.72)
-%!assert (chop (-e, 4, 7), -2.716)
-%!assert (chop (hilb (3), 3), [1,.5,.333;.5,.333,.25;.333,.25,.2])
-%!assert (chop (hilb (3), 2, 7), [.7,.49,.35;.49,.35,.28;.35,.28,.21], 2*eps)
--- a/scripts/deprecated/comma.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-## Copyright (C) 1995-2019 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 {} {} ,
-## Array index, function argument, or command separator.
-## @seealso{semicolon}
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
--- a/scripts/deprecated/desktop.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-## Copyright (C) 2013-2019 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{used} =} desktop ("-inuse")
-##
-## @code{desktop} is deprecated and will be removed in Octave version 6.
-## Use @code{isguirunning} for the equivalent functionality.
-##
-## Return true if the desktop (GUI) is currently in use.
-## @seealso{isguirunning}
-## @end deftypefn
-
-## Deprecated in version 4.4
-
-function retval = desktop (arg)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "desktop is obsolete and will be removed from a future version of Octave, please use isguirunning instead");
-  endif
-
-  if (nargin == 0)
-    if (isguirunning ())
-      return;  # desktop() is a NOP when GUI running
-    else
-      print_usage ();
-    endif
-  elseif (nargin > 1)
-    error ('desktop: only one argument, "-inuse", is allowed');
-  endif
-
-  switch (tolower (arg))
-    case "-inuse"
-      retval = isguirunning ();
-    otherwise
-      print_usage ();
-  endswitch
-
-endfunction
-
-
-## Test input validation
-%!error <only one argument, "-inuse", is allowed> desktop (1,2)
-%!error desktop ("-invalid_option")
--- a/scripts/deprecated/java2mat.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-## Copyright (C) 2018-2019 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 {} {} java2mat (@var{javaobj})
-## @code{java2mat} is deprecated and will be removed in Octave version 6.
-##
-## For the next two releases, use @code{__java2mat__} if necessary, and file
-## a bug report explaining your programming use of @code{java2mat} and how it
-## can't be done with other Octave functions.
-## @end deftypefn
-
-function retval = java2mat (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java2mat is obsolete and will be removed from a future version of Octave");
-  endif
-
-  retval = __java2mat__ (varargin{:});
-
-endfunction
-
-
-## No tests needed for alias.
-%!assert (1)
--- a/scripts/deprecated/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/deprecated/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -1,15 +1,8 @@
 FCN_FILE_DIRS += scripts/deprecated
 
 %canon_reldir%_FCN_FILES = \
-  %reldir%/chop.m \
-  %reldir%/comma.m \
-  %reldir%/desktop.m \
-  %reldir%/java2mat.m \
   %reldir%/output_max_field_width.m \
-  %reldir%/paren.m \
-  %reldir%/semicolon.m \
-  %reldir%/tmpnam.m \
-  %reldir%/toascii.m
+  %reldir%/runtests.m
 
 %canon_reldir%dir = $(fcnfiledir)/deprecated
 
--- a/scripts/deprecated/output_max_field_width.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/deprecated/output_max_field_width.m	Fri Jul 12 12:14:43 2019 -0400
@@ -41,7 +41,7 @@
   if (! warned)
     warned = true;
     warning ("Octave:deprecated-function",
-             "output_max_field_width is obsolete and will be removed from a future version of Octave, please use output_precision instead");
+             "output_max_field_width is obsolete and will be removed from a future version of Octave, please use output_precision instead\n");
   endif
 
   retval = 20;
--- a/scripts/deprecated/paren.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-## Copyright (C) 1996-2019 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  {} {} (
-## @deftypefnx {} {} )
-## Array index or function argument delimeter.
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/runtests.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,49 @@
+## Copyright (C) 2010-2019 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  {} {} runtests ()
+## @deftypefnx {} {} runtests (@var{directory})
+##
+##
+## @code{runtests} is deprecated and will be removed in Octave version 8.
+## Use @code{oruntests} instead.
+##
+## Execute built-in tests for all m-files in the specified @var{directory}.
+##
+## Test blocks in any C++ source files (@file{*.cc}) will also be executed
+## for use with dynamically linked oct-file functions.
+##
+## If no directory is specified, operate on all directories in Octave's search
+## path for functions.
+## @seealso{oruntests, rundemos, test, path}
+## @end deftypefn
+
+## FIXME: DEPRECATED: Remove in version 8.
+
+function runtests (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "runtests is obsolete and will be removed from a future version of Octave, please use oruntests instead\n");
+  endif
+
+  oruntests (varargin{:}); 
+endfunction
--- a/scripts/deprecated/semicolon.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-## Copyright (C) 1995-2019 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 {} {} ;
-## Array row or command separator.
-## @seealso{comma}
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
--- a/scripts/deprecated/tmpnam.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-## Copyright (C) 2003-2019 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{fname} =} tmpnam ()
-## @deftypefnx {} {@var{fname} =} tmpnam (@var{dir})
-## @deftypefnx {} {@var{fname} =} tmpnam (@var{dir}, @var{prefix})
-## @code{tmpnam} is deprecated and will be removed in Octave version 6.
-## Use @code{tempname} instead.
-##
-## Return a unique temporary filename as a string.
-##
-## If @var{prefix} is omitted, a value of @qcode{"oct-"} is used.
-##
-## If @var{dir} is also omitted, the default directory for temporary files
-## (@code{P_tmpdir} is used.  If @var{dir} is provided, it must exist,
-## otherwise the default directory for temporary files is used.
-##
-## Programming Note: Because the named file is not opened by @code{tmpnam},
-## it is possible, though relatively unlikely, that it will not be available
-## by the time your program attempts to open it.  If this is a concern,
-## see @code{tmpfile}.  The functions @code{tmpnam} and @code{tempname} are
-## equivalent with the latter provided for @sc{matlab} compatibility.
-##
-## @strong{Caution}: @code{tmpnam} will be removed in Octave version 6, or
-## whatever the version number is two releases from 4.4. Use the equivalent
-## @code{tempname} in all new code.
-## @seealso{tempname, mkstemp, tempdir, P_tmpdir, tmpfile}
-## @end deftypefn
-
-function filename = tmpnam (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "tmpnam is obsolete and will be removed from a future version of Octave, please use tempname instead");
-  endif
-
-  filename = tempname (varargin{:});
-
-endfunction
-
-
-## No tests needed for alias.
-%!assert (1)
--- a/scripts/deprecated/toascii.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-## Copyright (C) 2018-2019 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software: you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} toascii (@var{str})
-##
-## @code{toascii} is deprecated and will be removed in Octave version 6.
-## Use @code{double} instead.
-##
-## Return ASCII representation of @var{str} in a matrix.
-##
-## For example:
-##
-## @example
-## @group
-## toascii ("ASCII"
-##      @result{} [ 65, 83, 67, 73, 73 ]
-## @end group
-##
-## @end example
-## @seealso{double, char}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 6.
-
-function retval = toascii (str)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "toascii is obsolete and will be removed from a future version of Octave, please use double instead");
-  endif
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  if (iscell (str))
-    retval = cellfun (@(x) bitand (double (x), 0x7F), str, "uniformoutput", 0);
-  else
-    retval = bitand (double (str), 0x7F);  # Restrict to 7-bit ASCII
-  endif
-
-endfunction
-
-
-## First test is necessary to provoke 1-time legacy warning
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! toascii ("");
-
-%!assert (toascii (char (0:127)), 0:127)
-%!assert (toascii (" ":"@"), 32:64)
-%!assert (toascii ("A":"Z"), 65:90)
-%!assert (toascii ("[":"`"), 91:96)
-%!assert (toascii ("a":"z"), 97:122)
-%!assert (toascii ("{":"~"), 123:126)
-
-%!error toascii ()
-%!error toascii (1, 2)
--- a/scripts/elfun/asech.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/elfun/asech.m	Fri Jul 12 12:14:43 2019 -0400
@@ -40,7 +40,7 @@
 %! x = [1, -1];
 %! assert (asech (x), v, sqrt (eps));
 
-%!xtest <52627>
+%!xtest <*52627>
 %! ## Same test code as above, but intended only for test statistics on Mac.
 %! ## Mac trig/hyperbolic functions have huge tolerances.
 %! if (! ismac ()), return; endif
--- a/scripts/general/gradient.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/general/gradient.m	Fri Jul 12 12:14:43 2019 -0400
@@ -99,7 +99,7 @@
   endif
 
   if (nargin > 2 && nargin != nd + 1)
-    print_usage ();
+    print_usage ("gradient");
   endif
 
   ## cell d stores a spacing vector for each dimension
--- a/scripts/general/quadgk.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/general/quadgk.m	Fri Jul 12 12:14:43 2019 -0400
@@ -318,10 +318,6 @@
   endwhile
   subs = [subs(1:end-1), subs(2:end)];
 
-  ## Singularity will cause divide by zero warnings.
-  ## Turn off warning locally for quadgk function only.
-  warning ("off", "Octave:divide-by-zero", "local");
-
   warn_id = "Octave:quadgk:warning-termination";
 
   if (issingle)
@@ -466,7 +462,7 @@
 %!assert (quadgk (@sin,-pi,pi, "WayPoints", 0, "MaxIntervalCount", 100,
 %!                "RelTol", 1e-3, "AbsTol", 1e-6, "trace", false), 0, 1e-6)
 %!assert (quadgk (@sin,-pi,pi, 1e-6, false), 0, 1e-6)
-%!assert <51867> (quadgk (@(x) x, 0, 0), 0, 0)
+%!assert <*51867> (quadgk (@(x) x, 0, 0), 0, 0)
 
 %!assert (quadgk (@sin,-pi,0), -2, 1e-10)
 %!assert (quadgk (@sin,0,pi), 2, 1e-10)
--- a/scripts/general/quadv.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/general/quadv.m	Fri Jul 12 12:14:43 2019 -0400
@@ -152,18 +152,14 @@
 %!assert (quadv (@sin, 0, pi), 2, 1e-6)
 
 ## Test weak singularities at the edge
-%!test
-%! warning ("off", "Octave:divide-by-zero", "local");
-%! assert (quadv (@(x) 1 ./ sqrt (x), 0, 1), 2, 2e-6);
+%!assert (quadv (@(x) 1 ./ sqrt (x), 0, 1), 2, 2e-6);
 
 ## Test vector-valued functions
 %!assert (quadv (@(x) [(sin (x)), (sin (2 * x))], 0, pi), [2, 0], 1e-6)
 
 ## Test matrix-valued functions
-%!test
-%! warning ("off", "Octave:divide-by-zero", "local");
-%! assert (quadv (@(x) [ x,x,x; x,1./sqrt(x),x; x,x,x ], 0, 1),
-%!         [0.5,0.5,0.5; 0.5,2,0.5; 0.5,0.5,0.5], 2e-6);
+%!assert (quadv (@(x) [ x,x,x; x,1./sqrt(x),x; x,x,x ], 0, 1),
+%!        [0.5,0.5,0.5; 0.5,2,0.5; 0.5,0.5,0.5], 2e-6);
 
 ## Test input validation
 %!error quadv ()
--- a/scripts/geometry/griddatan.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/geometry/griddatan.m	Fri Jul 12 12:14:43 2019 -0400
@@ -81,7 +81,9 @@
     yt = y(tri(tri_list,:));
 
     ## Use barycentric coordinate of point to calculate yi
-    yi(valid) = sum (y(tri(tri_list,:)) .* bary_list, 2);
+    if (! isempty (bary_list))
+      yi(valid) = sum (y(tri(tri_list,:))' .* bary_list, 2);
+    endif
 
   else
     error ("griddatan: unknown interpolation METHOD");
--- a/scripts/gui/msgbox.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/gui/msgbox.m	Fri Jul 12 12:14:43 2019 -0400
@@ -44,8 +44,10 @@
 ## The dialog is normal.
 ##
 ## @item @qcode{"modal"}
-## The dialog is displayed @qcode{"modal"} which means it prevents users from
-## interacting with any other GUI element until the dialog has been closed.
+## If any dialogs already exist with the same title, the most recent is reused
+## and all others are closed.  The dialog is displayed @qcode{"modal"} which
+## means it prevents users from interacting with any other GUI element until
+## the dialog has been closed.
 ##
 ## @item @qcode{"replace"}
 ## If any dialogs already exist with the same title, the most recent is reused
@@ -86,59 +88,81 @@
 ## @seealso{errordlg, helpdlg, inputdlg, listdlg, questdlg, warndlg}
 ## @end deftypefn
 
-function retval = msgbox (msg, tit = "", icon = "none", varargin)
+function retval = msgbox (msg, varargin)
 
-  ## Input checks
-  nargs = numel (varargin);
   if (nargin < 1)
     print_usage ();
-  elseif (! ischar (msg) && ! iscellstr (msg))
+  endif
+
+  if (! ischar (msg) && ! iscellstr (msg))
     error ("msgbox: MSG must be a string or cell array of strings");
-  elseif (! ischar (tit))
-    error ("msgbox: TITLE must be a string");
-  elseif (isstruct (icon))
-    varargin{end+1} = icon;
-    nargs += 1;
-    icon = "none";
-  elseif (! any (strcmp (icon, {"help", "warn", "error", "none", "custom"})))
-    error ("msgbox: unhandled value for ICON data");
-  elseif (strcmp (icon, "custom"))
-    if (nargs < 1)
-      error ("msgbox: missing data for 'custom' icon");
+  endif
+
+  nargs = numel (varargin);
+  tit = "";
+  icon = "none";
+  windowstyle = "non-modal";
+  interpreter = "tex";
+
+  if (nargs > 0)
+    ## Check for option argument in last position
+    if (isstruct (varargin{nargs}))
+      opts = varargin{nargs};
+      if (isfield (opts, "WindowStyle"))
+        windowstyle = opts.WindowStyle;
+      endif
+      if (isfield (opts, "Interpreter"))
+        interpreter = opts.Interpreter;
+      endif
+
+      if (! any (strcmp (windowstyle, {"non-modal", "modal", "replace"})))
+        error ('msgbox: invalid value "%s" for WindowStyle', windowstyle);
+      endif
+      nargs -= 1;
+
+    elseif (any (strcmp (varargin{nargs}, {"non-modal", "modal", "replace"})))
+      windowstyle = varargin{nargs};
+      nargs -= 1;
     endif
-    icon = struct ("cdata", varargin{1}, "colormap", []);
-    ## FIXME: This doesn't seem to be a robust test for RGB data.
-    if (! (ismatrix (icon.cdata) || size (icon.cdata, 3) == 3))
-      error ("msgbox: unhandled data for 'custom' icon");
-    elseif (size (icon.cdata, 3) == 1 && nargs > 1)
-      icon.colormap = varargin{2};
-      varargin(2) = [];
-      nargs--;
+  endif
+
+  if (nargs > 0)
+    tit = varargin{1};
+    if (! ischar (tit))
+      error ("msgbox: TITLE must be a string");
     endif
-    varargin(1) = [];
-    nargs--;
+    if (nargs > 1)
+      icon = varargin{2};
+      if (! any (strcmp (icon, {"help", "warn", "error", "none", "custom"})))
+        if (ischar (icon))
+          error ('msgbox: invalid value "%s" for ICON', icon);
+        else
+          error ("msgbox: ICON must be a string");
+        endif
+      elseif (strcmp (icon, "custom"))
+        if (nargs < 3)
+          error ('msgbox: missing data for "custom" icon');
+        endif
+        icon = struct ("cdata", varargin{3}, "colormap", []);
+        if (! isnumeric (icon.cdata))
+          error ('msgbox: invalid data for "custom" icon');
+        elseif (! ismatrix (icon.cdata)
+                && (ndims (icon.cdata) != 3 || size (icon.cdata, 3) != 3))
+          error ('msgbox: invalid data for "custom" icon');
+        elseif (ismatrix (icon.cdata) && nargs == 4)
+          icon.colormap = varargin{4};
+        else
+          print_usage ();
+        endif
+      elseif (nargs > 2)
+        print_usage ();
+      endif
+    endif
   endif
 
   ## Window behavior and text interpreter
-  windowstyle = "normal";
-  interpreter = "tex";
-  if (nargs > 0)
-    if (isstruct (varargin{1}))
-      if (isfield (varargin{1}, "WindowStyle"))
-        windowstyle = varargin{1}.WindowStyle;
-      endif
-      if (isfield (varargin{1}, "Interpreter"))
-        interpreter = varargin{1}.Interpreter;
-      endif
-    else
-      windowstyle = varargin{1};
-    endif
-
-    if (! any (strcmp (windowstyle, {"non-modal", "modal", "replace"})))
-      error ("msgbox: unhandled value %s for OPT", windowstyle);
-    elseif (strcmp (windowstyle, "non-modal"))
-      windowstyle = "normal";
-    endif
+  if (strcmp (windowstyle, "non-modal"))
+    windowstyle = "normal";
   endif
 
   ## Make a GUI element or print to console
@@ -162,9 +186,11 @@
 
   ## Prepare graphics objects
   hf = [];
+  if (strcmp (windowstyle, "replace") || strcmp (windowstyle, "modal"))
+    hf = findall (groot, "tag", "__dialog__", "-and", "name", tit);
+  endif
   if (strcmp (windowstyle, "replace"))
     windowstyle = "normal";
-    hf = findall (groot, "tag", "__dialog__", "-and", "name", tit);
   endif
 
   if (! isempty (hf))
@@ -326,8 +352,15 @@
 %!         "Dialog Title", "custom", cdata, copper (64));
 
 ## Test input validation
+%!error msgbox ()
 %!error <MSG must be a string or cell array of strings> msgbox (1)
+%!error <invalid value "foobar" for WindowStyle>
+%! msgbox ("msg", struct ("WindowStyle", "foobar"))
 %!error <TITLE must be a string> msgbox ("msg", 1)
-%!error <unhandled value for ICON data> msgbox ("msg", "title", 1)
-%!error <missing data for 'custom' icon> msgbox ("msg", "title", "custom")
-%!error <unhandled value 1 for OPT> msgbox ("msg", "title", "help", "1")
+%!error <invalid value "foobar" for ICON> msgbox ("msg", "title", "foobar")
+%!error <ICON must be a string> msgbox ("msg", "title", {1})
+%!error <missing data for "custom" icon> msgbox ("msg", "title", "custom")
+%!error <invalid data for "custom" icon>
+%! msgbox ("msg", "title", "custom", {{1}})
+%!error <Invalid call to msgbox> msgbox ("msg", "title", "custom", 1, 2, 3)
+%!error <Invalid call to msgbox> msgbox ("msg", "title", "help", "1")
--- a/scripts/gui/uimenu.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/gui/uimenu.m	Fri Jul 12 12:14:43 2019 -0400
@@ -105,8 +105,8 @@
 %! uimenu (f, 'label', 'Close', 'accelerator', 'q', 'callback', 'close (gcf)');
 %! uimenu (e, 'label', 'Toggle &Grid', 'accelerator', 'g', 'callback', 'grid (gca)');
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
-%! toolkit = graphics_toolkit ("fltk");
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
+%! toolkit = graphics_toolkit ("qt");
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   ui = uimenu ("label", "mylabel");
@@ -115,15 +115,15 @@
 %!   assert (get (ui, "checked"), "off");
 %!   assert (get (ui, "separator"), "off");
 %!   assert (get (ui, "enable"), "on");
-%!   assert (get (ui, "position"), 0);
+%!   assert (get (ui, "position"), 4);
 %! unwind_protect_cleanup
 %!   close (hf);
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
 ## check for top level menus file and edit
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
-%! toolkit = graphics_toolkit ("fltk");
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
+%! toolkit = graphics_toolkit ("qt");
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   uif = findall (hf, "label", "&file");
@@ -135,8 +135,8 @@
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
-%! toolkit = graphics_toolkit ("fltk");
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
+%! toolkit = graphics_toolkit ("qt");
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   uie = findall (hf, "label", "&edit");
--- a/scripts/help/__makeinfo__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/__makeinfo__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -94,6 +94,7 @@
   endif
   ## Texinfo crashes if @end tex does not appear first on the line.
   text = regexprep (text, '^ +@end tex', '@end tex', 'lineanchors');
+  text = regexprep (text, '@seealso', '@xseealso');
 
   file = texi_macros_file ();
   fid = fopen (file, "r");
--- a/scripts/help/__unimplemented__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/__unimplemented__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -557,7 +557,7 @@
       txt = sprintf ("%s but has not yet been implemented.", txt);
     case "not loaded",
       txt = sprintf (["%s which you have installed but not loaded.  To ", ...
-                      "load the package, run `pkg load %s' from the ", ...
+                      "load the package, run 'pkg load %s' from the ", ...
                       "Octave prompt."], txt, name);
     otherwise
       ## this includes "not installed" and anything else if pkg changes
@@ -968,7 +968,6 @@
   "libisloaded",
   "libpointer",
   "libstruct",
-  "lightangle",
   "linkdata",
   "listfonts",
   "loadlibrary",
@@ -1048,7 +1047,6 @@
   "nearestNeighbor",
   "neighbors",
   "netcdf",
-  "newline",
   "noanimate",
   "notebook",
   "notify",
@@ -1328,7 +1326,6 @@
   "varfun",
   "vartype",
   "verctrl",
-  "verLessThan",
   "vertexAttachments",
   "vertexNormal",
   "VideoReader",
@@ -1338,11 +1335,7 @@
   "volume",
   "volumebounds",
   "voronoiDiagram",
-  "web",
-  "weboptions",
-  "webread",
   "websave",
-  "webwrite",
   "week",
   "whatsnew",
   "width",
--- a/scripts/help/error_ids.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/error_ids.m	Fri Jul 12 12:14:43 2019 -0400
@@ -20,14 +20,14 @@
 ## @cindex error ids
 ##
 ## @table @code
+## @item Octave:bad-alloc
+## Indicates that memory couldn't be allocated.
+##
 ## @item Octave:invalid-context
 ## Indicates the error was generated by an operation that cannot be executed in
 ## the scope from which it was called.  For example, the function
 ## @code{print_usage ()} when called from the Octave prompt raises this error.
 ##
-## @item Octave:invalid-input-arg
-## Indicates that a function was called with invalid input arguments.
-##
 ## @item Octave:invalid-fun-call
 ## Indicates that a function was called in an incorrect way, e.g., wrong number
 ## of input arguments.
@@ -36,8 +36,8 @@
 ## Indicates that a data-type was indexed incorrectly, e.g., real-value index
 ## for arrays, nonexistent field of a structure.
 ##
-## @item Octave:bad-alloc
-## Indicates that memory couldn't be allocated.
+## @item Octave:invalid-input-arg
+## Indicates that a function was called with invalid input arguments.
 ##
 ## @item Octave:undefined-function
 ## Indicates a call to a function that is not defined.  The function may exist
--- a/scripts/help/print_usage.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/print_usage.m	Fri Jul 12 12:14:43 2019 -0400
@@ -37,9 +37,9 @@
     else
       error ("Octave:invalid-context", "print_usage: invalid function\n");
     endif
-    fullpath = evalin ("caller", 'mfilename ("fullpath")');
-    if (strcmp (fullpath(end-length(name)+1:end), name))
-      fullname = [fullpath ".m"];
+    fullname = evalin ("caller", 'mfilename ("fullpath")');
+    if (strcmp (fullname(end-length(name)+1:end), name))
+      fullname = [fullname ".m"];
     endif
   elseif (! ischar (name))
     error ("Octave:invalid-input-arg",
--- a/scripts/help/warning_ids.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/warning_ids.m	Fri Jul 12 12:14:43 2019 -0400
@@ -33,7 +33,7 @@
 ## @item Octave:array-as-logical
 ## If the @code{Octave:array-as-logical} warning is enabled,
 ## Octave will warn when an array of size greater than 1x1 is used
-## as a truth value in an if, while or until statement.
+## as a truth value in an if, while, or until statement.
 ## By default, the @code{Octave:array-as-logical} warning is disabled.
 ##
 ## @item Octave:array-to-scalar
@@ -140,6 +140,14 @@
 ## By default, the @code{Octave:built-in-variable-assignment} warning is
 ## enabled.
 ##
+## @item Octave:data-file-in-path
+## If the @code{Octave:data-file-in-path} warning is enabled, a warning is
+## issued when Octave does not find the target of a file operation such as
+## @code{load} or @code{fopen} directly, but is able to locate the file in
+## Octave's search @code{path} for files.  The warning could indicate that a
+## different file target than the programmer intended is being used.
+## By default, the @code{Octave:data-file-in-path} warning is enabled.
+##
 ## @item Octave:deprecated-function
 ## If the @code{Octave:deprecated-function} warning is enabled, a
 ## warning is issued when Octave encounters a function that is obsolete and
@@ -158,11 +166,6 @@
 ## is obsolete and scheduled for removal from Octave.
 ## By default, the @code{Octave:deprecated-property} warning is enabled.
 ##
-## @item Octave:divide-by-zero
-## If the @code{Octave:divide-by-zero} warning is enabled, a
-## warning is issued when Octave encounters a division by zero.
-## By default, the @code{Octave:divide-by-zero} warning is enabled.
-##
 ## @item Octave:eigs:UnconvergedEigenvalues
 ## If the @code{Octave:eigs:UnconvergedEigenvalues} warning is enabled then
 ## the eigs function will issue a warning if the number of calculated
@@ -170,20 +173,18 @@
 ## By default, the @code{Octave:eigs:UnconvergedEigenvalues} warning is
 ## enabled.
 ##
+## @item Octave:empty-index
+## If the @code{Octave:empty-index} warning is enabled then Octave will emit a
+## warning whenever indexing operators are used without an index, for example
+## @code{@var{x}()}.
+## By default, the @code{Octave:empty-index} warning is enabled.
+##
 ## @item Octave:erase:chararray
 ## If the @code{Octave:erase:chararray} warning is enabled then the erase
 ## function will issue a warning if the input pattern is a character array
 ## rather than a string or cell array of strings.
 ## By default, the @code{Octave:erase:chararray} warning is enabled.
 ##
-## @item Octave:data-file-in-path
-## If the @code{Octave:data-file-in-path} warning is enabled, a warning is
-## issued when Octave does not find the target of a file operation such as
-## @code{load} or @code{fopen} directly, but is able to locate the file in
-## Octave's search @code{path} for files.  The warning could indicate that a
-## different file target than the programmer intended is being used.
-## By default, the @code{Octave:data-file-in-path} warning is enabled.
-##
 ## @item Octave:function-name-clash
 ## If the @code{Octave:function-name-clash} warning is enabled, a
 ## warning is issued when Octave finds that the name of a function
@@ -359,6 +360,13 @@
 ## elicits a warning if the @code{Octave:str-to-num} warning is enabled.
 ## By default, the @code{Octave:str-to-num} warning is disabled.
 ##
+## @item Octave:text_interpreter
+## If the @code{Octave:text_interpreter} warning is enabled, a warning is
+## printed when the @qcode{"interpreter"} property of a text graphics object
+## is set to the unsupported value of @qcode{"latex"}.  Even when enabled,
+## the warning message is printed just once per Octave session.
+## By default, the @code{Octave:glyph-render} warning is enabled.
+##
 ## @item Octave:variable-switch-label
 ## If the @code{Octave:variable-switch-label} warning is enabled, Octave
 ## will print a warning if a switch label is not a constant or constant
--- a/scripts/help/which.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/help/which.m	Fri Jul 12 12:14:43 2019 -0400
@@ -37,7 +37,7 @@
   ## functions in name resolution.
   for i = 1:nargin
     m(i).is_variable = evalin ("caller",
-                               ['exist ("' undo_string_escapes(m(i).name) '", "var")'], false);
+                               ['exist ("' undo_string_escapes(m(i).name) '", "var")'], "");
     if (m(i).is_variable)
       m(i).file = "variable";
     endif
--- a/scripts/image/imformats.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/imformats.m	Fri Jul 12 12:14:43 2019 -0400
@@ -106,7 +106,7 @@
           ##        whole format, or just that extension from the format?
           match = find_ext_idx (formats, arg2);
           if (! any (match))
-            error ("imformats: no EXT `%s' found.", arg2);
+            error ("imformats: no EXT '%s' found.", arg2);
           endif
           if (strcmpi (arg1, "remove"))
             formats(match) = [];
@@ -155,7 +155,7 @@
   ## It will still fail if we test only the ones marked as readable and
   ## writable because some RW coders are not of image formats (NULL, 8BIM,
   ## or EXIF for example).
-  ## So we'd need a blacklist (unacceptable because a `bad' coder may be
+  ## So we'd need a blacklist (unacceptable because a 'bad' coder may be
   ## added later) or a whitelist.  A whitelist means that even with a
   ## super-fancy recent build of GraphicsMagick, some formats won't be listed
   ## by imformats but in truth, we will still be able to read and write them
@@ -268,7 +268,7 @@
   min_fields  = {"ext", "read", "isa", "write", "info", "alpha", "description"};
   fields_mask = isfield (format, min_fields);
   if (! all (fields_mask))
-    error ("imformats: structure has missing field `%s'.", min_fields(! fields_mask){1});
+    error ("imformats: structure has missing field '%s'.", min_fields(! fields_mask){1});
   endif
 
 endfunction
--- a/scripts/image/imshow.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/imshow.m	Fri Jul 12 12:14:43 2019 -0400
@@ -86,8 +86,12 @@
   ## Get the image.
   if (ischar (im))
     [im, map] = imread (im);
-    indexed = true;
-    colormap (gca, map);
+    if (isempty (map))
+      indexed = false;
+    else
+      indexed = true;
+      colormap (gca, map);
+    endif
   endif
 
   nd = ndims (im);
--- a/scripts/image/imwrite.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/imwrite.m	Fri Jul 12 12:14:43 2019 -0400
@@ -106,7 +106,7 @@
 
   fmt = imformats (ext);
   ## When there is no match, fmt will be a 1x1 structure with
-  ## no fields, so we can't just use `isempty (fmt)'.
+  ## no fields, so we can't just use 'isempty (fmt)'.
   if (numfields (fmt) == 0)
     if (isempty (ext))
       error ("imwrite: no extension found for %s to identify the image format",
--- a/scripts/image/private/__imread__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/private/__imread__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -68,7 +68,7 @@
     endif
     val = varargin{shift (idx, 1)};
     if (! is_valid_index_option (val) && ! strcmpi (val, "all"))
-      error ("imread: %s must be a vector or the string `all'", varargin{idx});
+      error ("imread: %s must be a vector or the string 'all'", varargin{idx});
     endif
     options.index = val;
   endif
@@ -123,7 +123,7 @@
         ## we allow to load multiple pages with one command.
 
       otherwise
-        error ("imread: invalid PARAMETER `%s'", varargin{idx});
+        error ("imread: invalid PARAMETER '%s'", varargin{idx});
 
     endswitch
   endfor
--- a/scripts/image/private/__imwrite__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/private/__imwrite__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -78,7 +78,7 @@
         if (! any (strcmp (options.compression, {"none", "bzip", "fax3", ...
                                                  "fax4", "jpeg", "lzw", ...
                                                  "rle", "deflate"})))
-          error ("imwrite: invalid compression `%s'", options.compression);
+          error ("imwrite: invalid compression '%s'", options.compression);
         endif
 
       case "delaytime"
@@ -169,7 +169,7 @@
         options.writemode = tolower (options.writemode);
 
       otherwise
-        error ("imwrite: invalid PARAMETER `%s'", param_list{idx});
+        error ("imwrite: invalid PARAMETER '%s'", param_list{idx});
 
     endswitch
   endfor
--- a/scripts/image/rgbplot.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/image/rgbplot.m	Fri Jul 12 12:14:43 2019 -0400
@@ -60,8 +60,7 @@
     case "profile"
       x = 1:rows (cmap);
       htmp = plot (x,cmap(:,1),"r", x,cmap(:,2),"g", x,cmap(:,3),"b");
-      set (gca (), "ytick", 0:0.1:1);
-      set (gca (), "xlim", [0 rows(cmap)]);
+      set (gca, "ytick", 0:0.1:1, "xlim", [0 rows(cmap)]);
     case "composite"
       htmp = image (1:rows (cmap));
       set (gca, "ytick", []);
--- a/scripts/java/org/octave/ClassHelper.java	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/java/org/octave/ClassHelper.java	Fri Jul 12 12:14:43 2019 -0400
@@ -143,11 +143,57 @@
   public static String getMethods (Class klass)
   {
     StringBuilder sb = new StringBuilder();
+    boolean first = true;
+
+    Constructor theConstructor[] = klass.getConstructors ();
+    for (int i = 0; i < theConstructor.length; i++)
+      {
+        if (first)
+          {
+            first = false;
+          }
+        else
+          {
+            sb.append (";");
+          }
+
+        sb.append (theConstructor[i].getName ());
+        sb.append ("(");
+
+        Class theParameter[] = theConstructor[i].getParameterTypes ();
+        for (int j = 0; j < theParameter.length; j++)
+          {
+            if (j > 0)
+              {
+                sb.append (", ");
+              }
+            sb.append (theParameter[j].getCanonicalName ());
+          }
+        sb.append (")");
+
+        Class theExceptions[] = theConstructor[i].getExceptionTypes ();
+        if (theExceptions.length > 0)
+          {
+            sb.append (" throws ");
+            for (int j = 0; j < theExceptions.length; j++)
+              {
+                if (j > 0)
+                  {
+                    sb.append (", ");
+                  }
+                sb.append (theExceptions[j].getCanonicalName ());
+              }
+          }
+      }
 
     Method theMethod[] = klass.getMethods ();
     for (int i = 0; i < theMethod.length; i++)
       {
-        if (i > 0)
+        if (first)
+          {
+            first = false;
+          }
+        else
           {
             sb.append (";");
           }
--- a/scripts/java/org/octave/Matrix.java	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/java/org/octave/Matrix.java	Fri Jul 12 12:14:43 2019 -0400
@@ -96,7 +96,7 @@
     if (data instanceof DoubleBuffer)
       return ((DoubleBuffer)data).array ();
     else
-      throw new ClassCastException ("matrix is not of type `double'");
+      throw new ClassCastException ("matrix is not of type 'double'");
   }
 
   public byte[] toByte ()
@@ -104,7 +104,7 @@
     if (data instanceof ByteBuffer)
       return ((ByteBuffer)data).array ();
     else
-      throw new ClassCastException ("matrix is not of type `byte'");
+      throw new ClassCastException ("matrix is not of type 'byte'");
   }
 
   public int[] toInt ()
@@ -112,7 +112,7 @@
     if (data instanceof IntBuffer)
       return ((IntBuffer)data).array ();
     else
-      throw new ClassCastException ("matrix is not of type `integer'");
+      throw new ClassCastException ("matrix is not of type 'integer'");
   }
 
   public int getNDims ()
@@ -330,7 +330,7 @@
             val = buf[i];
       }
     else
-      System.out.println ("Warning: cannot compute min value for array of type `" + getClassName () + "'");
+      System.out.println ("Warning: cannot compute min value for array of type '" + getClassName () + "'");
 
     return val;
   }
@@ -354,7 +354,7 @@
             val = buf[i];
       }
     else
-      System.out.println ("Warning: cannot compute max value for array of type `" + getClassName () + "'");
+      System.out.println ("Warning: cannot compute max value for array of type '" + getClassName () + "'");
 
     return val;
   }
--- a/scripts/linear-algebra/condeig.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/linear-algebra/condeig.m	Fri Jul 12 12:14:43 2019 -0400
@@ -101,7 +101,7 @@
 
     ## Condition numbers
     ## Definition: cos (angle) = (norm (v1) * norm (v2)) / dot (v1, v2)
-    ## Eigenvectors have been normalized so `norm (v1) * norm (v2)' = 1
+    ## Eigenvectors have been normalized so 'norm (v1) * norm (v2)' = 1
     c = abs (1 ./ dot (vl, v)');
   endif
 
--- a/scripts/linear-algebra/ishermitian.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/linear-algebra/ishermitian.m	Fri Jul 12 12:14:43 2019 -0400
@@ -82,7 +82,7 @@
   if (strcmp (skewopt, "nonskew"))
     if (tol == 0)
       ## check for exact symmetry
-      retval = ! any ((A != A')(:));
+      retval = full (! any ((A != A')(:)));
     else
       if (islogical (A))
         ## Hack to allow norm to work.  Choose single to minimize memory.
@@ -94,7 +94,7 @@
   else
     ## skew-Hermitian
     if (tol == 0)
-      retval = ! any ((A != -A')(:));
+      retval = full (! any ((A != -A')(:)));
     else
       if (islogical (A))
         ## Hack to allow norm to work.  Choose single to minimize memory.
@@ -114,7 +114,7 @@
 %!assert (ishermitian ([1, 2; 2, 1]))
 %!assert (ishermitian ([1, 2.1; 2, 1.1], 0.2))
 %!assert (ishermitian ([1, -2i; 2i, 1]))
-%!assert (ishermitian (speye (100)))
+%!assert (ishermitian (speye (100)), true)  # Return full logical value.
 %!assert (ishermitian (logical (eye (2))))
 %!assert (! ishermitian (logical ([1 1; 0 1])))
 %!assert (ishermitian (logical ([1 1; 0 1]), 0.5))
--- a/scripts/linear-algebra/issymmetric.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/linear-algebra/issymmetric.m	Fri Jul 12 12:14:43 2019 -0400
@@ -81,7 +81,7 @@
   if (strcmp (skewopt, "nonskew"))
     if (tol == 0)
       ## check for exact symmetry
-      retval = ! any ((A != A.')(:));
+      retval = full (! any ((A != A.')(:)));
     else
       if (islogical (A))
         ## Hack to allow norm to work.  Choose single to minimize memory.
@@ -93,7 +93,7 @@
   else
     ## skew symmetry
     if (tol == 0)
-      retval = ! any ((A != -A.')(:));
+      retval = full (! any ((A != -A.')(:)));
     else
       if (islogical (A))
         ## Hack to allow norm to work.  Choose single to minimize memory.
@@ -113,7 +113,7 @@
 %!assert (issymmetric ([1, 2; 2, 1]))
 %!assert (issymmetric ([1, 2.1; 2, 1.1], 0.2))
 %!assert (issymmetric ([1, 2i; 2i, 1]))
-%!assert (issymmetric (speye (100)))
+%!assert (issymmetric (speye (100)), true)  # Return full logical value.
 %!assert (issymmetric (logical (eye (2))))
 %!assert (! issymmetric (logical ([1 1; 0 1])))
 %!assert (issymmetric (logical ([1 1; 0 1]), 0.5))
--- a/scripts/miscellaneous/clearvars.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/clearvars.m	Fri Jul 12 12:14:43 2019 -0400
@@ -127,9 +127,9 @@
   endfor
 
   if (global_mode)
-    varlist = evalin ("caller", "who global");
+    varlist = evalin ("caller", "who ('global')");
   else
-    varlist = evalin ("caller", "who");
+    varlist = evalin ("caller", "who ()");
   endif
 
   ## evalin will cause the automatic creation of 'ans' variable (bug #53339).
@@ -151,19 +151,19 @@
   endif
 
   varlist = varlist(idx_clear);
-  names = strjoin (varlist, " ");
+  names = strjoin (varlist, "', '");
 
   if (! isempty (names))
     if (global_mode)
-      evalin ("caller", ["clear -global " names]);
+      evalin ("caller", ["clear ('-global', '", names, "')"]);
     else
-      evalin ("caller", ["clear " names]);
+      evalin ("caller", ["clear ('", names, "')"]);
     endif
   endif
 
   ## Clean up automatic variable "ans" if necessary
   if (clear_ans)
-    evalin ("caller", "clear ans");
+    evalin ("caller", "clear ('ans')");
   endif
 
 endfunction
--- a/scripts/miscellaneous/dir.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/dir.m	Fri Jul 12 12:14:43 2019 -0400
@@ -111,7 +111,7 @@
     endif
   endif
 
-  if (numel (flst) > 0)
+  if (nf > 0)
 
     fs = regexptranslate ("escape", filesep ("all"));
     re = sprintf ('(^.+)[%s]([^%s.]*)([.][^%s]*)?$', fs, fs, fs);
@@ -119,11 +119,13 @@
     info(nf,1).name = "";  # pre-declare size of struct array
 
     ## Collect results.
-    for i = nf:-1:1
+    cnt = 0;
+    for i = 1:nf
       fn = flst{i};
       [st, err, msg] = lstat (fn);
       if (err < 0)
         warning ("dir: 'lstat (%s)' failed: %s", fn, msg);
+        continue;
       else
         ## If we are looking at a link that points to something,
         ## return info about the target of the link, otherwise, return
@@ -136,27 +138,28 @@
         endif
         tmpdir = regexprep (fn, re, '$1');
         fn = regexprep (fn, re, '$2$3');
-        info(i).name = fn;
+        info(++cnt).name = fn;
         if (! strcmp (last_dir, tmpdir))
           ## Caching mechanism to speed up function
           last_dir = tmpdir;
           last_absdir = canonicalize_file_name (last_dir);
         endif
-        info(i).folder = last_absdir;
+        info(cnt).folder = last_absdir;
         lt = localtime (st.mtime);
-        info(i).date = strftime ("%d-%b-%Y %T", lt);
-        info(i).bytes = st.size;
-        info(i).isdir = S_ISDIR (st.mode);
-        info(i).datenum = [lt.year + 1900, lt.mon + 1, lt.mday, ...
+        info(cnt).date = strftime ("%d-%b-%Y %T", lt);
+        info(cnt).bytes = st.size;
+        info(cnt).isdir = S_ISDIR (st.mode);
+        info(cnt).datenum = [lt.year + 1900, lt.mon + 1, lt.mday, ...
                              lt.hour, lt.min, lt.sec];
-        info(i).statinfo = st;
+        info(cnt).statinfo = st;
       endif
     endfor
+    info((cnt+1):end) = [];  # remove any unused entries
     ## A lot of gymnastics in order to call datenum just once.  2x speed up.
     dvec = [info.datenum]([[1:6:end]', [2:6:end]', [3:6:end]', ...
                            [4:6:end]', [5:6:end]', [6:6:end]']);
     dnum = datenum (dvec);
-    ctmp = mat2cell (dnum, ones (nf,1), 1);
+    ctmp = mat2cell (dnum, ones (cnt,1), 1);
     [info.datenum] = ctmp{:};
   endif
 
@@ -175,23 +178,36 @@
 
 
 %!test
-%! list = dir ();
-%! assert (isstruct (list) && ! isempty (list));
-%! assert (fieldnames (list),
-%!         {"name"; "folder"; "date"; "bytes"; "isdir"; "datenum"; "statinfo"});
+%! orig_dir = pwd ();
+%! tmp_dir = tempname ();
+%! unwind_protect
+%!   assert (mkdir (tmp_dir));
+%!   chdir (tmp_dir);
+%!   fclose (fopen ("f1", "w"));
+%!   list = dir ();
+%!   assert (isstruct (list) && ! isempty (list));
+%!   assert (fieldnames (list),
+%!           {"name"; "folder"; "date"; "bytes"; "isdir"; "datenum"; "statinfo"});
 %!
-%! if (isunix ())
-%!   idx = find (strcmp ({list.name}, "."), 1);
-%!   assert ({list(idx:idx+1).name}, {".", ".."});
-%!   assert ([list(idx:idx+1).isdir], [true true]);
-%! endif
+%!   if (isunix ())
+%!     idx = find (strcmp ({list.name}, "."), 1);
+%!     assert ({list(idx:idx+1).name}, {".", ".."});
+%!     assert ([list(idx:idx+1).isdir], [true true]);
+%!   endif
 %!
-%! ## test that specifying a filename works the same as using a directory.
-%! found = find (! [list.isdir], 1);
-%! if (! isempty (found))
-%!   list2 = dir (fullfile (list(found).folder, list(found).name));
-%!   assert (list(found), list2);
-%! endif
+%!   ## test that specifying a filename works the same as using a directory.
+%!   found = find (! [list.isdir], 1);
+%!   if (! isempty (found))
+%!     list2 = dir (fullfile (list(found).folder, list(found).name));
+%!     assert (list(found), list2);
+%!   endif
+%! unwind_protect_cleanup
+%!   chdir (orig_dir);
+%!   confirm_recursive_rmdir (false, "local");
+%!   if (exist (tmp_dir))
+%!     rmdir (tmp_dir, "s");
+%!   endif
+%! end_unwind_protect
 
 ## Test input validation
 %!error <DIRECTORY argument must be a string> dir (1)
--- a/scripts/miscellaneous/edit.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/edit.m	Fri Jul 12 12:14:43 2019 -0400
@@ -28,31 +28,27 @@
 ##
 ## @itemize @bullet
 ## @item
-## If the function @var{name} is available in a file on your path and that
-## file is modifiable, then it will be edited in place.  If it is a system
-## function, then it will first be copied to the directory @env{HOME} (see
-## below) and then edited.  If no file is found, then the m-file variant,
-## ending with @qcode{".m"}, will be considered.  If still no file is found,
-## then variants with a leading @qcode{"@@"} and then with both a leading
-## @qcode{"@@"} and trailing @qcode{".m"} will be considered.
+## If the function @var{name} is available in a file on your path, then it
+## will be opened in the editor.  If no file is found, then the m-file
+## variant, ending with @qcode{".m"}, will be considered.  If still no file is
+## found, then variants with a leading @qcode{"@@"} and then with both a
+## leading @qcode{"@@"} and trailing @qcode{".m"} will be considered.
 ##
 ## @item
-## If @var{name} is the name of a function defined in the interpreter but not
-## in an m-file, then an m-file will be created in @env{HOME} to contain that
-## function along with its current definition.
+## If @var{name} is the name of a command-line function, then an m-file will
+## be created to contain that function along with its current definition.
 ##
 ## @item
 ## If @code{@var{name}.cc} is specified, then it will search for
-## @code{@var{name}.cc} in the path and try to modify it, otherwise it will
-## create a new @file{.cc} file in the current directory.  If @var{name}
-## happens to be an m-file or interpreter defined function, then the text of
-## that function will be inserted into the .cc file as a comment.
+## @file{@var{name}.cc} in the path and open it in the editor.  If the file is
+## not found, then a new @file{.cc} file will be created.  If @var{name}
+## happens to be an m-file or command-line function, then the text of that
+## function will be inserted into the .cc file as a comment.
 ##
 ## @item
 ## If @file{@var{name}.ext} is on your path then it will be edited, otherwise
 ## the editor will be started with @file{@var{name}.ext} in the current
-## directory as the filename.  If @file{@var{name}.ext} is not modifiable,
-## it will be copied to @env{HOME} before editing.
+## directory as the filename.
 ##
 ## @strong{Warning:} You may need to clear @var{name} before the new definition
 ## is available.  If you are editing a .cc file, you will need to execute
@@ -72,10 +68,6 @@
 ## The following control fields are used:
 ##
 ## @table @samp
-## @item home
-## This is the location of user local m-files.  Be sure it is in your path.
-## The default is @file{~/octave}.
-##
 ## @item author
 ## This is the name to put after the "## Author:" field of new functions.  By
 ## default it guesses from the @code{gecos} field of the password database.
@@ -114,8 +106,20 @@
 ##
 ## @item editinplace
 ## Determines whether files should be edited in place, without regard to
-## whether they are modifiable or not.  The default is @code{false}.
+## whether they are modifiable or not.  The default is @code{true}.
+## Set it to @code{false} to have read-only function files automatically
+## copied to @samp{home}, if it exists, when editing them.
+##
+## @item home
+## This value indicates a directory that system m-files should be copied into
+## before opening them in the editor.  The intent is that this directory is
+## also in the path, so that the edited copy of a system function file shadows
+## the original.  This setting only has an effect when @samp{editinplace} is
+## set to @code{false}.  The default is the empty matrix (@code{[]}), which
+## means it is not used.  The default in previous versions of Octave was
+## @file{~/octave}.
 ## @end table
+## @seealso{EDITOR, path}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
@@ -127,13 +131,12 @@
 
   ## Pick up globals or default them.
 
-  persistent FUNCTION = struct ("HOME",
-                                fullfile (get_home_directory (), "octave"),
+  persistent FUNCTION = struct ("HOME", [],
                                 "AUTHOR", default_user(1),
                                 "EMAIL", [],
                                 "LICENSE", "GPL",
                                 "MODE", "async",
-                                "EDITINPLACE", false);
+                                "EDITINPLACE", true);
   ## Make sure the stateval variables survive "clear functions".
   mlock;
 
@@ -165,9 +168,6 @@
         error ("Octave:deprecated-function",
                "The EDITOR option of edit has been removed.  Use EDITOR() directly.");
       case "HOME"
-        if (! isempty (stateval) && stateval(1) == "~")
-          stateval = [ get_home_directory, stateval(2:end) ];
-        endif
         FUNCTION.HOME = stateval;
         return;
       case "AUTHOR"
@@ -218,15 +218,23 @@
     endif
   endif
 
+  ## Only use the legacy "HOME" directory if the user explicitly configured
+  ## it and if the directory exists.  In previous versions of Octave, HOME
+  ## was ~/octave by default and edited functions were copied into ~/octave.
+  ## Now 'edit_file_in_place' should be true by default unless the user
+  ## opts in by setting "EDITINPLACE" to false and "HOME" to a directory.
+  edit_file_in_place = (FUNCTION.EDITINPLACE || isempty (FUNCTION.HOME)
+                        || ! isfolder (FUNCTION.HOME));
+
   ## Start the editor without a file if no file is given.
   if (nargin == 0)
-    if (isfolder (FUNCTION.HOME))
+    if (! edit_file_in_place && ! strcmp (FUNCTION.HOME, "."))
       curr_dir = pwd ();
       unwind_protect
-        cd (FUNCTION.HOME);
+        chdir (FUNCTION.HOME);
         do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE);
       unwind_protect_cleanup
-        cd (curr_dir);
+        chdir (curr_dir);
       end_unwind_protect
     else
       do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE);
@@ -307,7 +315,7 @@
 
     if (! isempty (fileandpath))
       ## If the file exists, then edit it.
-      if (FUNCTION.EDITINPLACE)
+      if (edit_file_in_place)
         ## Edit in place even if it is protected.
         do_edit (FUNCTION.EDITOR, fileandpath, FUNCTION.MODE);
         return;
@@ -317,7 +325,8 @@
         fid = fopen (fileandpath, "r+t");
         if (fid < 0)
           from = fileandpath;
-          fileandpath = [FUNCTION.HOME, from(rindex(from, filesep):end)];
+          [~, fname, ext] = fileparts (from);
+          fileandpath = fullfile (tilde_expand (FUNCTION.HOME), [fname, ext]);
           [status, msg] = copyfile (from, fileandpath, 1);
           if (status == 0)
             error (msg);
@@ -409,33 +418,31 @@
     switch (uclicense)
       case "GPL"
         head = cstrcat (copyright, "\n\n", "\
-This program is free software: you can redistribute it and/or modify it\n\
-under the terms of the GNU General Public License as published by\n\
+This program is free software: you can redistribute it and/or modify\n\
+it under the terms of the GNU General Public License as published by\n\
 the Free Software Foundation, either version 3 of the License, or\n\
 (at your option) any later version.\n\
 \n\
-This program is distributed in the hope that it will be useful, but\n\
-WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+This program is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
 GNU General Public License for more details.\n\
 \n\
 You should have received a copy of the GNU General Public License\n\
-along with this program.  If not, see\n\
-<https://www.gnu.org/licenses/>.\
+along with this program.  If not, see <https://www.gnu.org/licenses/>.\
 ");
         tail = [author, "\n", revs];
 
       case "BSD"
         head = cstrcat (copyright, "\n\n", "\
-This program is free software; redistribution and use in source and\n\
+This program is free software: redistribution and use in source and\n\
 binary forms, with or without modification, are permitted provided that\n\
 the following conditions are met:\n\
-\n\
-   1.Redistributions of source code must retain the above copyright\n\
-     notice, this list of conditions and the following disclaimer.\n\
-   2.Redistributions in binary form must reproduce the above copyright\n\
-     notice, this list of conditions and the following disclaimer in the\n\
-     documentation and/or other materials provided with the distribution.\n\
+1. Redistributions of source code must retain the above copyright\n\
+   notice, this list of conditions and the following disclaimer.\n\
+2. Redistributions in binary form must reproduce the above copyright\n\
+   notice, this list of conditions and the following disclaimer in the\n\
+   documentation and/or other materials provided with the distribution.\n\
 \n\
 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n\
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\
@@ -504,12 +511,13 @@
                      "## " strrep(tail, "\n", "\n## ") "\n\n"];
         else
           comment = ["## " strrep(head,"\n","\n## ") "\n\n"                ...
-                     "## -*- texinfo -*- \n## @deftypefn {} " ...
+                     "## -*- texinfo -*-\n## @deftypefn {} " ...
                      "{@var{retval} =} " basename                          ...
                      " (@var{input1}, @var{input2})\n##\n"                 ...
                      "## @seealso{}\n## @end deftypefn\n\n"                ...
                      "## " strrep(tail, "\n", "\n## ") "\n\n"];
         endif
+        comment = strrep (comment, " \n", "\n");
         text = [comment, body];
     endswitch
 
--- a/scripts/miscellaneous/inputParser.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/inputParser.m	Fri Jul 12 12:14:43 2019 -0400
@@ -123,7 +123,7 @@
 ## check ("mech", "~/dev", [0 1 0 0], "verbose", "tolerance", "high");
 ##
 ## ## following returns an error since not all optional arguments,
-## ## `path' and `mat', were given before the named argument `type'.
+## ## 'path' and 'mat', were given before the named argument 'type'.
 ## check ("mech", "~/dev", "type", "linear");
 ## @end group
 ## @end example
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/ismethod.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,51 @@
+## Copyright (C) 2012-2019 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} ismethod (@var{obj}, @var{method})
+## @deftypefnx {} {} ismethod (@var{class_name}, @var{method})
+## Return true if the string @var{method} is a valid method of the object
+## @var{obj} or of the class @var{clsname}.
+## @seealso{isprop, isobject, isjava, methods}
+## @end deftypefn
+
+function retval = ismethod (obj, method)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (! (ischar (obj) || isobject (obj) || isjava (obj)))
+    error ("ismethod: first argument must be object or class name");
+  endif
+
+  if (! ischar (method))
+    error ("ismethod: second argument must be a method name");
+  endif
+
+  method_list = methods (obj);
+
+  retval = ismember (method, method_list);
+
+endfunction
+
+%!testif HAVE_JAVA; usejava ("jvm")
+%! assert (ismethod (javaObject ("java.lang.String", "Yo"), "hashCode"));
+
+%!assert (ismethod (ftp (), "ascii"))
+%!assert (ismethod (inputParser (), "addRequired"))
--- a/scripts/miscellaneous/methods.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/methods.m	Fri Jul 12 12:14:43 2019 -0400
@@ -19,6 +19,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {} methods (@var{obj})
 ## @deftypefnx {} {} methods ("@var{classname}")
+## @deftypefnx {} {} methods (@dots{}, "-full")
 ## @deftypefnx {} {@var{mtds} =} methods (@dots{})
 ## List the names of the public methods for the object @var{obj} or the
 ## named class @var{classname}.
@@ -26,16 +27,29 @@
 ## @var{obj} may be an Octave class object or a Java object.
 ## @var{classname} may be the name of an Octave class or a Java class.
 ##
+## If the optional argument @qcode{"-full"} is given then Octave returns
+## full method signatures which include output type, name of method,
+## and the number and type of inputs.
+##
 ## When called with no output arguments, @code{methods} prints the list of
 ## method names to the screen.  Otherwise, the output argument @var{mtds}
 ## contains the list in a cell array of strings.
-## @seealso{fieldnames}
+## @seealso{ismethod, properties, fieldnames}
 ## @end deftypefn
 
-function mtds = methods (obj)
+function mtds = methods (obj, opt)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
 
-  if (nargin != 1)
-    print_usage ();
+  havesigs = false;
+  showsigs = false;
+  if (nargin == 2)
+    if (! strcmp (opt, "-full"))
+      error ("methods: invalid option");
+    endif
+    showsigs = true;
   endif
 
   if (isobject (obj))
@@ -48,19 +62,39 @@
     if (isempty (mtds_list))
       mtds_str = javaMethod ("getMethods", "org.octave.ClassHelper", obj);
       mtds_list = ostrsplit (mtds_str, ';');
+      mtds_list = mtds_list(:);  # return a column vector for compatibility
+      havesigs = true;
     endif
   elseif (isjava (obj))
-    ## FIXME: Function prototype accepts java obj, but doesn't work if obj
-    ##        is e.g., java.lang.String.  Convert obj to classname then.
-    try
+    ## If obj is a String or a subclass of String, then get the methods of its
+    ## class name, not the methods of the class that may be named by the
+    ## content of the string.
+    if (isa (obj, "java.lang.String"))
+      klass = class (obj);
+      mtds_str = javaMethod ("getMethods", "org.octave.ClassHelper", klass);
+    else
       mtds_str = javaMethod ("getMethods", "org.octave.ClassHelper", obj);
-    catch
-      obj = class (obj);
-      mtds_str = javaMethod ("getMethods", "org.octave.ClassHelper", obj);
-    end_try_catch
+    endif
     mtds_list = strsplit (mtds_str, ';');
+    mtds_list = mtds_list(:);  # return a column vector for compatibility
+    havesigs = true;
   else
-    error ("methods: Invalid input argument");
+    error ("methods: invalid input argument");
+  endif
+
+  if (havesigs && ! showsigs)
+    ## Extract only the method name for ordinary class methods, delete the
+    ## return type and the argument list.
+    mtds_list = regexprep (mtds_list, '^(?:[^(]+) (\w+) ?\(.*$', '$1');
+
+    ## Extract only the class name for class constructors, delete the optional
+    ## "org.example." package prefix and the argument list.
+    mtds_list = regexprep (mtds_list, '^(?:[\.\w]+\.)?(\w+) ?\(.*$', '$1');
+
+    mtds_list = unique (mtds_list);
+  else
+    ## Delete the "org.example." package prefix if present.
+    mtds_list = regexprep (mtds_list, '^(?:[\.\w]+\.)(\w+ ?\(.*)$', '$1');
   endif
 
   if (nargout == 0)
@@ -74,7 +108,7 @@
 endfunction
 
 
-## test Octave classname
+## test old-style @classname
 %!test
 %! mtds = methods ("ftp");
 %! assert (mtds{1}, "ascii");
@@ -82,5 +116,29 @@
 ## test Java classname
 %!testif HAVE_JAVA; usejava ("jvm")
 %! mtds = methods ("java.lang.Double");
+%! search = strfind (mtds, "valueOf");
+%! assert (! isempty ([search{:}]));
+
+## test Java classname with -full prototypes
+%!testif HAVE_JAVA; usejava ("jvm")
+%! mtds = methods ("java.lang.Double", "-full");
 %! search = strfind (mtds, "java.lang.Double valueOf");
 %! assert (! isempty ([search{:}]));
+
+## test that methods does the right thing when passed a String object
+%!testif HAVE_JAVA; usejava ("jvm") <*48758>
+%! object = javaObject ("java.lang.String", "java.lang.Integer");
+%! assert (methods (object), methods ("java.lang.String"));
+
+## test classdef classname
+%!assert (methods ("inputParser"),
+%!        {"addOptional"; "addParamValue"; "addParameter";
+%!         "addRequired"; "addSwitch"; "add_missing"; "delete";
+%!         "disp"; "error"; "is_argname"; "parse"; "validate_arg";
+%!         "validate_name"});
+
+## Test input validation
+%!error methods ()
+%!error methods ("a", "b", "c")
+%!error <invalid option> methods ("ftp", "option1")
+%!error <invalid input argument> methods (1)
--- a/scripts/miscellaneous/mex.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/mex.m	Fri Jul 12 12:14:43 2019 -0400
@@ -17,22 +17,35 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} mex [options] file @dots{}
+## @deftypefn  {} {} mex [-options] file @dots{}
+## @deftypefnx {} {@code{status} =} mex (@dots{})
 ## Compile source code written in C, C++, or Fortran, to a MEX file.
 ##
-## This is equivalent to @code{mkoctfile --mex [options] file}.
+## @var{status} is the return status of the @code{mkoctfile} function.
+##
+## If the compilation fails, and the output argument is not requested,
+## an error is raised.  If the programmer requests @var{status}, however,
+## Octave will merely issue a warning and it is the programmer's responsibility
+## to verify the command was successful.
+##
+## This is equivalent to @code{mkoctfile --mex [-options] file}.
+##
 ## @seealso{mkoctfile, mexext}
 ## @end deftypefn
 
-function retval = mex (varargin)
+function status = mex (varargin)
 
-  [output, status] = mkoctfile ("--mex", varargin{:});
+  [out, sts] = mkoctfile ("--mex", varargin{:});
 
-  if (! isempty (output))
-    printf ("%s", output);
+  if (! isempty (out))
+    printf ("%s", out);
   endif
   if (nargout > 0)
-    retval = status;
+    status = sts;
+  else
+    if (sts != 0)
+      error ("mex: building exited with failure status\n");
+    endif
   endif
 
 endfunction
--- a/scripts/miscellaneous/mkoctfile.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/mkoctfile.m	Fri Jul 12 12:14:43 2019 -0400
@@ -27,8 +27,12 @@
 ##
 ## @code{mkoctfile} can be called from the shell prompt or from the Octave
 ## prompt.  Calling it from the Octave prompt simply delegates the call to
-## the shell prompt.  The output is stored in the @var{output} variable and
-## the exit status in the @var{status} variable.
+## the shell prompt.  Any output is stored in the @var{output} variable and
+## the exit status in the @var{status} variable.  If called with no outputs
+## and the compilation fails then Octave will emit an error.  If the programmer
+## requests @var{output} or @var{status}, however, Octave will merely issue
+## a warning and it is the programmer's responsibility to verify the command
+## was successful.
 ##
 ## @code{mkoctfile} accepts the following options, all of which are optional
 ## except for the filename of the code you wish to compile:
@@ -69,8 +73,8 @@
 ##
 ## @item  -o FILE
 ## @itemx --output FILE
-## Output filename.  Default extension is .oct (or .mex if @samp{--mex} is
-## specified) unless linking a stand-alone executable.
+## Output filename.  Default extension is @file{.oct} (or @file{.mex} if
+## @samp{--mex} is specified) unless linking a stand-alone executable.
 ##
 ## @item  -p VAR
 ## @itemx --print VAR
@@ -160,8 +164,8 @@
 ## Link a stand-alone executable file.
 ##
 ## @item --mex
-## Assume we are creating a MEX file.  Set the default output extension to
-## ".mex".
+## Assume creation of a MEX file.  Set the default output extension to
+## @file{.mex}.
 ##
 ## @item  -s
 ## @itemx --strip
@@ -213,16 +217,18 @@
     cmd = [cmd ' "' varargin{i} '"'];
   endfor
 
-  [sys, out] = system (cmd);
+  [sts, out] = system (cmd);
 
   if (nargout > 0)
-    [output, status] = deal (out, sys);
+    [output, status] = deal (out, sts);
+    if (sts != 0)
+      warning ("mkoctfile: building exited with failure status\n");
+    endif
   else
     printf ("%s", out);
-  endif
-
-  if (sys != 0)
-    warning ("mkoctfile: building exited with failure status\n");
+    if (sts != 0)
+      error ("mkoctfile: building exited with failure status\n");
+    endif
   endif
 
 endfunction
--- a/scripts/miscellaneous/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -36,6 +36,7 @@
   %reldir%/isfile.m \
   %reldir%/isfolder.m \
   %reldir%/ismac.m \
+  %reldir%/ismethod.m \
   %reldir%/ispc.m \
   %reldir%/isunix.m \
   %reldir%/license.m \
@@ -78,6 +79,7 @@
   %reldir%/unzip.m \
   %reldir%/validateattributes.m \
   %reldir%/ver.m \
+  %reldir%/verLessThan.m \
   %reldir%/version.m \
   %reldir%/what.m \
   %reldir%/zip.m
--- a/scripts/miscellaneous/perl.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/perl.m	Fri Jul 12 12:14:43 2019 -0400
@@ -31,7 +31,7 @@
 
 function [output, status] = perl (scriptfile = "-e ''", varargin)
 
-  ## VARARGIN is intialized to {}(1x0) if no additional arguments are
+  ## VARARGIN is initialized to {}(1x0) if no additional arguments are
   ## supplied, so there is no need to check for it, or provide an
   ## initial value in the argument list of the function definition.
 
--- a/scripts/miscellaneous/publish.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/miscellaneous/publish.m	Fri Jul 12 12:14:43 2019 -0400
@@ -819,7 +819,7 @@
 
   ## Helper to clarify the following regular expressions.  It is suitable for
   ## inline formatting, that is delimited literally at start and end by
-  ## `delim`.  `term` is an indicating character for the end delimiter.
+  ## 'delim'.  'term' is an indicating character for the end delimiter.
   ##
   ## Best explained by example ('^' start and '$' end of input):
   ##
@@ -1104,7 +1104,7 @@
 endfunction
 
 
-## Note: Functional BIST tests are located in the `test/publish` directory.
+## Note: Functional BIST tests are located in the 'test/publish' directory.
 
 ## Test input validation
 %!error publish ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/verLessThan.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,85 @@
+## Copyright (C) 2019 Andrew Janke
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for 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 {} {} verLessThan (@var{package}, @var{version})
+## Return true if the installed version of the package is less than
+## @var{version}.
+##
+## @var{package} is the name of the package to check.  Use @qcode{"Octave"} as
+## the @var{package} to check the version of Octave itself.
+##
+## @var{version} is the version to compare it to.  A version is a string in the
+## format accepted by @code{compare_versions}: an arbitrarily long string
+## composed of numeric and period characters, possibly followed by an arbitrary
+## string (e.g., @qcode{"1.2.3"}, @qcode{"0.3"}, @qcode{"0.1.2+"}, or
+## @qcode{"1.2.3.4-test1"}).
+##
+## Examples:
+##
+## @example
+## @group
+## tf = verLessThan ("Octave", "5")
+## @result{} tf = 0
+##
+## tf = verLessThan ("io", "2.4.12")
+## @result{} ...
+##
+## if (! verLessThan ("Octave", "5"))
+##   ## ... use new Octave 5 features ...
+## endif
+## @end group
+## @end example
+##
+## @seealso{compare_versions, version, ver, pkg}
+## @end deftypefn
+
+function retval = verLessThan (package, version)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (! ischar (package) || rows (package) != 1)
+    error ("verLessThan: PACKAGE must be a string");
+  endif
+
+  v = ver ();
+  idx = find (strcmpi (package, {v.Name}));
+  if (isempty (idx))
+    error ('verLessThan: package "%s" is not installed', package);
+  endif
+
+  retval = compare_versions (v(idx).Version, version, "<");
+
+endfunction
+
+
+%!assert (! verLessThan ("Octave", "0"))
+%!assert (! verLessThan ("Octave", "6"))
+%!assert (! verLessThan ("Octave", "3.0.0"))
+%!assert (verLessThan ("Octave", "99.9.9"))
+
+## Test input validation
+%!error verLessThan ()
+%!error verLessThan ("a")
+%!error verLessThan ("a", "1", "b")
+%!error <package "no-such-package" is not installed>
+%! verLessThan ("no-such-package", "1.1.1")
+%!error <compare_versions: version numbers V1 and V2 must be strings>
+%! verLessThan ("Octave", 4.1)
--- a/scripts/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -39,6 +39,7 @@
 include %reldir%/strings/module.mk
 include %reldir%/testfun/module.mk
 include %reldir%/time/module.mk
+include %reldir%/web/module.mk
 
 ## include %reldir%/@ftp/module.mk
 ## The include above fails because Automake cannot process the '@' character.
--- a/scripts/ode/ode15i.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/ode/ode15i.m	Fri Jul 12 12:14:43 2019 -0400
@@ -452,7 +452,7 @@
 %! assert ([t(end), y(end,:)], fref, 1e-3);
 
 ## Jacobian fun sparse
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! opt = odeset ("Jacobian", @jacfunsparse, "AbsTol", 1e-7, "RelTol", 1e-7);
 %! [t, y] = ode15i (@rob, [0, 100], [1; 0; 0], [-1e-4; 1e-4; 0], opt);
 %! assert ([t(end), y(end,:)], fref, 1e-3);
@@ -545,7 +545,7 @@
 %!       "invalid value assigned to field 'Jacobian'");
 
 ## Jacobian cell sparse wrong dimension
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! DFDY = sparse ([-0.04, 1;
 %!                  0.04, 1]);
 %! DFDYP = sparse ([-1,  0, 0;
@@ -575,14 +575,16 @@
 %!       "invalid value assigned to field 'Jacobian'");
 
 ## Jacobian strange field
-## FIXME: we need a better way to silence the warning from odeset.
-%!testif HAVE_SUNDIALS
-%! saved_opts = warning ();
-%! warning ("off", "all");
-%! opt = odeset ("Jacobian", "_5yVNhWVJWJn47RKnzxPsyb_");
-%! fail ("[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)",
-%!       "invalid value assigned to field 'Jacobian'");
-%! warning (saved_opts);
+## FIXME: for compatibility with Matlab, it is no longer an error to
+## create a handle to a nonexistent function and ode15i just checks that
+## the argument is a function handle (it is) so there is no error for
+## this case now.  If this check really must be done early, before
+## attempting to use the invalid function handle, then one way is to
+## call "functions" on it and catch the error if it is invalid.
+##%!testif HAVE_SUNDIALS
+##%! opt = odeset ("Jacobian", "_5yVNhWVJWJn47RKnzxPsyb_");
+##%! fail ("[t, y] = ode15i (@rob, [0, 4e6], [1; 0; 0], [-1e-4; 1e-4; 0], opt)",
+##%!       "invalid value assigned to field 'Jacobian'");
 
 %!function ydot = fun (t, y, yp)
 %!  ydot = [y - yp];
--- a/scripts/ode/ode15s.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/ode/ode15s.m	Fri Jul 12 12:14:43 2019 -0400
@@ -545,21 +545,21 @@
 %! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);
 %! assert ([t(end), y(end,:)], frefrob, 1e-3);
 
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! opt = odeset ("MStateDependence", "none",
 %!               "Mass", [1, 0, 0; 0, 1, 0; 0, 0, 0],
 %!               "Jacobian", @jacfunsparse);
 %! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);
 %! assert ([t(end), y(end,:)], frefrob, 1e-3);
 
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! opt = odeset ("MStateDependence", "none",
 %!               "Mass", sparse ([1, 0, 0; 0, 1, 0; 0, 0, 0]),
 %!               "Jacobian", @jacfunsparse);
 %! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);
 %! assert ([t(end), y(end,:)], frefrob, 1e-3);
 
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! warning ("off", "ode15s:mass_state_dependent_provided", "local");
 %! opt = odeset ("MStateDependence", "none",
 %!               "Mass", @massdensefunstate,
@@ -575,14 +575,14 @@
 %! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);
 %! assert ([t(end), y(end,:)], frefrob, 1e-3);
 
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! opt = odeset ("MStateDependence", "none",
 %!               "Mass", @massdensefuntime,
 %!               "Jacobian", @jacfunsparse);
 %! [t, y] = ode15s (@rob, [0, 100], [1; 0; 0], opt);
 %! assert ([t(end), y(end,:)], frefrob, 1e-3);
 
-%!testif HAVE_SUNDIALS_IDAKLU
+%!testif HAVE_SUNDIALS_SUNLINSOL_KLU
 %! opt = odeset ("MStateDependence", "none",
 %!               "Mass", @masssparsefuntime,
 %!               "Jacobian", @jacfunsparse);
--- a/scripts/optimization/fminbnd.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/fminbnd.m	Fri Jul 12 12:14:43 2019 -0400
@@ -272,9 +272,9 @@
   fx = fun (x);
   fx = fx(1);
   if (! isreal (fx))
-    error ("fminbnd:notreal", "fminbnd: non-real value encountered");
+    error ("Octave:fmindbnd:notreal", "fminbnd: non-real value encountered");
   elseif (isnan (fx))
-    error ("fminbnd:isnan", "fminbnd: NaN value encountered");
+    error ("Octave:fmindbnd:isnan", "fminbnd: NaN value encountered");
   endif
 endfunction
 
--- a/scripts/optimization/fminunc.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/fminunc.m	Fri Jul 12 12:14:43 2019 -0400
@@ -410,11 +410,11 @@
   endif
 
   if (! (isreal (fx) && isreal (gx)))
-    error ("fminunc:notreal", "fminunc: non-real value encountered");
+    error ("Octave:fminunc:notreal", "fminunc: non-real value encountered");
   elseif (any (isnan (fx(:))))
-    error ("fminunc:isnan", "fminunc: NaN value encountered");
+    error ("Octave:fminunc:isnan", "fminunc: NaN value encountered");
   elseif (any (isinf (fx(:))))
-    error ("fminunc:isinf", "fminunc: Inf value encountered");
+    error ("Octave:fminunc:isinf", "fminunc: Inf value encountered");
   endif
 
 endfunction
--- a/scripts/optimization/fsolve.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/fsolve.m	Fri Jul 12 12:14:43 2019 -0400
@@ -499,13 +499,13 @@
   endif
 
   if (! complexeqn && ! (isreal (fx) && isreal (jx)))
-    error ("fsolve:notreal", "fsolve: non-real value encountered");
+    error ("Octave:fsolve:notreal", "fsolve: non-real value encountered");
   elseif (complexeqn && ! (isnumeric (fx) && isnumeric (jx)))
-    error ("fsolve:notnum", "fsolve: non-numeric value encountered");
+    error ("Octave:fsolve:notnum", "fsolve: non-numeric value encountered");
   elseif (any (isnan (fx(:))))
-    error ("fsolve:isnan", "fsolve: NaN value encountered");
+    error ("Octave:fsolve:isnan", "fsolve: NaN value encountered");
   elseif (any (isinf (fx(:))))
-    error ("fsolve:isinf", "fsolve: Inf value encountered");
+    error ("Octave:fsolve:isinf", "fsolve: Inf value encountered");
   endif
 
 endfunction
--- a/scripts/optimization/fzero.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/fzero.m	Fri Jul 12 12:14:43 2019 -0400
@@ -197,7 +197,7 @@
   endif
 
   if (! (sign (fa) * sign (fb) <= 0))
-    error ("fzero:bracket", "fzero: not a valid initial bracketing");
+    error ("Octave:fzero:bracket", "fzero: not a valid initial bracketing");
   endif
 
   slope0 = (fb - fa) / (b - a);
@@ -331,7 +331,7 @@
       break;
     else
       ## This should never happen.
-      error ("fzero:bracket", "fzero: zero point is not bracketed");
+      error ("Octave:fzero:bracket", "fzero: zero point is not bracketed");
     endif
 
     ## If there's an output function, use it now.
@@ -385,9 +385,9 @@
   fx = fun (x);
   fx = fx(1);
   if (! isreal (fx))
-    error ("fzero:notreal", "fzero: non-real value encountered");
+    error ("Octave:fzero:notreal", "fzero: non-real value encountered");
   elseif (isnan (fx))
-    error ("fzero:isnan", "fzero: NaN value encountered");
+    error ("Octave:fzero:isnan", "fzero: NaN value encountered");
   endif
 endfunction
 
--- a/scripts/optimization/qp.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/qp.m	Fri Jul 12 12:14:43 2019 -0400
@@ -69,18 +69,19 @@
 ## the number of constraints.  The algorithm is faster if the initial guess is
 ## feasible.
 ##
-## @table @var
-## @item options
-## An optional structure containing the following parameter(s) used to define
-## the behavior of the solver.  Missing elements in the structure take on
-## default values, so you only need to set the elements that you wish to
-## change from the default.
+## @var{options} is a structure specifying additional parameters which
+## control the algorithm.  Currently, @code{qp} recognizes these options:
+## @qcode{"MaxIter"}, @qcode{"TolX"}.
 ##
-## @table @code
-## @item MaxIter (default: 200)
-## Maximum number of iterations.
-## @end table
-## @end table
+## @qcode{"MaxIter"} proscribes the maximum number of algorithm iterations
+## before optimization is halted.  The default value is 200.
+## The value must be a positive integer.
+##
+## @qcode{"TolX"} specifies the termination tolerance for the unknown variables
+## @var{x}.  The default is @code{sqrt (eps)} or approximately 1e-8.
+##
+## On return, @var{x} is the location of the minimum and @var{fval} contains
+## the value of the objective function at @var{x}.
 ##
 ## @table @var
 ## @item info
@@ -112,6 +113,7 @@
 ## @end table
 ## @end table
 ## @end table
+## @seealso{sqp}
 ## @end deftypefn
 
 ## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
@@ -120,7 +122,7 @@
 function [x, obj, INFO, lambda] = qp (x0, H, varargin)
 
   if (nargin == 1 && ischar (x0) && strcmp (x0, "defaults"))
-    x = struct ("MaxIter", 200);
+    x = struct ("MaxIter", 200, "TolX", sqrt (eps));
     return;
   endif
 
@@ -169,6 +171,7 @@
   endif
 
   maxit = optimget (options, "MaxIter", 200);
+  tol = optimget (options, "TolX", sqrt (eps));
 
   ## Validate the quadratic penalty.
   if (! issquare (H))
@@ -243,7 +246,7 @@
     endif
 
     if (! isempty (lb) && ! isempty (ub))
-      rtol = sqrt (eps);
+      rtol = tol;
       for i = 1:n
         if (abs (lb (i) - ub(i)) < rtol*(1 + max (abs (lb(i) + ub(i)))))
           ## These are actually an equality constraint
@@ -291,7 +294,7 @@
       endif
 
       if (! isempty (A_lb) && ! isempty (A_ub))
-        rtol = sqrt (eps);
+        rtol = tol;
         for i = 1:dimA_in
           if (abs (A_lb(i) - A_ub(i))
               < rtol*(1 + max (abs (A_lb(i) + A_ub(i)))))
@@ -331,7 +334,7 @@
       || isa (A, "single") || isa (b, "single"))
     rtol = sqrt (eps ("single"));
   else
-    rtol = sqrt (eps);
+    rtol = tol;
   endif
 
   eq_infeasible = (n_eq > 0 && norm (A*x0-b) > rtol*(1+abs (b)));
@@ -410,7 +413,7 @@
 
   if (info == 0)
     ## The initial (or computed) guess is feasible.  Call the solver.
-    [x, lambda, info, iter] = __qp__ (x0, H, q, A, b, Ain, bin, maxit);
+    [x, lambda, info, iter] = __qp__ (x0, H, q, A, b, Ain, bin, maxit, rtol);
   else
     iter = 0;
     x = x0;
--- a/scripts/optimization/sqp.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/optimization/sqp.m	Fri Jul 12 12:14:43 2019 -0400
@@ -417,7 +417,7 @@
 
     old_lambda = lambda;
     [p, obj_qp, INFO, lambda] = qp (x, B, c, F, g, [], [], d, C,
-                                    Inf (size (d)));
+                                    Inf (size (d)), struct ("TolX", tol));
 
     info = INFO.info;
 
--- a/scripts/pkg/pkg.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/pkg/pkg.m	Fri Jul 12 12:14:43 2019 -0400
@@ -417,23 +417,57 @@
         else
           ## If files do not exist, maybe they are not local files.
           ## Try to download them.
-          external_files_mask = cellfun (@(x) isempty (glob (x)), files);
-          if (any (external_files_mask))
+          not_local_files = cellfun (@(x) isempty (glob (x)), files);
+          if (any (not_local_files))
             [success, msg] = mkdir (tmp_dir);
             if (success != 1)
               error ("pkg: failed to create temporary directory: %s", msg);
             endif
 
-            for file_idx = find (external_files_mask)
-
-              [~, fname, fext] = fileparts (files{file_idx});
-              local_files{end+1} = fullfile (tmp_dir, [fname fext]);
-              [~, success, msg] = urlwrite (files{file_idx}, local_files{end});
-              if (success != 1)
-                error ("pkg: failed to read package '%s': %s",
-                       files{file_idx}, msg);
+            for file = files(not_local_files)
+              file = file{1};
+              [~, fname, fext] = fileparts (file);
+              tmp_file = fullfile (tmp_dir, [fname fext]);
+              local_files{end+1} = tmp_file;
+              looks_like_url = regexp (file, '^\w+://');
+              if (looks_like_url)
+                [~, success, msg] = urlwrite (file, local_files{end});
+                if (success != 1)
+                  error ("pkg: failed downloading '%s': %s", file, msg);
+                endif
+                ## Verify that download is a tarball,
+                ## to protect against ISP DNS hijacking.
+                ## FIXME: Need a test which does not rely on external OS.
+                #{
+                if (isunix ())
+                  [ok, file_descr] = ...
+                    system (sprintf ('file "%s" | cut -d ":" -f 2', ...
+                                     local_files{end}));
+                  if (! ok)
+                    if (strfind (file_descr, "HTML"))
+                      error (["pkg: Invalid package file downloaded from " ...
+                              "%s\n" ...
+                              "File is HTML, not a tar archive."], ...
+                             file);
+                    endif
+                  else
+                    ## Ignore: maybe something went wrong with the "file" call.
+                  endif
+                endif
+                #}
+              else
+                looks_like_pkg_name = regexp (file, '^[\w-]+$');
+                if (looks_like_pkg_name)
+                  error (["pkg: file not found: %s.\n" ...
+                          "This looks like an Octave Forge package name." ...
+                          "  Did you mean:\n" ...
+                          "       pkg install -forge %s"], ...
+                         file, file);
+                else
+                  error ("pkg: file not found: %s", file);
+                endif
               endif
-              files{file_idx} = local_files{end};
+              files{strcmp (files, file)} = local_files{end};
 
             endfor
           endif
--- a/scripts/pkg/private/configure_make.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/pkg/private/configure_make.m	Fri Jul 12 12:14:43 2019 -0400
@@ -96,7 +96,7 @@
       if (status != 0)
         rmdir (desc.dir, "s");
         disp (output);
-        error ("pkg: error running `make' for the %s package.", desc.name);
+        error ("pkg: error running 'make' for the %s package.", desc.name);
       endif
     endif
   endif
@@ -129,7 +129,7 @@
     endif
   endif
   ## if verbose, we want to display the output in real time.  To do this, we
-  ## must call system with 1 output argument.  But then the variable `output'
+  ## must call system with 1 output argument.  But then the variable 'output'
   ## won't exist.  So we initialize it empty.  If an error does occur, and we
   ## are verbose we will return an empty string but it's all fine since
   ## the error message has already been displayed.
--- a/scripts/plot/appearance/annotation.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/annotation.m	Fri Jul 12 12:14:43 2019 -0400
@@ -480,13 +480,12 @@
 
       hr = patch (x, y, "parent", h);
 
-      ## FIXME: DEPRECATED: Remove warn state switching in version 6.
-      old_warn_state = warning ("off", "Octave:deprecated-property");
       propnames = rectprops ("names");
+      ## FIXME: Remove in Octave 6
+      propnames(strcmp ("edgecolor", propnames)) = [];
       for ii = 1:numel (propnames)
         update_rect (h, {}, propnames{ii}, hr, objtype);
       endfor
-      warning (old_warn_state);
 
       rectmenu (hui, h);
       set (hr, "uicontextmenu", hui);
@@ -851,7 +850,7 @@
       val = label = vals{ii};
     else
       val = vals(ii);
-      label = num2str (val);
+      label = disp (val);
     endif
 
     fcn = @() set (hpar, pname, val);
@@ -868,7 +867,7 @@
   vals = get (hmenus, "label");
   current = get (h, prop);
   if (is_numeric)
-    current = num2str (current);
+    current = disp (current);
   endif
 
   idx = strcmp (vals, current);
@@ -939,16 +938,14 @@
         y = [pos(2) (pos(2) + pos(4))];
 
         recursive = true;
-        set (h, "x", x);
-        set (h, "y", y);
+        set (h, "x", x, "y", y);
         recursive = false;
 
         ## Draw in normalized coordinates
         pos = getnormpos (h);
         x = [pos(1) (pos(1) + pos(3))];
         y = [pos(2) (pos(2) + pos(4))];
-        set (hli, "xdata", x);
-        set (hli, "ydata", y);
+        set (hli, "xdata", x, "ydata", y);
 
     endswitch
   endif
@@ -1035,8 +1032,8 @@
           [x, y] = arrowcoordinates (h, nar);
           set (hpa(ii), "xdata", x, "ydata", y);
         case "color"
-          set (hpa(ii), "facecolor", get (h, "color"));
-          set (hpa(ii), "edgecolor", get (h, "color"));
+          set (hpa(ii), "facecolor", get (h, "color"),
+                        "edgecolor", get (h, "color"));
       endswitch
     endif
   endfor
--- a/scripts/plot/appearance/axis.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/axis.m	Fri Jul 12 12:14:43 2019 -0400
@@ -487,6 +487,8 @@
 
 %!demo
 %! clf;
+%! def_ticklen = get (0, "DefaultAxesTickLength");
+%! set (0, "DefaultAxesTickLength", [.028, .025]);
 %! t = 0:0.01:2*pi;
 %! x = sin (t);
 %!
@@ -534,6 +536,8 @@
 %!  plot (t, x);
 %!  title ("all ticks and labels");
 %!  axis ("on");
+%!
+%! set (0, "DefaultAxesTickLength", def_ticklen);
 
 %!demo
 %! clf;
--- a/scripts/plot/appearance/gtext.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/gtext.m	Fri Jul 12 12:14:43 2019 -0400
@@ -24,16 +24,30 @@
 ## @deftypefnx {} {@var{h} =} gtext (@dots{})
 ## Place text on the current figure using the mouse.
 ##
-## The text is defined by the string @var{s}.  If @var{s} is a cell string
-## organized as a row vector then each string of the cell array is written to a
-## separate line.  If @var{s} is organized as a column vector then one string
-## element of the cell array is placed for every mouse click.
+## The string argument @var{s} may be a character array or a cell array
+## of strings.  If @var{s} has more than one row, each row is used
+## to create a separate text object after a mouse click. For example:
+##
+## Place a single string after one mouse click
+## @example
+## gtext ("I clicked here")
+## @end example
 ##
-## Optional property/value pairs are passed directly to the underlying text
-## objects.
+## Place two strings after two mouse clicks
+## @example
+## gtext (@{"I clicked here"; "and there"@})
+## @end example
 ##
-## The optional return value @var{h} is a graphics handle to the created
-## text object(s).
+## Place two strings, each with two lines, after two mouse clicks
+## @example
+## gtext (@{"I clicked", "here"; "and", "there"@})
+## @end example
+##
+## Optional @var{property}/@var{value} pairs are passed directly to the
+## underlying text objects.
+##
+## The optional return value @var{h} holds the graphics handle(s) to the
+## created text object(s).
 ## @seealso{ginput, text}
 ## @end deftypefn
 
@@ -44,20 +58,15 @@
   endif
 
   if (! (ischar (s) || iscellstr (s)))
-    error ("gtext: S must be a string or cell array of strings");
+    error ("gtext: S must a character array or cell array of strings");
   endif
 
-  htmp = -1;
+  htmp = [];
   if (! isempty (s))
-    if (ischar (s) || isrow (s))
+    for i = 1:rows (s)
       [x, y] = ginput (1);
-      htmp = text (x, y, s, varargin{:});
-    else
-      for i = 1:numel (s)
-        [x, y] = ginput (1);
-        htmp = text (x, y, s{i}, varargin{:});
-      endfor
-    endif
+      htmp = [htmp, text(x, y, s(i,:), varargin{:})];
+    endfor
   endif
 
   if (nargout > 0)
--- a/scripts/plot/appearance/legend.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/legend.m	Fri Jul 12 12:14:43 2019 -0400
@@ -203,38 +203,21 @@
   find_leg_hdl = (nargs == 0);  # possibly overridden
   propvals = {};
 
-  ## Process old way of specifying location with a number rather than a string.
-  ## FIXME: When can this be deleted?
-  if (nargs > 0)
-    pos = varargin{nargs};
-    if (isnumeric (pos) && isscalar (pos) && pos == fix (pos))
-      warning ("legend: specifying location with a numeric argument is obsolete and will be removed from a future version of Octave, use a string specification instead");
-      if (pos >= -1 && pos <= 4)
-        location = [{"northeastoutside", "best", "northeast",
-                     "northwest", "southwest", "southeast"}] {pos + 2};
-        varargin(nargs) = [];
-        nargs -= 1;
-      else
-        error ("legend: invalid location specified");
-      endif
-    endif
-  endif
-
   ## Find "location" and "orientation" property/value pairs
-  while (nargs > 1)
-    pos = varargin{nargs-1};
-    str = varargin{nargs};
+  i = nargs - 1;
+  while (i > 0)
+    pos = varargin{i};
+    str = varargin{i+1};
     if (strcmpi (pos, "location") && ischar (str))
       location = lower (str);
-      varargin(nargs-1:nargs) = [];
+      varargin(i:i+1) = [];
       nargs -= 2;
     elseif (strcmpi (pos, "orientation") && ischar (str))
       orientation = lower (str);
-      varargin(nargs-1:nargs) = [];
+      varargin(i:i+1) = [];
       nargs -= 2;
-    else
-      break;
     endif
+    i -= 2;
   endwhile
 
   ## Validate the orientation
@@ -559,8 +542,7 @@
       ## Rely on listener to handle conversion.
       units = get (cax, "units");
       unwind_protect
-        set (cax, "units", "points");
-        set (cax, "fontunits", "points");
+        set (cax, "units", "points", "fontunits", "points");
         if (isempty (hlegend) || ! isprop (hlegend, "unmodified_axes_position"))
           unmodified_axes_position = get (cax, "position");
           unmodified_axes_outerposition = get (cax, "outerposition");
@@ -627,6 +609,11 @@
           fontsz *= 0.90;  # Reduce legend fontsize to 90% of axes fontsize
           set (hlegend, {"fontunits", "fontsize"}, {fontunits, fontsz});
           set (hlegend, "fontunits", "points");  # legend always works in pts.
+          ## Also inherit colormap from axes if it is different than figure
+          cax_cmap = get (cax, "colormap");
+          if (! isequal (cax_cmap, get (hpar, "colormap")))
+            set (hlegend, "colormap", cax_cmap);
+          endif
           old_hplots = [];
         else
           ## Re-use existing legend.
@@ -865,8 +852,7 @@
 
         units = get (hlegend, "units");
         unwind_protect
-          set (hlegend, "units", "points");
-          set (hlegend, "position", lpos);
+          set (hlegend, "units", "points", "position", lpos);
         unwind_protect_cleanup
           set (hlegend, "units", units);
         end_unwind_protect
@@ -1040,8 +1026,8 @@
                 ## Let gnuplot handle the positioning of the keybox.
                 ## This violates strict Matlab compatibility, but reliably
                 ## renders an aesthetic result.
-                set (ca(i), "position",  unmodified_axes_position);
-                set (ca(i), "activepositionproperty", "outerposition");
+                set (ca(i), "position",  unmodified_axes_position,
+                            "activepositionproperty", "outerposition");
               else
                 ## numel (ca) > 1 for axes overlays (like plotyy)
                 set (ca(i), "position", new_pos);
@@ -1084,6 +1070,7 @@
         endif
 
         if (addprops)
+          addlistener (cax, "colormap", {@cb_legend_colormap_update, hlegend});
           addlistener (hlegend, "edgecolor", @cb_legend_text_update);
           addlistener (hlegend, "fontangle", @cb_legend_text_update);
           addlistener (hlegend, "fontname", @cb_legend_text_update);
@@ -1139,6 +1126,11 @@
 
 endfunction
 
+## Colormap of the base axes has changed.
+function cb_legend_colormap_update (cax, ~, hlegend)
+  set (hlegend, "colormap", get (cax, "colormap"));
+endfunction
+
 ## A non-text property of legend has changed requiring an update.
 function cb_legend_update (hleg, ~)
   persistent recursive = false;
@@ -1156,11 +1148,9 @@
       set (hax, "units", "points");
       switch (get (hax, "activepositionproperty"))
         case "position"
-          set (hax, "outerposition", outerposition);
-          set (hax, "position", position);
+          set (hax, "outerposition", outerposition, "position", position);
         case "outerposition"
-          set (hax, "position", position);
-          set (hax, "outerposition", outerposition);
+          set (hax, "position", position, "outerposition", outerposition);
       endswitch
       if (isscalar (hax))
         set (hax, "units", units);
@@ -1259,8 +1249,7 @@
       if (isaxes (cax))
         units = get (cax, "units");
         unwind_protect
-          set (cax, "units", "points");
-          set (cax, "position", pos);
+          set (cax, "units", "points", "position", pos);
         unwind_protect_cleanup
           set (cax, "units", units);
         end_unwind_protect
--- a/scripts/plot/appearance/orient.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/orient.m	Fri Jul 12 12:14:43 2019 -0400
@@ -85,9 +85,9 @@
           ##        set the papersize and paperposition here.
           papersize = get (cf, "papersize");
           paperposition = get (cf, "paperposition");
-          set (cf, "paperorientation", orientation);
-          set (cf, "papersize", papersize([2, 1]));
-          set (cf, "paperposition", paperposition([2, 1, 4, 3]));
+          set (cf, "paperorientation", orientation,
+                   "papersize", papersize([2, 1]),
+                   "paperposition", paperposition([2, 1, 4, 3]));
         endif
         if (strcmpi (orientation, "portrait"))
           ## portrait restores the default
--- a/scripts/plot/appearance/text.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/appearance/text.m	Fri Jul 12 12:14:43 2019 -0400
@@ -20,6 +20,7 @@
 ## @deftypefn  {} {} text (@var{x}, @var{y}, @var{string})
 ## @deftypefnx {} {} text (@var{x}, @var{y}, @var{z}, @var{string})
 ## @deftypefnx {} {} text (@dots{}, @var{prop}, @var{val}, @dots{})
+## @deftypefnx {} {} text (@var{hax}, @dots{})
 ## @deftypefnx {} {@var{h} =} text (@dots{})
 ## Create a text object with text @var{string} at position @var{x}, @var{y},
 ## (@var{z}) on the current axes.
@@ -31,6 +32,9 @@
 ## Optional property/value pairs may be used to control the appearance of the
 ## text.
 ##
+## If the first argument @var{hax} is an axes handle, then add text to this
+## axes, rather than the current axes returned by @code{gca}.
+##
 ## The optional return value @var{h} is a vector of graphics handles to the
 ## created text objects.
 ##
@@ -46,6 +50,8 @@
 
 function h = text (varargin)
 
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("text", varargin{:});
+
   nargs = nargin;
   offset = 0;
 
@@ -82,9 +88,6 @@
     print_usage ();
   endif
 
-  ## Get axis argument which may be in a "parent" PROP/VAL pair
-  [hax, varargin] = __plt_get_axis_arg__ ("text", varargin{:});
-
   ## String argument may be in PROP/VAL pair
   idx = find (strcmpi (varargin, "string"), 1);
   if (idx)
--- a/scripts/plot/draw/colorbar.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/colorbar.m	Fri Jul 12 12:14:43 2019 -0400
@@ -209,8 +209,8 @@
     ## Restore original axes position before applying new colorbar settings
     orig_props = get (hcb, "deletefcn"){3};
     units = get (hax, "units");
-    set (hax, "units", orig_props.units);
-    set (hax, "position", orig_props.position,
+    set (hax, "units", orig_props.units,
+              "position", orig_props.position,
               "outerposition", orig_props.outerposition,
               "activepositionproperty", orig_props.activepositionproperty);
     set (hax, "units", units);
@@ -428,8 +428,8 @@
 
     ## Restore original axes position
     units = get (hax, "units");
-    set (hax, "units", orig_props.units);
-    set (hax, "position", orig_props.position,
+    set (hax, "units", orig_props.units,
+              "position", orig_props.position,
               "outerposition", orig_props.outerposition,
               "activepositionproperty", orig_props.activepositionproperty);
     set (hax, "units", units);
--- a/scripts/plot/draw/comet.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/comet.m	Fri Jul 12 12:14:43 2019 -0400
@@ -28,7 +28,7 @@
 ##
 ## The speed of the comet may be controlled by @var{p}, which represents the
 ## time each point is displayed before moving to the next one.  The default for
-## @var{p} is 0.1 seconds.
+## @var{p} is @code{5 / numel (@var{y})}.
 ##
 ## If the first argument @var{hax} is an axes handle, then plot into this axes,
 ## rather than the current axes returned by @code{gca}.
@@ -47,11 +47,11 @@
   elseif (nargin == 1)
     y = varargin{1};
     x = 1:numel (y);
-    p = 0.1;
+    p = 5 / numel (y);
   elseif (nargin == 2)
     x = varargin{1};
     y = varargin{2};
-    p = 0.1;
+    p = 5 / numel (y);
   elseif (nargin == 3)
     x = varargin{1};
     y = varargin{2};
@@ -73,6 +73,10 @@
                x(1), y(1), "color", "b", "marker", "o");
     axis (limits);  # set manual limits to speed up plotting
 
+    ## Initialize the timer
+    t = p;
+    timerid = tic ();
+
     for n = 2:(num+dn)
       m = n - dn;
       m = max ([m, 1]);
@@ -80,8 +84,9 @@
       set (hl(1), "xdata", x(1:m), "ydata", y(1:m));
       set (hl(2), "xdata", x(m:k), "ydata", y(m:k));
       set (hl(3), "xdata", x(k),   "ydata", y(k));
-      drawnow ();
-      pause (p);
+
+      pause (t - toc (timerid));
+      t += p;
     endfor
 
   unwind_protect_cleanup
@@ -100,5 +105,5 @@
 %! t = 0:.1:2*pi;
 %! x = cos (2*t) .* (cos (t).^2);
 %! y = sin (2*t) .* (sin (t).^2);
-%! comet (x, y, 0.05);
+%! comet (x, y, .05);
 %! hold off;
--- a/scripts/plot/draw/comet3.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/comet3.m	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,7 @@
 ##
 ## The speed of the comet may be controlled by @var{p}, which represents the
 ## time each point is displayed before moving to the next one.  The default for
-## @var{p} is 0.1 seconds.
+## @var{p} is @code{5 / numel (@var{z})}.
 ##
 ## If the first argument @var{hax} is an axes handle, then plot into this axes,
 ## rather than the current axes returned by @code{gca}.
@@ -48,12 +48,12 @@
   elseif (nargin == 1)
     z = varargin{1};
     x = y = 1:numel (z);
-    p = 0.1;
+    p = 5 / numel (z);
   elseif (nargin == 3)
     x = varargin{1};
     y = varargin{2};
     z = varargin{3};
-    p = 0.1;
+    p = 5 / numel (z);
   elseif (nargin == 4)
     x = varargin{1};
     y = varargin{2};
@@ -76,6 +76,10 @@
                 x(1), y(1), z(1), "color", "b", "marker", "o");
     axis (limits);  # set manual limits to speed up plotting
 
+    ## Initialize the timer
+    t = p;
+    timerid = tic ();
+
     for n = 2:(num+dn)
       m = n - dn;
       m = max ([m, 1]);
@@ -83,8 +87,9 @@
       set (hl(1), "xdata", x(1:m), "ydata", y(1:m), "zdata", z(1:m));
       set (hl(2), "xdata", x(m:k), "ydata", y(m:k), "zdata", z(m:k));
       set (hl(3), "xdata", x(k)  , "ydata", y(k)  , "zdata", z(k));
-      drawnow ();
-      pause (p);
+
+      pause (t - toc (timerid));
+      t += p;
     endfor
   unwind_protect_cleanup
     if (! isempty (oldfig))
@@ -100,5 +105,5 @@
 %! title ("comet3() animation");
 %! view (3); hold on;
 %! t = 0:pi/20:5*pi;
-%! comet3 (cos (t), sin (t), t, 0.05);
+%! comet3 (cos (t), sin (t), t);
 %! hold off;
--- a/scripts/plot/draw/ezplot3.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/ezplot3.m	Fri Jul 12 12:14:43 2019 -0400
@@ -77,11 +77,11 @@
 %! fx = @(t) cos (t);
 %! fy = @(t) sin (t);
 %! fz = @(t) t;
-%! ezplot3 (fx, fy, fz, [0, 10*pi], 100);
+%! ezplot3 (fx, fy, fz, [0, 10*pi]);
 
 %!demo
 %! clf;
 %! fx = @(t) cos (t);
 %! fy = @(t) sin (t);
 %! fz = @(t) t;
-%! ezplot3 (fx, fy, fz, [0, 5*pi], 100, "animate");
+%! ezplot3 (fx, fy, fz, [0, 5*pi], "animate");
--- a/scripts/plot/draw/hist.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/hist.m	Fri Jul 12 12:14:43 2019 -0400
@@ -104,6 +104,9 @@
     min_val = double (min_val);
   endif
 
+  ## Equidistant entries allow much more efficient algorithms.
+  equal_bin_spacing = true;
+
   ## Process possible second argument
   if (nargin == 1 || ischar (varargin{iarg}))
     n = 10;
@@ -122,8 +125,8 @@
       error ("hist: bin specification must be a numeric scalar or vector");
     endif
 
-    ## Do not convert if input is of class single (or if already is double).
-    if (! isfloat (x))
+    ## Convert integer types or a single specification of N bins to double
+    if (! isfloat (x) || isscalar (x))
       x = double (x);
     endif
 
@@ -141,6 +144,13 @@
       endif
       x = x.';  # Convert to matrix;
     elseif (isvector (x))
+      equal_bin_spacing = strcmp (typeinfo (x), "range");
+      if (! equal_bin_spacing)
+        diffs = diff (x);
+        if (all (diffs == diffs(1)))
+          equal_bin_spacing = true;
+        endif
+      endif
       x = x(:);
       if (! issorted (x))
         warning ("hist: bin values X not sorted on input");
@@ -162,35 +172,54 @@
 
   ## Perform histogram calculation
   cutoff = (x(1:end-1,:) + x(2:end,:)) / 2;
-  if (isinteger (y))
-    cutoff = floor (cutoff);
-  endif
 
   n = rows (x);
   y_nc = columns (y);
-  if (n < 30 && columns (x) == 1)
-    ## The following algorithm works fastest for n less than about 30.
+
+  if (n < 11 * (1 + (! equal_bin_spacing)))
+    ## The following algorithm works fastest for small n.
+    nanidx = isnan (y);
     chist = zeros (n+1, y_nc);
     for i = 1:n-1
       chist(i+1,:) = sum (y <= cutoff(i));
     endfor
-    chist(n+1,:) = sum (! isnan (y));
+    chist(n+1,:) = sum (! nanidx);
+
+    freq = diff (chist);
   else
-    ## The following algorithm works fastest for n greater than about 30.
-    ## Put cutoff elements between boundaries, integrate over all
-    ## elements, keep totals at boundaries.
-    m = (nthargout (2, @sort, [y; repmat(cutoff, 1, y_nc)]) <= rows (y));
-    chist = cumsum (m);
-    chist = [(zeros (1, y_nc));
-             (reshape (chist(! m), rows (cutoff), y_nc));
-             (chist(end,:) - sum (isnan (y)))];
+    ## Lookup is more efficient if y is sorted, but sorting costs.
+    if (! equal_bin_spacing && n > sqrt (rows (y) * 1e4))
+      y = sort (y);
+    end
+
+    nanidx = isnan (y);
+    y(nanidx) = 0;
+    freq = zeros (n, y_nc);
+    if (equal_bin_spacing)
+      if (n < 3)
+        d = 1;
+      else
+        d = (x(end) - x(1)) / (length (x) - 1);
+      end
+      cutlen = length (cutoff);
+      for j = 1:y_nc
+        freq(:,j) = accumarray (1 + max (0, min (cutlen, ceil ((double (y(:,j))
+                                                         - cutoff(1)) / d))),
+                                double (! nanidx(:,j)),
+                                [n, 1]);
+      end
+    else
+      for j = 1:y_nc
+        i = lookup (cutoff, y(:,j));
+        i = 1 + i - (cutoff(max (i, 1)) == y(:,j));
+        freq(:,j) = accumarray (i, double (! nanidx(:,j)), [n, 1]);
+      end
+    end
   endif
 
-  freq = diff (chist);
-
   if (norm)
     ## Normalize the histogram
-    freq = freq .* norm ./ sum (! isnan (y));
+    freq .*= norm ./ sum (! nanidx);
   endif
 
   if (nargout == 0)
@@ -257,9 +286,9 @@
 %! assert (nn, n);
 %! assert (xx, x);
 %!
-%! ## test again with N > 30 because there's a special case for it
-%! [n, x] = hist (y, 35);
-%! [nn, xx] = hist (uint8 (y), 35);
+%! ## test again with N > 26 because there's a special case for it
+%! [n, x] = hist (y, 30);
+%! [nn, xx] = hist (uint8 (y), 30);
 %! assert (nn, n);
 %! assert (xx, x);
 
@@ -271,9 +300,9 @@
 %! assert (nn, n);
 %! assert (xx, x);
 %!
-%! ## test again with N > 30 because there's a special case for it
-%! [n, x] = hist (y, 35);
-%! [nn, xx] = hist (logical (y), 35);
+%! ## test again with N > 26 because there's a special case for it
+%! [n, x] = hist (y, 30);
+%! [nn, xx] = hist (logical (y), 30);
 %! assert (nn, n);
 %! assert (xx, x);
 
@@ -337,6 +366,17 @@
 %! assert (nn, [2 0 0 0 0 0 0 0 0 2]);
 %! assert (xx, 0.5:10);
 
+## Test return class of second output
+%!test <*56465>
+%! [nn, xx] = hist (double (1:10), single (7));
+%! assert (isa (xx, "double"));
+%! [nn, xx] = hist (single (1:10), double (7));
+%! assert (isa (xx, "single"));
+%! [nn, xx] = hist (single (1:10), double ([1, 5, 10]));
+%! assert (isa (xx, "double"));
+%! [nn, xx] = hist (double (1:10), single ([1, 5, 10]));
+%! assert (isa (xx, "single"));
+
 ## Test input validation
 %!error hist ()
 %!error <Y must be real-valued> hist (2+i)
--- a/scripts/plot/draw/isosurface.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/isosurface.m	Fri Jul 12 12:14:43 2019 -0400
@@ -62,8 +62,7 @@
 ##
 ## If given the string input argument @qcode{"noshare"}, vertices may be
 ## returned multiple times for different faces.  The default behavior is to
-## eliminate vertices shared by adjacent faces with @code{unique} which may be
-## time consuming.
+## eliminate vertices shared by adjacent faces.
 ##
 ## The string input argument @qcode{"verbose"} is supported for @sc{matlab}
 ## compatibility, but has no effect.
@@ -169,7 +168,7 @@
                                                               fvc.vertices);
 
     if (calc_colors)
-      fvc.facevertexcdata(J) = [];  # share very close vertices
+      fvc.facevertexcdata = fvc.facevertexcdata(J);  # share very close vertices
     endif
   endif
 
--- a/scripts/plot/draw/light.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/light.m	Fri Jul 12 12:14:43 2019 -0400
@@ -198,7 +198,8 @@
 %! ## Diffuse and specular reflection
 %! clf;
 %! h_axes = axes ();
-%! [x,y,z] = meshgrid (-.2:0.04:.2, -.2:0.04:.2, -.2:0.04:.2);
+%! rng = linspace (-0.2, +0.2, 12);
+%! [x,y,z] = meshgrid (rng);
 %! val = (x.^2 + y.^2 + z.^2);
 %!
 %! fv = isosurface (x, y, z, val, .039);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/lightangle.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,167 @@
+## Copyright (C) 2019 Guillaume Flandin
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for 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  {} {} lightangle (@var{az}, @var{el})
+## @deftypefnx {} {} lightangle (@var{hax}, @var{az}, @var{el})
+## @deftypefnx {} {} lightangle (@var{hl}, @var{az}, @var{el})
+## @deftypefnx {} {@var{hl} =} lightangle (@dots{})
+## @deftypefnx {} {[@var{az}, @var{el}] =} lightangle (@var{hl})
+## Add a light object to the current axes using spherical coordinates.
+##
+## The light position is specified by an azimuthal rotation @var{az} and an
+## elevation angle @var{el}, both in degrees.
+##
+## If the first argument @var{hax} is an axes handle, then create a new light
+## object in this axes, rather than the current axes returned by @code{gca}.
+##
+## If the first argument @var{hl} is a handle to a light object, then act on
+## this light object rather than creating a new object.
+##
+## The optional return value @var{hl} is a graphics handle to the light object.
+##
+## Example:
+##
+## Add a light object to a plot
+##
+## @example
+## @group
+## @c doctest: +SKIP
+## clf;
+## sphere (36);
+## lightangle (45, 30);
+## @end group
+## @end example
+##
+## @seealso{light, view, camlight}
+## @end deftypefn
+
+function varargout = lightangle (varargin)
+
+  if (nargin == 0 || nargin > 3 || nargout > 2 || (nargin > 1 && nargout > 1))
+    print_usage ();
+  endif
+
+  hl = hax = az = el = [];
+
+  if (nargin == 1)
+    hl = varargin{1};
+    if (! isscalar (hl) || ! isgraphics (hl, "light"))
+      error ("lightangle: HL must be a handle to a light object");
+    endif
+  elseif (nargin == 2)
+    az = varargin{1};
+    el = varargin{2};
+  elseif (nargin == 3)
+    h = varargin{1};
+    if (isscalar (h) && isaxes (h))
+      hax = h;
+    elseif (isscalar (h) && isgraphics (h, "light"))
+      hl = h;
+    else
+      error ("lightangle: H must be a handle to an axes or light object");
+    endif
+    az = varargin{2};
+    el = varargin{3};
+  endif
+
+  if (nargin == 1)
+    pos = get (hl, "Position");
+    [az, el] = cart2sph (pos(1), pos(2), pos(3));
+    az = rad2deg (az) + 90;  # see view.m
+    el = rad2deg (el);
+    varargout = { az, el };
+    return;
+  endif
+
+  if (! isscalar (az) || ! isnumeric (az)
+      || ! isscalar (el) || ! isnumeric (el))
+    error ("lightangle: AZ and EL must be numeric scalars");
+  endif
+
+  if (! isempty (hl))
+    hax = ancestor (hl, "axes");
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  endif
+
+  if (isempty (hl))
+    hl = light (hax);
+  endif
+
+  pos = get (hl, "Position");
+
+  az = deg2rad (az - 90);
+  el = deg2rad (el);
+
+  if (strcmp (get (hl, "Style"), "local"))
+    pos -= get (hax, "CameraTarget");
+  endif
+
+  pos = sph2cart (az, el, norm (pos));
+
+  if (strcmp (get (hl, "Style"), "local"))
+    pos += get (hax, "CameraTarget");
+  endif
+
+  set (hl, "Position", pos);
+
+  if (nargout == 1)
+    varargout = { hl };
+  endif
+
+endfunction
+
+
+%!demo
+%! clf;
+%! sphere (36);
+%! lightangle (45, 30);
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   sphere (24);
+%!   hl = lightangle (45, 20);
+%!   assert (isgraphics (hl, "light"));
+%!   [az, el] = lightangle (hl);
+%!   assert ([45, 20], [az, el], -20*eps);
+%!   lightangle (hl, 90, 45);
+%!   [az, el] = lightangle (hl);
+%!   assert ([90, 45], [az, el], -20*eps);
+%!   pos = get (hl, "Position");
+%!   assert ([1, 0, 1], pos, -20*eps);
+%!   hl = lightangle (gca (), 45, 20);
+%!   assert (isgraphics (hl, "light"));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error <Invalid call> lightangle ()
+%!error <Invalid call> lightangle (1, 2, 3, 4)
+%!error <Invalid call> [a, b] = lightangle (45, 30)
+%!error <Invalid call> [a, b, c] = lightangle (45, 30)
+%!error <HL must be a handle to a light object> lightangle (0)
+%!error <H must be a handle to an axes or light object> lightangle (0, 90, 45)
+%!error <AZ and EL must be numeric scalars> lightangle ([1 2], 0)
+%!error <AZ and EL must be numeric scalars> lightangle ({1}, 0)
+%!error <AZ and EL must be numeric scalars> lightangle (0, [1 2])
+%!error <AZ and EL must be numeric scalars> lightangle (0, {1})
--- a/scripts/plot/draw/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -54,6 +54,7 @@
   %reldir%/isonormals.m \
   %reldir%/isosurface.m \
   %reldir%/light.m \
+  %reldir%/lightangle.m \
   %reldir%/line.m \
   %reldir%/loglog.m \
   %reldir%/loglogerr.m \
--- a/scripts/plot/draw/plotyy.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/plotyy.m	Fri Jul 12 12:14:43 2019 -0400
@@ -288,8 +288,9 @@
 %! xlabel ("X");
 %! ylabel (ax(1), "Axis 1");
 %! ylabel (ax(2), "Axis 2");
-%! lcolor = get (gca, "ColorOrder")(1,:);
-%! rcolor = get (gca, "ColorOrder")(2,:);
+%! colororder = get (gca, "ColorOrder");
+%! lcolor = colororder(1,:);
+%! rcolor = colororder(2,:);
 %! text (0.5, 0.5, "Left Axis", ...
 %!       "color", lcolor, "horizontalalignment", "center", "parent", ax(1));
 %! text (4.5, 80, "Right Axis", ...
--- a/scripts/plot/draw/polar.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/polar.m	Fri Jul 12 12:14:43 2019 -0400
@@ -335,7 +335,7 @@
 
   lprops = {"linestyle", get(hax, "gridlinestyle"), ...
             "linewidth", get(hax, "linewidth"), ...
-            "color", get(hax, "xcolor")};
+            "color", min(5.8167 * get(hax, "xcolor"), 1)};
   ## "fontunits" should be first because it affects "fontsize" property.
   tprops(1:2:12) = {"fontunits", "fontangle", "fontname", "fontsize", ...
                     "fontweight", "ticklabelinterpreter"};
--- a/scripts/plot/draw/private/__bar__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__bar__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -220,7 +220,7 @@
         else
           set (hax, "clim", [0 1], "ylimmode", "manual");
         endif
-        set (hax, "box", "on");
+        set (hax, "box", "on", "layer", "top");
       endif
     unwind_protect_cleanup
       if (! isempty (oldfig))
@@ -285,8 +285,8 @@
       h_baseline = __go_line__ (hax, "xdata", x_axis_range,
                                      "ydata", [base_value, base_value],
                                      "color", [0, 0, 0]);
-      set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
-      set (h_baseline, "parent", get (hg, "parent"));
+      set (h_baseline, "handlevisibility", "off", "xliminclude", "off",
+                       "parent", get (hg, "parent"));
     endif
 
     ## Setup the hggroup and listeners
--- a/scripts/plot/draw/private/__contour__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__contour__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -470,8 +470,7 @@
       else
         lvl = lvl(1) : lvs : lvl(2);
       endif
-      set (h, "levellist", lvl);
-      set (h, "levellistmode", "auto");
+      set (h, "levellist", lvl, "levellistmode", "auto");
     else
       z = get (h, "zdata");
       ## FIXME: The levels should be determined similarly to {x,y,z}ticks
--- a/scripts/plot/draw/private/__errplot__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__errplot__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -389,14 +389,12 @@
   xudata = get (hg, "xudata");
   ifmt = get (hg, "format");
 
-  set (hl(2), "xdata", xdata);
-  set (hl(2), "ydata", ydata);
+  set (hl(2), "xdata", xdata, "ydata", ydata);
 
   [errorbar_xdata, errorbar_ydata] = ...
           errorbar_data (xdata, ydata, ldata, udata, xldata, xudata, ...
                          ifmt, xscale, yscale);
 
-  set (hl(1), "xdata", errorbar_xdata);
-  set (hl(1), "ydata", errorbar_ydata);
+  set (hl(1), "xdata", errorbar_xdata, "ydata", errorbar_ydata);
 
 endfunction
--- a/scripts/plot/draw/private/__ezplot__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__ezplot__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -445,10 +445,10 @@
       endif
     elseif (isplot3)
       if (animate)
-        ## draw animation, then replace with true plot3
-        comet3 (hax, X, Y, Z, .05);
+        comet3 (hax, X, Y, Z);
+      else
+        h = feval (pltfunc, hax, X, Y, Z);
       endif
-      h = feval (pltfunc, hax, X, Y, Z);
       grid (hax, "on");
       zlabel (hax, "z");
     else  # mesh and surf plots
--- a/scripts/plot/draw/private/__line__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__line__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -131,25 +131,37 @@
     data_args = {"xdata", data{1}, "ydata", data{2}, "zdata", data{3}};
     mask = [false, ismat(1), false, ismat(2), false, ismat(3)];
 
-    handles = zeros (nlines, 1);
-    for i = 1:nlines
-      data_args(mask) = cellindexmat (data(ismat), ":", i);
+    [colororder_idx, styleorder_idx] = get (hp, {"ColorOrderIndex",
+                                                 "LinestyleOrderIndex"}){:};
+
+    unwind_protect
+      handles = zeros (nlines, 1);
+      for i = 1:nlines
+        data_args(mask) = cellindexmat (data(ismat), ":", i);
 
-      ## FIXME: Technically, it may not be the right thing to do to rotate
-      ##        the style if the options in other_args specify a color
-      ##        or linestyle.  The plot will be made correctly, but the next
-      ##        call to line may not use the correct value.
-      [linestyle, marker] = __next_line_style__ ();
-      if (nr == 1)
-        ## Marker for a single point is always '.' (bug #38825).
-        marker = '.';
-      endif
-      color = __next_line_color__ ();
+        ## FIXME: It would be potentially more efficient to write code to
+        ##        cycle line styles and colors within __line__.m itself.
+        ##        However, these are not easy routines to get exactly right,
+        ##        and then there would be duplicate code.  For the time being,
+        ##        use an unwind_protect block to restore any values we may
+        ##        have modified.  Testing shows only 4 millisecond extra delay
+        ##        when plotting 53 lines.
+        [linestyle, marker] = __next_line_style__ ();
+        if (nr == 1)
+          ## Marker for a single point is always '.' (bug #38825).
+          marker = '.';
+        endif
+        color = __next_line_color__ ();
 
-      handles(i) = __go_line__ (hp, data_args{:},
-                                "color", color, "linestyle", linestyle,
-                                "marker", marker, other_args{:});
-    endfor
+        handles(i) = __go_line__ (hp, data_args{:},
+                                  "color", color, "linestyle", linestyle,
+                                  "marker", marker, other_args{:});
+      endfor
+    unwind_protect_cleanup
+      set (hp, {"ColorOrderIndex", "LinestyleOrderIndex"},
+               {colororder_idx, styleorder_idx});
+    end_unwind_protect
+
   endif
 
   if (nargout > 0)
--- a/scripts/plot/draw/private/__quiver__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__quiver__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -51,7 +51,17 @@
     if (is3d)
       w = varargin{ioff++};
     endif
+    if (is3d)
+      if (! size_equal (z, u, v, w))
+        error ("quiver3: Z, U, V, and W must be the same size");
+      endif
+    else
+      if (! size_equal (u, v))
+        error ("quiver: U and V must be the same size");
+      endif
+    endif
     [x, y] = meshgrid (1:columns (u), 1:rows (u));
+
     if (nargin >= ioff && isnumeric (varargin{ioff})
         && isscalar (varargin{ioff}))
       autoscale = varargin{ioff++};
@@ -75,6 +85,16 @@
         [x, y] = meshgrid (x, y);
       endif
     endif
+    if (is3d)
+      if (! size_equal (x, y, z, u, v, w))
+        error ("quiver3: X, Y, Z, U, V, and W must be the same size");
+      endif
+    else
+      if (! size_equal (x, y, u, v))
+        error ("quiver: X, Y, U, and V must be the same size");
+      endif
+    endif
+
     if (nargin >= ioff && isnumeric (varargin{ioff})
         && isscalar (varargin{ioff}))
       autoscale = varargin{ioff++};
@@ -373,8 +393,8 @@
     zend = z + w(:);
   endif
 
-  set (kids(3), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
-  set (kids(3), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
+  set (kids(3), "xdata", [x.'; xend.'; NaN(1, length (x))](:),
+                "ydata", [y.'; yend.'; NaN(1, length (y))](:));
   if (is3d)
     set (kids(3), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
   endif
@@ -397,20 +417,19 @@
     yarrw2 = ytmp + u(:) * arrowsize / 3;
   endif
 
-  set (kids(2), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
-  set (kids(2), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
+  set (kids(2), "xdata", [x.'; xend.'; NaN(1, length (x))](:),
+                "ydata", [y.'; yend.'; NaN(1, length (y))](:));
   if (is3d)
     set (kids(2), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
   endif
 
-  set (kids(2), "xdata", [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:));
-  set (kids(2), "ydata", [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
+  set (kids(2), "xdata", [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+                "ydata", [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
   if (is3d)
     set (kids(2), "zdata", [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:));
   endif
 
-  set (kids(1), "xdata", x);
-  set (kids(1), "ydata", y);
+  set (kids(1), "xdata", x, "ydata", y);
   if (is3d)
     set (kids(1), "zdata", z);
   endif
--- a/scripts/plot/draw/private/__stem__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__stem__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -173,9 +173,13 @@
         set (h, args{:});
     endif
 
-    if (! strcmp (hold_state, "add") && have_z)
-      set (hax, "view", [-37.5 30],
-                "xgrid", "on", "ygrid", "on", "zgrid", "on");
+    if (! strcmp (hold_state, "add"))
+      if (! have_z)
+        set (hax, "box", "on");
+      else
+        set (hax, "view", [-37.5 30],
+                  "xgrid", "on", "ygrid", "on", "zgrid", "on");
+      endif
     endif
     set (hax, "nextplot", hold_state);
 
@@ -412,8 +416,7 @@
   b0 = get (h, "basevalue");
   bl = get (h, "baseline");
 
-  set (bl, "ydata", [b0, b0]);
-  set (bl, "basevalue", b0);
+  set (bl, "ydata", [b0, b0], "basevalue", b0);
 
   kids = get (h, "children");
   yt = get (h, "ydata")(:)';
--- a/scripts/plot/draw/private/__unite_shared_vertices__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/private/__unite_shared_vertices__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -1,3 +1,4 @@
+## Copyright (C) 2019 Michael Leitner
 ## Copyright (C) 2016-2019 Markus Muetzel
 ##
 ## This file is part of Octave.
@@ -26,66 +27,30 @@
 ## calculated.  If all coordinates are closer than
 ## @code{2 * eps (max (abs (vertices(:))))}, the vertices are united to one.
 ##
-## @var{J} holds the indices of the deleted vertices.
+## @var{J} holds the indices of the remaining vertices.
 ##
 ## @seealso{isosurface, reducepatch}
 ## @end deftypefn
 
-## Author: mmuetzel
-
 function [faces, vertices, J] = __unite_shared_vertices__ (faces, vertices)
 
-  J = [];
-
-  ## Calculate the mutual differences of all vertex coordinates
-  close_points = zeros (0, 2);
-  num_vertices = rows (vertices);
-  skip_point = false (num_vertices, 1);
-  ## FIXME: Can this be vectorized in some way to increase performance?
-  ##        Regardless, should probably allocate close_points to be the
-  ##        same size as the number of vertices and then truncate the
-  ##        array at the end of the calculation.  Extending an array
-  ##        involves a copy operation every time.
-  for (i_point1 = 1:num_vertices - 1)
-    if (skip_point(i_point1))
-      ## points already detected as duplicates can be skipped
-      continue;
-    endif
-
-    diff = vertices(i_point1,:) - vertices(i_point1 + 1:end,:);
-    is_close_point = all (abs (diff) <= sqrt (3) * eps * ...
-        (max (abs (vertices(i_point1,:)), abs (vertices(i_point1 + 1:end,:)))), 2);
+  lut = (1:rows (vertices))';
+  J = lut;
+  for di = 1:3
+    [v, idx] = sortrows (vertices, 1 + mod ((0:2)+di, 3));
+    Js = [true;
+          any(abs (diff (v, 1, 1)) > eps * abs (v(2:end,:)+v(1:end-1,:)), 2)];
+    vertices = v(Js,:);
+    J = J(idx(Js));
+    l(idx) = cumsum (Js);
+    lut = l(lut);
+  endfor
+  [J, idx] = sort (J);
+  j(idx) = 1:length (idx);
+  vertices = vertices(idx,:);
+  faces = j(lut(faces));
 
-    if (any (is_close_point))
-      close_points_idx = find (is_close_point) + i_point1;
-      new_close_points_num = rows (close_points_idx);
-      close_points(end + 1:end + new_close_points_num,1) = i_point1;
-      close_points(end - new_close_points_num + 1:end,2) = close_points_idx;
-      skip_point(close_points_idx) = true;
-    endif
-  endfor
-
-  if (! isempty (close_points))
-    vertices(close_points(:,2),:) = []; # delete multiple shared vertices
-    ## renumber deleted vertices in faces to the one it is replaced by
-    vertex_renum = 1:num_vertices;
-    vertex_renum(close_points(:,2)) = close_points(:,1);
-    faces = vertex_renum(faces);
-    ## renumber vertices in faces with subsequent numbers
-    vertex_renum2 = ones (1, num_vertices);
-    vertex_renum2(close_points(:,2)) = 0;
-    vertex_renum2 = cumsum (vertex_renum2);
-    faces = vertex_renum2(faces);
-
-    ## eliminate identical faces
-    faces = sort (faces, 2);
-    faces = unique (faces, "rows");
-
-    ## eliminate faces with zero area.  Vertices in faces are sorted.
-    is_zero_area = (faces(:,1) == faces(:,2)) | (faces(:,2) == faces(:,3));
-    faces = faces(! is_zero_area, :);
-
-    J = close_points(:,2);
-  endif
+  ## Eliminate faces with zero area
+  faces = faces(all (faces - faces(:, [2 3 1]) != 0, 2), :);
 
 endfunction
--- a/scripts/plot/draw/reducepatch.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/reducepatch.m	Fri Jul 12 12:14:43 2019 -0400
@@ -197,7 +197,7 @@
              "FACES, second argument must be a matrix containing VERTICES"]);
     endif
   else
-    print_usage ();
+    print_usage ("reducepatch");
   endif
 
   ## get reduction_factor
--- a/scripts/plot/draw/shrinkfaces.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/draw/shrinkfaces.m	Fri Jul 12 12:14:43 2019 -0400
@@ -135,8 +135,8 @@
     case 0
       if (ishghandle (p))
         ## avoid exceptions
-        set (p, "FaceVertexCData", [], "CData", []);
-        set (p, "Vertices", v, "Faces", f, "FaceVertexCData", c);
+        set (p, "FaceVertexCData", [], "CData", [],
+                "Vertices", v, "Faces", f, "FaceVertexCData", c);
       else
         nf = struct ("faces", f, "vertices", v, "facevertexcdata", c);
       endif
--- a/scripts/plot/util/__actual_axis_position__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/__actual_axis_position__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -40,8 +40,8 @@
     set (axis_obj.parent, "units", "pixels");
     fig_position = get (axis_obj.parent, "position");
   unwind_protect_cleanup
-    set (axis_obj.parent, "units", orig_fig_units);
-    set (axis_obj.parent, "position", orig_fig_position);
+    set (axis_obj.parent, "units", orig_fig_units,
+                          "position", orig_fig_position);
   end_unwind_protect
   ## Get axes size in pixels
   if (strcmp (get (axis_obj.parent, "__graphics_toolkit__"), "gnuplot")
--- a/scripts/plot/util/allchild.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/allchild.m	Fri Jul 12 12:14:43 2019 -0400
@@ -48,13 +48,14 @@
 endfunction
 
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
-%! toolkit = graphics_toolkit ("fltk");
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
+%! toolkit = graphics_toolkit ("qt");
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   l = line;
 %!   kids = allchild (hf);
-%!   assert (get (kids, "type"), {"axes"; "uimenu"; "uimenu"; "uimenu"});
+%!   assert (get (kids, "type"), ...
+%!           {"axes"; "uitoolbar"; "uimenu"; "uimenu"; "uimenu"});
 %! unwind_protect_cleanup
 %!   close (hf);
 %!   graphics_toolkit (toolkit);
--- a/scripts/plot/util/clf.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/clf.m	Fri Jul 12 12:14:43 2019 -0400
@@ -71,15 +71,28 @@
 
   if (do_reset)
     ## Delete all the children, including the ones with hidden handles,
-    ## except default menus.
+    ## except default menus and toolbar.
+
     kids = allchild (hfig);
-    ismenu = cellfun (@(s) strncmp (s, "__default_menu_", 15), ...
-                      get (kids, "tag"));
-    delete (kids(! ismenu));
+
+    if (! isempty (kids))
+      tags = get (kids, "tag");
+      ## It's possible for a figure to have just one child and then get
+      ## will return a single value instead of a cell array.
+      if (! iscell (tags))
+        tags = {tags};
+      endif
+      ismenu = cellfun (@(s) strncmp (s, "__default_menu_", 15), tags);
+      istoolbar = cellfun (@(s) strncmp (s, "__default_toolbar_menu_", 18), tags);
+      delete (kids(! ismenu & ! istoolbar));
+    endif
+
     reset (hfig);
 
-    ## Recover figure listeners which have been deleted
-    __add_default_menu__ (hfig, kids(ismenu));
+    if (! isempty (kids))
+      ## Recover figure listeners which have been deleted
+      __add_default_menu__ (hfig, kids(ismenu), kids(istoolbar));
+    endif
 
     __set_default_mouse_modes__ (hfig);
   else
--- a/scripts/plot/util/copyobj.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/copyobj.m	Fri Jul 12 12:14:43 2019 -0400
@@ -132,7 +132,7 @@
 %! scrn = get (0, "screensize");
 %! set (hobj, "position", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
 %! drawnow ();
-%! hnew = copyobj (hobj);
+%! hnew = copyobj (hobj, groot);
 %! drawnow ();
 %! set (hnew, "name", "Copyobj");
 %! drawnow ();
@@ -162,7 +162,7 @@
 %! scrn = get (0, "screensize");
 %! set (hobj, "position", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
 %! drawnow ();
-%! hnew = copyobj (hobj);
+%! hnew = copyobj (hobj, groot);
 %! drawnow ();
 %! set (hnew, "name", "Copyobj");
 %! drawnow ();
@@ -179,8 +179,9 @@
 %! xlabel ("X");
 %! ylabel (ax(1), "Axis 1");
 %! ylabel (ax(2), "Axis 2");
-%! lcolor = get (gca, "ColorOrder")(1,:);
-%! rcolor = get (gca, "ColorOrder")(2,:);
+%! colororder = get (gca, "ColorOrder");
+%! lcolor = colororder(1,:);
+%! rcolor = colororder(2,:);
 %! text (0.5, 0.5, "Left Axis", ...
 %!       "color", lcolor, "horizontalalignment", "center", "parent", ax(1));
 %! text (4.5, 80, "Right Axis", ...
@@ -191,7 +192,7 @@
 %! scrn = get (0, "screensize");
 %! set (hobj, "position", [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
 %! drawnow ();
-%! hnew = copyobj (hobj);
+%! hnew = copyobj (hobj, groot);
 %! drawnow ();
 %! set (hnew, "name", "Copyobj");
 %! drawnow ();
--- a/scripts/plot/util/findall.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/findall.m	Fri Jul 12 12:14:43 2019 -0400
@@ -50,13 +50,17 @@
 endfunction
 
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
-%! toolkit = graphics_toolkit ("fltk");
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
+%! toolkit = graphics_toolkit ("qt");
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   h = findall (hf);
 %!   all_handles(1) = {"figure"};
-%!   all_handles(2:24,1) = {"uimenu"};
+%!   all_handles(2,1) = {"uitoolbar"};
+%!   all_handles(3:5) = {"uimenu"};
+%!   all_handles([6:7, 9]) = {"uipushtool"};
+%!   all_handles([8, 10:13]) = {"uitoggletool"};
+%!   all_handles(14:33) = {"uimenu"};
 %!   assert (get (h, "type"), all_handles);
 %! unwind_protect_cleanup
 %!   close (hf);
--- a/scripts/plot/util/ginput.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/ginput.m	Fri Jul 12 12:14:43 2019 -0400
@@ -72,14 +72,14 @@
   orig_keypressfcn = get (fig, "keypressfcn");
   orig_closerequestfcn = get (fig, "closerequestfcn");
   orig_mousemode = get (fig, "__mouse_mode__");
+  orig_pointer = get (fig, "pointer");
 
   unwind_protect
 
-    set (fig, "windowbuttondownfcn", @ginput_windowbuttondownfcn);
-    set (fig, "keypressfcn", @ginput_keypressfcn);
-    set (fig, "closerequestfcn", {@ginput_closerequestfcn,
-                                  orig_closerequestfcn});
-    set (fig, "__mouse_mode__", "none");
+    set (fig, "windowbuttondownfcn", @ginput_windowbuttondownfcn, ...
+         "keypressfcn", @ginput_keypressfcn, ...
+         "closerequestfcn", {@ginput_closerequestfcn, orig_closerequestfcn}, ...
+         "pointer", "crosshair", "__mouse_mode__", "none");
 
     do
       if (strcmp (toolkit, "fltk"))
@@ -102,10 +102,10 @@
   unwind_protect_cleanup
     if (isfigure (fig))
       ## Only execute if window still exists
-      set (fig, "windowbuttondownfcn", orig_windowbuttondownfcn);
-      set (fig, "keypressfcn", orig_keypressfcn);
-      set (fig, "closerequestfcn", orig_closerequestfcn);
-      set (fig, "__mouse_mode__", orig_mousemode);
+      set (fig, "windowbuttondownfcn", orig_windowbuttondownfcn, ...
+           "keypressfcn", orig_keypressfcn, ...
+           "closerequestfcn", orig_closerequestfcn, ...
+           "pointer", orig_pointer, "__mouse_mode__", orig_mousemode);
     endif
   end_unwind_protect
 
@@ -146,8 +146,8 @@
 function ginput_keypressfcn (~, evt)
 
   point = get (gca (), "currentpoint");
-  if (strcmp (evt.Key, "return"))
-    ## Enter key stops ginput.
+  if (strcmp (evt.Key, "return") || strcmp (evt.Key, "enter"))
+    ## <Return> or <Enter> on numeric keypad stops ginput.
     ginput_accumulator (2, NaN, NaN, NaN);
   else
     character = evt.Character;
--- a/scripts/plot/util/graphics_toolkit.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/graphics_toolkit.m	Fri Jul 12 12:14:43 2019 -0400
@@ -102,23 +102,22 @@
 
 endfunction
 
-
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", available_graphics_toolkits ()))
 %! unwind_protect
 %!   hf = figure ("visible", "off");
 %!   toolkit = graphics_toolkit ();
 %!   assert (get (0, "defaultfigure__graphics_toolkit__"), toolkit);
-%!   graphics_toolkit (hf, "fltk");
-%!   assert (graphics_toolkit (hf), "fltk");
+%!   graphics_toolkit (hf, "qt");
+%!   assert (graphics_toolkit (hf), "qt");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
 
-%!testif HAVE_OPENGL, HAVE_FLTK; have_window_system () && any (strcmp ("gnuplot", available_graphics_toolkits ())) && any (strcmp ("fltk", available_graphics_toolkits ()))
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("gnuplot", available_graphics_toolkits ())) && any (strcmp ("qt", available_graphics_toolkits ()))
 %! old_toolkit = graphics_toolkit ();
 %! switch (old_toolkit)
 %!   case {"gnuplot"}
-%!     new_toolkit = "fltk";
+%!     new_toolkit = "qt";
 %!   otherwise
 %!     new_toolkit = "gnuplot";
 %! endswitch
--- a/scripts/plot/util/hgtransform.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/hgtransform.m	Fri Jul 12 12:14:43 2019 -0400
@@ -145,8 +145,8 @@
     if (strcmp (type, "text"))
       set (hk, "position", [data(1), data(2), data(3)]);
     else
-      set (hk, "xdata", reshape (data(1,:), xsz));
-      set (hk, "ydata", reshape (data(2,:), ysz));
+      set (hk, "xdata", reshape (data(1,:), xsz),
+               "ydata", reshape (data(2,:), ysz));
       if (! z_empty)
         set (hk, "zdata", reshape (data(3,:), zsz));
       endif
@@ -172,13 +172,13 @@
         switch (get (hk, "type"))
 
           case {"line", "patch", "surface"}
-            set (hk, "xdata", orig_data(idx).xdata);
-            set (hk, "ydata", orig_data(idx).ydata);
-            set (hk, "zdata", orig_data(idx).zdata);
+            set (hk, "xdata", orig_data(idx).xdata,
+                     "ydata", orig_data(idx).ydata,
+                     "zdata", orig_data(idx).zdata);
 
           case "image"
-            set (hk, "xdata", orig_data(idx).xdata);
-            set (hk, "ydata", orig_data(idx).ydata);
+            set (hk, "xdata", orig_data(idx).xdata,
+                     "ydata", orig_data(idx).ydata);
 
           case "text"
             set (hk, "position", orig_data(idx).position);
--- a/scripts/plot/util/print.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/print.m	Fri Jul 12 12:14:43 2019 -0400
@@ -189,9 +189,9 @@
 ## Octave interpreter from recognizing the embedded comma (',').  For example,
 ## by writing @w{"-S640,480"}.
 ##
-## @item  -loose
-## @itemx -tight
-##   Force a tight or loose bounding box for EPS files.  The default is loose.
+## @item  -tight
+## @itemx -loose
+##   Force a tight or loose bounding box for EPS files.  The default is tight.
 ##
 ## @item -@var{preview}
 ##   Add a preview to EPS files.  Supported formats are:
@@ -217,7 +217,7 @@
 ## @itemx -F@var{fontname}:@var{size}
 ## @itemx -F:@var{size}
 ##   Use @var{fontname} and/or @var{fontsize} for all text.
-## @var{fontname} is ignored for some devices: dxf, fig, hpgl, etc.
+## @var{fontname} is ignored for some devices: fig, etc.
 ##
 ## @item -d@var{device}
 ##   The available output format is specified by the option @var{device}, and
@@ -299,16 +299,6 @@
 ##   @item canvas*
 ##     Javascript-based drawing on an HTML5 canvas viewable in a web browser.
 ##
-##   @item  cdr*
-##   @itemx @nospell{corel*}
-##     CorelDraw
-##
-##   @item cgm*
-##     Computer Graphics Metafile, Version 1, ANSI X3.122-1986
-##
-##   @item dxf
-##     AutoCAD
-##
 ##   @item  emf
 ##   @itemx meta
 ##     Microsoft Enhanced Metafile
@@ -319,20 +309,10 @@
 ## whether the special flag should be set for the text in the figure.
 ## (default is @option{-textnormal})
 ##
-##   @item hpgl
-##     HP plotter language
-##
-##   @item  ill
-##   @itemx @nospell{aifm}
-##     Adobe Illustrator (obsolete for Gnuplot versions > 4.2)
-##
 ##   @item  latex*
 ##   @itemx eepic*
 ##     @LaTeX{} picture environment and extended picture environment.
 ##
-##   @item mf*
-##     Metafont
-##
 ##   @item  tikz
 ##   @itemx tikzstandalone*
 ##     Generate a @LaTeX{} file using PGF/TikZ format.  The OpenGL-based
@@ -466,6 +446,13 @@
 
     drawnow ();
 
+    ## Set the __printing__ property first
+    props(1).h = opts.figure;
+    props(1).name = "__printing__";
+    props(1).value = {"off"};
+    set (opts.figure, "__printing__", "on");
+    nfig += 1;
+
     ## print() requires children of axes to have units = "normalized", or "data"
     hobj = findall (opts.figure, "-not", "type", "figure", ...
                     "-not", "type", "axes", "-property", "units", ...
@@ -552,13 +539,10 @@
     ## graphics toolkit translates figure position to eps bbox (points)
     fpos = get (opts.figure, "position");
     props(end+1).h = opts.figure;
-    props(end).name = "__printing__";
-    props(end).value = {"off"};
-    props(end+1).h = opts.figure;
     props(end).name = "position";
     props(end).value = {fpos};
     fpos(3:4) = opts.canvas_size;
-    set (opts.figure, "__printing__", "on", "position", fpos);
+    set (opts.figure, "position", fpos);
     nfig += 1;
 
     ## Implement InvertHardCopy option
@@ -631,50 +615,74 @@
       endfor
     endif
 
-    if (! isempty (opts.font) || ! isempty (opts.fontsize))
+    do_font = ! isempty (opts.font);
+    do_scalefontsize =  ! isempty (opts.scalefontsize) && opts.scalefontsize != 1;
+    do_fontsize = ! isempty (opts.fontsize) || do_scalefontsize;
+    if (do_font || do_fontsize)
       h = findall (opts.figure, "-property", "fontname");
       m = numel (props);
       for n = 1:numel (h)
         if (ishghandle (h(n)))
-          if (! isempty (opts.font))
+          if (do_font)
             props(end+1).h = h(n);
             props(end).name = "fontname";
             props(end).value = {get(h(n), "fontname")};
           endif
-        endif
-        if (ishghandle (h(n)))
-          if (! isempty (opts.fontsize))
+          if (do_fontsize)
             props(end+1).h = h(n);
             props(end).name = "fontsize";
             props(end).value = {get(h(n), "fontsize")};
           endif
         endif
       endfor
-      if (! isempty (opts.font))
+      if (do_font)
         set (h(ishghandle (h)), "fontname", opts.font);
       endif
-      if (! isempty (opts.fontsize))
-        if (ischar (opts.fontsize))
-          fontsize = str2double (opts.fontsize);
+      if (do_fontsize)
+        if (! isempty (opts.fontsize))
+          ## Changing all fontsizes to a fixed value
+          if (ischar (opts.fontsize))
+            fontsize = str2double (opts.fontsize);
+          else
+            fontsize = opts.fontsize;
+          endif
+          if (do_scalefontsize)
+            ## This is done to work around the bbox being whole numbers.
+            fontsize *= opts.scalefontsize;
+          endif
+
+          ## FIXME: legend child objects need to be acted on first.
+          ##        or legend fontsize callback will destroy them.
+          hlist = h(ishghandle (h));
+          haxes = strcmp (get (hlist, "type"), "axes");
+          set (hlist(! haxes), "fontsize", fontsize);
+          set (hlist(haxes), "fontsize", fontsize);
+
         else
-          fontsize = opts.fontsize;
+          ## Scaling fonts
+          ## FIXME: legend child objects need to be acted on first.
+          ##        or legend fontsize callback will destroy them.
+          hlist = h(ishghandle (h));
+          haxes = strcmp (get (hlist, "type"), "axes");
+          for h = hlist(! haxes).'
+            fontsz = get (h, "fontsize");
+            set (h, "fontsize", fontsz * opts.scalefontsize);
+          endfor
+          for h = hlist(haxes).'
+            fontsz = get (h, "fontsize");
+            set (h, "fontsize", fontsz * opts.scalefontsize);
+          endfor
+
         endif
-        if (! isempty (opts.scalefontsize) && ! opts.scalefontsize != 1)
-          ## This is done to work around the bbox being whole numbers.
-          fontsize *= opts.scalefontsize;
-        endif
-        ## FIXME: legend child objects need to be acted on first.
-        ##        or legend fontsize callback will destroy them.
-        hlist = h(ishghandle (h));
-        haxes = strcmp (get (hlist, "type"), "axes");
-        set (hlist(! haxes), "fontsize", fontsize);
-        set (hlist(haxes), "fontsize", fontsize);
       endif
     endif
 
     ## When exporting latex files use "latex" for the ticklabelinterpreter.
     ## It will format tick labels in log axes correctly
     if (strfind (opts.devopt, "latex"))
+      ## Disable warnings about Latex being unsupported since Octave will be
+      ## passing Latex code directly to interpreter with no rendering.
+      warning ("off", "Octave:text_interpreter", "local");
       h = findall (opts.figure, "type", "axes");
       for n = 1:numel (h)
         if (ishghandle (h(n)))
@@ -727,12 +735,15 @@
       endfor
     endif
 
+    ## Avoid a redraw since the figure should not have changed
+    set (gcf, "__modified__", "off");
+
     ## Unlink temporary files
     for n = 1:numel (opts.unlink)
       [status, output] = unlink (opts.unlink{n});
       if (status != 0)
-        warning ("octave:print:unlinkerror", ...
-                 "print.m: %s, '%s'", output, opts.unlink{n});
+        warning ("Octave:print:unlinkerror", ...
+                 "print: %s, '%s'", output, opts.unlink{n});
       endif
     endfor
   end_unwind_protect
@@ -740,7 +751,6 @@
   if (isfigure (orig_figure))
     set (0, "currentfigure", orig_figure);
   endif
-
 endfunction
 
 function cmd = epstool (opts, filein, fileout)
@@ -754,9 +764,16 @@
   ## Unix Shell;
   ##   cat > <filein> ; epstool -bbox -preview-tiff <filein> <fileout> ; rm <filein>
 
+  dos_shell = (ispc () && ! isunix ());
+
   ## HACK: Keep track of whether ghostscript supports epswrite or eps2write.
   persistent epsdevice;
-  if (isempty (epsdevice))
+  if (dos_shell && isempty (epsdevice))
+    if (isempty (opts.ghostscript.binary))
+      error ("Octave:print:nogs",
+             "print: 'gs' (Ghostscript) is required for specified output format, but binary is not available in PATH");
+    endif
+
     [status, devlist] = system (sprintf ("%s -h", opts.ghostscript.binary));
     if (isempty (strfind (devlist, "eps2write")))
       epsdevice = "epswrite";
@@ -765,8 +782,6 @@
     endif
   endif
 
-  dos_shell = (ispc () && ! isunix ());
-
   cleanup = "";
   if (nargin < 3)
     fileout = opts.name;
@@ -800,13 +815,13 @@
   endif
 
   if (! isempty (opts.preview) && opts.tight)
-    warning ("octave:print:previewandtight",
-             "print.m: eps preview may not be combined with -tight");
+    warning ("Octave:print:previewandtight",
+             "print: eps preview may not be combined with -tight");
   endif
   if (! isempty (opts.preview) || opts.tight)
 
     if (isempty (opts.epstool_binary))
-      error ("print:noepstool", "print.m: 'epstool' is required for specified output format, but binary is not available in PATH");
+      error ("Octave:print:noepstool", "print: 'epstool' is required for specified output format, but binary is not available in PATH");
     endif
 
     if (opts.tight)
@@ -822,8 +837,8 @@
         case "pict"
           cmd = sprintf ("--add-%s-preview --mac-single", opts.preview);
         otherwise
-          error ("print:invalidpreview",
-                 "print.m: epstool cannot include preview for format '%s'",
+          error ("Octave:print:invalidpreview",
+                 "print: epstool cannot include preview for format '%s'",
                  opts.preview);
       endswitch
       if (! isempty (opts.ghostscript.resolution))
@@ -857,8 +872,8 @@
     endif
     if (! isempty (cleanup))
       if (pipeout && dos_shell)
-        error ("print:epstoolpipe",
-               "print.m: cannot pipe output of 'epstool' for DOS shell");
+        error ("Octave:print:epstoolpipe",
+               "print: cannot pipe output of 'epstool' for DOS shell");
       elseif (pipeout)
         cmd = sprintf ("( %s %s )", cmd, cleanup);
       else
@@ -913,7 +928,7 @@
   endif
 
   if (isempty (opts.fig2dev_binary))
-    error ("print:nofig2dev", "print.m: 'fig2dev' is required for specified output format, but binary is not available in PATH");
+    error ("Octave:print:nofig2dev", "print: 'fig2dev' is required for specified output format, but binary is not available in PATH");
   endif
 
   dos_shell = (ispc () && ! isunix ());
@@ -961,14 +976,14 @@
 
   fid = fopen (latexfile, "r");
   if (fid < 0)
-    error ("print:erroropeningfile",
-           "print.m: error opening file '%s'", latexfile);
+    error ("Octave:print:erroropeningfile",
+           "print: error opening file '%s'", latexfile);
   endif
   latex = fscanf (fid, "%c", Inf);
   status = fclose (fid);
   if (status != 0)
-    error ("print:errorclosingfile",
-           "print.m: error closing file '%s'", latexfile);
+    error ("Octave:print:errorclosingfile",
+           "print: error closing file '%s'", latexfile);
   endif
   ## FIXME: should this be fixed in GL2PS?
   latex = strrep (latex, "\\includegraphics{}",
@@ -981,12 +996,12 @@
     fprintf (fid, "%s\n", postpend{:});
     status = fclose (fid);
     if (status != 0)
-      error ("print:errorclosingfile",
-             "print.m: error closing file '%s'", latexfile);
+      error ("Octave:print:errorclosingfile",
+             "print: error closing file '%s'", latexfile);
     endif
   else
-    error ("print:erroropeningfile",
-           "print.m: error opening file '%s'", latexfile);
+    error ("Octave:print:erroropeningfile",
+           "print: error opening file '%s'", latexfile);
   endif
 
 endfunction
@@ -1006,7 +1021,7 @@
       cmd = sprintf ("%s %s", cmd, opts.printer);
     endif
   elseif (isempty (opts.lpr_binary))
-    error ("print:nolpr", "print.m: 'lpr' not found in PATH");
+    error ("Octave:print:nolpr", "print: 'lpr' not found in PATH");
   endif
   if (opts.debug)
     fprintf ("lpr command: '%s'\n", cmd);
@@ -1021,9 +1036,8 @@
   endif
 
   if (isempty (opts.pstoedit_binary))
-    error ("print:nopstoedit", ...
-           ["print.m: 'pstoedit' is required for specified output format, ", ...
-            "but binary is not available in PATH"]);
+    error ("Octave:print:nopstoedit", ...
+           "print: 'pstoedit' is required for specified output format, but binary is not available in PATH");
   endif
 
   dos_shell = (ispc () && ! isunix ());
@@ -1061,9 +1075,9 @@
   endif
 
   if (isempty (opts.svgconvert_binary))
-    warning ("octave:print:nosvgconvert", ...
-             ["print.m: unale to find octave-svgconvert, ", ...
-              "falling back to eps convertion"]);
+    warning ("Octave:print:nosvgconvert", ...
+             ["print: unable to find octave-svgconvert, ", ...
+              "falling back to eps conversion"]);
   else
     fontdir = getenv ("OCTAVE_FONTS_DIR");
 
--- a/scripts/plot/util/private/__add_default_menu__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__add_default_menu__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -28,18 +28,23 @@
 
 ## Author: Kai Habel
 
-function __add_default_menu__ (hf, hmenu = [])
+function __add_default_menu__ (hf, hmenu = [], htb = [])
+
+  ## Gnuplot doesn't handle uimenu and uitoolbar objects
+  if (strcmp (graphics_toolkit (), "gnuplot"))
+    return
+  endif
 
   ## Create
   if (isempty (hmenu))
     ## File menu
-    hui = uimenu (hf, "label", "&File", "handlevisibility", "off", ...
-                  "tag", "__default_menu__File");
+    hui = uimenu (hf, "label", "&File", "tag", "__default_menu__File", ...
+                      "handlevisibility", "off");
     uimenu (hui, "label", "&Open", "callback", @open_cb, ...
             "accelerator", "o");
-    uimenu (hui, "label", "&Save", "callback", @save_cb, ...
+    uimenu (hui, "label", "&Save", "callback", {@save_cb, "save"}, ...
             "accelerator", "s");
-    uimenu (hui, "label", "Save &As", "callback", @save_cb, ...
+    uimenu (hui, "label", "Save &As", "callback", {@save_cb, "saveas"}, ...
             "accelerator", "S");
     uimenu (hui, "label", "&Close", "callback", @close_cb, ...
             "accelerator", "w", "separator", "on");
@@ -86,20 +91,78 @@
     uimenu (hui2, "label", "Disable mousezoom", "tag", "zoom_off", ...
             "callback", @guimode_cb);
     hmenu(3) = hui;
+
+    ## Default toolbar
+    init_mouse_tools (hf);
+    htb = uitoolbar (hf, "tag", "__default_toolbar__", ...
+                     "handlevisibility", "off", "visible", "off");
+
+    ht(1) = uitoggletool (htb, "tooltipstring", "Pan", ...
+                          "tag", "__default_button_pan__", ...
+                          "__named_icon__", "figure-pan");
+    ht(2) = uitoggletool (htb, "tooltipstring", "Rotate", ...
+                          "tag", "__default_button_rotate__", ...
+                          "__named_icon__", "figure-rotate");
+
+    ht(3) = uitoggletool (htb, "tooltipstring", "Zoom In", ...
+                          "tag", "__default_button_zoomin__", ...
+                          "__named_icon__", "figure-zoom-in", ...
+                          "separator", "on");
+    ht(4) = uitoggletool (htb, "tooltipstring", "Zoom Out", ...
+                          "tag", "__default_button_zoomout__", ...
+                          "__named_icon__", "figure-zoom-out");
+    uipushtool (htb, "tooltipstring", "Automatic limits for current axes", ...
+                "clickedcallback", @auto_cb, ...
+                "__named_icon__", "figure-zoom-original");
+
+    ht(5) = uitoggletool (htb, "tooltipstring", "Insert Text", ...
+                          "tag", "__default_button_text__", ...
+                          "separator", "on", "__named_icon__", "figure-text");
+
+    uipushtool (htb, "tooltipstring", "Toggle current axes visibility", ...
+                "clickedcallback", @axes_cb, "separator", "on", ...
+                "__named_icon__", "figure-axes");
+    uipushtool (htb, "tooltipstring", "Toggle current axes grid visibility", ...
+                "clickedcallback", @grid_cb,  "__named_icon__", "figure-grid");
+
+    set (ht(1), "oncallback", {@mouse_tools_cb, ht, "pan"}, ...
+         "offcallback", {@mouse_tools_cb, ht, "pan"});
+    set (ht(2), "oncallback", {@mouse_tools_cb, ht, "rotate"}, ...
+         "offcallback", {@mouse_tools_cb, ht, "rotate"});
+    set (ht(3), "oncallback", {@mouse_tools_cb, ht, "zoomin"}, ...
+         "offcallback", {@mouse_tools_cb, ht, "zoomin"});
+    set (ht(4), "oncallback", {@mouse_tools_cb, ht, "zoomout"}, ...
+         "offcallback", {@mouse_tools_cb, ht, "zoomout"});
+    set (ht(5), "oncallback", {@mouse_tools_cb, ht, "text"}, ...
+         "offcallback", {@mouse_tools_cb, ht, "text"});
   endif
 
-  ## Figure listeners
-  toggle_visibility_cb (hf, [], hmenu);
-  addlistener (hf, "menubar", {@toggle_visibility_cb, hmenu});
+  if (! exist ("ht", "var"))
+    ht = get (htb, "children")(end:-1:1);
+    istoggletool = strcmp (get (ht, "type"), "uitoggletool");
+    ht(! istoggletool) = [];
+  endif
+
+  ## Add/Restore figure listeners
+  toggle_visibility_cb (hf, [], hmenu, htb);
+  addlistener (hf, "menubar", {@toggle_visibility_cb, hmenu, htb});
+  addlistener (hf, "toolbar", {@toggle_visibility_cb, hmenu, htb});
+  addlistener (hf, "__mouse_mode__", {@mouse_tools_cb, ht, "mode"});
+  addlistener (hf, "__zoom_mode__", {@mouse_tools_cb, ht, "mode"});
 
 endfunction
 
-function toggle_visibility_cb (hf, ~, hmenu)
-  if (strcmp (get (hf, "menubar"), "none"))
-    set (hmenu, "visible", "off")
-  else
-    set (hmenu, "visible", "on")
+function toggle_visibility_cb (hf, ~, hmenu, htb)
+  menu_state = ifelse (strcmp (get (hf, "menubar"), "figure"), "on", "off");
+  toolbar_state = "on";
+  if (strcmp (get (hf, "toolbar"), "auto"))
+    toolbar_state = menu_state;
+  elseif (strcmp (get (hf, "toolbar"), "none"))
+    toolbar_state = "off";
   endif
+
+  set (hmenu, "visible", menu_state);
+  set (htb, "visible", toolbar_state);
 endfunction
 
 function open_cb (h, e)
@@ -112,28 +175,30 @@
   endif
 endfunction
 
-function save_cb (h, e)
-  [hcbo, hfig] = gcbo ();
-  lbl = get (hcbo, "label");
-  if (strcmp (lbl, "&Save"))
-    fname = get (hfig, "filename");
+function save_cb (h, e, action)
+  hfig = gcbf ();
+  fname = get (hfig, "filename");
+
+  if (strcmp (action, "save"))
     if (isempty (fname))
       __save_as__ (hfig);
     else
       saveas (hfig, fname);
     endif
-  elseif (strcmp (lbl, "Save &As"))
-    __save_as__ (hfig);
+  elseif (strcmp (action, "saveas"))
+    __save_as__ (hfig, fname);
   endif
 endfunction
 
 
-function __save_as__ (hf)
-  [filename, filedir] = uiputfile ...
-    ({"*.ofig", "Octave Figure File";
-      "*.eps;*.epsc;*.pdf;*.svg;*.ps;*.tikz", "Vector Image Formats";
-      "*.gif;*.jpg;*.png;*.tiff", "Bitmap Image Formats"},
-     "Save Figure", fullfile (pwd, "untitled.ofig"));
+function __save_as__ (hf, fname = "")
+  filter = ifelse (! isempty (fname), fname, ...
+                   {"*.ofig", "Octave Figure File";
+                    "*.eps;*.pdf;*.svg;*.ps", "Vector Image Formats";
+                    "*.gif;*.jpg;*.png;*.tiff", "Bitmap Image Formats"});
+  def = ifelse (! isempty (fname), fname, fullfile (pwd, "untitled.ofig"));
+
+  [filename, filedir] = uiputfile (filter, "Save Figure", def);
 
   if (filename != 0)
     fname = fullfile (filedir, filename);
@@ -161,26 +226,24 @@
   hax = findobj (fig, "type", "axes", "-not", "tag", "legend");
 endfunction
 
-
-function grid_cb (h, e)
-  hax = __get_axes__ (h);
-  id = get (h, "tag");
-  switch (id)
-    case "toggle"
-      arrayfun (@grid, hax);
-    otherwise
-      arrayfun (@(h) grid(h, id), hax);
-  endswitch
-  drawnow ();
-endfunction
-
-
 function autoscale_cb (h, e)
   hax = __get_axes__ (h);
   arrayfun (@(h) axis (h, "auto"), hax);
   drawnow ();
 endfunction
 
+function init_mouse_tools (hf)
+  set (hf, "__pan_mode__", struct ("Enable", "off",
+                                   "Motion", "both",
+                                   "FigureHandle", hf),
+           "__rotate_mode__", struct ("Enable", "off",
+                                      "RotateStyle", "box",
+                                      "FigureHandle", hf),
+           "__zoom_mode__", struct ("Enable", "off",
+                                    "Motion", "both",
+                                    "Direction", "in",
+                                    "FigureHandle", hf));
+endfunction
 
 function guimode_cb (h, e)
   [hax, fig] = __get_axes__ (h);
@@ -203,3 +266,118 @@
       arrayfun (@(h) set (h, "mousewheelzoom", 0.0), hax);
   endswitch
 endfunction
+
+function mouse_tools_cb (h, ev, htools, typ = "")
+
+  persistent recursion = false;
+
+  if (! recursion)
+    recursion = true;
+
+    hf = gcbf ();
+
+    if (strcmp (typ, "mode"))
+      ## The mouse mode has been changed from outside this callback,
+      ## change the buttons state accordingly
+      mode = get (hf, "__mouse_mode__");
+      state = "on";
+
+      switch mode
+        case "zoom"
+          zm = get (hf, "__zoom_mode__");
+          if (strcmp (zm.Direction, "in"))
+            htool = htools(3);
+          else
+            htool = htools(4);
+          endif
+        case "pan"
+          htool = htools(1);
+        case "rotate"
+          htool = htools(2);
+        case "text"
+          htool = htools(5);
+        case "none"
+          state = "off";
+          htool = htools;
+      endswitch
+
+      set (htool, "state", state);
+      if (strcmp (state, "on"))
+        set (htools(htools != htool), "state", "off");
+      endif
+
+    else
+      ## Update the mouse mode according to the button state
+      state = get (h, "state");
+
+      switch typ
+        case {"zoomin", "zoomout"}
+          prop = "__zoom_mode__";
+          val = get (hf, prop);
+
+          if (strcmp (state, "on"))
+            if (strcmp (typ, "zoomin"))
+              val.Direction = "in";
+            else
+              val.Direction = "out";
+            endif
+            set (hf, "__mouse_mode__" , "zoom");
+          endif
+          val.Enable = state;
+          set (hf, prop, val);
+
+        case {"pan", "rotate"}
+          prop = ["__", typ, "_mode__"];
+          val = get (hf, prop);
+          if (strcmp (state, "on"))
+            set (hf, "__mouse_mode__" , typ);
+          endif
+          val.Enable = state;
+          set (hf, prop, val);
+
+        case {"text", "select"}
+          if (strcmp (state, "on"))
+            set (hf, "__mouse_mode__" , typ);
+          endif
+      endswitch
+
+      if (strcmp (state, "on"))
+        set (htools(htools != h), "state", "off");
+      elseif (! any (strcmp (get (htools, "state"), "on")))
+        set (hf, "__mouse_mode__" , "none");
+      endif
+    endif
+
+    recursion = false;
+  endif
+
+endfunction
+
+function axes_cb (h)
+  hax = get (gcbf (), "currentaxes");
+  if (! isempty (hax))
+    if (strcmp (get (hax, "visible"), "on"))
+      set (hax, "visible", "off");
+    else
+      set (hax, "visible", "on");
+    endif
+  endif
+endfunction
+
+function grid_cb (h)
+  hax = get (gcbf (), "currentaxes");
+  if (! isempty (hax))
+    if (strcmp (get (hax, "xgrid"), "on") && strcmp (get (hax, "ygrid"), "on"))
+      grid (hax, "off");
+    else
+      grid (hax, "on");
+    endif
+  endif
+endfunction
+
+function auto_cb (h)
+  hax = get (gcbf (), "currentaxes");
+  if (! isempty (hax))
+    axis (hax, "auto");
+  endif
+endfunction
--- a/scripts/plot/util/private/__ghostscript__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__ghostscript__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -61,7 +61,7 @@
   endfor
 
   if (isempty (opts.binary))
-    error ("print:no_ghostscript", "__ghostscript__.m: Ghostscript binary is required for specified output format, but binary is not available in PATH");
+    error ("Octave:print:nogs", "__ghostscript__: 'gs' (Ghostscript) binary is required for specified output format, but binary is not available in PATH");
   endif
 
   if (isempty (opts.papersize))
@@ -111,7 +111,7 @@
         gs_opts = sprintf ("%s -dNORANGEPAGESIZE", gs_opts);
       endif
     else
-      error ("print:badpapersize", "__ghostscript__.m: invalid 'papersize'");
+      error ("Octave:print:badpapersize", "__ghostscript__.m: invalid 'papersize'");
     endif
     gs_opts = sprintf ("%s -dFIXEDMEDIA", gs_opts);
     ## "pageoffset" is relative to the coordinates, not the BBox LLHC.
@@ -132,13 +132,13 @@
     unwind_protect
       fid = fopen (offsetfile, "w");
       if (fid == -1)
-        error ("print:fopenfailed", "__ghostscript__.m: fopen () failed");
+        error ("Octave:print:fopenfailed", "__ghostscript__.m: fopen () failed");
       endif
       fprintf (fid, "%s\n", offset_ps{:});
     unwind_protect_cleanup
       status = fclose (fid);
       if (status == -1)
-        error ("print:fclosefailed", "__ghostscript__.m: fclose () failed");
+        error ("Octave:print:fclosefailed", "__ghostscript__.m: fclose () failed");
       endif
     end_unwind_protect
     if (opts.debug)
--- a/scripts/plot/util/private/__gnuplot_draw_axes__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -154,8 +154,8 @@
       ## Change meaning of "normalized", but it at least gives user some control
       if (! strcmp (get (axis_obj.title, "units"), "normalized"))
         unwind_protect
-          set (axis_obj.title, "units", "normalized");
-          set (axis_obj.title, "position", [0.5 1.02 0.5]);
+          set (axis_obj.title, "units", "normalized",
+                               "position", [0.5 1.02 0.5]);
         unwind_protect_cleanup
         end_unwind_protect
       endif
@@ -2254,8 +2254,12 @@
     endfor
   elseif (strcmp (interpreter, "latex"))
     if (! warned_latex)
-      warning ("latex markup not supported for tick marks");
-      warned_latex = true;
+      do_warn = (warning ("query", "Octave:text_interpreter")).state;
+      if (strcmp (do_warn, "on"))
+        warning ("Octave:text_interpreter",
+                 "latex markup not supported for tick marks");
+        warned_latex = true;
+      endif
     endif
   endif
   if (strcmp (scale, "log"))
@@ -2421,8 +2425,12 @@
       endif
     elseif (strcmp (ntrp, "latex"))
       if (! warned_latex)
-        warning ("latex markup not supported for text objects");
-        warned_latex = true;
+        do_warn = (warning ("query", "Octave:text_interpreter")).state;
+        if (strcmp (do_warn, "on"))
+          warning ("Octave:text_interpreter",
+                   "latex markup not supported for text objects");
+          warned_latex = true;
+        endif
       endif
     endif
   endif
--- a/scripts/plot/util/private/__gnuplot_draw_figure__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_draw_figure__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -166,13 +166,13 @@
               unwind_protect_cleanup
                 ## Return axes "units" and "position" back to
                 ## their original values.
-                set (kids(i), "units", orig_axes_units);
-                set (kids(i), "position", orig_axes_position);
+                set (kids(i), "units", orig_axes_units,
+                              "position", orig_axes_position);
                 bg_is_set = false;
                 fg_is_set = false;
               end_unwind_protect
             endif
-          case {"uimenu", "uicontextmenu"}
+          case {"uimenu", "uicontextmenu", "uitoolbar"}
             ## ignore uimenu objects
             kids(i) = [];
           otherwise
--- a/scripts/plot/util/private/__gnuplot_has_feature__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_has_feature__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -37,12 +37,7 @@
   persistent has_features;
 
   if (isempty (has_features))
-    try
-      gnuplot_version = __gnuplot_version__ ();
-    catch
-      ## Don't throw an error if gnuplot isn't installed
-      gnuplot_version = "0.0.0";
-    end_try_catch
+    gnuplot_version = __gnuplot_version__ ();
     versions  = {"4.4", "4.6", "5.0", "4.6", "4.6", "5.0", "5.0", "5.0"};
     operators = {">=" , ">=" , ">=" , ">=" , ">=" , ">=" , ">=" , ">=" };
     have_features = false (size (features));
--- a/scripts/plot/util/private/__gnuplot_print__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_print__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -93,7 +93,7 @@
           suffix = ext;  # If user provides eps/ps/pdf suffix, use it.
         endif
       else
-        error ("print:invalid-suffix",
+        error ("Octave:print:invalid-suffix",
                "invalid suffix '%s' for device '%s'.",
                ext, lower (opts.devopt));
       endif
@@ -114,7 +114,7 @@
         local_drawnow (["tikz " gp_opts], opts.name, opts);
       else
         error (sprintf ("print:no%soutput", opts.devopt),
-               "print.m: '%s' output is not available for gnuplot-%s",
+               "print: '%s' output is not available for gnuplot-%s",
                upper (opts.devopt), __gnuplot_version__ ());
       endif
     case "svg"
@@ -144,7 +144,7 @@
         local_drawnow ([term " " gp_opts], opts.name, opts);
       else
         error (sprintf ("print:no%soutput", opts.devopt),
-               "print.m: '%s' output is not available for gnuplot-%s",
+               "print: '%s' output is not available for gnuplot-%s",
                upper (opts.devopt), __gnuplot_version__ ());
       endif
     case {"canvas", "cgm", "dxf", "hpgl", "latex", "mf", "gif", ...
@@ -153,7 +153,7 @@
         local_drawnow ([opts.devopt " " gp_opts], opts.name, opts);
       else
         error (sprintf ("print:no%soutput", opts.devopt),
-               "print.m: '%s' output is not available for gnuplot-%s",
+               "print: '%s' output is not available for gnuplot-%s",
                upper (opts.devopt), __gnuplot_version__ ());
       endif
     case "dumb"
@@ -187,7 +187,7 @@
       endif
     otherwise
       error (sprintf ("print:no%soutput", opts.devopt),
-             "print.m: %s output is not available for the Gnuplot graphics toolkit",
+             "print: %s output is not available for the Gnuplot graphics toolkit",
              upper (opts.devopt));
   endswitch
 
@@ -204,7 +204,7 @@
                "---------- output begin ----------",
                output,
                "----------- output end -----------");
-      error ("gnuplot:failedpipe", "print: failed to print");
+      error ("Octave:gnuplot:failedpipe", "print: failed to print");
     endif
   endfor
 
--- a/scripts/plot/util/private/__gnuplot_version__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_version__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -36,7 +36,7 @@
       ## are skipped and people might actually see the message, read it,
       ## comprehend it, take the advice it gives, and stop asking us
       ## why plotting fails when gnuplot is not found.
-      error ("you must have gnuplot installed to display graphics; if you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\n");
+      error ("The gnuplot executable '%s' was not found or does not work.  If you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\n", gnuplot_binary ());
     endif
     output = strrep (output, "gnuplot", "");
     output = strrep (output, "patchlevel", ".");
--- a/scripts/plot/util/private/__opengl_print__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__opengl_print__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -57,7 +57,7 @@
           suffix = ext;  # If user provides eps/ps/pdf suffix, use it.
         endif
       else
-        error ("print:invalid-suffix",
+        error ("Octave:print:invalid-suffix",
                "invalid suffix '%s' for device '%s'.",
                ext, lower (opts.devopt));
       endif
@@ -125,13 +125,9 @@
       cmd = sprintf (opts.pstoedit_cmd (opts), "pdf", tmp, tmp);
       gl2ps_device = {"svg"};
       pipeline = {sprintf("%s > %s", cmd, opts.name)};
-    case {"corel", "gif"}
-      error ("print:unsupporteddevice",
-             "print.m: %s output is not available for OpenGL graphics toolkits",
-             upper (opts.devopt));
     case opts.ghostscript.device
       ## Except for postscript, use svg format and first convert to pdf
-      ## before going through ghostscript for final adjusments
+      ## before going through ghostscript for final adjustments.
       svgcmd = "";
       if (opts.svgconvert)
         svgcmd = opts.svgconvert_cmd (opts, opts.ghostscript.device);
@@ -183,7 +179,7 @@
       endif
     otherwise
       error (sprintf ("print:no%soutput", opts.devopt),
-             "print.m: %s output is not available for OpenGL toolkits",
+             "print: %s output is not available for OpenGL toolkits",
              upper (opts.devopt));
   endswitch
 
--- a/scripts/plot/util/private/__print_parse_opts__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -34,7 +34,7 @@
   arg_st.epstool_binary = __quote_path__ (__find_binary__ ("epstool"));
   arg_st.figure = get (0, "currentfigure");
   arg_st.fig2dev_binary = __quote_path__ (__find_binary__ ("fig2dev"));
-  arg_st.fontsize = "";
+  arg_st.fontsize = [];
   arg_st.font = "";
   arg_st.scalefontsize = 1;
   arg_st.force_solid = 0; # 0=default, -1=dashed, +1=solid
@@ -64,7 +64,7 @@
   arg_st.special_flag = "textnormal";
   arg_st.svgconvert = false;
   arg_st.svgconvert_binary = __quote_path__ (__svgconv_binary__ ());
-  arg_st.tight = false;
+  arg_st.tight = true;
   arg_st.use_color = 0; # 0=default, -1=mono, +1=color
 
   if (isunix ())
@@ -210,6 +210,16 @@
     endif
   endif
 
+  ## Warn about deprecated output formats
+  persistent unsupported = {"aifm", "ill","cdr", "corel", ...
+                            "hpgl", "mf", "cgm", "dxf"}
+
+  if (any (strcmp (unsupported, arg_st.devopt)))
+    warning ('Octave:print:deprecated-format',
+             'print: "%s" format is no more officially supported', ...
+             arg_st.devopt);
+  endif
+
   ## By default, postprocess svg files using svgconvert.
   if (strcmp (arg_st.devopt, "svg"))
     arg_st.svgconvert = true;
@@ -345,10 +355,10 @@
         endif
       else
         arg_st.append_to_file = false;
-        warning ("print.m: appended output requires Ghostscript to be installed");
+        warning ("print: appended output requires Ghostscript to be installed");
       endif
     else
-      warning ("print.m: appended output is not supported for device '%s'",
+      warning ("print: appended output is not supported for device '%s'",
                arg_st.devopt);
       arg_st.append_to_file = false;
     endif
@@ -356,7 +366,7 @@
 
   if (arg_st.rgb_output)
     if (! isempty (arg_st.printer) || ! isempty (arg_st.name))
-      warning ("octave:print:ignored_argument",
+      warning ("Octave:print:ignored_argument",
                "print: ignoring file name and printer argument when using -RGBImage option");
     endif
   elseif (! isempty (arg_st.printer) || isempty (arg_st.name))
@@ -464,11 +474,12 @@
       arg_st.ghostscript.pageoffset = paperposition(1:2);
     endif
   else
-    ## Convert canvas size to points from pixels.
-    if (! isempty (arg_st.fontsize))
-      ## Work around the eps bbox having whole numbers (both gnuplot & gl2ps).
-      arg_st.scalefontsize = arg_st.ghostscript.resolution / 72;
+    ## Size specified with -S option
+    if (arg_st.ghostscript.resolution != 150)
+      warning ("print: '-Sxsize,ysize' overrides resolution option -r\n");
     endif
+    arg_st.scalefontsize = arg_st.canvas_size(1) / ...
+                           6 / get (0, "screenpixelsperinch");
     arg_st.ghostscript.resolution = 72;
     arg_st.ghostscript.papersize = arg_st.canvas_size;
     arg_st.ghostscript.epscrop = true;
@@ -484,9 +495,8 @@
 
   if (warn_on_missing_ghostscript)
     if (isempty (arg_st.ghostscript.binary))
-      warning ("octave:print:missing_gs", ...
-               ["print.m: Ghostscript binary is not available.  ", ...
-                "Only eps output is possible"]);
+      warning ("print:nogs", ...
+               "print: 'gs' (Ghostscript) binary is not available.  Many formats may not be available\n");
     endif
     warn_on_missing_ghostscript = false;
   endif
@@ -580,8 +590,8 @@
         || (! isempty (GSC) && file_in_path (getenv ("PATH"), GSC)))
       gs_binaries = {GSC};
     elseif (! isempty (GSC) && warn_on_bad_gsc)
-      warning ("octave:print:badgscenv",
-               "print.m: GSC environment variable not set properly");
+      warning ("Octave:print:badgscenv",
+               "print: GSC environment variable not set properly");
       warn_on_bad_gsc = false;
       gs_binaries = {};
     else
@@ -734,8 +744,8 @@
     case "centimeters"
       value *= (72 / 2.54);
     case "normalized"
-      error ("print:customnormalized",
-             "print.m: papersize=='<custom>' and paperunits='normalized' may not be combined");
+      error ("Octave:print:customnormalized",
+             "print: papersize=='<custom>' and paperunits='normalized' may not be combined");
   endswitch
 
 endfunction
--- a/scripts/polynomial/deconv.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/polynomial/deconv.m	Fri Jul 12 12:14:43 2019 -0400
@@ -116,7 +116,7 @@
 %! [b, r] = deconv (y, a);
 %! assert (conv (a, b) + r, y, eps)
 
-%!test <51221>
+%!test <*51221>
 %! a = [1.92306958582241e+15, 3.20449986572221e+24, 1.34271290136344e+32, ...
 %!     2.32739765751038e+38];
 %! b = [7.33727670161595e+27, 1.05919311870816e+36, 4.56169848520627e+42];
--- a/scripts/polynomial/poly.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/polynomial/poly.m	Fri Jul 12 12:14:43 2019 -0400
@@ -104,7 +104,7 @@
 %! y = poly (x);
 %! assert (isreal (y), true);
 
-%!test <53897>
+%!test <*53897>
 %! x = [1 + 1i, 1 + 2i, 3, 4];
 %! y = poly (x);
 %! assert (y, [1 + 0i, -9 - 3i, 25 + 24i, -17 - 57i, -12 + 36i]);
--- a/scripts/polynomial/splinefit.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/polynomial/splinefit.m	Fri Jul 12 12:14:43 2019 -0400
@@ -111,7 +111,7 @@
   for f = 1:numel (fields)
     if (! any (strcmp (fields{f},
                        {"periodic", "robust", "beta", "order", "constraints"})))
-      error ("splinefit:invalidproperty",
+      error ("Octave:splinefit:invalidproperty",
              "unrecognized property '%s'", fields{f});
     endif
   endfor
@@ -127,14 +127,14 @@
     if (0 < props.beta && props.beta < 1)
       args{end+1} = props.beta;
     else
-      error ("splinefit:invalidbeta", "invalid beta parameter (0 < BETA < 1)");
+      error ("Octave:splinefit:invalidbeta", "invalid beta parameter (0 < BETA < 1)");
     endif
   endif
   if (isfield (props, "order"))
     if (props.order >= 0)
       args{end+1} = props.order + 1;
     else
-      error ("splinefit:invalidorder", "invalid ORDER");
+      error ("Octave:splinefit:invalidorder", "invalid ORDER");
     endif
   endif
   if (isfield (props, "constraints"))
--- a/scripts/prefs/addpref.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/prefs/addpref.m	Fri Jul 12 12:14:43 2019 -0400
@@ -77,6 +77,7 @@
 
 %!test
 %! HOME = getenv ("HOME");
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   setenv ("HOME", P_tmpdir ());
 %!
--- a/scripts/prefs/getpref.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/prefs/getpref.m	Fri Jul 12 12:14:43 2019 -0400
@@ -109,6 +109,7 @@
 %!test
 %! HOME = getenv ("HOME");
 %! tmp_home = tempname ();
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   mkdir (tmp_home);
 %!   setenv ("HOME", tmp_home);
--- a/scripts/prefs/ispref.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/prefs/ispref.m	Fri Jul 12 12:14:43 2019 -0400
@@ -67,6 +67,7 @@
 
 %!test
 %! HOME = getenv ("HOME");
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   setenv ("HOME", P_tmpdir ());
 %!   addpref ("group1", "pref1", [1 2 3]);
--- a/scripts/prefs/rmpref.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/prefs/rmpref.m	Fri Jul 12 12:14:43 2019 -0400
@@ -75,6 +75,7 @@
 
 %!test
 %! HOME = getenv ("HOME");
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   setenv ("HOME", P_tmpdir ());
 %!   addpref ("group1", "pref1", [1 2 3]);
--- a/scripts/set/intersect.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/intersect.m	Fri Jul 12 12:14:43 2019 -0400
@@ -20,6 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{c} =} intersect (@var{a}, @var{b})
 ## @deftypefnx {} {@var{c} =} intersect (@var{a}, @var{b}, "rows")
+## @deftypefnx {} {@var{c} =} intersect (@dots{}, "legacy")
 ## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} intersect (@dots{})
 ##
 ## Return the unique elements common to both @var{a} and @var{b} sorted in
@@ -32,15 +33,18 @@
 ## If the optional input @qcode{"rows"} is given then return the common rows of
 ## @var{a} and @var{b}.  The inputs must be 2-D matrices to use this option.
 ##
-## If requested, return index vectors @var{ia} and @var{ib} such that
+## If requested, return column index vectors @var{ia} and @var{ib} such that
 ## @code{@var{c} = @var{a}(@var{ia})} and @code{@var{c} = @var{b}(@var{ib})}.
 ##
+## Programming Note: The input flag @qcode{"legacy"} changes the algorithm
+## to be compatible with @sc{matlab} releases prior to R2012b.
+##
 ## @seealso{unique, union, setdiff, setxor, ismember}
 ## @end deftypefn
 
 function [c, ia, ib] = intersect (a, b, varargin)
 
-  if (nargin < 2 || nargin > 3)
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
@@ -58,13 +62,21 @@
     endif
     ia = ib = [];
   else
-    by_rows = nargin == 3;
-    isrowvec = isrow (a) && isrow (b);
+    by_rows = any (strcmp ("rows", varargin));
+    optlegacy = any (strcmp ("legacy", varargin));
+
+    if (optlegacy)
+      isrowvec = ! iscolumn (a) || ! iscolumn (b);
+    else
+      isrowvec = isrow (a) && isrow (b);
+    endif
 
     ## Form A and B into sets
     if (nargout > 1)
       [a, ja] = unique (a, varargin{:});
+      ja = ja(:);
       [b, jb] = unique (b, varargin{:});
+      jb = jb(:);
     else
       a = unique (a, varargin{:});
       b = unique (b, varargin{:});
@@ -72,13 +84,21 @@
 
     if (by_rows)
       c = [a; b];
-      [c, ic] = sortrows (c);
+      if (nargout > 1)
+        [c, ic] = sortrows (c);
+      else
+        c = sortrows (c);
+      endif
       ii = find (all (c(1:end-1,:) == c(2:end,:), 2));
       c = c(ii,:);
       len_a = rows (a);
     else
       c = [a(:); b(:)];
-      [c, ic] = sort (c);         # [a(:);b(:)](ic) == c
+      if (nargout > 1)
+        [c, ic] = sort (c);         # [a(:);b(:)](ic) == c
+      else
+        c = sort (c);
+      endif
       if (iscellstr (c))
         ii = find (strcmp (c(1:end-1), c(2:end)));
       else
@@ -88,15 +108,20 @@
       len_a = length (a);
     endif
 
+    ## Adjust output orientation for Matlab compatibility
+    if (isrowvec)
+      c = c.';
+    endif
+
     if (nargout > 1)
       ia = ja(ic(ii));            # a(ia) == c
       ib = jb(ic(ii+1) - len_a);  # b(ib) == c
+      if (optlegacy && isrowvec)
+        ia = ia.';
+        ib = ib.';
+      endif
     endif
 
-    ## Adjust output orientation for Matlab compatibility
-    if (! by_rows && isrowvec)
-      c = c.';
-    endif
   endif
 
 endfunction
@@ -107,10 +132,17 @@
 %! a = 1:4;
 %! b = 2:5;
 
-%!assert (size (intersect (a, b)), [1 3])
-%!assert (size (intersect (a', b)), [3 1])
-%!assert (size (intersect (a, b')), [3 1])
-%!assert (size (intersect (a', b')), [3 1])
+%!assert (size (intersect (a, b)), [1, 3])
+%!assert (size (intersect (a', b)), [3, 1])
+%!assert (size (intersect (a, b')), [3, 1])
+%!assert (size (intersect (a', b')), [3, 1])
+%!assert (size (intersect (a, b, "legacy")), [1, 3])
+%!assert (size (intersect (a', b, "legacy")), [1, 3])
+%!assert (size (intersect (a, b', "legacy")), [1, 3])
+%!assert (size (intersect (a', b', "legacy")), [3, 1])
+
+## Clear shared variables
+%!shared
 
 ## Test multi-dimensional arrays
 %!test
@@ -124,9 +156,9 @@
 %! a = [3 2 4 5 7 6 5 1 0 13 13];
 %! b = [3 5 12 1 1 7];
 %! [c,ia,ib] = intersect (a, b);
-%! assert (c, [1 3 5 7]);
-%! assert (ia, [8 1 7 5]);
-%! assert (ib, [5 1 2 6]);
+%! assert (c, [1, 3, 5, 7]);
+%! assert (ia, [8; 1; 4; 5]);
+%! assert (ib, [4; 1; 2; 6]);
 %! assert (a(ia), c);
 %! assert (b(ib), c);
 %!test
@@ -150,6 +182,19 @@
 %! assert (ia, [1:3]');
 %! assert (ib, [1:3]');
 
+## Test "legacy" argument
+%!test
+%! a = [7 1 7 7 4]; 
+%! b = [7 0 4 4 0];
+%! [c, ia, ib] = intersect (a, b);
+%! assert (c, [4, 7]);
+%! assert (ia, [5; 1]);
+%! assert (ib, [3; 1]);
+%! [c, ia, ib] = intersect (a, b, "legacy");
+%! assert (c, [4, 7]);
+%! assert (ia, [5, 4]);
+%! assert (ib, [4, 1]);
+
 ## Test return type of empty intersections
 %!assert (intersect (['a', 'b'], {}), {})
 %!assert (intersect ([], {'a', 'b'}), {})
--- a/scripts/set/private/validsetargs.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/private/validsetargs.m	Fri Jul 12 12:14:43 2019 -0400
@@ -19,7 +19,7 @@
 
 ## Validate arguments for binary set operation.
 
-function [x, y] = validsetargs (caller, x, y, byrows_arg)
+function [x, y] = validsetargs (caller, x, y, varargin)
 
   isallowedarraytype = @(x) isnumeric (x) || ischar (x) || islogical (x);
 
@@ -42,21 +42,29 @@
       error ("%s: A and B must be arrays or cell arrays of strings", caller);
     endif
   elseif (nargin == 4)
-    if (! strcmpi (byrows_arg, "rows"))
-      error ("%s: invalid option: %s", caller, byrows_arg);
-    endif
+    for arg = varargin
+      switch (arg{1})
+        case "legacy"
+          ## Accepted option, do nothing.
 
-    if (iscell (x) || iscell (y))
-      error ('%s: cells not supported with "rows"', caller);
-    elseif (! (isallowedarraytype (x) && isallowedarraytype (y)))
-      error ("%s: A and B must be arrays or cell arrays of strings", caller);
-    else
-      if (ndims (x) > 2 || ndims (y) > 2)
-        error ('%s: A and B must be 2-dimensional matrices for "rows"', caller);
-      elseif (columns (x) != columns (y) && ! (isempty (x) || isempty (y)))
-        error ("%s: number of columns in A and B must match", caller);
-      endif
-    endif
+        case "rows"
+          if (iscell (x) || iscell (y))
+            error ('%s: cells not supported with "rows"', caller);
+          elseif (! (isallowedarraytype (x) && isallowedarraytype (y)))
+            error ("%s: A and B must be arrays or cell arrays of strings", caller);
+          else
+            if (ndims (x) > 2 || ndims (y) > 2)
+              error ('%s: A and B must be 2-dimensional matrices for "rows"', caller);
+            elseif (columns (x) != columns (y) && ! (isempty (x) || isempty (y)))
+              error ("%s: number of columns in A and B must match", caller);
+            endif
+          endif
+
+        otherwise
+          error ("%s: invalid option: %s", caller, arg{1});
+
+      endswitch
+    endfor
   endif
 
 endfunction
--- a/scripts/set/setdiff.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/setdiff.m	Fri Jul 12 12:14:43 2019 -0400
@@ -20,6 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{c} =} setdiff (@var{a}, @var{b})
 ## @deftypefnx {} {@var{c} =} setdiff (@var{a}, @var{b}, "rows")
+## @deftypefnx {} {@var{c} =} setdiff (@dots{}, "legacy")
 ## @deftypefnx {} {[@var{c}, @var{ia}] =} setdiff (@dots{})
 ## Return the unique elements in @var{a} that are not in @var{b} sorted in
 ## ascending order.
@@ -33,6 +34,10 @@
 ##
 ## If requested, return the index vector @var{ia} such that
 ## @code{@var{c} = @var{a}(@var{ia})}.
+##
+## Programming Note: The input flag @qcode{"legacy"} changes the algorithm
+## to be compatible with @sc{matlab} releases prior to R2012b.
+##
 ## @seealso{unique, union, intersect, setxor, ismember}
 ## @end deftypefn
 
@@ -41,24 +46,30 @@
 
 function [c, ia] = setdiff (a, b, varargin)
 
-  if (nargin < 2 || nargin > 3)
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
   [a, b] = validsetargs ("setdiff", a, b, varargin{:});
 
-  by_rows = nargin == 3;
-  isrowvec = isrow (a);
+  by_rows = any (strcmp ("rows", varargin));
+  optlegacy = any (strcmp ("legacy", varargin));
+
+  if (optlegacy)
+    isrowvec = ! iscolumn (a) || ! iscolumn (b);
+  else
+    isrowvec = isrow (a);
+  endif
 
   if (by_rows)
     if (nargout > 1)
-      [c, ia] = unique (a, "rows");
+      [c, ia] = unique (a, varargin{:});
     else
-      c = unique (a, "rows");
+      c = unique (a, varargin{:});
     endif
     if (! isempty (c) && ! isempty (b))
       ## Form A and B into combined set.
-      b = unique (b, "rows");
+      b = unique (b, varargin{:});
       [tmp, idx] = sortrows ([c; b]);
       ## Eliminate those elements of A that are the same as in B.
       dups = find (all (tmp(1:end-1,:) == tmp(2:end,:), 2));
@@ -69,9 +80,9 @@
     endif
   else
     if (nargout > 1)
-      [c, ia] = unique (a);
+      [c, ia] = unique (a, varargin{:});
     else
-      c = unique (a);
+      c = unique (a, varargin{:});
     endif
     if (! isempty (c) && ! isempty (b))
       ## Form a and b into combined set.
@@ -84,15 +95,18 @@
         dups = find (tmp(1:end-1) == tmp(2:end));
       endif
       c(idx(dups)) = [];
-      if (nargout > 1)
-        ia(idx(dups)) = [];
-      endif
       ## Reshape if necessary for Matlab compatibility.
       if (isrowvec)
         c = c(:).';
       else
         c = c(:);
       endif
+      if (nargout > 1)
+        ia(idx(dups)) = [];
+        if (optlegacy && isrowvec)
+          ia = ia(:).';
+        endif
+      endif
     endif
   endif
 
@@ -126,3 +140,36 @@
 %! a = rand (3,3,3);
 %! b = a(1);
 %! assert (setdiff (a, b), sort (a(2:end)'));
+
+## Test "rows" compatibility
+%!test
+%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];
+%! b = [0 0 0; 5 5 5];
+%! [c, ia] = setdiff (a, b, "rows");
+%! assert (c, [1, 4 ,5; 7, 9 7]);
+%! assert (ia, [5; 1]);
+
+## Test "legacy" option
+%!test
+%! a = [3, 6, 2, 1, 5, 1, 1];
+%! b = [2, 4, 6];
+%! [c, ia] = setdiff (a, b);
+%! assert (c, [1, 3, 5]);
+%! assert (ia, [4; 1; 5]);
+%! [c, ia] = setdiff (a, b, "legacy");
+%! assert (c, [1, 3, 5]);
+%! assert (ia, [7, 1, 5]);
+
+## "legacy" + "rows" compatibility
+%!test
+%! a = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];
+%! b = [0 0 0; 5 5 5];
+%! [c, ia] = setdiff (a, b, "rows", "legacy");
+%! assert (c, [1, 4 ,5; 7, 9 7]);
+%! assert (ia, [5; 3]);
+
+## Output orientation with "legacy" option 
+%!assert (size (setdiff ([1:5], [2:3], "legacy")), [1, 3])
+%!assert (size (setdiff ([1:5]', [2:3], "legacy")), [1, 3])
+%!assert (size (setdiff ([1:5], [2:3]', "legacy")), [1, 3])
+%!assert (size (setdiff ([1:5]', [2:3]', "legacy")), [3, 1])
--- a/scripts/set/setxor.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/setxor.m	Fri Jul 12 12:14:43 2019 -0400
@@ -21,6 +21,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{c} =} setxor (@var{a}, @var{b})
 ## @deftypefnx {} {@var{c} =} setxor (@var{a}, @var{b}, "rows")
+## @deftypefnx {} {@var{c} =} setxor (@dots{}, "legacy")
 ## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@dots{})
 ##
 ## Return the unique elements exclusive to sets @var{a} or @var{b} sorted in
@@ -34,23 +35,32 @@
 ## to sets @var{a} and @var{b}.  The inputs must be 2-D matrices to use this
 ## option.
 ##
-## If requested, return index vectors @var{ia} and @var{ib} such that
-## @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
+## The optional outputs @var{ia} and @var{ib} are column index vectors such
+## that @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
 ## whose union is @var{c}.
 ##
+## Programming Note: The input flag @qcode{"legacy"} changes the algorithm
+## to be compatible with @sc{matlab} releases prior to R2012b.
+##
 ## @seealso{unique, union, intersect, setdiff, ismember}
 ## @end deftypefn
 
 function [c, ia, ib] = setxor (a, b, varargin)
 
-  if (nargin < 2 || nargin > 3)
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
   [a, b] = validsetargs ("setxor", a, b, varargin{:});
 
-  by_rows = nargin == 3;
-  isrowvec = isrow (a) && isrow (b);
+  by_rows = any (strcmp ("rows", varargin));
+  optlegacy = any (strcmp ("legacy", varargin));
+
+  if (optlegacy)
+    isrowvec = ! iscolumn (a) || ! iscolumn (b);
+  else
+    isrowvec = isrow (a) && isrow (b);
+  endif
 
   ## Form A and B into sets.
   if (nargout > 1)
@@ -99,6 +109,10 @@
     if (nargout > 1)
       ia = ia(i(i <= na));
       ib = ib(i(i > na) - na);
+      if (optlegacy && isrowvec)
+        ia = ia(:).';
+        ib = ib(:).';
+      endif
     endif
   endif
 
@@ -166,3 +180,16 @@
 %! b = a;
 %! b(1,1,1) = 2;
 %! assert (intersect (a, b), sort (a(2:end)'));
+
+## Test "legacy" input
+%!test
+%! a = [5 1 3 3 3];
+%! b = [4 1 2 2];
+%! [c,ia,ib] = setxor (a,b);
+%! assert (c, [2, 3, 4, 5]);
+%! assert (ia, [3; 1]);
+%! assert (ib, [3; 1]);
+%! [c,ia,ib] = setxor (a,b, "legacy");
+%! assert (c, [2, 3, 4, 5]);
+%! assert (ia, [5, 1]);
+%! assert (ib, [4, 1]);
--- a/scripts/set/union.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/union.m	Fri Jul 12 12:14:43 2019 -0400
@@ -20,6 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{c} =} union (@var{a}, @var{b})
 ## @deftypefnx {} {@var{c} =} union (@var{a}, @var{b}, "rows")
+## @deftypefnx {} {@var{c} =} union (@dots{}, "legacy")
 ## @deftypefnx {} {[@var{c}, @var{ia}, @var{ib}] =} union (@dots{})
 ##
 ## Return the unique elements that are in either @var{a} or @var{b} sorted in
@@ -33,10 +34,13 @@
 ## either @var{a} or @var{b}.  The inputs must be 2-D matrices to use this
 ## option.
 ##
-## The optional outputs @var{ia} and @var{ib} are index vectors such that
-## @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
+## The optional outputs @var{ia} and @var{ib} are column index vectors such
+## that @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
 ## whose union is @var{c}.
 ##
+## Programming Note: The input flag @qcode{"legacy"} changes the algorithm
+## to be compatible with @sc{matlab} releases prior to R2012b.
+##
 ## @seealso{unique, intersect, setdiff, setxor, ismember}
 ## @end deftypefn
 
@@ -44,14 +48,20 @@
 
 function [y, ia, ib] = union (a, b, varargin)
 
-  if (nargin < 2 || nargin > 3)
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
   [a, b] = validsetargs ("union", a, b, varargin{:});
 
-  by_rows = nargin == 3;
-  isrowvec = isrow (a) && isrow (b);
+  by_rows = any (strcmp ("rows", varargin));
+  optlegacy = any (strcmp ("legacy", varargin));
+
+  if (optlegacy)
+    isrowvec = ! iscolumn (a) || ! iscolumn (b);
+  else
+    isrowvec = isrow (a) && isrow (b);
+  endif
 
   if (by_rows)
     y = [a; b];
@@ -100,9 +110,22 @@
 %! assert (y, [1; 2; 3; 4; 5]);
 %! assert (y, sort ([a(ia)'; b(ib)']));
 
-%!assert (nthargout (2:3, @union, [1, 2, 4], [2, 3, 5]), {[1, 3], [1, 2, 3]})
+%!assert (nthargout (2:3, @union, [1, 2, 4], [2, 3, 5]), {[1; 2; 3], [2; 3]})
 %!assert (nthargout (2:3, @union, [1 2; 2 3; 4 5], [2 3; 3 4; 5 6], "rows"),
-%!        {[1; 3], [1; 2; 3]})
+%!        {[1; 2; 3], [2; 3]})
+
+## Test "legacy" option
+%!test
+%! a = [5, 7, 1];
+%! b = [3, 1, 1];
+%! [c, ia, ib] = union (a,b);
+%! assert (c, [1, 3, 5, 7]);
+%! assert (ia, [3; 1; 2]);
+%! assert (ib, [1]);
+%! [c, ia, ib] = union (a,b, "legacy");
+%! assert (c, [1, 3, 5, 7]);
+%! assert (ia, [1, 2]);
+%! assert (ib, [3, 1]);
 
 ## Test empty cell string array unions
 %!assert (union ({}, []), cell (0,1))
--- a/scripts/set/unique.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/set/unique.m	Fri Jul 12 12:14:43 2019 -0400
@@ -23,6 +23,7 @@
 ## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{})
 ## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, "first")
 ## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, "last")
+## @deftypefnx {} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, "legacy")
 ## Return the unique elements of @var{x} sorted in ascending order.
 ##
 ## If the input @var{x} is a column vector then return a column vector;
@@ -33,14 +34,21 @@
 ## rows of @var{x} sorted in ascending order.  The input must be a 2-D matrix
 ## to use this option.
 ##
-## If requested, return index vectors @var{i} and @var{j} such that
+## If requested, return column index vectors @var{i} and @var{j} such that
 ## @code{@var{y} = @var{x}(@var{i})} and @code{@var{x} = @var{y}(@var{j})}.
 ##
-## Additionally, if @var{i} is a requested output then one of
-## @qcode{"first"} or @qcode{"last"} may be given as an input.  If
-## @qcode{"last"} is specified, return the highest possible indices in
-## @var{i}, otherwise, if @qcode{"first"} is specified, return the lowest.
-## The default is @qcode{"last"}.
+## Additionally, if @var{i} is a requested output then one of the flags
+## @qcode{"first"} or @qcode{"last"} may be given.  If @qcode{"last"} is
+## specified, return the highest possible indices in @var{i}, otherwise, if
+## @qcode{"first"} is specified, return the lowest.  The default is
+## @qcode{"first"}.
+##
+## Programming Note: The input flag @qcode{"legacy"} changes the algorithm
+## to be compatible with @sc{matlab} releases prior to R2012b.  Specifically,
+## The index ordering flag is changed to @qcode{"last"}, and the shape of the
+## outputs @var{i}, @var{j} will follow the shape of the input @var{x} rather
+## than always being column vectors.
+##
 ## @seealso{union, intersect, setdiff, setxor, ismember}
 ## @end deftypefn
 
@@ -58,22 +66,29 @@
       error ("unique: options must be strings");
     endif
 
-    optrows  = any (strcmp ("rows", varargin));
-    optfirst = any (strcmp ("first", varargin));
-    optlast  = any (strcmp ("last", varargin));
+    optrows   = any (strcmp ("rows", varargin));
+    optfirst  = any (strcmp ("first", varargin));
+    optlast   = any (strcmp ("last", varargin));
+    optlegacy = any (strcmp ("legacy", varargin));
     if (optfirst && optlast)
       error ('unique: cannot specify both "first" and "last"');
-    elseif (optfirst + optlast + optrows != nargin-1)
+    elseif (optfirst + optlast + optrows + optlegacy != nargin-1)
       error ("unique: invalid option");
     endif
 
+    ## Set default to "first" if not set earlier.
+    if (! optfirst && ! optlast)
+      optfirst = true;
+    endif
+
     if (optrows && iscellstr (x))
       warning ('unique: "rows" is ignored for cell arrays');
       optrows = false;
     endif
   else
     optrows = false;
-    optfirst = false;
+    optfirst = true;
+    optlegacy = false;
   endif
 
   ## FIXME: The operations
@@ -97,10 +112,10 @@
 
   if (optrows)
     n = rows (x);
-    dim = 1;
+    isrowvec = false;
   else
     n = numel (x);
-    dim = (rows (x) == 1) + 1;
+    isrowvec = isrow (x);
   endif
 
   y = x;
@@ -123,6 +138,7 @@
   if (optrows)
     if (nargout > 1)
       [y, i] = sortrows (y);
+      i = i(:);
     else
       y = sortrows (y);
     endif
@@ -134,6 +150,7 @@
     endif
     if (nargout > 1)
       [y, i] = sort (y);
+      i = i(:);
     else
       y = sort (y);
     endif
@@ -147,19 +164,21 @@
 
   if (isargout (3))
     j = i;
-    if (dim == 1)
-      j(i) = cumsum ([1; ! match]);
-    else
-      j(i) = cumsum ([1, ! match]);
+    j(i) = cumsum ([1; ! match(:)]);
+    if (optlegacy && isrowvec)
+      j = j.';
     endif
   endif
 
   if (isargout (2))
     idx = find (match);
-    if (optfirst)
+    if (! optlegacy && optfirst)
       idx += 1;   # in-place is faster than other forms of increment
     endif
     i(idx) = [];
+    if (optlegacy && isrowvec)
+      i = i.';
+    endif
   endif
 
 endfunction
@@ -192,29 +211,42 @@
 %!assert (unique (uint8 ([1,2,2,3,2,4]'), "rows"), uint8 ([1,2,3,4]'))
 
 %!test
-%! [a,i,j] = unique ([1,1,2,3,3,3,4]);
-%! assert (a, [1,2,3,4]);
+%! [y,i,j] = unique ([1,1,2,3,3,3,4]);
+%! assert (y, [1,2,3,4]);
+%! assert (i, [1;3;4;7]);
+%! assert (j, [1;1;2;3;3;3;4]);
+
+%!test
+%! [y,i,j] = unique ([1,1,2,3,3,3,4]', "last");
+%! assert (y, [1,2,3,4]');
+%! assert (i, [2;3;6;7]);
+%! assert (j, [1;1;2;3;3;3;4]);
+
+%!test
+%! [y,i,j] = unique ({"z"; "z"; "z"});
+%! assert (y, {"z"});
+%! assert (i, [1]);
+%! assert (j, [1;1;1]);
+
+%!test
+%! A = [1,2,3; 1,2,3];
+%! [y,i,j] = unique (A, "rows");
+%! assert (y, [1,2,3]);
+%! assert (A(i,:), y);
+%! assert (y(j,:), A);
+
+%!test
+%! [y,i,j] = unique ([1,1,2,3,3,3,4], "legacy");
+%! assert (y, [1,2,3,4]);
 %! assert (i, [2,3,6,7]);
 %! assert (j, [1,1,2,3,3,3,4]);
-%!
-%!test
-%! [a,i,j] = unique ([1,1,2,3,3,3,4]', "first");
-%! assert (a, [1,2,3,4]');
-%! assert (i, [1,3,4,7]');
-%! assert (j, [1,1,2,3,3,3,4]');
-%!
+
 %!test
-%! [a,i,j] = unique ({"z"; "z"; "z"});
-%! assert (a, {"z"});
-%! assert (i, [3]');
-%! assert (j, [1;1;1]);
-%!
-%!test
-%! A = [1,2,3;1,2,3];
-%! [a,i,j] = unique (A, "rows");
-%! assert (a, [1,2,3]);
-%! assert (A(i,:), a);
-%! assert (a(j,:), A);
+%! A = [7 9 7; 0 0 0; 7 9 7; 5 5 5; 1 4 5];
+%! [y,i,j] = unique (A, "rows", "legacy");
+%! assert (y, [0 0 0; 1 4 5; 5 5 5; 7 9 7]);
+%! assert (i, [2; 5; 4; 3]);
+%! assert (j, [4; 1; 4; 3; 2]);
 
 ## Test input validation
 %!error unique ()
--- a/scripts/signal/detrend.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/signal/detrend.m	Fri Jul 12 12:14:43 2019 -0400
@@ -39,30 +39,33 @@
 
 function y = detrend (x, p = 1)
 
-  if (nargin > 0 && isreal (x) && ndims (x) <= 2)
-    ## Check p
-    if (ischar (p) && strcmpi (p, "constant"))
-      p = 0;
-    elseif (ischar (p) && strcmpi (p, "linear"))
-      p = 1;
-    elseif (! isscalar (p) || p < 0 || p != fix (p))
-      error ("detrend: second input argument must be 'constant', 'linear' or a positive integer");
-    endif
-  else
-    error ("detrend: first input argument must be a real vector or matrix");
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (! isnumeric (x) || ndims (x) > 2)
+    error ("detrend: X must be a numeric vector or matrix");
+  endif
+
+  if (ischar (p) && strcmpi (p, "constant"))
+    p = 0;
+  elseif (ischar (p) && strcmpi (p, "linear"))
+    p = 1;
+  elseif (! isscalar (p) || p < 0 || p != fix (p))
+    error ("detrend: P must be \"constant\", \"linear\", or a positive integer");
   endif
 
   [m, n] = size (x);
   if (m == 1)
-    x = x';
+    x = x.';
   endif
 
   r = rows (x);
-  b = ((1 : r)' * ones (1, p + 1)) .^ (ones (r, 1) * (0 : p));
+  b = ((1 : r).' * ones (1, p + 1)) .^ (ones (r, 1) * (0 : p));
   y = x - b * (b \ x);
 
   if (m == 1)
-    y = y';
+    y = y.';
   endif
 
 endfunction
@@ -84,6 +87,22 @@
 %!test
 %! N = 32;
 %! t = (0:1:N-1)/N;
-%! x = [t;4*t-3]';
+%! x = [t;4*t-3].';
+%! y = detrend (x);
+%! assert (abs (y(:)) < 20*eps);
+
+%!test
+%! N = 32;
+%! x = ((0:1:N-1)/N + 2) * 1i;
 %! y = detrend (x);
 %! assert (abs (y(:)) < 20*eps);
+
+## Test input validation
+%!error detrend ()
+%!error detrend (1, 2, 3)
+%!error detrend ("a")
+%!error detrend (true)
+%!error detrend (1, "invalid")
+%!error detrend (1, -1)
+%!error detrend (1, 1.25)
+
--- a/scripts/specfun/betainc.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/specfun/betainc.m	Fri Jul 12 12:14:43 2019 -0400
@@ -194,14 +194,14 @@
 %! assert (v1, v2, sqrt (eps ("single")));
 %! assert (v3, v4, sqrt (eps ("single")));
 
-%!test <51157>
+%!test <*51157>
 %! y = betainc ([0.00780;0.00782;0.00784],250.005,49750.995);
 %! y_ex = [0.999999999999989; 0.999999999999992; 0.999999999999995];
 %! assert (y, y_ex, -1e-14);
 
 %!assert (betainc (0.001, 20, 30), 2.750687665855991e-47, -3e-14);
 %!assert (betainc (0.0001, 20, 30), 2.819953178893307e-67, -7e-14);
-%!assert <54383> (betainc (0.99, 20, 30, "upper"), 1.5671643161872703e-47, -7e-14);
+%!assert <*54383> (betainc (0.99, 20, 30, "upper"), 1.5671643161872703e-47, -7e-14);
 %!assert (betainc (0.999, 20, 30, "upper"), 1.850806276141535e-77, -7e-14);
 %!assert (betainc (0.5, 200, 300), 0.9999964565197356, -1e-15);
 %!assert (betainc (0.5, 200, 300, "upper"), 3.54348026439253e-06, -3e-13);
@@ -212,7 +212,7 @@
 %! assert (betainc (0, a, b), zeros (20));
 %! assert (betainc (1, a, b), ones (20));
 
-%!test <34405>
+%!test <*34405>
 %! assert (betainc (NaN, 1, 2), NaN);
 %! assert (betainc (0.5, 1, Inf), NaN);
 
--- a/scripts/specfun/expint.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/specfun/expint.m	Fri Jul 12 12:14:43 2019 -0400
@@ -240,13 +240,13 @@
 %! y = expint (x);
 %! assert (y, y_exp, 5*eps);
 
-%!test <53351>
+%!test <*53351>
 %! assert (expint (32.5 + 1i),
 %!         1.181108930758065e-16 - 1.966348533426658e-16i, -4*eps);
 %! assert (expint (44 + 1i),
 %!         9.018757389858152e-22 - 1.475771020004195e-21i, -4*eps);
 
-%!test <47738>
+%!test <*47738>
 %! assert (expint (10i), 0.0454564330044554 + 0.0875512674239774i, -4*eps);
 
 ## Test preservation or conversion of the class
--- a/scripts/specfun/gammainc.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/specfun/gammainc.m	Fri Jul 12 12:14:43 2019 -0400
@@ -484,7 +484,7 @@
 %!assert (gammainc (709, 1000, "upper"), 0.99999999999999999999999954358, -eps)
 
 ## Test: case 9
-%!test <47800>
+%!test <*47800>
 %! assert (gammainc (60, 6, "upper"), 6.18022358081160257327264261e-20,
 %!         -10*eps);
 ## Matlab is better here than Octave
--- a/scripts/specfun/legendre.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/specfun/legendre.m	Fri Jul 12 12:14:43 2019 -0400
@@ -196,9 +196,9 @@
 
   ## Based on the recurrence relation below
   ##            m                 m              m
-  ## (n-m+1) * P (x) = (2*n+1)*x*P (x)  - (n+1)*P (x)
+  ## (n-m+1) * P (x) = (2*n+1)*x*P (x)  - (n+m)*P (x)
   ##            n+1               n              n-1
-  ## http://en.wikipedia.org/wiki/Associated_Legendre_function
+  ## https://en.wikipedia.org/wiki/Associated_Legendre_polynomials
 
   overflow = false;
   retval = zeros ([n+1, size(x)]);
--- a/scripts/specfun/perms.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/specfun/perms.m	Fri Jul 12 12:14:43 2019 -0400
@@ -124,36 +124,36 @@
 ## Should work for any array type, such as cells and structs, and not
 ## only for numeric data.
 
-%!assert <52431> (perms ({1}), {1})
-%!assert <52431> (perms ({0.1, "foo"}), {"foo", 0.1; 0.1, "foo"})
-%!assert <52431> (perms ({"foo", 0.1}), {0.1, "foo"; "foo", 0.1})
-%!assert <52431> (perms ({"foo"; 0.1}), {0.1, "foo"; "foo", 0.1})
-%!assert <52431> (perms ({0.1; "foo"}), {"foo", 0.1; 0.1, "foo"})
-%!assert <52431> (perms ({"foo", "bar"}), {"bar", "foo"; "foo", "bar"})
-%!assert <52431> (perms ({"bar", "foo"}), {"foo", "bar"; "bar", "foo"})
+%!assert <*52431> (perms ({1}), {1})
+%!assert <*52431> (perms ({0.1, "foo"}), {"foo", 0.1; 0.1, "foo"})
+%!assert <*52431> (perms ({"foo", 0.1}), {0.1, "foo"; "foo", 0.1})
+%!assert <*52431> (perms ({"foo"; 0.1}), {0.1, "foo"; "foo", 0.1})
+%!assert <*52431> (perms ({0.1; "foo"}), {"foo", 0.1; 0.1, "foo"})
+%!assert <*52431> (perms ({"foo", "bar"}), {"bar", "foo"; "foo", "bar"})
+%!assert <*52431> (perms ({"bar", "foo"}), {"foo", "bar"; "bar", "foo"})
 %!
-%!assert <52431> (perms (struct ()), struct ())
-%!assert <52431> (perms (struct ("foo", {1, 2})),
+%!assert <*52431> (perms (struct ()), struct ())
+%!assert <*52431> (perms (struct ("foo", {1, 2})),
 %!                struct ("foo", {2, 1; 1, 2}))
-%!assert <52431> (perms (struct ("foo", {1, 2}, "bar", {3, 4})),
+%!assert <*52431> (perms (struct ("foo", {1, 2}, "bar", {3, 4})),
 %!                struct ("foo", {2, 1; 1, 2}, "bar", {4, 3; 3, 4}))
 
 ## Also sort logical input with order dependent on the input order and
 ## not their values.
 
-%!assert <52431> (perms (logical ([1 0])), logical ([0 1;, 1 0]))
-%!assert <52431> (perms (logical ([0 1])), logical ([1 0; 0 1]))
-%!assert <52431> (perms (logical ([0 1 0])),
+%!assert <*52431> (perms (logical ([1 0])), logical ([0 1;, 1 0]))
+%!assert <*52431> (perms (logical ([0 1])), logical ([1 0; 0 1]))
+%!assert <*52431> (perms (logical ([0 1 0])),
 %!                logical ([0 1 0; 0 0 1; 1 0 0; 1 0 0; 0 0 1; 0 1 0]))
-%!assert <52431> (perms (logical ([0 1 1])),
+%!assert <*52431> (perms (logical ([0 1 1])),
 %!                logical ([1 1 0; 1 0 1; 1 1 0; 1 0 1; 0 1 1; 0 1 1]))
 
-%!assert <52432> (perms ([]), reshape ([], 1, 0))
-%!assert <52432> (perms (single ([])), reshape (single ([]), 1, 0))
-%!assert <52432> (perms (int8 ([])), reshape (int8 ([]), 1, 0))
-%!assert <52432> (perms ({}), cell (1, 0))
+%!assert <*52432> (perms ([]), reshape ([], 1, 0))
+%!assert <*52432> (perms (single ([])), reshape (single ([]), 1, 0))
+%!assert <*52432> (perms (int8 ([])), reshape (int8 ([]), 1, 0))
+%!assert <*52432> (perms ({}), cell (1, 0))
 
-%!test <52432>
+%!test <*52432>
 %! s = struct ();
 %! s(1) = [];
 %! assert (perms (reshape (s, 0, 0)), reshape (s, 1, 0))
--- a/scripts/special-matrix/gallery.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/special-matrix/gallery.m	Fri Jul 12 12:14:43 2019 -0400
@@ -69,7 +69,7 @@
 ## @deftypefn  {} {@var{a} =} gallery ("condex", @var{n})
 ## @deftypefnx {} {@var{a} =} gallery ("condex", @var{n}, @var{k})
 ## @deftypefnx {} {@var{a} =} gallery ("condex", @var{n}, @var{k}, @var{theta})
-## Create a `counterexample' matrix to a condition estimator.
+## Create a 'counterexample' matrix to a condition estimator.
 ##
 ## @end deftypefn
 ##
@@ -335,7 +335,7 @@
 ##
 ## @deftypefn  {} {@var{a} =} gallery ("smoke", @var{n})
 ## @deftypefnx {} {@var{a} =} gallery ("smoke", @var{n}, @var{k})
-## Create a complex matrix, with a `smoke ring' pseudospectrum.
+## Create a complex matrix, with a 'smoke ring' pseudospectrum.
 ##
 ## @end deftypefn
 ##
@@ -563,7 +563,7 @@
   ## CHEBSPEC  Chebyshev spectral differentiation matrix.
   ##   C = CHEBSPEC(N, K) is a Chebyshev spectral differentiation
   ##   matrix of order N.  K = 0 (the default) or 1.
-  ##   For K = 0 (`no boundary conditions'), C is nilpotent, with
+  ##   For K = 0 ('no boundary conditions'), C is nilpotent, with
   ##       C^N = 0 and it has the null vector ONES(N,1).
   ##       C is similar to a Jordan block of size N with eigenvalue zero.
   ##   For K = 1, C is nonsingular and well-conditioned, and its eigenvalues
@@ -711,7 +711,7 @@
   ##   (A circulant matrix has the property that each row is obtained
   ##   from the previous one by cyclically permuting the entries one step
   ##   forward; it is a special Toeplitz matrix in which the diagonals
-  ##   `wrap round'.)
+  ##   'wrap round'.)
   ##   Special case: if V is a scalar then C = CIRCUL(1:V).
   ##   The eigensystem of C (N-by-N) is known explicitly.   If t is an Nth
   ##   root of unity, then the inner product of V with W = [1 t t^2 ... t^N]
@@ -814,7 +814,7 @@
 
   if (k == 0)
     ## This code uses less temporary storage than
-    ## the `high level' definition above.
+    ## the 'high level' definition above.
     C = -abs (A);
     for j = 1:p
       C(j,j) = abs (A(j,j));
@@ -840,10 +840,10 @@
 endfunction
 
 function A = condex (n, k = 4, theta = 100)
-  ## CONDEX   `Counterexamples' to matrix condition number estimators.
-  ##   CONDEX(N, K, THETA) is a `counterexample' matrix to a condition
+  ## CONDEX   'Counterexamples' to matrix condition number estimators.
+  ##   CONDEX(N, K, THETA) is a 'counterexample' matrix to a condition
   ##   estimator.  It has order N and scalar parameter THETA (default 100).
-  ##   If N is not equal to the `natural' size of the matrix then
+  ##   If N is not equal to the 'natural' size of the matrix then
   ##   the matrix is padded out with an identity matrix to order N.
   ##   The matrix, its natural size, and the estimator to which it applies
   ##   are specified by K (default K = 4) as follows:
@@ -2291,7 +2291,7 @@
   ##   a new proof of the prime number theorem.
   ##   The Riemann hypothesis is true if and only if
   ##   DET(A) = O( N^(1/2+epsilon) ) for every epsilon > 0
-  ##                                     (`!' denotes factorial).
+  ##                                     ('!' denotes factorial).
   ##   See also RIEMANN.
   ##
   ##   Reference:
@@ -2315,7 +2315,7 @@
   ##   A = RIEMANN(N) is an N-by-N matrix for which the
   ##   Riemann hypothesis is true if and only if
   ##   DET(A) = O( N! N^(-1/2+epsilon) ) for every epsilon > 0
-  ##                                     (`!' denotes factorial).
+  ##                                     ('!' denotes factorial).
   ##   A = B(2:N+1, 2:N+1), where
   ##   B(i,j) = i-1 if i divides j and -1 otherwise.
   ##   Properties include, with M = N+1:
@@ -2366,7 +2366,7 @@
 endfunction
 
 function A = smoke (n, k = 0)
-  ## SMOKE     Smoke matrix - complex, with a `smoke ring' pseudospectrum.
+  ## SMOKE     Smoke matrix - complex, with a 'smoke ring' pseudospectrum.
   ##   SMOKE(N) is an N-by-N matrix with 1s on the
   ##   superdiagonal, 1 in the (N,1) position, and powers of
   ##   roots of unity along the diagonal.
@@ -2446,9 +2446,9 @@
   ##             the line segment 2*cos(2*t) + 20*i*sin(t).
   ##
   ##   Interesting plots are
-  ##   PS(FULL(TOEPPEN(32,0,1,0,0,1/4)))  - `triangle'
-  ##   PS(FULL(TOEPPEN(32,0,1/2,0,0,1)))  - `propeller'
-  ##   PS(FULL(TOEPPEN(32,0,1/2,1,1,1)))  - `fish'
+  ##   PS(FULL(TOEPPEN(32,0,1,0,0,1/4)))  - 'triangle'
+  ##   PS(FULL(TOEPPEN(32,0,1/2,0,0,1)))  - 'propeller'
+  ##   PS(FULL(TOEPPEN(32,0,1/2,1,1,1)))  - 'fish'
   ##
   ##   References:
   ##   R.M. Beam and R.F. Warming, The asymptotic spectra of
@@ -2810,7 +2810,7 @@
   ##   If KU is omitted it defaults to KL.
   ##
   ##   Called by RANDSVD.
-  ##   This is a `standard' reduction.  Cf. reduction to bidiagonal form
+  ##   This is a 'standard' reduction.  Cf. reduction to bidiagonal form
   ##   prior to computing the SVD.  This code is a little wasteful in that
   ##   it computes certain elements which are immediately set to zero!
   ##
--- a/scripts/startup/__finish__.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/startup/__finish__.m	Fri Jul 12 12:14:43 2019 -0400
@@ -29,7 +29,7 @@
 
 function __finish__ ()
 
-  if (exist ("finish", "file"))
+  if (exist ("finish.m", "file"))
     ## Must use evalin for access to base workspace and user variables.
     ## No argument list for finish because it might be a script, not function.
     evalin ("base", "finish;");
--- a/scripts/startup/version-rcfile	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/startup/version-rcfile	Fri Jul 12 12:14:43 2019 -0400
@@ -25,11 +25,3 @@
 if (strcmp (PAGER (), "less") && isempty (getenv ("LESS")))
   PAGER_FLAGS ('-e -X -P"-- less ?pB(%pB\\%):--. (f)orward, (b)ack, (q)uit$"');
 endif
-
-## For Matlab compatibility, run startup.m when starting Octave.
-if (exist ("startup.m", "file") == 2)
-  startup;  # No arg list here since startup might be a script.
-endif
-
-## For Matlab compatibility, schedule finish.m to run when exiting Octave.
-atexit ("__finish__");
--- a/scripts/statistics/kurtosis.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/kurtosis.m	Fri Jul 12 12:14:43 2019 -0400
@@ -153,9 +153,8 @@
 %!assert (kurtosis (single ([1:5 10])), single (2.9786513), eps ("single"))
 %!assert (kurtosis (single ([1 2]), 0), single (NaN))
 
-## Verify no "divide-by-zero" warnings
+## Verify no warnings
 %!test
-%! warning ("on", "Octave:divide-by-zero", "local");
 %! lastwarn ("");  # clear last warning
 %! kurtosis (1);
 %! assert (lastwarn (), "");
--- a/scripts/statistics/mean.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/mean.m	Fri Jul 12 12:14:43 2019 -0400
@@ -142,10 +142,6 @@
       print_usage ();
   endswitch
 
-  ## FIXME: Delete this when the "divide-by-zero" warning is
-  ##        removed in Octave 6.0.
-  warning ("off", "Octave:divide-by-zero", "local");
-
   ## The actual mean computation
   n = size (x, dim);
   switch (mean_type)
--- a/scripts/statistics/movmax.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/movmax.m	Fri Jul 12 12:14:43 2019 -0400
@@ -127,7 +127,8 @@
     print_usage ();
   endif
 
-  y = movfun (@max, x, wlen, __parse_movargs__ ("movmax", varargin{:}){:});
+  y = movfun (@max, x, wlen, "Endpoints", -Inf,
+              __parse_movargs__ ("movmax", varargin{:}){:});
 
 endfunction
 
--- a/scripts/statistics/movmin.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/movmin.m	Fri Jul 12 12:14:43 2019 -0400
@@ -127,7 +127,8 @@
     print_usage ();
   endif
 
-  y = movfun (@min, x, wlen, __parse_movargs__ ("movmin", varargin{:}){:});
+  y = movfun (@min, x, wlen, "Endpoints", Inf,
+              __parse_movargs__ ("movmin", varargin{:}){:});
 
 endfunction
 
--- a/scripts/statistics/movprod.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/movprod.m	Fri Jul 12 12:14:43 2019 -0400
@@ -127,7 +127,8 @@
     print_usage ();
   endif
 
-  y = movfun (@prod, x, wlen, __parse_movargs__ ("movprod", varargin{:}){:});
+  y = movfun (@prod, x, wlen, "Endpoints", 1,
+              __parse_movargs__ ("movprod", varargin{:}){:});
 
 endfunction
 
--- a/scripts/statistics/movsum.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/movsum.m	Fri Jul 12 12:14:43 2019 -0400
@@ -127,7 +127,8 @@
     print_usage ();
   endif
 
-  y = movfun (@sum, x, wlen, __parse_movargs__ ("movsum", varargin{:}){:});
+  y = movfun (@sum, x, wlen, "Endpoints", 0,
+              __parse_movargs__ ("movsum", varargin{:}){:});
 
 endfunction
 
--- a/scripts/statistics/quantile.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/quantile.m	Fri Jul 12 12:14:43 2019 -0400
@@ -406,7 +406,7 @@
 function inv = __quantile__ (x, p, method = 5)
 
   if (nargin < 2 || nargin > 3)
-    print_usage ();
+    print_usage ("quantile");
   endif
 
   if (isinteger (x) || islogical (x))
--- a/scripts/statistics/skewness.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/statistics/skewness.m	Fri Jul 12 12:14:43 2019 -0400
@@ -152,9 +152,8 @@
 %!assert (skewness (single ([1:5 10])), single (1.0513283), eps ("single"))
 %!assert (skewness (single ([1 2]), 0), single (NaN))
 
-## Verify no "divide-by-zero" warnings
+## Verify no warnings
 %!test
-%! warning ("on", "Octave:divide-by-zero", "local");
 %! lastwarn ("");  # clear last warning
 %! skewness (1);
 %! assert (lastwarn (), "");
--- a/scripts/strings/native2unicode.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/strings/native2unicode.m	Fri Jul 12 12:14:43 2019 -0400
@@ -82,7 +82,7 @@
 %!         [208 132 208 133 208 134 0 208 135 208 136 208 137 208 138]);
 
 %!assert (native2unicode ("foobar"), "foobar");
-%!assert <54384> (double (native2unicode ([0 0 120.3 0 0 122.6 0 0])),
+%!assert <*54384> (double (native2unicode ([0 0 120.3 0 0 122.6 0 0])),
 %!        [0 0 120 0 0 123 0 0]);
 
 %!error <Invalid call> native2unicode ()
--- a/scripts/strings/str2num.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/strings/str2num.m	Fri Jul 12 12:14:43 2019 -0400
@@ -59,7 +59,14 @@
   s(:, end+1) = ";";
   s = sprintf ("m = [%s];", reshape (s', 1, numel (s)));
   state = true;
-  eval (s, "m = []; state = false;");
+  ## Swallow any errors from eval (bug #55939).
+  try
+    eval (s);
+  catch
+    m = [];
+    state = false;
+  end_try_catch
+
   if (ischar (m))
     m = [];
     state = false;
--- a/scripts/strings/strjoin.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/strings/strjoin.m	Fri Jul 12 12:14:43 2019 -0400
@@ -71,7 +71,7 @@
     delimiter = repmat (delimiter, 1, num);
     delimiter(end) = {""};
   elseif (num > 0 && numel (delimiter) != num - 1)
-    error ("strjoin:cellstring_delimiter_mismatch",
+    error ("Octave:strjoin:cellstring_delimiter_mismatch",
       "strjoin: the number of delimiters does not match the number of strings");
   else
     delimiter(end+1) = {""};
--- a/scripts/strings/strsplit.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/strings/strsplit.m	Fri Jul 12 12:14:43 2019 -0400
@@ -154,7 +154,7 @@
     if (any (strcmpi (params{n}, fields)))
       args.(tolower (params{n})) = params{n+1};
     elseif (ischar (varargin{n}))
-      error ("strsplit:invalid_parameter_name",
+      error ("Octave:strsplit:invalid_parameter_name",
              "strsplit: invalid parameter name, '%s'", varargin{n});
     else
       print_usage ();
@@ -190,7 +190,7 @@
   elseif (strncmpi (args.delimitertype, "regularexpression", length_deltype))
     is_simple = false;
   else
-    error ("strsplit:invalid_delimitertype", "strsplit: Invalid DELIMITERTYPE");
+    error ("Octave:strsplit:invalid_delimitertype", "strsplit: Invalid DELIMITERTYPE");
   endif
 
   if (is_simple)
--- a/scripts/testfun/assert.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/testfun/assert.m	Fri Jul 12 12:14:43 2019 -0400
@@ -225,7 +225,7 @@
             err.observed{end+1} = "O";
             err.expected{end+1} = "E";
             err.reason{end+1} = ["Class " class(cond) " != " class(expected)];
-          elseif (isnumeric (cond))
+          elseif (isnumeric (cond) || islogical (cond))
             if (issparse (cond) != issparse (expected))
               err.index{end+1} = "()";
               err.observed{end+1} = "O";
--- a/scripts/testfun/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/testfun/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -16,7 +16,7 @@
   %reldir%/example.m \
   %reldir%/fail.m \
   %reldir%/rundemos.m \
-  %reldir%/runtests.m \
+  %reldir%/oruntests.m \
   %reldir%/speed.m \
   %reldir%/test.m
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/oruntests.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,176 @@
+## Copyright (C) 2010-2019 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  {} {} oruntests ()
+## @deftypefnx {} {} oruntests (@var{directory})
+## Execute built-in tests for all m-files in the specified @var{directory}.
+##
+## Test blocks in any C++ source files (@file{*.cc}) will also be executed
+## for use with dynamically linked oct-file functions.
+##
+## If no directory is specified, operate on all directories in Octave's search
+## path for functions.
+## @seealso{rundemos, test, path}
+## @end deftypefn
+
+## Author: jwe
+
+function oruntests (directory)
+
+  if (nargin == 0)
+    dirs = ostrsplit (path (), pathsep ());
+    do_class_dirs = true;
+  elseif (nargin == 1)
+    dirs = {canonicalize_file_name(directory)};
+    if (isempty (dirs{1}) || ! isfolder (dirs{1}))
+      ## Search for directory name in path
+      if (directory(end) == '/' || directory(end) == '\')
+        directory(end) = [];
+      endif
+      fullname = dir_in_loadpath (directory);
+      if (isempty (fullname))
+        error ("oruntests: DIRECTORY argument must be a valid pathname");
+      endif
+      dirs = {fullname};
+    endif
+    do_class_dirs = false;
+  else
+    print_usage ();
+  endif
+
+  for i = 1:numel (dirs)
+    d = dirs{i};
+    run_all_tests (d, do_class_dirs);
+  endfor
+
+endfunction
+
+function run_all_tests (directory, do_class_dirs)
+
+  flist = readdir (directory);
+  dirs = {};
+  no_tests = {};
+  printf ("Processing files in %s:\n\n", directory);
+  fflush (stdout);
+  for i = 1:numel (flist)
+    f = flist{i};
+    if ((length (f) > 2 && strcmpi (f((end-1):end), ".m"))
+        || (length (f) > 3 && strcmpi (f((end-2):end), ".cc")))
+      ff = fullfile (directory, f);
+      if (has_tests (ff))
+        print_test_file_name (f);
+        [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet");
+        print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
+        fflush (stdout);
+      elseif (has_functions (ff))
+        no_tests(end+1) = f;
+      endif
+    elseif (f(1) == "@")
+      f = fullfile (directory, f);
+      if (isfolder (f))
+        dirs(end+1) = f;
+      endif
+    endif
+  endfor
+  if (! isempty (no_tests))
+    printf ("\nThe following files in %s have no tests:\n\n", directory);
+    printf ("%s", list_in_columns (no_tests));
+  endif
+
+  ## Recurse into class directories since they are implied in the path
+  if (do_class_dirs)
+    for i = 1:numel (dirs)
+      d = dirs{i};
+      run_all_tests (d, false);
+    endfor
+  endif
+
+endfunction
+
+function retval = has_functions (f)
+
+  n = length (f);
+  if (n > 3 && strcmpi (f((end-2):end), ".cc"))
+    fid = fopen (f);
+    if (fid < 0)
+      error ("oruntests: fopen failed: %s", f);
+    endif
+    str = fread (fid, "*char")';
+    fclose (fid);
+    retval = ! isempty (regexp (str,'^(?:DEFUN|DEFUN_DLD|DEFUNX)\>',
+                                    'lineanchors', 'once'));
+  elseif (n > 2 && strcmpi (f((end-1):end), ".m"))
+    retval = true;
+  else
+    retval = false;
+  endif
+
+endfunction
+
+function retval = has_tests (f)
+
+  fid = fopen (f);
+  if (fid < 0)
+    error ("oruntests: fopen failed: %s", f);
+  endif
+
+  str = fread (fid, "*char").';
+  fclose (fid);
+  retval = ! isempty (regexp (str,
+                              '^%!(assert|error|fail|test|xtest|warning)',
+                              'lineanchors', 'once'));
+
+endfunction
+
+function print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs)
+
+  if ((n + sk + rtsk + rgrs) > 0)
+    printf (" PASS   %4d/%-4d", p, n);
+    nfail = n - p - xf - xb - rgrs;
+    if (nfail > 0)
+      printf ("\n%71s %3d", "FAIL ", nfail);
+    endif
+    if (rgrs > 0)
+      printf ("\n%71s %3d", "REGRESSION", rgrs);
+    endif
+    if (xb > 0)
+      printf ("\n%71s %3d", "(reported bug) XFAIL", xb);
+    endif
+    if (xf > 0)
+      printf ("\n%71s %3d", "(expected failure) XFAIL", xf);
+    endif
+    if (sk > 0)
+      printf ("\n%71s %3d", "(missing feature) SKIP", sk);
+    endif
+    if (rtsk > 0)
+      printf ("\n%71s %3d", "(run-time condition) SKIP", rtsk);
+    endif
+  endif
+  puts ("\n");
+
+endfunction
+
+function print_test_file_name (nm)
+  filler = repmat (".", 1, 60-length (nm));
+  printf ("  %s %s", nm, filler);
+endfunction
+
+
+%!error oruntests ("foo", 1)
+%!error <DIRECTORY argument> oruntests ("#_TOTALLY_/_INVALID_/_PATHNAME_#")
--- a/scripts/testfun/private/dump_demos.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/testfun/private/dump_demos.m	Fri Jul 12 12:14:43 2019 -0400
@@ -76,13 +76,79 @@
   fprintf (fid, "%% DO NOT EDIT!  Generated automatically by dump_demos.m\n");
   fprintf (fid, "function %s ()\n", funcname);
   fprintf (fid, "set (0, 'DefaultAxesColorOrder', ...\n");
-  fprintf (fid, "  [ 0.00000   0.00000   1.00000 ;\n");
-  fprintf (fid, "    0.00000   0.50000   0.00000 ;\n");
-  fprintf (fid, "    1.00000   0.00000   0.00000 ;\n");
-  fprintf (fid, "    0.00000   0.75000   0.75000 ;\n");
-  fprintf (fid, "    0.75000   0.00000   0.75000 ;\n");
-  fprintf (fid, "    0.75000   0.75000   0.00000 ;\n");
-  fprintf (fid, "    0.25000   0.25000   0.25000 ]);\n");
+  fprintf (fid, "  [ 0.00000   0.44700   0.74100 ;\n");
+  fprintf (fid, "    0.85000   0.32500   0.09800 ;\n");
+  fprintf (fid, "    0.92900   0.69400   0.12500 ;\n");
+  fprintf (fid, "    0.49400   0.18400   0.55600 ;\n");
+  fprintf (fid, "    0.46600   0.67400   0.18800 ;\n");
+  fprintf (fid, "    0.30100   0.74500   0.93300 ;\n");
+  fprintf (fid, "    0.63500   0.07800   0.18400 ]);\n");
+  fprintf (fid, "set (0, 'DefaultFigureColorMap', ...\n");
+  fprintf (fid, "  [ 0.2670040   0.0048743   0.3294152 ;\n");
+  fprintf (fid, "    0.2726517   0.0258457   0.3533673 ;\n");
+  fprintf (fid, "    0.2771063   0.0509139   0.3762361 ;\n");
+  fprintf (fid, "    0.2803562   0.0742015   0.3979015 ;\n");
+  fprintf (fid, "    0.2823900   0.0959536   0.4182508 ;\n");
+  fprintf (fid, "    0.2832046   0.1168933   0.4371789 ;\n");
+  fprintf (fid, "    0.2828093   0.1373502   0.4545959 ;\n");
+  fprintf (fid, "    0.2812308   0.1574799   0.4704339 ;\n");
+  fprintf (fid, "    0.2785162   0.1773480   0.4846539 ;\n");
+  fprintf (fid, "    0.2747355   0.1969692   0.4972505 ;\n");
+  fprintf (fid, "    0.2699818   0.2163303   0.5082545 ;\n");
+  fprintf (fid, "    0.2643686   0.2354047   0.5177319 ;\n");
+  fprintf (fid, "    0.2580262   0.2541617   0.5257802 ;\n");
+  fprintf (fid, "    0.2510987   0.2725732   0.5325222 ;\n");
+  fprintf (fid, "    0.2437329   0.2906195   0.5380971 ;\n");
+  fprintf (fid, "    0.2360733   0.3082910   0.5426518 ;\n");
+  fprintf (fid, "    0.2282632   0.3255865   0.5463354 ;\n");
+  fprintf (fid, "    0.2204250   0.3425172   0.5492871 ;\n");
+  fprintf (fid, "    0.2126666   0.3591022   0.5516350 ;\n");
+  fprintf (fid, "    0.2050791   0.3753661   0.5534932 ;\n");
+  fprintf (fid, "    0.1977219   0.3913409   0.5549535 ;\n");
+  fprintf (fid, "    0.1906314   0.4070615   0.5560891 ;\n");
+  fprintf (fid, "    0.1838194   0.4225638   0.5569522 ;\n");
+  fprintf (fid, "    0.1772724   0.4378855   0.5575761 ;\n");
+  fprintf (fid, "    0.1709575   0.4530630   0.5579740 ;\n");
+  fprintf (fid, "    0.1648329   0.4681295   0.5581427 ;\n");
+  fprintf (fid, "    0.1588454   0.4831171   0.5580587 ;\n");
+  fprintf (fid, "    0.1529512   0.4980530   0.5576847 ;\n");
+  fprintf (fid, "    0.1471316   0.5129595   0.5569733 ;\n");
+  fprintf (fid, "    0.1414022   0.5278543   0.5558645 ;\n");
+  fprintf (fid, "    0.1358330   0.5427501   0.5542887 ;\n");
+  fprintf (fid, "    0.1305821   0.5576525   0.5521757 ;\n");
+  fprintf (fid, "    0.1258984   0.5725631   0.5494454 ;\n");
+  fprintf (fid, "    0.1221631   0.5874763   0.5460234 ;\n");
+  fprintf (fid, "    0.1198724   0.6023824   0.5418306 ;\n");
+  fprintf (fid, "    0.1196266   0.6172658   0.5367956 ;\n");
+  fprintf (fid, "    0.1220459   0.6321070   0.5308480 ;\n");
+  fprintf (fid, "    0.1276677   0.6468818   0.5239242 ;\n");
+  fprintf (fid, "    0.1368349   0.6615629   0.5159668 ;\n");
+  fprintf (fid, "    0.1496433   0.6761197   0.5069243 ;\n");
+  fprintf (fid, "    0.1659673   0.6905190   0.4967519 ;\n");
+  fprintf (fid, "    0.1855384   0.7047252   0.4854121 ;\n");
+  fprintf (fid, "    0.2080305   0.7187010   0.4728733 ;\n");
+  fprintf (fid, "    0.2331273   0.7324064   0.4591059 ;\n");
+  fprintf (fid, "    0.2605315   0.7458020   0.4440959 ;\n");
+  fprintf (fid, "    0.2900007   0.7588465   0.4278259 ;\n");
+  fprintf (fid, "    0.3213300   0.7714979   0.4102927 ;\n");
+  fprintf (fid, "    0.3543553   0.7837140   0.3914876 ;\n");
+  fprintf (fid, "    0.3889303   0.7954531   0.3714207 ;\n");
+  fprintf (fid, "    0.4249331   0.8066739   0.3500988 ;\n");
+  fprintf (fid, "    0.4622468   0.8173376   0.3275447 ;\n");
+  fprintf (fid, "    0.5007536   0.8274091   0.3037990 ;\n");
+  fprintf (fid, "    0.5403370   0.8368582   0.2789167 ;\n");
+  fprintf (fid, "    0.5808612   0.8456634   0.2530009 ;\n");
+  fprintf (fid, "    0.6221708   0.8538156   0.2262237 ;\n");
+  fprintf (fid, "    0.6640873   0.8613210   0.1988794 ;\n");
+  fprintf (fid, "    0.7064038   0.8682063   0.1714949 ;\n");
+  fprintf (fid, "    0.7488853   0.8745222   0.1450376 ;\n");
+  fprintf (fid, "    0.7912731   0.8803462   0.1212910 ;\n");
+  fprintf (fid, "    0.8333021   0.8857801   0.1033262 ;\n");
+  fprintf (fid, "    0.8747175   0.8909453   0.0953508 ;\n");
+  fprintf (fid, "    0.9152963   0.8959735   0.1004700 ;\n");
+  fprintf (fid, "    0.9548396   0.9010058   0.1178764 ;\n");
+  fprintf (fid, "    0.9932479   0.9061566   0.1439362 ]);\n");
+
   fprintf (fid, "close all\n");
   fprintf (fid, "more off\n");
   fprintf (fid, "diary diary.log\n");
--- a/scripts/testfun/rundemos.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/testfun/rundemos.m	Fri Jul 12 12:14:43 2019 -0400
@@ -26,7 +26,7 @@
 ##
 ## If no directory is specified, operate on all directories in Octave's search
 ## path for functions.
-## @seealso{demo, runtests, path}
+## @seealso{demo, oruntests, path}
 ## @end deftypefn
 
 ## Author: jwe
--- a/scripts/testfun/runtests.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-## Copyright (C) 2010-2019 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  {} {} runtests ()
-## @deftypefnx {} {} runtests (@var{directory})
-## Execute built-in tests for all m-files in the specified @var{directory}.
-##
-## Test blocks in any C++ source files (@file{*.cc}) will also be executed
-## for use with dynamically linked oct-file functions.
-##
-## If no directory is specified, operate on all directories in Octave's search
-## path for functions.
-## @seealso{rundemos, test, path}
-## @end deftypefn
-
-## Author: jwe
-
-function runtests (directory)
-
-  if (nargin == 0)
-    dirs = ostrsplit (path (), pathsep ());
-    do_class_dirs = true;
-  elseif (nargin == 1)
-    dirs = {canonicalize_file_name(directory)};
-    if (isempty (dirs{1}) || ! isfolder (dirs{1}))
-      ## Search for directory name in path
-      if (directory(end) == '/' || directory(end) == '\')
-        directory(end) = [];
-      endif
-      fullname = dir_in_loadpath (directory);
-      if (isempty (fullname))
-        error ("runtests: DIRECTORY argument must be a valid pathname");
-      endif
-      dirs = {fullname};
-    endif
-    do_class_dirs = false;
-  else
-    print_usage ();
-  endif
-
-  for i = 1:numel (dirs)
-    d = dirs{i};
-    run_all_tests (d, do_class_dirs);
-  endfor
-
-endfunction
-
-function run_all_tests (directory, do_class_dirs)
-
-  flist = readdir (directory);
-  dirs = {};
-  no_tests = {};
-  printf ("Processing files in %s:\n\n", directory);
-  fflush (stdout);
-  for i = 1:numel (flist)
-    f = flist{i};
-    if ((length (f) > 2 && strcmpi (f((end-1):end), ".m"))
-        || (length (f) > 3 && strcmpi (f((end-2):end), ".cc")))
-      ff = fullfile (directory, f);
-      if (has_tests (ff))
-        print_test_file_name (f);
-        [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet");
-        print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
-        fflush (stdout);
-      elseif (has_functions (ff))
-        no_tests(end+1) = f;
-      endif
-    elseif (f(1) == "@")
-      f = fullfile (directory, f);
-      if (isfolder (f))
-        dirs(end+1) = f;
-      endif
-    endif
-  endfor
-  if (! isempty (no_tests))
-    printf ("\nThe following files in %s have no tests:\n\n", directory);
-    printf ("%s", list_in_columns (no_tests));
-  endif
-
-  ## Recurse into class directories since they are implied in the path
-  if (do_class_dirs)
-    for i = 1:numel (dirs)
-      d = dirs{i};
-      run_all_tests (d, false);
-    endfor
-  endif
-
-endfunction
-
-function retval = has_functions (f)
-
-  n = length (f);
-  if (n > 3 && strcmpi (f((end-2):end), ".cc"))
-    fid = fopen (f);
-    if (fid < 0)
-      error ("runtests: fopen failed: %s", f);
-    endif
-    str = fread (fid, "*char")';
-    fclose (fid);
-    retval = ! isempty (regexp (str,'^(?:DEFUN|DEFUN_DLD|DEFUNX)\>',
-                                    'lineanchors', 'once'));
-  elseif (n > 2 && strcmpi (f((end-1):end), ".m"))
-    retval = true;
-  else
-    retval = false;
-  endif
-
-endfunction
-
-function retval = has_tests (f)
-
-  fid = fopen (f);
-  if (fid < 0)
-    error ("runtests: fopen failed: %s", f);
-  endif
-
-  str = fread (fid, "*char").';
-  fclose (fid);
-  retval = ! isempty (regexp (str,
-                              '^%!(assert|error|fail|test|xtest|warning)',
-                              'lineanchors', 'once'));
-
-endfunction
-
-function print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs)
-
-  if ((n + sk + rtsk + rgrs) > 0)
-    printf (" PASS   %4d/%-4d", p, n);
-    nfail = n - p - xf - xb - rgrs;
-    if (nfail > 0)
-      printf ("\n%71s %3d", "FAIL ", nfail);
-    endif
-    if (rgrs > 0)
-      printf ("\n%71s %3d", "REGRESSION", rgrs);
-    endif
-    if (xb > 0)
-      printf ("\n%71s %3d", "(reported bug) XFAIL", xb);
-    endif
-    if (xf > 0)
-      printf ("\n%71s %3d", "(expected failure) XFAIL", xf);
-    endif
-    if (sk > 0)
-      printf ("\n%71s %3d", "(missing feature) SKIP", sk);
-    endif
-    if (rtsk > 0)
-      printf ("\n%71s %3d", "(run-time condition) SKIP", rtsk);
-    endif
-  endif
-  puts ("\n");
-
-endfunction
-
-function print_test_file_name (nm)
-  filler = repmat (".", 1, 60-length (nm));
-  printf ("  %s %s", nm, filler);
-endfunction
-
-
-%!error runtests ("foo", 1)
-%!error <DIRECTORY argument> runtests ("#_TOTALLY_/_INVALID_/_PATHNAME_#")
--- a/scripts/testfun/test.m	Wed Jul 10 20:02:44 2019 -0700
+++ b/scripts/testfun/test.m	Fri Jul 12 12:14:43 2019 -0400
@@ -741,7 +741,7 @@
   endfor
 
   ## Clear any functions created during test run.
-  eval (__clearfcn, "");
+  __clear_functions = onCleanup (@() eval (__clearfcn, ""));
 
   ## Verify test file did not leak file descriptors.
   if (! isempty (setdiff (fopen ("all"), __fid_list_orig)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/web/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,17 @@
+FCN_FILE_DIRS += scripts/web
+
+%canon_reldir%_FCN_FILES = \
+  %reldir%/web.m \
+  %reldir%/weboptions.m \
+  %reldir%/webread.m \
+  %reldir%/webwrite.m
+
+%canon_reldir%dir = $(fcnfiledir)/web
+
+%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)
+
+FCN_FILES += $(%canon_reldir%_FCN_FILES)
+
+PKG_ADD_FILES += %reldir%/PKG_ADD
+
+DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/web/web.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,116 @@
+## Copyright (C) 2017-2019 Kai T. Ohlhus <k.ohlhus@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{status} =} web ()
+## @deftypefnx {} {@var{status} =} web (@var{url})
+## @deftypefnx {} {@var{status} =} web (@var{url}, @var{option})
+## @deftypefnx {} {@var{status} =} web (@var{url}, @var{option_1}, @dots{}, @var{option_N})
+## @deftypefnx {} {[@var{status}, @var{h}, @var{url}] =} web (@dots{})
+##
+## Open @var{url} in the default system web browser.
+##
+## With no arguments given, the address @url{https://www.octave.org} is
+## opened.
+##
+## Additional options can be passed for @sc{matlab} compatibility, but are
+## ignored.
+##
+## @itemize @bullet
+## @item
+## @samp{-browser} Open @var{url} in the default system browser.
+##
+## @item
+## @samp{-new} No effect on the system browser.
+##
+## @item
+## @samp{-noaddressbox} No effect on the system browser.
+##
+## @item
+## @samp{-notoolbar} No effect on the system browser.
+##
+## @end itemize
+##
+## The return value @var{status} has one of the values:
+##
+## @itemize @bullet
+## @item
+## @samp{0} Found and opened system browser successfully.
+##
+## @item
+## @samp{1} Cannot find the system browser.
+##
+## @item
+## @samp{2} System browser found, but an error occurred.
+##
+## @end itemize
+##
+## The return values @var{handle} and @var{url} are currently unimplemented
+## but given for compatibility.
+##
+## @seealso{weboptions, webread, webwrite, websave, urlread, urlwrite}
+## @end deftypefn
+
+function [status, h, url] = web (url, varargin)
+
+  if (nargin == 0)
+    url = "https://www.octave.org";
+  endif
+
+  if (! (ischar (url) && isrow (url)))
+    error ("web: URL must be a string");
+  endif
+
+  for i = 1:numel (varargin)
+    validatestring (varargin{i},
+                    {"-browser", "-new", "-noaddressbox", "-notoolbar"});
+  endfor
+
+  ## Store text after "text://" to a temporary file and open it.
+  if (strncmpi (url, "text://", 7))
+    fname = [tempname() ".html"];
+    fid = fopen (fname, "w");
+    if (fid < 0)
+      error ("web: could not open temporary file for text:// content");
+    endif
+    fprintf (fid, "%s", url(8:end));
+    fclose (fid);
+    url = ["file://" fname];
+  endif
+
+  sts = __open_with_system_app__ (url);
+  sts = ifelse (sts == 1, 0, 2);
+
+  h = [];  # Empty handle, as we cannot control an external browser.
+
+  ## For Matlab compatibility.
+  if (any (strcmp (varargin, "-browser")))
+    url = [];
+  endif
+  
+  if (nargout > 0)
+    status = sts;
+  endif
+
+endfunction
+
+
+%!error <URL must be a string> web (1)
+%!error <URL must be a string> web ('')
+%!error <'-invalid_Option' does not match>
+%!  web ("https://www.octave.org", "-invalid_Option")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/web/weboptions.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,392 @@
+## Copyright (C) 2018-2019 Sahil Yadav <yadavsahil5198@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{output} =} weboptions ()
+## @deftypefnx {} {@var{output} =} weboptions (@var{name1}, @var{value1}, @dots{})
+##
+## Specify parameters for RESTful web services.
+##
+## @code{weboptions} with no inputs returns a default @code{weboptions} object
+## to specify parameters for a request to a web service.  A @code{weboptions}
+## object can be an optional input argument to the @code{webread},
+## @code{websave}, and ## @code{webwrite} functions.
+##
+## Multiple name and value pair arguments may be specified in any order as
+## @var{name1}, @var{value1}, @var{name2}, @var{value2}, etc.
+##
+## The option names must match @strong{exactly} one of those specified in the
+## table below.
+##
+## The following options are available:
+##
+## @itemize @bullet
+## @item
+## @samp{CharacterEncoding} --- Specify the character encoding of the data:
+##
+## @samp{auto} (default), @samp{UTF-8}, @samp{US-ASCII}
+## @samp{auto} chooses an encoding based on the content-type of the data.
+##
+## @item
+## @samp{UserAgent} --- Specify the User Agent for the connection.
+##
+## Default value is @samp{GNU Octave/version}, where @samp{version} is the
+## current version of Octave as returned by @code{version}.
+##
+## @item
+## @samp{Timeout} --- Specify the timeout value for the connection in seconds.
+##
+## Default is 10 seconds.  @samp{Inf} is not currently supported.
+##
+## @item
+## @samp{Username} --- User identifier for a basic HTTP connection.
+##
+## Default is NULL@.  It must be a string.
+##
+## @item
+## @samp{Password} --- User authentication password for HTTP connection.
+##
+## Default is NULL@.  It must be a string or character vector.
+## Programming Note: If you display a @code{weboption} object with the Password
+## property set, the value is displayed as a string containing
+## @qcode{\"*\"}.  However, the object stores the value of the Password
+## property as plain text.
+##
+## @item
+## @samp{KeyName} --- Specify the name of an additional key to be added to
+## the HTTP request header.  It should be coupled with @samp{KeyValue}.  It
+## must be a string or character vector.
+##
+## @item
+## @samp{KeyValue} --- Specify the value of the key @samp{KeyName}.
+##
+## @samp{KeyName} must be present in order to assign to this field.
+##
+## @item
+## @samp{HeaderFields} --- Specify the header fields for the connection.
+##
+## Names and values of header fields, specified as an m-by-2 array of strings
+## or cell array of character vectors to add to the HTTP request header.
+## HeaderFields@{i,1@} is the name of a field and HeaderFields@{i,2@} is its
+## value.
+##
+## @example
+## @group
+## weboptions ("HeaderFields", @{"Content-Length" "78";"Content-Type" "application/json"@})
+## Creates a weboptions object that contains two header fields: Content-Length
+## with value 78 and Content-Type with value application/json.
+## @end group
+## @end example
+##
+## @item
+## @samp{ContentType} --- Specify the content type of the data.
+##
+## The following values are available:
+## @samp{auto}, @samp{text}, @samp{json}
+##
+## Default is @samp{auto}.  It automatically determines the content type.
+## All other formats like @samp{audio}, @samp{binary}, etc.@: available in
+## @sc{matlab} are not currently supported.
+##
+## @item
+## @samp{ContentReader} --- Not yet implemented.  Only for @sc{matlab}
+## compatibility.
+##
+## @item
+## @samp{MediaType} --- Not yet implemented.  Only for @sc{matlab}
+## compatibility.
+##
+## @item
+## @samp{RequestMethod} --- Specifies the type of request to be made.
+##
+## The following methods are available:
+## @samp{get}, @samp{put}, @samp{post}, @samp{delete}, @samp{patch}
+##
+## @code{webread} and @code{websave} use the HTTP GET method.  @code{webwrite}
+## uses the HTTP POST method as default.
+##
+## @item
+## @samp{ArrayFormat} -- Not yet implemented.  Only for @sc{matlab}
+## compatibility.
+##
+## @item
+## @samp{CertificateFilename} --- Not yet implemented.  Only for @sc{matlab}
+## compatibility.
+## @end itemize
+##
+## @seealso{webwrite, webread, websave}
+## @end deftypefn
+
+classdef weboptions < handle
+  properties
+    CharacterEncoding = "auto";
+    UserAgent = ["GNU Octave/", version()];
+    Timeout = 10;
+    Username = "";
+    Password = "";
+    KeyName = "";
+    KeyValue = "";
+    HeaderFields = {};
+    ContentType = "auto";
+    ContentReader = "";
+    MediaType = "auto";
+    RequestMethod = "auto";
+    ArrayFormat = "csv";
+    CertificateFilename = "";
+  endproperties
+
+  methods
+    function f = weboptions (varargin)
+      if (rem (numel (varargin), 2) != 0)
+        error ("weboptions: invalid number of arguments");
+      else
+        h = cell2struct (varargin(2:2:end), varargin(1:2:end), 2);
+        if (numfields (h) > 14)
+          error ("weboptions: invalid number of arguments");
+        endif
+
+        if (isfield (h, "CharacterEncoding"))
+          f.CharacterEncoding = h.CharacterEncoding;
+          h = rmfield (h, "CharacterEncoding");
+        endif
+
+        if (isfield (h, "UserAgent"))
+          f.UserAgent = h.UserAgent;
+          h = rmfield (h, "UserAgent");
+        endif
+
+        if (isfield (h, "Timeout"))
+          f.Timeout = h.Timeout;
+          h = rmfield (h, "Timeout");
+        endif
+
+        if (isfield (h, "Username"))
+          f.Username = h.Username;
+          h = rmfield (h, "Username");
+        endif
+
+        if (isfield (h, "Password"))
+          f.Password = h.Password;
+          h = rmfield (h, "Password");
+        endif
+
+        if (isfield (h, "KeyName"))
+          f.KeyName = h.KeyName;
+          h = rmfield (h, "KeyName");
+        endif
+
+        if (isfield (h, "KeyValue"))
+          f.KeyValue = h.KeyValue;
+          h = rmfield (h, "KeyValue");
+        endif
+
+        if (isfield (h, "HeaderFields"))
+          f.HeaderFields = h.HeaderFields;
+          h = rmfield (h, "HeaderFields");
+        endif
+
+        if (isfield (h, "ContentType"))
+          f.ContentType = h.ContentType;
+          h = rmfield (h, "ContentType");
+        endif
+
+        if (isfield (h, "ContentReader"))
+          f.ContentReader = h.ContentReader;
+          h = rmfield (h, "ContentReader");
+        endif
+
+        if (isfield (h, "MediaType"))
+          f.MediaType = h.MediaType;
+          h = rmfield (h, "MediaType");
+        endif
+
+        if (isfield (h, "RequestMethod"))
+          f.RequestMethod = h.RequestMethod;
+          h = rmfield (h, "RequestMethod");
+        endif
+
+        if (isfield (h, "ArrayFormat"))
+          f.ArrayFormat = h.ArrayFormat;
+          h = rmfield (h, "ArrayFormat");
+        endif
+
+        if (isfield (h, "CertificateFilename"))
+          f.CertificateFilename = h.CertificateFilename;
+          h = rmfield (h, "CertificateFilename");
+        endif
+
+        if (! isempty (fieldnames (h)))
+          field = fieldnames (h){1};
+          error (["weboptions: Undefined field " field]);
+        endif
+      endif
+    endfunction
+
+    function f = set.CharacterEncoding (f, value)
+      if (! any (strcmpi (value, {"UTF-8", 'US-ASCII', "auto"})));
+        error ("weboptions: Invalid CharacterEncoding value");
+      else
+        f.CharacterEncoding = value;
+      endif
+    endfunction
+
+    function f = set.UserAgent (f, value)
+      if (! ischar (value) && ! isrow (value));
+        error ("weboptions: UserAgent must be a string");
+      else
+        f.UserAgent = value;
+      endif
+    endfunction
+
+    function f = set.Timeout (f, value)
+      if (! isreal (value) || ! isscalar (value)
+          || floor(value) != value || value < 0)
+        error ("weboptions: invalid Timeout value");
+      else
+        f.Timeout = value;
+      endif
+    endfunction
+
+    function f = set.Username (f, value)
+      if (! ischar (value) && ! isrow (value))
+        error ("weboptions: Username must be a string");
+      else
+        f.Username = value;
+      endif
+    endfunction
+
+    function f = set.Password (f, value)
+      if (! ischar (value) && ! isrow (value))
+        error ("weboptions: Password must be a string");
+      else
+        f.Password = value;
+      endif
+    endfunction
+
+    function f = set.KeyName (f, value)
+      if (! ischar (value) && ! isrow (value))
+        error ("weboptions: invalid KeyName value");
+      else
+        f.KeyName = value;
+      endif
+    endfunction
+
+    function f = set.KeyValue (f, value)
+      if (isempty (f.KeyName) && ! isempty (value))
+        error ("weboptions: field KeyName empty.  Cannot set KeyValue.");
+      else
+        f.KeyValue = value;
+      endif
+    endfunction
+
+    function f = set.HeaderFields (f, value)
+      if (! isempty (value))
+        if (! iscellstr (value) || ! ismatrix (value))
+          error ("weboptions: HeaderFields must be array of strings or a cell array");
+        elseif (columns (value) != 2)
+          error ("weboptions: HeaderFields must be of size m-by-2");
+        endif
+      endif
+      f.HeaderFields = value;
+    endfunction
+
+    function f = set.ContentType (f, value)
+      if (! isempty (value))
+        if (! any (strcmpi (value, {"auto", "json", "text"})))
+          error ("weboptions: invalid ContentType value");
+        endif
+      endif
+      f.ContentType = value;
+    endfunction
+
+    function f = set.ContentReader (f, value)
+      f.ContentReader = value;
+    endfunction
+
+    function f = set.MediaType (f, value)
+      f.MediaType = value;
+    endfunction
+
+    function f = set.RequestMethod (f, value)
+      if (! isempty (value))
+        if (! any (strcmpi (value, {"auto", "get", "put", "post",...
+                                    "delete", "patch"})))
+          error ("weboptions: invalid RequestMethod value");
+        endif
+      endif
+      f.RequestMethod = value;
+    endfunction
+
+    function f = set.ArrayFormat (f, value)
+      if (! isempty (value))
+        if (! any (strcmpi (value, {"csv", "json", "php", "repeating"})))
+          error ("weboptions: invalid ArrayFormat value");
+        endif
+      endif
+      f.ArrayFormat = value;
+    endfunction
+
+    function f = set.CertificateFilename (f, value)
+      f.CertificateFilename = value;
+    endfunction
+
+    function display (f)
+      Timeout = int2str (f.Timeout);
+      Password = repmat ("*", 1, numel (num2str (f.Password)));
+
+      if (! isempty (f.ContentReader))
+        ContentReader = ['["', strjoin(f.ContentReader, '", "'), '"]'];
+      else
+        ContentReader = "[]";
+      endif
+
+      if (! isempty (f.HeaderFields))
+        HeaderFields = ['{"', strjoin(f.HeaderFields, '", "'), '"}'];
+      else
+        HeaderFields = "{}";
+      endif
+
+      if (! isempty (f.KeyValue))
+        KeyValue = num2str (f.KeyValue);
+      else
+        KeyValue = "''";
+      endif
+
+      printf ("%s =", inputname (1));
+      output = ["\n\n   weboptions with properties:     \n",...
+                "\n      CharacterEncoding: '", f.CharacterEncoding, "'",...
+                "\n              UserAgent: '", f.UserAgent, "'",...
+                "\n                Timeout: " , Timeout, "",...
+                "\n               Username: '", f.Username, "'",...
+                "\n               Password: '", Password, "'",...
+                "\n                KeyName: '", f.KeyName, "'",...
+                "\n               KeyValue: " , KeyValue,...
+                "\n            ContentType: '", f.ContentType, "'",...
+                "\n          ContentReader: " , ContentReader,...
+                "\n              MediaType: '", f.MediaType, "'",...
+                "\n          RequestMethod: '", f.RequestMethod, "'",...
+                "\n            ArrayFormat: '", f.ArrayFormat, "'",...
+                "\n           HeaderFields: " , HeaderFields,...
+                "\n    CertificateFilename: '", f.CertificateFilename, "'\n"];
+      disp (output);
+    endfunction
+
+  endmethods
+
+endclassdef
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/web/webread.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,105 @@
+## Copyright (C) 2018-2019 Sahil Yadav <yadavsahil5198@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{response} =} webread (@var{url})
+## @deftypefnx {} {@var{response} =} webread (@var{url}, @var{name1}, @var{value1}, @dots{})
+## @deftypefnx {} {@var{response} =} webread (@dots{}, @var{options})
+##
+## Read content from RESTful web service.
+##
+## Read content from the web service specified by @var{url} and return the
+## content in @var{response}.
+##
+## All key-value pairs given (@var{name1}, @var{value1}, @dots{}) are appended
+## as query parameters to @var{url}.  To place a query in the body of the
+## message, use @code{webwrite}.  The web service defines the acceptable query
+## parameters.
+##
+## @var{options} is a @code{weboptions} object that may be used to add other
+## HTTP request options.  This argument can be used with either calling form.
+## See @code{help weboptions} for a complete list of supported HTTP options.
+##
+## @seealso{weboptions, webwrite, websave}
+## @end deftypefn
+
+function response = webread (url, varargin)
+
+  if (nargin < 1)
+    print_usage();
+  endif
+
+  if (! (ischar (url) && isrow (url)))
+    error ("webread: URL must be a string");
+  endif
+
+  if (isa (varargin{end}, "weboptions"))
+    has_weboptions = true;
+    options = varargin{end};
+    varargin(end) = [];
+  else
+    has_weboptions = false;
+    options = weboptions ();
+  endif
+
+  if (strcmp (options.MediaType, "auto"))
+    options.MediaType = "application/x-www-form-urlencoded";
+  endif
+
+  ## If MediaType is set by the user, append it to other headers.
+  if (! strcmp (options.CharacterEncoding, "auto"))
+    options.HeaderFields{end+1,1} = "Content-Type";
+    options.HeaderFields{end,2} = [options.MediaType, ...
+                                   "; charset=", options.CharacterEncoding];
+  endif
+
+  if (! isempty (options.KeyName))
+    options.HeaderFields{end+1,1} = options.KeyName;
+    options.HeaderFields{end,2} = options.KeyValue;
+  endif
+
+  if (strcmp (options.RequestMethod, "auto"))
+    options.RequestMethod = "get";
+  endif
+
+  ## Flatten the cell array because the internal processing takes place on
+  ## a flattened array.
+  options.HeaderFields = options.HeaderFields(:)';
+
+  nargs = 1 + numel (varargin);
+  if (nargs == 1)
+    response = __restful_service__ (url, cell (), options);
+  elseif (rem (nargs, 2) == 1)
+    if (! iscellstr (varargin))
+      error ("webwrite: KEYS and VALUES must be strings");
+    else
+      response = __restful_service__ (url, varargin, options);
+    endif
+  else
+    error ("webread: KEYS/VALUES must occur in pairs");
+  endif
+
+endfunction
+
+
+## Test input validation
+%!error webread ()
+%!error <URL must be a string> webread (1)
+%!error <URL must be a string> webread (["a";"b"])
+%!error <KEYS and VALUES must be strings> webread ("URL", "NAME1", 5)
+%!error <KEYS/VALUES must occur in pairs> webread ("URL", "KEY1")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/web/webwrite.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,117 @@
+## Copyright (C) 2018-2019 Sahil Yadav <yadavsahil5198@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{response} =} webwrite (@var{url}, @var{name1}, @var{value1}, @dots{})
+## @deftypefnx {} {@var{response} =} webwrite (@var{url}, @var{data})
+## @deftypefnx {} {@var{response} =} webwrite (@dots{}, @var{options})
+##
+## Write data to RESTful web services.
+##
+## Write content to the web service specified by @var{url} and return the
+## response in @var{response}.
+##
+## All key-value pairs given (@var{name1}, @var{value1}, @dots{}) are added
+## as pairs of query parameters to the body of request method (@code{get},
+## @code{post}, @code{put}, etc.).
+##
+## @var{options} is a @code{weboptions} object that may be used to add other
+## HTTP request options.  This argument can be used with either calling form.
+## See @code{help weboptions} for a complete list of supported HTTP options.
+##
+## @seealso{weboptions, webread, websave}
+## @end deftypefn
+
+function response = webwrite (url, varargin)
+
+  if (nargin < 2)
+    print_usage();
+  endif
+
+  if (! (ischar (url) && isrow (url)))
+    error ("webwrite: URL must be a string");
+  endif
+
+  if (isa (varargin{end}, "weboptions"))
+    has_weboptions = true;
+    options = varargin{end};
+    varargin(end) = [];
+  else
+    has_weboptions = false;
+    options = weboptions ();
+  endif
+
+  if (strcmp (options.MediaType, "auto"))
+    options.MediaType = "application/x-www-form-urlencoded";
+  endif
+
+  ## If MediaType is set by the user, append it to other headers.
+  if (! strcmp (options.CharacterEncoding, "auto"))
+    options.HeaderFields{end+1, 1} = "Content-Type";
+    options.HeaderFields{end, 2} = [options.MediaType, ...
+                                    "; charset=", options.CharacterEncoding];
+  endif
+
+  if (! isempty (options.KeyName))
+    options.HeaderFields{end+1, 1} = options.KeyName;
+    options.HeaderFields{end, 2} = options.KeyValue;
+  endif
+
+  if (strcmp (options.RequestMethod, "auto"))
+    options.RequestMethod = "post";
+  endif
+
+  ## Flatten the cell array because the internal processing takes place on
+  ## a flattened array.
+  options.HeaderFields = options.HeaderFields(:)';
+
+  nargs = numel (varargin);
+  if (nargs == 0)
+    error ("webwrite: DATA must be a string");
+  elseif (nargs == 1)
+    if (ischar (varargin{1}) && isrow (varargin{1}))
+      param = strsplit (varargin{1}, {"=", "&"});
+      response = __restful_service__ (url, param, options);
+    elseif  (! iscellstr (varargin))
+      error ("webwrite: DATA must be a string");
+    else
+      response = __restful_service__ (url, varargin, options);
+    endif
+  elseif (rem (nargs, 2) == 0)
+    if (! iscellstr (varargin))
+      error ("webwrite: KEYS and VALUES must be strings");
+    else
+      response = __restful_service__ (url, varargin, options);
+    endif
+  else
+    error ("webwrite: KEYS/VALUES must occur in pairs");
+  endif
+
+endfunction
+
+
+## Test input validation
+%!error webwrite ()
+%!error webwrite ("abc")
+%!error <URL must be a string> webwrite (1, "NAME1", "VALUE1")
+%!error <URL must be a string> webwrite (["a";"b"], "NAME1", "VALUE1")
+%!error <DATA must be a string> webwrite ("URL", 1, weboptions ())
+%!error <DATA must be a string> webwrite ("URL", 1)
+%!error <KEYS and VALUES must be strings> webwrite ("URL", "NAME1", 5)
+%!error <KEYS/VALUES must occur in pairs> webwrite ("URL", "KEY1", "VAL1", "A")
+
--- a/src/main-gui.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/src/main-gui.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -39,7 +39,7 @@
 
 #include "octave.h"
 #include "octave-build-info.h"
-#include "octave-gui.h"
+#include "qt-application.h"
 #include "sysdep.h"
 
 static void
@@ -98,7 +98,7 @@
 
   octave::sys::env::set_program_name (argv[0]);
 
-  octave::gui_application app (argc, argv);
+  octave::qt_application app (argc, argv);
 
   return app.execute ();
 }
--- a/src/main.in.cc	Wed Jul 10 20:02:44 2019 -0700
+++ b/src/main.in.cc	Fri Jul 12 12:14:43 2019 -0400
@@ -369,6 +369,7 @@
   // so we can forward them to the child.
 
   octave_block_async_signals ();
+  octave_block_signal_by_name ("SIGTSTP");
 
 #if defined (HAVE_OCTAVE_QT_GUI) && ! defined (OCTAVE_USE_WINDOWS_API)
 
@@ -412,6 +413,7 @@
           install_signal_handlers ();
 
           octave_unblock_async_signals ();
+          octave_unblock_signal_by_name ("SIGTSTP");
 
           int status;
 
--- a/test/bug-38236/bug-38236.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/bug-38236/bug-38236.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -16,5 +16,5 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <https://www.gnu.org/licenses/>.
 
-%!test <38236>
+%!test <*38236>
 %! u_vr
--- a/test/bug-38565.tst	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-## Copyright (C) 2013-2019 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/>.
-
-%!function r = f (x)
-%!  if (ischar (x))
-%!    r = x;
-%!  else
-%!    error ("expecting character string");
-%!  endif
-%!endfunction
-
-%!assert (eval ("f 10;"), "10")
--- a/test/bug-38576.tst	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2013-2019 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/>.
-
-%!function r = f1 ()
-%!  ls = svd (1);
-%!  r = eval ("ls -1;");
-%!endfunction
-%!function r = f2 ()
-%!  [u,ls,v] = svd (1);
-%!  r = eval ("ls -1;");
-%!endfunction
-%!function r = f3 (ls)
-%!  r = eval ("ls -1;");
-%!endfunction
-
-%!test
-%! ## Windows systems can't run "ls -1"
-%! if (! ispc ())
-%!   assert (f1 (), 0);
-%!   assert (f2 (), 0);
-%!   assert (ischar (f3 ()), true);
-%!   assert (f3 (1), 0);
-%! endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-45351/bug-45351.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,12 @@
+%!shared obj, h1, h2, h3
+%! obj = bug45351 ();
+%! [h1, h2, h3] = obj.get_handles ();
+%!assert <*45351> (obj.bar (1), 'bug45351.foo: 1')
+%!assert <*45351> (obj.bar (2), 'bug45351.foo: 2')
+%!assert <*45351> (obj.bar (3), 'bug45351.foo: 3')
+%!assert <*45351> (h1 (obj, 1), 'bug45351.foo: 1')
+%!assert <*45351> (h2 (obj, 2), 'bug45351.foo: 2')
+%!assert <*45351> (h3 (obj, 3), 'bug45351.foo: 3')
+%!error (obj.h1 (1))
+%!error (obj.h2 (2))
+%!error (obj.h3 (3))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-45351/bug45351.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,37 @@
+classdef bug45351
+
+  properties (Hidden, SetAccess = protected)
+    h1 = [];% handle to function
+    h2 = [];% handle to function
+    h3 = [];% handle to function
+  end
+
+  methods
+    function self = bug45351 ()
+      self.h1 = @foo;
+      self.h2 = @(self, n) self.foo (n);
+      self.h3 = @(~, n) self.foo (n);
+    end
+    function [h1, h2, h3] = get_handles (self)
+      h1 = self.h1;
+      h2 = self.h2;
+      h3 = self.h3;
+    end
+    function r = bar (self, hnum)
+      switch (hnum)
+        case 1
+          r = self.h1 (self, hnum);
+        case 2
+          r = self.h2 (self, hnum);
+        case 3
+          r = self.h3 (self, hnum);
+      end
+    end
+  end
+
+  methods (Hidden, Access = protected)
+    function r = foo (self, n)
+      r = sprintf ('bug45351.foo: %d', n);
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-45351/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,5 @@
+bug_45351_TEST_FILES = \
+  %reldir%/bug45351.m \
+  %reldir%/bug-45351.tst
+
+TEST_FILES += $(bug_45351_TEST_FILES)
--- a/test/bug-45969.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/bug-45969.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -1,5 +1,5 @@
 %!test
-%! ascii_filename = tempname ();
+%! text_filename = tempname ();
 %! binary_filename = tempname ();
 %! a = 2;
 %! b = 10;
@@ -9,14 +9,14 @@
 %! f2_arg = 5;
 %! save_default_options ("-text", "local");
 %! unwind_protect
-%!   save (ascii_filename, "f2");
+%!   save (text_filename, "f2");
 %!   save ("-binary", binary_filename, "f2");
-%!   ascii = load (ascii_filename);
+%!   text = load (text_filename);
 %!   binary = load (binary_filename);
-%!   assert (f2 (f2_arg), ascii.f2 (f2_arg));
+%!   assert (f2 (f2_arg), text.f2 (f2_arg));
 %!   assert (f2 (f2_arg), binary.f2 (f2_arg));
 %! unwind_protect_cleanup
-%!   unlink (ascii_filename);
+%!   unlink (text_filename);
 %!   unlink (binary_filename);
 %! end_unwind_protect
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/bug-47680.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,6 @@
+%!shared obj
+%! obj = sub_bug47680 ("foo");
+%!assert<*47680> (obj.meth1 (), "foo:super:meth1:sub:meth1")
+%!assert<*47680> (obj.meth2 (), "foo:super:meth2:sub:meth2")
+%!assert<*47680> (obj.meth3 (), "foo:super:meth3:sub:meth3")
+%!assert<*47680> (obj.meth4 (), "foo:super:meth4:sub:meth4")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,6 @@
+bug_47680_TEST_FILES = \
+  %reldir%/bug-47680.tst \
+  %reldir%/sub_bug47680.m \
+  %reldir%/super_bug47680.m
+
+TEST_FILES += $(bug_47680_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/sub_bug47680.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,19 @@
+classdef sub_bug47680 < super_bug47680
+  methods
+    function obj = sub_bug47680 (x)
+      obj = obj@super_bug47680 (x);
+    endfunction
+    function r = meth1 (obj)
+      r = meth1@super_bug47680 (obj, "sub:meth1");
+    endfunction
+    function r = meth2 (obj)
+      r = obj.meth2@super_bug47680 ("sub:meth2");
+    endfunction
+    function r = meth3 (obj)
+      r = meth3@super_bug47680 (obj, "sub:meth3");
+    endfunction
+    function r = meth4 (obj)
+      r = obj.meth4@super_bug47680 ("sub:meth4");
+    endfunction
+  endmethods
+endclassdef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-47680/super_bug47680.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,22 @@
+classdef super_bug47680
+  properties
+    tag;
+  end
+  methods
+    function obj = super_bug47680 (x)
+      obj.tag = x;
+    endfunction
+    function r = meth1 (obj, x)
+      r = [obj.tag ":super:meth1:" x];
+    endfunction
+    function r = meth2 (obj, x)
+      r = [obj.tag ":super:meth2:" x];
+    endfunction
+    function r = meth3 (obj, x)
+      r = [obj.tag ":super:meth3:" x];
+    endfunction
+    function r = meth4 (obj, x)
+      r = [obj.tag ":super:meth4:" x];
+    endfunction
+  endmethods
+endclassdef
--- a/test/bug-50716/bug-50716.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/bug-50716/bug-50716.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -22,14 +22,14 @@
 %! val = obj.methodA (str(1:end));
 %! assert (val, str);
 
-%!test <50716>
+%!test <*50716>
 %! obj = myclass ();
 %! foo = {obj};
 %! str = "Octave";
 %! val = foo{1}.methodA (str(1:end));
 %! assert (val, str);
 
-%!test <50716>
+%!test <*50716>
 %! obj = myclass ();
 %! foo = {obj};
 %! str = "Octave";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-53956/bug-53956.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,15 @@
+%!test <53956>
+%! global dtor2_called dtor4_called
+%!
+%! dtor2_called = dtor4_called = 0;
+%! x = bug53956_class_3 ();
+%! clear x
+%! assert (dtor2_called, 1);
+%!
+%! dtor2_called = dtor4_called = 0;
+%! x = bug53956_class_4 ();
+%! clear x
+%! assert (dtor2_called, 1);
+%! assert (dtor4_called, 1);
+%!
+%! clear -global dtor2_called dtor4_called;  # cleanup after test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-53956/bug53956_class_2.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,10 @@
+classdef bug53956_class_2 < handle
+  properties
+  end
+  methods
+    function delete (self)
+      global dtor2_called
+      dtor2_called++;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-53956/bug53956_class_3.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,6 @@
+classdef bug53956_class_3 < bug53956_class_2
+  properties
+  end
+  methods
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-53956/bug53956_class_4.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,10 @@
+classdef bug53956_class_4 < bug53956_class_3
+  properties
+  end
+  methods
+    function delete (self)
+      global dtor4_called
+      dtor4_called++;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-53956/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,7 @@
+bug_53956_TEST_FILES = \
+  %reldir%/bug-53956.tst \
+  %reldir%/bug53956_class_2.m \
+  %reldir%/bug53956_class_3.m \
+  %reldir%/bug53956_class_4.m
+
+TEST_FILES += $(bug_53956_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/bug-55758.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,16 @@
+%!test
+%! global class_bug_55758_dtor_called
+%! class_bug_55758_dtor_called = false;
+%!
+%! assert (class_bug_55758 (5).value, 5);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (class_bug_55758 (5)(1), 5);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (size (class_bug_55758 (5)), [1, 1]);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (numel (class_bug_55758 (5)), 1);
+%! assert (class_bug_55758_dtor_called);
+%! clear -global class_bug_55758_dtor_called;  # cleanup after test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/class_bug_55758.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,23 @@
+classdef class_bug_55758 < handle
+  properties
+    value
+  endproperties
+
+  methods
+    function self = class_bug_55758 (val)
+      if (nargin < 1)
+        val = 0;
+      endif
+      self.value = val;
+    endfunction
+
+    function delete (self)
+      global class_bug_55758_dtor_called;
+      class_bug_55758_dtor_called = true;
+    endfunction
+
+    function ret = subsref (self, idx)
+      ret = self.value;
+    endfunction
+  endmethods
+endclassdef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,5 @@
+bug_55758_TEST_FILES = \
+  %reldir%/bug-55758.tst \
+  %reldir%/class_bug_55758.m
+
+TEST_FILES += $(bug_55758_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/class_bug52614A.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,15 @@
+classdef class_bug52614A < handle
+  properties
+    a
+  end
+
+  methods
+    function obj = class_bug52614A ()
+      obj.foo ();
+    end
+
+    function foo (obj)
+      obj.a = 1;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/class_bug52614B.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,16 @@
+classdef class_bug52614B < class_bug52614A
+  properties
+    b
+  end
+
+  methods
+    function obj = class_bug52614B ()
+      obj = obj@class_bug52614A ();
+    end
+
+    function foo (obj)
+      foo@class_bug52614A (obj);
+      obj.b = 2;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/class_bug55766.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,27 @@
+classdef class_bug55766
+
+  properties
+    testprop = 0;
+  end
+
+  properties (Access = public)
+    publictestprop = 0;
+  end
+
+  properties (Access = protected)
+    protectedtestprop = 0;
+  end
+
+  properties (Hidden)
+    hiddentestprop = 0;
+  end
+
+  properties (Hidden = true)
+    anotherhiddentestprop = 0;
+  end
+
+  properties (Hidden = false)
+    notahiddentestprop = 0;
+  end
+
+end
--- a/test/classdef/classdef.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/classdef/classdef.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -48,19 +48,20 @@
 %!assert (p.principle == 50e3)
 %!assert (p.amount, amt, eps ())
 %!assert (amount (p), amt, eps ())
-%!xtest <53614>
+%!xtest <55961>
 %! assert (properties (p), {'rate'; 'term'; 'principle'});
-%!xtest <42510>
+%!xtest <*55858>
 %! assert (methods (p), {'amount'; 'foo_value_class'});
 %!assert (isempty (foo_value_class().rate))
-%!error <property `rate' is not constant> foo_value_class.rate
+%!error <property 'rate' is not constant> foo_value_class.rate
+%!shared  # clear all shared variables for remainder of tests
 
 %%  Static method and Constant Property
 %!assert (foo_static_method_constant_property.radians_per_cycle == 2*pi)
 %!assert (foo_static_method_constant_property().radians_per_cycle == 2*pi)
 %!assert (foo_static_method_constant_property().pie == pi)
-%!error <property `frequency' is not constant> foo_static_method_constant_property.frequency
-%!error <method `cosine' is not static> foo_static_method_constant_property.cosine
+%!error <property 'frequency' is not constant> foo_static_method_constant_property.frequency
+%!error <method 'cosine' is not static> foo_static_method_constant_property.cosine
 %!test
 %! obj = foo_static_method_constant_property;
 %! obj.frequency = 10;
@@ -185,3 +186,15 @@
 %! assert (isequal (obj{1:2}(1:2), ones (2)));
 %! obj{3:4}(3:4) = 4 * ones (2);
 %! assert (isequal (obj{3:4}(3:4), 4 * ones (2)));
+
+%!test <*52614>
+%! A = class_bug52614A ();
+%! assert (A.a, 1);
+%! B = class_bug52614B ();
+%! assert (B.a, 1);
+%! assert (B.b, 2);
+
+%!test <*55766>
+%! x = class_bug55766 ();
+%! props = {"notahiddentestprop"; "publictestprop"; "testprop"};
+%! assert (properties (x), props);
--- a/test/classdef/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/classdef/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -1,4 +1,7 @@
 classdef_TEST_FILES = \
+  %reldir%/class_bug52614A.m \
+  %reldir%/class_bug52614B.m \
+  %reldir%/class_bug55766.m \
   %reldir%/classdef.tst \
   %reldir%/foo_method_changes_property_size.m \
   %reldir%/foo_static_method_constant_property.m \
--- a/test/classes/classes.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/classes/classes.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -401,27 +401,27 @@
 %! assert (isequal (numel (st), 2));
 %!assert (isequal (ndims (st), 2))
 %!assert (isequal (rows (st), 1))
-%!assert <51308> (isequal (columns (st), 2))
+%!assert <*51308> (isequal (columns (st), 2))
 %!assert <*44334> (isequal (st, st))
-%!assert <44498> (not (isscalar (st)))
+%!assert <*44498> (not (isscalar (st)))
 %!assert (isvector (st))
 
 %!test st = SizeTester ([2 3]);
 %! assert (isequal (size (st), [2 3]));
 %! assert (isequal (numel (st), 6));
 %!assert (isequal (ndims (st), 2))
-%!assert <51308> (isequal (rows (st), 2))
-%!assert <51308> (isequal (columns (st), 3))
+%!assert <*51308> (isequal (rows (st), 2))
+%!assert <*51308> (isequal (columns (st), 3))
 %!assert <*44334> (isequal (st, st))
-%!assert <44498> (not (isscalar (st)))
-%!assert <44498> (not (isvector (st)))
+%!assert <*44498> (not (isscalar (st)))
+%!assert <*44498> (not (isvector (st)))
 
 %!test st = SizeTester ([2 3 4]);
 %! assert (isequal (size (st), [2 3 4]));
 %! assert (isequal (numel (st), 24));
-%!assert <51308> (isequal (ndims (st), 3))
-%!assert <51308> (isequal (rows (st), 2))
-%!assert <51308> (isequal (columns (st), 3))
+%!assert <*51308> (isequal (ndims (st), 3))
+%!assert <*51308> (isequal (rows (st), 2))
+%!assert <*51308> (isequal (columns (st), 3))
 %!assert <*44334> (isequal (st, st))
-%!assert <44498> (not (isscalar (st)))
-%!assert <44498> (not (isvector (st)))
+%!assert <*44498> (not (isscalar (st)))
+%!assert <*44498> (not (isvector (st)))
--- a/test/deprecate-props.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/deprecate-props.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -31,62 +31,24 @@
 %!  endif
 %!endfunction
 
-## annotation rectangle "edgecolor" deprecated in 4.4, remove from version 6.
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   ha = annotation ("rectangle");
-%!   testprop (ha, "edgecolor", "6.0");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-## figure "doublebuffer, mincolormap, wvisual, wvisualmode, xdisplay,
-## xvisual, xvisualmode" deprecated in 4.4, remove from version 6.
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   testprop (hf, "doublebuffer", "6.0");
-%!   testprop (hf, "mincolormap", "6.0");
-%!   testprop (hf, "wvisual", "6.0");
-%!   testprop (hf, "wvisualmode", "6.0");
-%!   testprop (hf, "xdisplay", "6.0");
-%!   testprop (hf, "xvisual", "6.0");
-%!   testprop (hf, "xvisualmode", "6.0");
-%! unwind_protect_cleanup
-%!   close (hf)
-%! end_unwind_protect
-
-## axes "drawmode" deprecated in 4.4, remove from version 6.
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   hax = axes ();
-%!   testprop (hax, "drawmode", "6.0");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-## text/uicontrol/uipanel/uibuttongroup  "demi" and "light" values for
-## "fontweight" property are deprecated in 4.4, remove from version 6:
-##   * remove "demi" and "light" options in graphics.in.h,
-##   QtHandlesUtils.cc and ft-text-renderer.cc
-##   * remove warnings from update_fontweight in graphics.in.h
+## text/uicontrol/uipanel/uibuttongroup/uitable  "oblique" value for
+## "fontangle" property was deprecated in 5.0, remove from version 7:
+##   * remove "oblique" options in graphics.in.h, QtHandlesUtils.cc,
+##     and ft-text-renderer.cc
+##   * remove warnings from update_fontangle in graphics.in.h
 %!test
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   ht = text ();
-%!   testprop (ht, "fontweight", "6.0", "demi");
-%!   testprop (ht, "fontweight", "6.0", "light");
+%!   testprop (ht, "fontangle", "7.0", "oblique");
 %!   hui = uicontrol ();
-%!   testprop (hui, "fontweight", "6.0", "demi");
-%!   testprop (hui, "fontweight", "6.0", "light");
+%!   testprop (hui, "fontangle", "7.0", "oblique");
 %!   hui = uipanel ();
-%!   testprop (hui, "fontweight", "6.0", "demi");
-%!   testprop (hui, "fontweight", "6.0", "light");
+%!   testprop (hui, "fontangle", "7.0", "oblique");
 %!   hui = uibuttongroup ();
-%!   testprop (hui, "fontweight", "6.0", "demi");
-%!   testprop (hui, "fontweight", "6.0", "light");
+%!   testprop (hui, "fontangle", "7.0", "oblique");
+%!   hui = uitable ();
+%!   testprop (hui, "fontangle", "7.0", "oblique");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/test/diag-perm.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/diag-perm.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -265,11 +265,12 @@
 %! assert (full (D - A), D - full (A));
 
 ## inverse preserves diagonal structure even for singular matrices (bug #46103)
+## but set all the diagonal elements to Inf (bug #56232)
 %!test
 %! x = diag (1:3);
 %! assert (inv (x), diag ([1 1/2 1/3]));
-%! x = diag (0:2);
-%! assert (inv (x), diag ([Inf 1 1/2]));
+%!warning <matrix singular> A = inv (diag (0:2));
+%! assert (A, diag ([Inf Inf Inf]));
 
 ## assignment to diagonal elements preserves diagonal structure (bug #36932)
 %!test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/eval-command.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,154 @@
+## Copyright (C) 2013-2019 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/>.
+
+%!function r = sigma (opt)
+%!  global sigma_call;
+%!  if (nargin == 0)
+%!    sigma_call = "function";
+%!    r = 1;
+%!  elseif (ischar (opt))
+%!    sigma_call = "command";
+%!    r = 1;
+%!  else
+%!    sigma_call = "unexpected";
+%!  endif
+%!endfunction
+%!
+%!function f1 ()
+%!  ## ERROR; sigma used as variable and later parsed as command
+%!  sigma = svd (1);
+%!  eval ("sigma -1;");
+%!endfunction
+%!
+%!function f1a ()
+%!  ## Assignment of eval result means eval code is not parsed as command.
+%!  sigma = svd (1);
+%!  val = eval ("sigma -1;");
+%!endfunction
+%!
+%!function f2 ()
+%!  ## ERROR; sigma used as variable and later parsed as command
+%!  [u, sigma, v] = svd (1);
+%!  eval ("sigma -1;");
+%!endfunction
+%!
+%!function f2a ()
+%!  ## Assignment of eval result means eval code is not parsed as command.
+%!  [u, sigma, v] = svd (1);
+%!  val = eval ("sigma -1;");
+%!endfunction
+%!
+%!function f3 (sigma)
+%!  ## No assignment of eval result means eval code is parsed as command.
+%!  ## If f3 is called with a value for sigma, it will be used.  Otherwise,
+%!  ## search for the function sigma and call with no arguments.
+%!  eval ("sigma -1;");
+%!endfunction
+%!
+%!function f3a (sigma)
+%!  ## Assignment of eval result means eval code is not parsed as command.
+%!  val = eval ("sigma -1;");
+%!endfunction
+%!
+%!function f4 ()
+%!  ## No assignment of eval result means eval code is parsed as command.
+%!  eval ("sigma -1;");
+%!endfunction
+%!
+%!function f4a ()
+%!  ## Assignment of eval result means eval code is not parsed as command.
+%!  val = eval ("sigma -1;");
+%!endfunction
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! ## Matlab complains about sigma previously being used as a variable
+%! ## before being used as a command.
+%! fail ("f1 ()", "used as variable and later as function");
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f1a ();
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! ## Matlab complains about sigma previously being used as a variable
+%! ## before being used as a command.
+%! fail ("f2 ()", "used as variable and later as function");
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f2a ();
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f3 ();
+%! assert (sigma_call, "command");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f3a ();
+%! assert (sigma_call, "function");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! ## NOTE: this result disagrees with Matlab, which evaluates sigma
+%! ## as a command-style function even though there is a variable named
+%! ## sigma defined in the workspace prior to evaluating the function
+%! ## call (compare with f1() and f2() above).
+%! fail ("f3 (1)", "used as variable and later as function");
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f3a (1);
+%! assert (sigma_call, "none");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f4 ();
+%! assert (sigma_call, "command");
+%! clear -global sigma_call
+%!
+%!test <55610>
+%! global sigma_call;
+%! sigma_call = "none";
+%! f4a ();
+%! assert (sigma_call, "function");
+%! clear -global sigma_call
--- a/test/fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-function r = fhdr_derived (n)
-  s.a = n;
-  p = fhdr_parent (n);
-  r = class (s, 'fhdr_derived', p);
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function r = fhdr_other (n)
-  s.d = fhdr_derived (n);
-  r = class (s, 'fhdr_other');
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_other/getsize_arrayfun.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = getsize_arrayfun (x)
-  r = arrayfun (@(i) numel (x(i).d), 1:numel (x), 'uniformoutput', true);
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_other/getsize_cellfun.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = getsize_cellfun (x)
-  r = cellfun (@numel, {x.d});
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_other/getsize_loop.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-function r = getsize_loop (x)
-  n = numel (x);
-  r = zeros (1, n);
-  for i = 1:n
-    r(i) = numel (x(i).d);
-  end
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function r = fhdr_parent (n)
-  s.a = rand (n, 1);
-  r = class (s, 'fhdr_parent');
-end
--- a/test/fcn-handle-derived-resolution/@fhdr_parent/numel.m	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = numel (x, varargin)
-  r = numel (x.a, varargin{:});
-end
--- a/test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-## Copyright (C) 2012-2019 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 script for legacy OOP.
-%%  Requires the path to contain the directory ctor-vs-method.
-%%
-%%  Note: This script and all classes are also intended to run
-%%        in Matlab to test compatibility.  Don't break that!
-
-%% FIXME: Can't use 'clear -classes' because it also clears all functions in the
-%% namespace of test.m (bug #35881).  This is a problem only if Octave would
-%% re-use a class definition that was defined somewhere else.  Unfortunately,
-%% that is exactly the case when running 'make check' since the ctor-vs-method
-%% test also uses an @parent, @derived, and @other class.
-%% Until the bug is fixed, it suffices to make the class names unique so that
-%% there is no re-use.  Using the prefix fhdr (fcn-handle-derived-resolution)
-%% for this directory.
-%%!shared
-%%! #clear -classes
-
-%!test
-%! p = fhdr_parent (7);
-%! assert (numel (p), 7);
-
-%!test
-%! d = fhdr_derived (13);
-%! assert (numel (d), 13);
-
-%!test
-%! p = fhdr_parent (11);
-%! f = @numel;
-%! assert (f (p), 11);
-
-%!test
-%! d = fhdr_parent (21);
-%! f = @numel;
-%! assert (f (d), 21);
-
-%!test
-%! o(1) = fhdr_other (13);
-%! o(2) = fhdr_other (42);
-%! assert (getsize_loop (o), [13, 42]);
-
-%!test
-%! o(1) = fhdr_other (13);
-%! o(2) = fhdr_other (42);
-%! assert (getsize_cellfun (o), [13, 42]);
-
-%!test
-%! o(1) = fhdr_other (13);
-%! o(2) = fhdr_other (42);
-%! assert (getsize_arrayfun (o), [13, 42]);
--- a/test/fcn-handle-derived-resolution/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-fcn_handle_derived_resolution_TEST_FILES = \
-  %reldir%/@fhdr_derived/fhdr_derived.m \
-  %reldir%/@fhdr_other/fhdr_other.m \
-  %reldir%/@fhdr_other/getsize_arrayfun.m \
-  %reldir%/@fhdr_other/getsize_cellfun.m \
-  %reldir%/@fhdr_other/getsize_loop.m \
-  %reldir%/@fhdr_parent/fhdr_parent.m \
-  %reldir%/@fhdr_parent/numel.m \
-  %reldir%/fcn-handle-derived-resolution.tst
-
-TEST_FILES += $(fcn_handle_derived_resolution_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/+pkga/+pkgb/bug51709_a.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,7 @@
+classdef bug51709_a
+  methods (Static)
+    function r = smeth ()
+      r = "pkg bug51709_a";
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/+pkga/+pkgb/bug51709_b.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,7 @@
+classdef bug51709_b
+  methods (Static)
+    function r = smeth ()
+      r = "pkg bug51709_b";
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/+pkga/+pkgb/f1.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = f1 ()
+  r = "pkg f1";
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/+pkga/+pkgb/f2.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = f2 ()
+  r = "pkg f2";
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_derived/fhdr_derived.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,5 @@
+function r = fhdr_derived (n)
+  s.a = n;
+  p = fhdr_parent (n);
+  r = class (s, 'fhdr_derived', p);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_other/fhdr_other.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,4 @@
+function r = fhdr_other (n)
+  s.d = fhdr_derived (n);
+  r = class (s, 'fhdr_other');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_other/getsize_arrayfun.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = getsize_arrayfun (x)
+  r = arrayfun (@(i) numel (x(i).d), 1:numel (x), 'uniformoutput', true);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_other/getsize_cellfun.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = getsize_cellfun (x)
+  r = cellfun (@numel, {x.d});
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_other/getsize_loop.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,7 @@
+function r = getsize_loop (x)
+  n = numel (x);
+  r = zeros (1, n);
+  for i = 1:n
+    r(i) = numel (x(i).d);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_parent/fhdr_parent.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,4 @@
+function r = fhdr_parent (n)
+  s.a = rand (n, 1);
+  r = class (s, 'fhdr_parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/@fhdr_parent/numel.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = numel (x, varargin)
+  r = numel (x.a, varargin{:});
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/bug51709_a.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,7 @@
+classdef bug51709_a
+  methods (Static)
+    function r = smeth ()
+      r = "top bug51709_a";
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/bug51709_c.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,12 @@
+classdef bug51709_c
+  methods
+    function out = meth (varargin)
+      out = {"meth", varargin};
+    endfunction
+  endmethods
+  methods (Static)
+    function out = smeth (varargin)
+      out = {"smeth", varargin};
+    endfunction
+  endmethods
+endclassdef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/derived-resolution.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,67 @@
+## Copyright (C) 2012-2019 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 script for legacy OOP.
+%%  Requires the path to contain the directory ctor-vs-method.
+%%
+%%  Note: This script and all classes are also intended to run
+%%        in Matlab to test compatibility.  Don't break that!
+
+%% FIXME: Can't use 'clear -classes' because it also clears all functions in the
+%% namespace of test.m (bug #35881).  This is a problem only if Octave would
+%% re-use a class definition that was defined somewhere else.  Unfortunately,
+%% that is exactly the case when running 'make check' since the ctor-vs-method
+%% test also uses an @parent, @derived, and @other class.
+%% Until the bug is fixed, it suffices to make the class names unique so that
+%% there is no re-use.  Using the prefix fhdr (fcn-handle/derived-resolution)
+%% for this directory.
+%%!shared
+%%! #clear -classes
+
+%!test
+%! p = fhdr_parent (7);
+%! assert (numel (p), 7);
+
+%!test
+%! d = fhdr_derived (13);
+%! assert (numel (d), 13);
+
+%!test
+%! p = fhdr_parent (11);
+%! f = @numel;
+%! assert (f (p), 11);
+
+%!test
+%! d = fhdr_parent (21);
+%! f = @numel;
+%! assert (f (d), 21);
+
+%!test
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
+%! assert (getsize_loop (o), [13, 42]);
+
+%!test
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
+%! assert (getsize_cellfun (o), [13, 42]);
+
+%!test
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
+%! assert (getsize_arrayfun (o), [13, 42]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/f1.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,3 @@
+function r = f1 ()
+  r = "top f1";
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,21 @@
+fcn_handle_TEST_FILES = \
+  %reldir%/+pkga/+pkgb/bug51709_a.m \
+  %reldir%/+pkga/+pkgb/bug51709_b.m \
+  %reldir%/+pkga/+pkgb/f1.m \
+  %reldir%/+pkga/+pkgb/f2.m \
+  %reldir%/@fhdr_derived/fhdr_derived.m \
+  %reldir%/@fhdr_other/fhdr_other.m \
+  %reldir%/@fhdr_other/getsize_arrayfun.m \
+  %reldir%/@fhdr_other/getsize_cellfun.m \
+  %reldir%/@fhdr_other/getsize_loop.m \
+  %reldir%/@fhdr_parent/fhdr_parent.m \
+  %reldir%/@fhdr_parent/numel.m \
+  %reldir%/bug51709_a.m \
+  %reldir%/bug51709_c.m \
+  %reldir%/derived-resolution.tst \
+  %reldir%/f1.m \
+  %reldir%/object-method.tst \
+  %reldir%/package-function.tst \
+  %reldir%/static-method.tst
+
+TEST_FILES += $(fcn_handle_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/object-method.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,65 @@
+## Copyright (C) 2019 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/>.
+
+%!function [fhm, fhsm] = foo ()
+%!  obj = bug51709_c ();
+%!  fhm = @obj.meth;
+%!  fhsm = @obj.smeth;
+%!endfunction
+
+%!test <*51709>
+%! [fhm, fhsm] = foo ();
+%!
+%! out = fhm (42);
+%! assert (out{1}, "meth");
+%! tmp = out{2};
+%! assert (numel (tmp), 2);
+%! assert (isobject (tmp{1}));
+%! assert (tmp{2}, 42);
+
+%!test <*51709>
+%! [fhm, fhsm] = foo ();
+%!
+%! out = fhsm (42);
+%! assert (out{1}, "smeth");
+%! tmp = out{2};
+%! assert (numel (tmp), 1);
+%! assert (tmp{1}, 42);
+
+%!test <*51709>
+%! fhm = @obj.meth;
+%!
+%! obj = bug51709_c ();
+%!
+%! out = fhm (42);
+%! assert (out{1}, "meth");
+%! tmp = out{2};
+%! assert (numel (tmp), 2);
+%! assert (isobject (tmp{1}));
+%! assert (tmp{2}, 42);
+
+%!test <*51709>
+%! fhsm = @obj.smeth;
+%!
+%! obj = bug51709_c ();
+%!
+%! out = fhsm (42);
+%! assert (out{1}, "smeth");
+%! tmp = out{2};
+%! assert (numel (tmp), 1);
+%! assert (tmp{1}, 42);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/package-function.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,29 @@
+## Copyright (C) 2019 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 <*46659>
+%! fh = @pkga.pkgb.f2;
+%! assert (fh (), "pkg f2");
+
+%!test <*55975>
+%! fh = @pkga.pkgb.f1;
+%! assert (fh (), "pkg f1");
+
+## Also test without function handle.
+%!assert <*55975> (pkga.pkgb.f1 (), "pkg f1");
+%!assert (pkga.pkgb.f2 (), "pkg f2");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle/static-method.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,29 @@
+## Copyright (C) 2019 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 <*51709>
+%! fh = @pkga.pkgb.bug51709_a.smeth;
+%! assert (fh (), "pkg bug51709_a");
+
+%!test <*55975>
+%! fh = @pkga.pkgb.bug51709_b.smeth;
+%! assert (fh (), "pkg bug51709_b");
+
+## Also test without function handle.
+%!assert <*55975> (pkga.pkgb.bug51709_a.smeth (), "pkg bug51709_a");
+%!assert (pkga.pkgb.bug51709_b.smeth (), "pkg bug51709_b");
--- a/test/for.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/for.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -123,7 +123,7 @@
 %! __printf_assert__ ("\n");
 %! assert (__prog_output_assert__ ("1234"));
 
-%!test <50893>
+%!test <*50893>
 %! cnt = 0;
 %! for k = zeros (0,3);
 %!   cnt++;
@@ -131,7 +131,7 @@
 %! assert (cnt, 0);
 %! assert (k, zeros (0,3));
 
-%!test <50893>
+%!test <*50893>
 %! cnt = 0;
 %! for k = zeros (3,0);
 %!   cnt++;
@@ -139,7 +139,7 @@
 %! assert (cnt, 0);
 %! assert (k, zeros (3,0));
 
-%!test <50893>
+%!test <*50893>
 %! cnt = 0;
 %! for k = zeros (3,0, "uint32");
 %!   cnt++;
@@ -147,7 +147,7 @@
 %! assert (cnt, 0);
 %! assert (k, zeros (3,0, "uint32"));
 
-%!test <50893>
+%!test <*50893>
 %! cnt = 0;
 %! for k = cell (0,3);
 %!   cnt++;
--- a/test/io.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/io.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -233,6 +233,8 @@
 %! STR.struct_fld.y = 1;
 %!
 %! struct_dat = fullfile (P_tmpdir, "struct.dat");
+%! save_default_options ("-text", "local");
+%! save_precision (17, "local");
 %! save (struct_dat, "-struct", "STR");
 %! STR = load (struct_dat);
 %!
@@ -334,7 +336,7 @@
 %! [val, count, msg, pos] = sscanf ("3I2", "%f");
 %! assert (val, 3);
 %! assert (count, 1);
-%! assert (msg, "");
+%! assert (msg, "sscanf: format failed to match");
 %! assert (pos, 2);
 
 %!xtest <47413>
@@ -343,14 +345,14 @@
 %! [val, count, msg, pos] = sscanf ("3I2", "%f");
 %! assert (val, 3);
 %! assert (count, 1);
-%! assert (msg, "");
+%! assert (msg, "sscanf: format failed to match");
 %! assert (pos, 2);
 
 %!testif ; ! ismac ()
 %! [val, count, msg, pos] = sscanf ("3In2", "%f");
 %! assert (val, 3);
 %! assert (count, 1);
-%! assert (msg, "");
+%! assert (msg, "sscanf: format failed to match");
 %! assert (pos, 2);
 
 %!xtest <47413>
@@ -494,7 +496,7 @@
 %! assert (__prog_output_assert__ ("error:"));
 
 %!error <Invalid call to fopen> fopen ()
-%!error <Invalid call to fopen> fopen ("foo", "wb", "native", 1)
+%!error <Invalid call to fopen> fopen ("foo", "wb", "native", "utf-8", 1)
 
 %!error fclose (0)
 %!error <Invalid call to fclose> fclose (1, 2)
@@ -649,6 +651,34 @@
 %!   unlink (nm);
 %! endif
 
+%!test   # write to and read from file with encoding
+%! temp_file = [tempname(), ".txt"];
+%! fid = fopen (temp_file, "wt", "n", "iso-8859-1");
+%! unwind_protect
+%!   [name, mode, arch, codepage] = fopen (fid);
+%!   assert (name, temp_file);
+%!   assert (mode, "w");
+%!   assert (codepage, "iso-8859-1");
+%!   fprintf (fid, "aäu %s", "AÄU");
+%!   fclose (fid);
+%!   # open in binary mode
+%!   fid2 = fopen (temp_file, "rb");
+%!   [name, mode, arch, codepage] = fopen (fid2);
+%!   assert (name, temp_file);
+%!   assert (mode, "rb");
+%!   assert (codepage, "utf-8");
+%!   read_binary = fread (fid2);
+%!   fclose (fid2);
+%!   assert (read_binary, [97 228 117 32 65 196 85].');
+%!   # open in text mode with correct encoding
+%!   fid3 = fopen (temp_file, "rt", "n", "iso-8859-1");
+%!   read_text = fscanf (fid3, "%s");
+%!   fclose (fid3);
+%!   assert (read_text, "aäuAÄU");
+%! unwind_protect_cleanup
+%!   unlink (temp_file);
+%! end_unwind_protect
+
 %!assert (fputs (1, 1),-1)
 
 %!error <Invalid call to fputs> fputs ()
--- a/test/jit.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/jit.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -377,16 +377,10 @@
 %! assert (jit_failcnt, 0);
 
 %!function test_divide ()
-%! state = warning ("query", "Octave:divide-by-zero").state;
-%! unwind_protect
-%!   warning ("error", "Octave:divide-by-zero");
-%!   for i=1:1e5
-%!     a = 1;
-%!     a / 0;
-%!   endfor
-%! unwind_protect_cleanup
-%!   warning (state, "Octave:divide-by-zero");
-%! end_unwind_protect
+%! for i=1:1e5
+%!   a = 1;
+%!   a / 0;
+%! endfor
 %!endfunction
 
 # %!testif HAVE_LLVM
--- a/test/mk-sparse-tst.sh	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/mk-sparse-tst.sh	Fri Jul 12 12:14:43 2019 -0400
@@ -209,12 +209,7 @@
 %!assert (nnz (sparse (1,1,0)), 0)
 %!assert (nnz (sparse (eye (3))*0), 0)
 %!assert (nnz (sparse (eye (3))-sparse (eye (3))), 0)
-
-%!test
-%! wdbz = warning ("query", "Octave:divide-by-zero");
-%! warning ("off", "Octave:divide-by-zero");
-%! assert (full (sparse (eye (3))/0), full (eye (3)/0));
-%! warning (wdbz.state, "Octave:divide-by-zero");
+%!assert (full (sparse (eye (3))/0), full (eye (3)/0));
 
 EOF
 }
--- a/test/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -8,8 +8,6 @@
   %reldir%/fntests.m \
   %reldir%/args.tst \
   %reldir%/bug-31371.tst \
-  %reldir%/bug-38565.tst \
-  %reldir%/bug-38576.tst \
   %reldir%/bug-45969.tst \
   %reldir%/bug-45972.tst \
   %reldir%/bug-46330.tst \
@@ -27,6 +25,7 @@
   %reldir%/diag-perm.tst \
   %reldir%/error.tst \
   %reldir%/eval-catch.tst \
+  %reldir%/eval-command.tst \
   %reldir%/for.tst \
   %reldir%/func.tst \
   %reldir%/global.tst \
@@ -62,8 +61,10 @@
 include %reldir%/bug-38236/module.mk
 include %reldir%/bug-38691/module.mk
 include %reldir%/bug-41723/module.mk
+include %reldir%/bug-45351/module.mk
 include %reldir%/bug-44940/module.mk
 include %reldir%/bug-46660/module.mk
+include %reldir%/bug-47680/module.mk
 include %reldir%/bug-49379/module.mk
 include %reldir%/bug-50014/module.mk
 include %reldir%/bug-50035/module.mk
@@ -76,13 +77,15 @@
 include %reldir%/bug-52722/module.mk
 include %reldir%/bug-53027/module.mk
 include %reldir%/bug-53468/module.mk
+include %reldir%/bug-53956/module.mk
 include %reldir%/bug-54995/module.mk
+include %reldir%/bug-55758/module.mk
 include %reldir%/class-concat/module.mk
 include %reldir%/classdef/module.mk
 include %reldir%/classdef-multiple-inheritance/module.mk
 include %reldir%/classes/module.mk
 include %reldir%/ctor-vs-method/module.mk
-include %reldir%/fcn-handle-derived-resolution/module.mk
+include %reldir%/fcn-handle/module.mk
 include %reldir%/local-functions/module.mk
 include %reldir%/mex/module.mk
 include %reldir%/nest/module.mk
@@ -90,7 +93,7 @@
 include %reldir%/pkg/module.mk
 
 define run-octave-tests
-  ( 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% ) && \
+  ( cd %reldir% && $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) $(1) --no-init-file --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 \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nest/counter.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,8 @@
+function fcnHandle = counter
+  value = 0;
+  function currentValue = increment
+    value = value+1;
+    currentValue = value;
+  end
+  fcnHandle = @increment;
+end
--- a/test/nest/module.mk	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/nest/module.mk	Fri Jul 12 12:14:43 2019 -0400
@@ -1,9 +1,13 @@
 nest_TEST_FILES = \
   %reldir%/arg_nest.m \
   %reldir%/arg_ret.m \
+  %reldir%/counter.m \
   %reldir%/nest.tst \
   %reldir%/nest_eval.m \
   %reldir%/no_closure.m \
+  %reldir%/nst1.m \
+  %reldir%/nst2.m \
+  %reldir%/nst3.m \
   %reldir%/persistent_nest.m \
   %reldir%/recursive_nest.m \
   %reldir%/recursive_nest2.m \
--- a/test/nest/nest.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/nest/nest.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -62,7 +62,7 @@
 %! assert (f("foo"), "nested foo");
 %! assert (f("foo"), "nested foo");
 
-%!test <39257>
+%!test <*39257>
 %! f = no_closure (1);
 %! assert (f(), "nested");
 %! assert (f("foo"), "nested foo");
@@ -70,3 +70,76 @@
 %!error <D' undefined near line 7> scope2
 %!error <can not add variable "y" to a static workspace> nest_eval ("y = 5;", "")
 %!error <can not add variable "y" to a static workspace> nest_eval ("y;", "")
+
+## Test the way that non-local variables referenced by nested functions
+## work with function handles.
+
+## FH1 and FH2 were created separately so will have distinct
+## closure contexts.handles, FH3 is a copy of FH2 so they will
+## share the same context.
+
+%!test <*39257>
+%! fh1 = nst1 (13);
+%! fh2 = nst1 (13);
+%! fh3 = fh2;
+%!
+%! assert (fh1 (), 13);
+%! assert (fh2 (), 13);
+%! assert (fh3 (), 13);
+%!
+%! assert (fh1 (42), 42);
+%! assert (fh2 (), 13);
+%! assert (fh3 (), 13);
+%!
+%! assert (fh2 (pi), pi);
+%! assert (fh1 (), 42);
+%! assert (fh3 (), pi);
+
+## Similar to the test above, but with persistent variables.  These are
+## stored in the function, not the closure context, so are shared among
+## all handles whether they are created separately or copied.
+
+%!test
+%! fh1 = nst2 (13);
+%! fh2 = nst2 (13);
+%! fh3 = fh2;
+%!
+%! assert (fh1 (), 13);
+%! assert (fh2 (), 13);
+%! assert (fh3 (), 13);
+%!
+%! assert (fh1 (42), 42);
+%! assert (fh2 (), 42);
+%! assert (fh3 (), 42);
+%!
+%! assert (fh2 (pi), pi);
+%! assert (fh1 (), pi);
+%! assert (fh3 (), pi);
+
+## And again with global variables.
+
+%!test
+%! fh1 = nst3 (13);
+%! fh2 = nst3 (13);
+%! fh3 = fh2;
+%!
+%! assert (fh1 (), 13);
+%! assert (fh2 (), 13);
+%! assert (fh3 (), 13);
+%!
+%! assert (fh1 (42), 42);
+%! assert (fh2 (), 42);
+%! assert (fh3 (), 42);
+%!
+%! assert (fh2 (pi), pi);
+%! assert (fh1 (), pi);
+%! assert (fh3 (), pi);
+%!
+%! clear -global g;  # cleanup after tests
+
+## Test case from <https://stackoverflow.com/q/26238491/6579744>
+%!test
+%! f1 = counter ();
+%! f2 = counter ();
+%! observed = [f1(), f1(), f2(), f1(), f2()];
+%! assert (observed, [1, 2, 1, 3, 2]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nest/nst1.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,12 @@
+function fh = nst1 (xval)
+  if (nargin > 0)
+    x = xval;
+  end
+  fh = @nst;
+  function r = nst (xval)
+    if (nargin > 0)
+      x = xval;
+    end
+    r = x;
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nest/nst2.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,13 @@
+function fh = nst2 (pval)
+  persistent p
+  if (nargin > 0)
+    p = pval;
+  end
+  fh = @nst;
+  function r = nst (pval)
+    if (nargin > 0)
+      p = pval;
+    end
+    r = p;
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nest/nst3.m	Fri Jul 12 12:14:43 2019 -0400
@@ -0,0 +1,13 @@
+function fh = nst3 (gval)
+  global g
+  if (nargin > 0)
+    g = gval;
+  end
+  fh = @nst;
+  function r = nst (gval)
+    if (nargin > 0)
+      g = gval;
+    end
+    r = g;
+  end
+end
--- a/test/pkg/pkg.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/pkg/pkg.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -91,6 +91,7 @@
 
 ## Action load/unload (within install/uninstall)
 %!testif HAVE_Z
+%! save_default_options ("-binary", "local");
 %! for i = 1:numel (mfile_pkg_name)
 %!   name = mfile_pkg_name{i};
 %!   silent_pkg_install ("-local", mfile_pkg_tgz{i});
--- a/test/prefer.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/prefer.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -176,15 +176,9 @@
 %! warning (watv.state, "Octave:assign-as-truth-value");
 
 %!test
-%! wdbz = warning ("query", "Octave:divide-by-zero");
-%! warning ("off", "Octave:divide-by-zero");
 %! assert (isinf (1/0));
-%! warning (wdbz.state, "Octave:divide-by-zero");
 
 %!test
-%! wdbz = warning ("query", "Octave:divide-by-zero");
-%! warning ("on", "Octave:divide-by-zero");
 %! a = 1;
 %! b = 0;
-%! fail ("isinf (a/b);", "warning", "division by zero");
-%! warning (wdbz.state, "Octave:divide-by-zero");
+%! assert (isinf (a/b));
--- a/test/struct.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/struct.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -231,7 +231,7 @@
 %! assert (s(3), struct ("foo", 42));
 
 ## empty index should return entire struct
-%!test <51633>
+%!test <*51633>
 %! x.a = 1:10;
 %! y = x;
 %! assert (! isempty (y));
@@ -242,7 +242,7 @@
 %! assert (z, y);
 
 ## test assigning to multi-dim struct with trailing singleton dimensions,
-%!test <35841>
+%!test <*35841>
 %! a(1,1,1).b(1) = 1;
 %! a(1,1,1).b(1) = 2;
 %! a(1,1,:).b(1) = 3;
--- a/test/system.tst	Wed Jul 10 20:02:44 2019 -0700
+++ b/test/system.tst	Fri Jul 12 12:14:43 2019 -0400
@@ -278,6 +278,8 @@
 
 %!test
 %! xdir = pwd ();
+%! ydir = cd ();
+%! assert (xdir, ydir);
 %! cd /
 %! d1 = pwd ();
 %! cd (xdir);