changeset 26964:b57d596b909b

maint: Merge stable to default.
author John W. Eaton <jwe@octave.org>
date Mon, 25 Mar 2019 10:56:14 +0000
parents b033cf021048 (diff) 589b00536a39 (current diff)
children be5c2a1bad93
files libinterp/corefcn/cellfun.cc
diffstat 568 files changed, 24372 insertions(+), 16481 deletions(-) [+]
line wrap: on
line diff
--- a/.dir-locals.el	Sun Mar 24 21:50:07 2019 -0700
+++ b/.dir-locals.el	Mon Mar 25 10:56:14 2019 +0000
@@ -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/NEWS	Sun Mar 24 21:50:07 2019 -0700
+++ b/NEWS	Mon Mar 25 10:56:14 2019 +0000
@@ -1,320 +1,115 @@
-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.
-
-- 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:
+- 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"`.
 
-  `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.
+#### Graphics backend
 
-- 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 ());`
+- 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 `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`
+- 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.
 
-- 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 appearance of patterned lines `"LineStyle" = ":"|"--"|"-."` has
+  been improved for small widths (`"LineWidth"` less than 1.5 pixels)
+  which is a common scenario.
 
-- 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.
-
-
-### Dependencies
+- 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 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.
-
+- The following print devices are no more officially supported: cdr, corel,
+  aifm, ill, cgm, hpgl, mf and dxf.  A warning will be thrown when using
+  those devices and the actual 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 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`
+- The interpreter now supports handles to nested functions.
 
-  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`
+- 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.
 
 
 ### 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`
+                         |
 
 - 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"`
+
+
+
+### Alphabetical list of new functions added in Octave 6
+
+- `lightangle`
+- `verLessThan`
 
 
 ### 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/build-aux/subst-config-vals.in.sh	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/build-aux/subst-cross-config-vals.in.sh	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/build-aux/update-bug-status.sh	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/configure.ac	Mon Mar 25 10:56:14 2019 +0000
@@ -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.])
   ;;
@@ -2220,38 +2206,57 @@
   [], [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])
+   OCTAVE_CHECK_SUNDIALS_SUNLINSOL_DENSE
+   OCTAVE_CHECK_SUNDIALS_SUNLINSOL_KLU])
 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_sunlinsol_dense = yes \
     && test $octave_cv_sundials_realtype_is_double = yes; 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=
+  warn_sundials_disabled="disabling SUNDIALS because something is missing, solvers odee15i and ode15s will be disabled"
+  OCTAVE_CONFIGURE_WARNING([warn_sundials_disabled])
 fi
 
 AC_SUBST(SUNDIALS_XCPPFLAGS)
 AC_SUBST(SUNDIALS_XLDFLAGS)
 AC_SUBST(SUNDIALS_XLIBS)
 
+save_LIBS="$LIBS"
+LIBS="$SUNDIALS_XLIBS $LIBS"
+## Current interface:
+AC_CHECK_FUNCS([IDASetJacFn IDASetLinearSolver SUNLinSol_Dense SUNLinSol_KLU])
+## Deprecated interface:
+AC_CHECK_HEADERS([ida/ida_direct.h ida_direct.h])
+AC_CHECK_FUNCS([IDADlsSetJacFn IDADlsSetLinearSolver SUNDenseLinearSolver SUNKLU])
+LIBS="$save_LIBS"
+
 ### Check for ARPACK library.
 
 save_LIBS="$LIBS"
@@ -2594,7 +2599,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 +3071,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/contributors.in	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/contributors.in	Mon Mar 25 10:56:14 2019 +0000
@@ -429,6 +429,7 @@
 Alexander Wilms
 Joe Winegarden
 Georg Wiora
+Eddy Xiao
 Sahil Yadav
 Fook Fah Yap
 Sean Young
--- a/doc/interpreter/genpropdoc.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/genpropdoc.m	Mon Mar 25 10:56:14 2019 +0000
@@ -696,12 +696,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 +1082,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/macros.texi	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/mk-doc-cache.pl	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/munge-texi.pl	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/oop.txi	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/plot.txi	Mon Mar 25 10:56:14 2019 +0000
@@ -459,6 +459,8 @@
 
 @DOCSTRING(camlight)
 
+@DOCSTRING(lightangle)
+
 @DOCSTRING(meshgrid)
 
 @DOCSTRING(ndgrid)
--- a/doc/interpreter/system.txi	Sun Mar 24 21:50:07 2019 -0700
+++ b/doc/interpreter/system.txi	Mon Mar 25 10:56:14 2019 +0000
@@ -533,6 +533,8 @@
 
 @DOCSTRING(compare_versions)
 
+@DOCSTRING(verLessThan)
+
 @DOCSTRING(license)
 
 @DOCSTRING(getrusage)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.5	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,320 @@
+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.
+
+
+### 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/etc/RELEASE.BUG_FIX_LIST	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/etc/RELEASE.CHECKLIST	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/etc/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -9,6 +9,7 @@
   %reldir%/NEWS.2 \
   %reldir%/NEWS.3 \
   %reldir%/NEWS.4 \
+  %reldir%/NEWS.5 \
   %reldir%/PROJECTS \
   %reldir%/gdbinit
 
--- a/examples/code/make_int.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/examples/code/make_int.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/libgui/graphics/BaseControl.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/BaseControl.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/BaseControl.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/ButtonGroup.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Canvas.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -43,6 +43,7 @@
 
 #include "oct-opengl.h"
 #include "octave-qt-link.h"
+#include "resource-manager.h"
 
 #include "builtin-defun-decls.h"
 
@@ -73,30 +74,45 @@
   Canvas::setCursor (MouseMode mode)
   {
     QWidget *w = qWidget ();
-
+    QCursor cursor = Qt::ArrowCursor;
     if (w)
       {
-        static QCursor origCursor = w->cursor ();
-
         switch (mode)
           {
+          case NoMode:
+          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);
       }
   }
 
@@ -191,73 +207,6 @@
     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 +221,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 +562,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));
 
@@ -718,7 +642,7 @@
           case RotateMode:
           case ZoomInMode:
           case ZoomOutMode:
-            if (axesObj && axesObj.get_properties ().handlevisibility_is ("on"))
+            if (valid_axes)
               {
                 bool redraw_figure = true;
 
--- a/libgui/graphics/Canvas.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Canvas.h	Mon Mar 25 10:56:14 2019 +0000
@@ -70,10 +70,6 @@
     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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Figure.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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"
@@ -92,42 +90,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 ();
@@ -155,6 +142,11 @@
     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 +154,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 +194,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 +219,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 +247,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 +305,6 @@
     if (canvas)
       canvas->blockRedraw (true);
 
-    m_menuBar->removeReceiver (this);
     m_container->removeReceiver (this);
     qWidget<FigureWindow> ()->removeReceiver (this);
   }
@@ -468,18 +384,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:
@@ -515,6 +427,7 @@
         break;
 
       case figure::properties::ID___MOUSE_MODE__:
+      case figure::properties::ID___ZOOM_MODE__:
         m_container->canvas (m_handle)->setCursor (mouseMode ());
         break;
 
@@ -526,22 +439,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 +496,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 +683,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 +705,6 @@
         win->addToolBar (bar);
         m_blockUpdates = false;
 
-        //qDebug () << "Figure::addCustomToolBar:" << win->geometry ();
         updateBoundingBox (false);
       }
   }
@@ -853,33 +740,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Figure.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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,6 @@
     QStatusBar *m_statusBar;
     QRect m_innerRect;
     QRect m_outerRect;
-    MouseModeActionGroup *m_mouseModeGroup;
     int m_previousHeight;
     bool m_resizable;
   };
--- a/libgui/graphics/GLCanvas.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/GLCanvas.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -159,24 +159,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/GLCanvas.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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/Panel.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Panel.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -337,6 +337,8 @@
   void
   Panel::redraw (void)
   {
+    update (uipanel::properties::ID_POSITION);
+
     Canvas *canvas = m_container->canvas (m_handle);
 
     if (canvas)
--- a/libgui/graphics/QtHandlesUtils.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/QtHandlesUtils.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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;
--- a/libgui/graphics/Table.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Table.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/Table.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/ToolBar.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/ToolBarButton.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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,20 @@
 
       case T::properties::ID_CDATA:
         {
-          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)));
         }
         break;
 
--- a/libgui/graphics/images/README	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/graphics/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslator.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslatorMac.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/history-dock-widget.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/history-dock-widget.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/history-dock-widget.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/figure-axes.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/icons/figure-axes.svg	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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>
--- a/libgui/src/icons/icons_license	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/icons/icons_license	Mon Mar 25 10:56:14 2019 +0000
@@ -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
--- a/libgui/src/m-editor/file-editor-tab.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/m-editor/file-editor-tab.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -618,9 +618,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 +638,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
@@ -916,7 +925,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 +937,9 @@
           return;   // still invalid filename: "save as" was cancelled
       }
 
+    if (step_into)
+      handle_request_add_breakpoint (1, QString ());
+
     QFileInfo info (_file_name);
     emit run_file_signal (info);
   }
@@ -2026,13 +2038,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)
       {
@@ -3109,6 +3115,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 +3129,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/m-editor/file-editor-tab.h	Mon Mar 25 10:56:14 2019 +0000
@@ -94,7 +94,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);
--- a/libgui/src/m-editor/file-editor.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/m-editor/file-editor.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -149,14 +149,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 +200,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
@@ -444,12 +452,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 +547,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)
@@ -1325,103 +1338,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 +2034,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
@@ -2119,6 +2129,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 *)));
 
@@ -2246,8 +2259,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*)));
--- a/libgui/src/m-editor/file-editor.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/m-editor/file-editor.h	Mon Mar 25 10:56:14 2019 +0000
@@ -136,7 +136,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,6 +176,9 @@
     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 focus (void);
@@ -198,6 +201,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);
--- a/libgui/src/main-window.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/main-window.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -1011,7 +1011,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);
 
@@ -1035,9 +1035,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)
@@ -1768,6 +1777,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,
@@ -2231,6 +2246,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,
--- a/libgui/src/main-window.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/main-window.h	Mon Mar 25 10:56:14 2019 +0000
@@ -123,6 +123,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 +195,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 ());
@@ -455,6 +457,7 @@
     //!@{
     bool m_prevent_readline_conflicts;
     bool m_suppress_dbg_location;
+    bool m_editor_has_tabs;
 
     //! Flag for closing the whole application.
 
--- a/libgui/src/module.mk	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -24,6 +24,14 @@
   %reldir%/icons/edit-find-replace.png \
   %reldir%/icons/edit-paste.png \
   %reldir%/icons/edit-redo.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/edit-undo.png \
   %reldir%/icons/folder.png \
   %reldir%/icons/folder-new.png \
--- a/libgui/src/resource-manager.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/resource-manager.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/resource-manager.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/resource.qrc	Mon Mar 25 10:56:14 2019 +0000
@@ -26,6 +26,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>
--- a/libgui/src/settings-dialog.ui	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/settings-dialog.ui	Mon Mar 25 10:56:14 2019 +0000
@@ -52,8 +52,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>617</width>
+            <height>575</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">
@@ -548,8 +561,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>638</width>
+            <height>543</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>662</width>
+            <height>1307</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -2155,8 +2168,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>628</width>
+            <height>558</height>
            </rect>
           </property>
           <layout class="QGridLayout" name="gridLayout_8">
@@ -2305,8 +2318,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>628</width>
+            <height>558</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_19">
@@ -2367,8 +2380,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>669</width>
-            <height>558</height>
+            <width>720</width>
+            <height>543</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_vesc_manual">
@@ -2569,8 +2582,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>628</width>
+            <height>558</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_25">
@@ -2768,8 +2781,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>658</width>
-            <height>571</height>
+            <width>628</width>
+            <height>558</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_20">
--- a/libgui/src/shortcut-manager.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/shortcut-manager.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/shortcut-manager.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/workspace-model.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/workspace-model.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -61,10 +61,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 +75,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");
       }
 
@@ -301,14 +295,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-view.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libgui/src/workspace-view.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -44,6 +44,7 @@
 #include "resource-manager.h"
 
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "syminfo.h"
 
 namespace octave
@@ -415,10 +416,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);
 
@@ -464,7 +468,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/libinterp/build-env.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/build-env.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/build-env.in.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/__ichol__.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/__ichol__.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -453,7 +453,7 @@
 }
 
 /*
-%!test <51736>
+%!test <*51736>
 %! k = 4;
 %! n = 2^k;
 %! Afull = diag (ones (n,1)) / ...
--- a/libinterp/corefcn/__qp__.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/__qp__.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -89,15 +89,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 ();
 
@@ -493,7 +491,7 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  if (args.length () != 8)
+  if (args.length () != 9)
     print_usage ();
 
   const ColumnVector x0  (args(0).vector_value ());
@@ -504,7 +502,8 @@
   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;
 
   // Copy the initial guess into the working variable
@@ -513,7 +512,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/base-text-renderer.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/call-stack.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -30,6 +30,7 @@
 #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,7 +38,10 @@
 #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"
@@ -45,180 +49,135 @@
 // 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 };
+  { "file", "name", "line", "column", "scope", 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
+  class stack_trace_generator : public stack_frame_walker
   {
-    std::string retval;
+  public:
+
+    stack_trace_generator (size_t nskip = 0)
+      : stack_frame_walker (), m_frames (), m_nskip (nskip),
+        m_curr_frame (0)
+    { }
+
+    stack_trace_generator (const stack_trace_generator&) = delete;
+
+    stack_trace_generator& operator = (const stack_trace_generator&) = delete;
+
+    ~stack_trace_generator (void) = default;
+
+    std::list<stack_frame *> frames (void) const { return m_frames; }
+
+    size_t current_frame (void) const { return m_curr_frame; }
 
-    if (m_fcn)
-      {
-        std::string parent_fcn_name = m_fcn->parent_fcn_name ();
+    void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)
+    {
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
+
+    void visit_script_stack_frame (script_stack_frame& frame)
+    {
+      maybe_add_frame (frame);
 
-        if (print_subfn && ! parent_fcn_name.empty ())
-          retval = parent_fcn_name + '>';
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
+
+    void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame)
+    {
+      maybe_add_frame (frame);
+
+      symbol_scope scope = frame.get_scope ();
 
-        if (m_fcn->is_anonymous_function ())
-          retval += octave_fcn_handle::anonymous;
-        else
-          retval += m_fcn->name ();
-      }
-    else
-      retval = "<unknown>";
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
 
-    return retval;
-  }
+    void visit_scope_stack_frame (scope_stack_frame& frame)
+    {
+      symbol_scope scope = frame.get_scope ();
+
+      stack_frame *slink = frame.static_link ();
+
+      if (slink)
+        slink->accept (*this);
+    }
+
+  private:
 
-  bool
-  call_stack::stack_frame::operator == (const call_stack::stack_frame& rhs) const
+    void maybe_add_frame (stack_frame& frame)
+    {
+      if (m_nskip > 0)
+        {
+          m_nskip--;
+          return;
+        }
+
+      m_frames.push_back (&frame);
+    }
+
+    std::list<stack_frame *> m_frames;
+
+    // Number of user code frames to skip.
+    size_t m_nskip;
+
+    size_t m_curr_frame;
+  };
+
+  call_stack::call_stack (tree_evaluator& evaluator)
+    : m_evaluator (evaluator), m_cs (), m_curr_frame (0),
+      m_max_stack_depth (1024), m_global_values ()
   {
-    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;
+    push (symbol_scope ("top scope"));
   }
 
-  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
-  {
-    size_t retval = 0;
-
-    curr_user_frame = 0;
-
-    // Look for the caller of dbstack.
-    size_t xframe = cs[curr_frame].m_prev;
-
-    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;
-
-        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;
-
-    return retval;
-  }
-
-  octave_user_code *
-  call_stack::caller_user_code (size_t nskip) const
+  octave_user_code * call_stack::caller_user_code (size_t nskip) const
   {
     octave_user_code *retval = nullptr;
 
-    auto p = cs.cend ();
+    size_t xframe = m_curr_frame;
 
-    while (p != cs.cbegin ())
+    while (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 ())
           {
@@ -230,98 +189,101 @@
                 break;
               }
           }
+
+        xframe = m_cs[xframe]->previous ();
       }
 
     return retval;
   }
 
-  int
-  call_stack::caller_user_code_line (void) const
+  int call_stack::caller_user_code_line (void) const
   {
     int retval = -1;
 
-    auto p = cs.cend ();
+    size_t xframe = m_curr_frame;
 
-    while (p != cs.cbegin ())
+    while (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_line > 0)
+            if (elt->line () > 0)
               {
-                retval = elt.m_line;
+                retval = elt->line ();
                 break;
               }
           }
+
+        xframe = m_cs[xframe]->previous ();
       }
 
     return retval;
   }
 
-  unwind_protect *
-  call_stack::curr_fcn_unwind_protect_frame (void) const
+  unwind_protect * call_stack::curr_fcn_unwind_protect_frame (void) const
   {
-    auto p = cs.cend ();
+    size_t xframe = m_curr_frame;
 
-    while (p != cs.cbegin ())
+    while (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 ())
-          return elt.m_unwind_protect_frame;
+          return elt->unwind_protect_frame ();
+
+        xframe = m_cs[xframe]->previous ();
       }
 
     return nullptr;
   }
 
-  int
-  call_stack::caller_user_code_column (void) const
+  int call_stack::caller_user_code_column (void) const
   {
     int retval = -1;
 
-    auto p = cs.cend ();
+    size_t xframe = m_curr_frame;
 
-    while (p != cs.cbegin ())
+    while (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)
+            if (elt->column ())
               {
-                retval = elt.m_column;
+                retval = elt->column ();
                 break;
               }
           }
+
+        xframe = m_cs[xframe]->previous ();
       }
 
     return retval;
   }
 
-  octave_user_code *
-  call_stack::debug_user_code (void) const
+  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 +295,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 +324,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 +354,45 @@
     return retval;
   }
 
-  bool
-  call_stack::all_scripts (void) const
+  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,64 +404,110 @@
     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 ();
+
+        slink = (t_fcn
+                 ? (t_fcn->is_user_code ()
+                    ? m_cs[prev_frame] : m_cs[prev_frame]->static_link ())
+                 : m_cs[prev_frame]);
+      }
 
-    push (fcn, up_frame, symtab.current_scope (), symtab.current_context ());
+    return slink;
+  }
+
+  void call_stack::push (const symbol_scope& scope)
+  {
+    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);
+
+    m_cs.push_back (new scope_stack_frame (*this, prev_frame, scope, 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 (octave_user_function *fcn, unwind_protect *up_frame,
+                         stack_frame *closure_frames)
   {
-    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 (m_curr_frame > static_cast<size_t> (m_max_stack_depth))
+      error ("max_stack_depth exceeded");
+
+    stack_frame *slink = get_static_link (prev_frame);
+
+    m_cs.push_back (new user_fcn_stack_frame (*this, fcn, up_frame,
+                                              prev_frame, slink,
+                                              closure_frames));
+  }
+
+  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 (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 ();
-
-    symtab.set_scope_and_context (scope, context);
+    m_cs.push_back (new script_stack_frame (*this, script, up_frame,
+                                            prev_frame, slink));
   }
 
-  bool
-  call_stack::goto_frame (size_t n, bool verbose)
+  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);
+
+    m_cs.push_back (new compiled_fcn_stack_frame (*this, fcn, prev_frame,
+                                                  slink));
+  }
+
+  bool call_stack::goto_frame (size_t n, bool verbose)
   {
     bool retval = false;
 
-    if (n < cs.size ())
+    if (n < m_cs.size ())
       {
         retval = true;
 
-        curr_frame = n;
-
-        const stack_frame& elt = cs[n];
+        m_curr_frame = n;
 
-        symbol_table& symtab = m_interpreter.get_symbol_table ();
-
-        symtab.set_scope_and_context (elt.m_scope, elt.m_context);
+        const stack_frame *elt = m_cs[n];
 
         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 << "])"
+          octave_stdout << "stopped in " << elt->fcn_name ()
+                        << " at line " << elt->line ()
+                        << " column " << elt->column ()
+                        << " [" << elt->fcn_file_name () << "] "
                         << std::endl;
       }
 
     return retval;
   }
 
-  bool
-  call_stack::goto_frame_relative (int nskip, bool verbose)
+  bool call_stack::goto_frame_relative (int nskip, bool verbose)
   {
     bool retval = false;
 
@@ -486,19 +518,18 @@
     else if (nskip > 0)
       incr = 1;
 
-    // Start looking with the caller of dbup/dbdown/keyboard.
-    size_t xframe = cs[curr_frame].m_prev;
+    size_t xframe = m_curr_frame;
 
     while (true)
       {
-        if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1))
+        if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == m_cs.size () - 1))
           break;
 
         xframe += incr;
 
-        const stack_frame& elt = cs[xframe];
+        const stack_frame *elt = m_cs[xframe];
 
-        octave_function *f = elt.m_fcn;
+        octave_function *f = elt->function ();
 
         if (xframe == 0 || (f && f->is_user_code ()))
           {
@@ -509,21 +540,16 @@
 
             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);
+                m_curr_frame = xframe;
 
                 if (verbose)
                   {
                     std::ostringstream buf;
 
                     if (f)
-                      buf << "stopped in " << elt.fcn_name ()
-                          << " at line " << elt.m_line
-                          << " [" << elt.fcn_file_name () << "] "
+                      buf << "stopped in " << elt->fcn_name ()
+                          << " at line " << elt->line ()
+                          << " [" << elt->fcn_file_name () << "] "
                           << std::endl;
                     else
                       buf << "at top level" << std::endl;
@@ -537,110 +563,103 @@
           }
         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 call_stack::find_caller_frame (void)
   {
-    size_t xframe = curr_frame;
+    // Find the preceeding frame that corresponds to a script or
+    // function.  Expected to be called from a stack frame corresponding
+    // to a compiled function.
+
+    size_t xframe = m_curr_frame;
 
     bool skipped = false;
 
     while (xframe != 0)
       {
-        xframe = cs[xframe].m_prev;
-
-        const stack_frame& elt = cs[xframe];
+        xframe = m_cs[xframe]->previous ();
 
-        octave_function *f = elt.m_fcn;
-
-        if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ()))
+        stack_frame *frm = m_cs[xframe];
+        if (frm->is_user_fcn_frame () || frm->is_user_script_frame ())
           {
             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;
-              }
+              return xframe;
           }
       }
+
+    return 0;
   }
 
-  void
-  call_stack::goto_base_frame (void)
+  void call_stack::goto_caller_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);
+    m_curr_frame = find_caller_frame ();
   }
 
-  std::list<call_stack::stack_frame>
+  void call_stack::goto_base_frame (void)
+  {
+    if (m_curr_frame > 0)
+      m_curr_frame = 0;
+  }
+
+  std::list<stack_frame *>
   call_stack::backtrace_frames (size_t nskip,
                                 octave_idx_type& curr_user_frame) const
   {
-    std::list<call_stack::stack_frame> retval;
+    stack_trace_generator stack_tracer (nskip);
+
+    // Start at the end of the stack, even if the current pointer is
+    // somewhere else.
+
+    size_t n = m_cs.size () - 1;
 
-    size_t user_code_frames = num_user_code_frames (curr_user_frame);
+    m_cs[n]->accept (stack_tracer);
 
-    size_t nframes = (nskip <= user_code_frames ? user_code_frames - nskip : 0);
+    std::list<stack_frame *> frame_list = stack_tracer.frames ();
+
+    if (frame_list.empty ())
+      return frame_list;
 
-    // Our list is reversed.
-    curr_user_frame = nframes - curr_user_frame - 1;
+    // Find the index into the list of frames where we are currently.
+    // We'll just search the list of frames for the one that matches
+    // where we are now.
+
+    stack_frame *frame = m_cs[m_curr_frame];
+
+    octave_function *fcn = frame->function ();
 
-    if (nframes > 0)
+    if (! (fcn && fcn->is_user_code ()))
+      frame = frame->static_link ();
+
+    curr_user_frame = 0;
+    bool found = false;
+    for (const auto *frm : frame_list)
       {
-        for (auto p = cs.crbegin (); p != cs.crend (); p++)
+        if (frm == frame)
           {
-            const stack_frame& elt = *p;
-
-            octave_function *f = elt.m_fcn;
+            found = true;
+            break;
+          }
 
-            if (f && f->is_user_code ())
-              {
-                if (nskip > 0)
-                  nskip--;
-                else
-                  retval.push_back (elt);
-              }
-          }
+        curr_user_frame++;
       }
 
-    return retval;
+    if (! found)
+      curr_user_frame = -1;
+
+    return frame_list;
   }
 
-  octave_map
-  call_stack::backtrace (size_t nskip, octave_idx_type& curr_user_frame,
-                         bool print_subfn) const
+  octave_map call_stack::backtrace (size_t nskip,
+                                    octave_idx_type& curr_user_frame,
+                                    bool print_subfn) const
   {
-    std::list<call_stack::stack_frame> frames
-      = backtrace_frames (nskip, curr_user_frame);
+    std::list<stack_frame *> frames = backtrace_frames (nskip, curr_user_frame);
 
     size_t nframes = frames.size ();
 
@@ -650,17 +669,15 @@
     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;
+        file(k) = frm->fcn_file_name ();
+        name(k) = frm->fcn_name (print_subfn);
+        line(k) = frm->line ();
+        column(k) = frm->column ();
 
         k++;
       }
@@ -668,64 +685,346 @@
     return retval;
   }
 
-  octave_map
-  call_stack::backtrace (size_t nskip)
+  octave_map call_stack::backtrace (size_t nskip)
   {
     octave_idx_type curr_user_frame = -1;
 
     return backtrace (nskip, 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 () > 0)
       {
-        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 ();
+
+        m_curr_frame = elt->previous ();
 
-        symbol_table& symtab = m_interpreter.get_symbol_table ();
+        m_cs.pop_back ();
 
-        symtab.set_scope_and_context (new_elt.m_scope, new_elt.m_context);
+        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_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 (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)
+  {
+    octave::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;
+
+                    octave::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 display_call_stack (void)
+  {
+    call_stack& cs = __get_call_stack__ ("display_call_stack");
+
+    cs.display ();
+  }
+
+  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,
@@ -764,106 +1063,11 @@
 */
 
 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;
@@ -904,20 +1108,22 @@
       i++;
     }
 
-  int npats = argc - i;
-  string_vector pats;
-  if (npats > 0)
+  int npatterns = argc - i;
+  string_vector patterns;
+  if (npatterns > 0)
     {
-      pats.resize (npats);
-      for (int j = 0; j < npats; j++)
-        pats[j] = argv[i+j];
+      patterns.resize (npatterns);
+      for (int j = 0; j < npatterns; j++)
+        patterns[j] = argv[i+j];
     }
   else
     {
-      pats.resize (1);
-      pats[0] = "*";
+      patterns.resize (1);
+      patterns[0] = "*";
     }
 
+  octave::call_stack& cs = interp.get_call_stack ();
+
   if (from_file)
     {
       // FIXME: This is an inefficient manner to implement this as the
@@ -933,21 +1139,28 @@
 
       octave::symbol_scope tmp_scope ("$dummy_scope$");
 
-      symtab.set_scope (tmp_scope);
-
-      cs.push (tmp_scope, 0);
+      cs.push (tmp_scope);
       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);
+      if (global_only)
+        return cs.do_global_who_two (patterns, have_regexp, return_list,
+                                     verbose, newmsg);
+      else
+        return cs.do_who_two (patterns, have_regexp, return_list,
+                              verbose, newmsg);
     }
   else
-    return do_who_two (interp, pats, global_only, have_regexp,
-                       return_list, verbose);
+    {
+      if (global_only)
+        return cs.do_global_who_two (patterns, have_regexp, return_list,
+                                     verbose);
+      else
+        return cs.do_who_two (patterns, have_regexp, return_list, verbose);
+    }
 }
 
 DEFMETHOD (who, interp, args, nargout,
@@ -996,6 +1209,7 @@
 %!test
 %! avar = magic (4);
 %! ftmp = [tempname() ".mat"];
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   save (ftmp, "avar");
 %!   vars = whos ("-file", ftmp);
@@ -1032,10 +1246,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.
 
--- a/libinterp/corefcn/call-stack.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/call-stack.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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,10 +125,10 @@
     {
       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;
@@ -173,7 +137,7 @@
     // User code caller.
     octave_user_code * caller_user_code (size_t nskip = 0) 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;
@@ -190,48 +154,52 @@
     // Column number in current function that we are debugging.
     int debug_user_code_column (void) const;
 
+    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);
         }
     }
 
@@ -244,15 +212,16 @@
 
     bool goto_frame_relative (int n, bool verbose = false);
 
+    size_t find_caller_frame (void);
+
     void goto_caller_frame (void);
 
     void goto_base_frame (void);
 
-    std::list<call_stack::stack_frame>
+    std::list<stack_frame *>
     backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
 
-    std::list<call_stack::stack_frame>
-    backtrace_frames (size_t nskip = 0) const
+    std::list<stack_frame *> backtrace_frames (size_t nskip = 0) const
     {
       octave_idx_type curr_user_frame = -1;
 
@@ -268,36 +237,86 @@
 
     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_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/cellfun.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/cellfun.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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"
@@ -426,17 +427,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 +452,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 +464,7 @@
         // optimized this way.
         if (f -> is_overloaded ())
           goto nevermind;
+#endif
       }
 
     std::string name = func.function_value () -> name ();
@@ -1141,17 +1138,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 +1163,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 +1175,9 @@
               // optimized this way.
               if (f -> is_overloaded ())
                 goto nevermind;
+#endif
             }
+
           octave_value f
             = symtab.find_function (func.function_value () -> name ());
 
--- a/libinterp/corefcn/daspk.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/daspk.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/dasrt.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/dassl.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/debug.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -90,10 +90,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 +176,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,7 +189,7 @@
     {
       // 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;
@@ -300,6 +304,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 +314,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")
     {
@@ -943,7 +948,7 @@
                  << std::endl;
             }
 
-          if (show_top_level)
+          if (cs.at_top_level () && show_top_level)
             os << "  --> top level" << std::endl;
         }
     }
@@ -951,7 +956,12 @@
     {
       octave_map stk = cs.backtrace (nskip, 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;
--- a/libinterp/corefcn/defun-int.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/defun-int.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/defun.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -83,32 +83,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,23 +135,6 @@
   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)
 {
@@ -205,19 +162,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/display.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/display.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/dot.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/dot.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/error.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/error.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -221,11 +221,7 @@
       octave_user_code *fcn = cs.caller_user_code ();
 
       if (fcn)
-        {
-          octave_idx_type curr_frame = -1;
-
-          Vlast_error_stack = cs.backtrace (0, curr_frame);
-        }
+        Vlast_error_stack = cs.backtrace ();
       else
         Vlast_error_stack = initialize_last_error_stack ();
     }
@@ -315,21 +311,20 @@
 {
   octave::call_stack& cs = octave::__get_call_stack__ ("pr_where");
 
-  std::list<octave::call_stack::stack_frame> call_stack_frames
-    = cs.backtrace_frames ();
+  std::list<octave::stack_frame *> call_stack_frames = cs.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);
     }
@@ -1565,22 +1560,18 @@
           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 ())
+          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_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 +1619,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.
@@ -1825,7 +1816,7 @@
 
 /*
 %!test <*51997>
-%! id = "Octave:divide-by-zero";
+%! id = "Octave:logical-conversion";
 %! current = warning ("query", id);
 %! current_all = warning ();
 %! previous = warning (current_all);
@@ -2038,12 +2029,9 @@
             }
           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);
+              Vlast_error_stack = cs.backtrace ();
             }
         }
       else
--- a/libinterp/corefcn/errwarn.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/errwarn.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -324,12 +324,6 @@
 }
 
 void
-warn_divide_by_zero (void)
-{
-  warning_with_id ("Octave:divide-by-zero", "division by zero");
-}
-
-void
 warn_empty_arg (const char *name)
 {
   warning ("%s: argument is empty matrix", name);
--- a/libinterp/corefcn/errwarn.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/errwarn.h	Mon Mar 25 10:56:14 2019 +0000
@@ -164,9 +164,6 @@
                        const std::string& pkg = "Octave");
 
 OCTINTERP_API extern void
-warn_divide_by_zero (void);
-
-OCTINTERP_API extern void
 warn_empty_arg (const char *name);
 
 OCTINTERP_API extern void
@@ -185,4 +182,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/event-queue.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/fcn-info.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -333,21 +333,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 +364,30 @@
 
         lp.update ();
 
-        retval = xfind (args);
+        retval = xfind (search_scope, args);
       }
 
     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 +399,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 +543,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 +561,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 +595,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 +658,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;
--- a/libinterp/corefcn/fcn-info.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/fcn-info.h	Mon Mar 25 10:56:14 2019 +0000
@@ -33,6 +33,7 @@
 
 #include "ov.h"
 #include "ovl.h"
+#include "symscope.h"
 
 namespace octave
 {
@@ -73,17 +74,16 @@
 
       ~fcn_info_rep (void) = default;
 
-      octave_value install_local_function (const std::string& file_name);
-
       octave_value load_private_function (const std::string& dir_name);
 
       octave_value load_class_constructor (void);
 
       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 +98,15 @@
         return function_on_path.is_defined ();
       }
 
-      octave_value find_function (const octave_value_list& args)
+      bool is_package_defined (void) const
       {
-        return find (args);
+        return package.is_defined ();
+      }
+
+      octave_value find_function (const symbol_scope& search_scope,
+                                  const octave_value_list& args)
+      {
+        return find (search_scope, args);
       }
 
       void install_cmdline_function (const octave_value& f)
@@ -114,6 +120,11 @@
         local_functions[file_name] = f;
       }
 
+      void install_package (const octave_value& pack)
+      {
+        package = pack;
+      }
+
       void install_user_function (const octave_value& f)
       {
         function_on_path = f;
@@ -221,9 +232,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 +249,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 +281,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 +292,16 @@
       return m_rep->is_user_function_defined ();
     }
 
-    octave_value find_function (const octave_value_list& args
-                                = octave_value_list ())
+    bool is_package_defined (void) const
     {
-      return m_rep->find_function (args);
+      return m_rep->is_package_defined ();
+    }
+
+    octave_value
+    find_function (const symbol_scope& search_scope,
+                   const octave_value_list& args = octave_value_list ())
+    {
+      return m_rep->find_function (search_scope, args);
     }
 
     void install_cmdline_function (const octave_value& f)
@@ -294,6 +315,11 @@
       m_rep->install_local_function (f, file_name);
     }
 
+    void install_package (const octave_value& pack)
+    {
+      m_rep->install_package (pack);
+    }
+
     void install_user_function (const octave_value& f)
     {
       m_rep->install_user_function (f);
--- a/libinterp/corefcn/file-io.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/file-io.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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"
@@ -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);
@@ -2214,43 +2235,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/ft-text-renderer.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
 
@@ -546,6 +539,9 @@
 
     // Used for computing the distance between lines.
     double m_max_fontsize;
+    
+    // Anti-aliasing.
+    bool m_antialias;
 
   };
 
@@ -712,7 +708,17 @@
         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 ())
                             {
--- a/libinterp/corefcn/gl-render.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/gl-render.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/gl-render.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/gl2ps-print.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
@@ -1027,6 +1028,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
--- a/libinterp/corefcn/graphics.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/graphics.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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,10 +1798,16 @@
 }
 
 void
-children_property::do_delete_children (bool clear)
-{
-  while (! children_list.empty ())
-    gh_manager::free (children_list.front ());
+children_property::do_delete_children (bool clear, bool from_root)
+{
+  for (graphics_handle hchild : children_list)
+    {
+      graphics_object go = gh_manager::get_object (hchild);
+
+      if (hchild.value () > 0 && go.valid_object ()
+          && ! go.get_properties ().is_beingdeleted ())
+        gh_manager::free (hchild, from_root);
+    }
 
   if (clear)
     children_list.clear ();
@@ -2720,7 +2752,7 @@
 }
 
 void
-gh_manager::do_free (const graphics_handle& h)
+gh_manager::do_free (const graphics_handle& h, bool from_root)
 {
   if (h.ok ())
     {
@@ -2738,7 +2770,9 @@
         return;
 
       graphics_handle parent_h = p->second.get_parent ();
-      graphics_object parent_go = gh_manager::get_object (parent_h);
+      graphics_object parent_go = nullptr;
+      if (! from_root)
+        parent_go = gh_manager::get_object (parent_h);
 
       bp.set_beingdeleted (true);
 
@@ -2755,9 +2789,11 @@
       // Notify graphics toolkit.
       p->second.finalize ();
 
-      // NOTE: Call remove_child before erasing the go from the map.
+
+      // NOTE: Call remove_child before erasing the go from the map if not
+      // removing from groot.
       // A callback function might have already deleted the parent
-      if (parent_go.valid_object () && h.ok ())
+      if (! from_root && parent_go.valid_object () && h.ok ())
         parent_go.remove_child (h);
 
       // Note: this will be valid only for first explicitly deleted
@@ -2884,7 +2920,7 @@
 }
 
 static void
-delete_graphics_object (const graphics_handle& h)
+delete_graphics_object (const graphics_handle& h, bool from_root = false)
 {
   if (h.ok ())
     {
@@ -2896,7 +2932,7 @@
           // NOTE: Freeing the handle also calls any deletefcn.  It also calls
           //       the parent's delete_child function.
 
-          gh_manager::free (h);
+          gh_manager::free (h, from_root);
 
           Vdrawnow_requested = true;
         }
@@ -2904,16 +2940,16 @@
 }
 
 static void
-delete_graphics_object (double val)
-{
-  delete_graphics_object (gh_manager::lookup (val));
+delete_graphics_object (double val, bool from_root = false)
+{
+  delete_graphics_object (gh_manager::lookup (val), from_root);
 }
 
 // Flag to stop redraws due to callbacks while deletion is in progress.
 static bool delete_executing = false;
 
 static void
-delete_graphics_objects (const NDArray vals)
+delete_graphics_objects (const NDArray vals, bool from_root = false)
 {
   // Prevent redraw of partially deleted objects.
   octave::unwind_protect frame;
@@ -2921,7 +2957,7 @@
   delete_executing = true;
 
   for (octave_idx_type i = 0; i < vals.numel (); i++)
-    delete_graphics_object (vals.elem (i));
+    delete_graphics_object (vals.elem (i), from_root);
 }
 
 static void
@@ -2941,7 +2977,7 @@
   xset (h, "deletefcn", Matrix ());
   xset (h, "closerequestfcn", Matrix ());
 
-  delete_graphics_object (h);
+  delete_graphics_object (h, true);
 }
 
 void
@@ -3900,7 +3936,7 @@
 */
 
 void
-root_figure::properties::remove_child (const graphics_handle& h)
+root_figure::properties::remove_child (const graphics_handle& h, bool)
 {
   gh_manager::pop_figure (h);
 
@@ -3908,7 +3944,7 @@
 
   xset (0, "currentfigure", cf.value ());
 
-  base_properties::remove_child (h);
+  base_properties::remove_child (h, true);
 }
 
 void
@@ -3936,9 +3972,9 @@
 }
 
 void
-figure::properties::remove_child (const graphics_handle& h)
-{
-  base_properties::remove_child (h);
+figure::properties::remove_child (const graphics_handle& h, bool from_root)
+{
+  base_properties::remove_child (h, from_root);
 
   if (h == currentaxes.handle_value ())
     {
@@ -5082,9 +5118,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");
@@ -5102,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");
 %! unwind_protect
 %!   plot (rand (3));
@@ -5122,9 +5158,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
@@ -5283,8 +5319,6 @@
   // Note: dataspectratio (not mode) will be set through update_aspectratios
   dataaspectratiomode = "auto";
 
-  drawmode = "normal";
-
   fontangle = "normal";
   fontname = OCTAVE_DEFAULT_FONTNAME;
   fontsize = 10;
@@ -5459,7 +5493,7 @@
 }
 
 void
-axes::properties::delete_text_child (handle_property& hp)
+axes::properties::delete_text_child (handle_property& hp, bool from_root)
 {
   graphics_handle h = hp.handle_value ();
 
@@ -5468,7 +5502,7 @@
       graphics_object go = gh_manager::get_object (h);
 
       if (go.valid_object ())
-        gh_manager::free (h);
+        gh_manager::free (h, from_root);
     }
 
   // FIXME: is it necessary to check whether the axes object is
@@ -5488,36 +5522,36 @@
 }
 
 void
-axes::properties::remove_child (const graphics_handle& h)
+axes::properties::remove_child (const graphics_handle& h, bool from_root)
 {
   graphics_object go = gh_manager::get_object (h);
 
-  if (go.isa ("light") && go.get_properties ().is_visible ())
-    decrease_num_lights ();
-
   if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
     {
-      delete_text_child (xlabel);
+      delete_text_child (xlabel, from_root);
       update_xlabel_position ();
     }
   else if (ylabel.handle_value ().ok () && h == ylabel.handle_value ())
     {
-      delete_text_child (ylabel);
+      delete_text_child (ylabel, from_root);
       update_ylabel_position ();
     }
   else if (zlabel.handle_value ().ok () && h == zlabel.handle_value ())
     {
-      delete_text_child (zlabel);
+      delete_text_child (zlabel, from_root);
       update_zlabel_position ();
     }
   else if (title.handle_value ().ok () && h == title.handle_value ())
     {
-      delete_text_child (title);
+      delete_text_child (title, from_root);
       update_title_position ();
     }
+  else if (get_num_lights () > 0 && go.isa ("light")
+           && go.get_properties ().is_visible ())
+    decrease_num_lights ();
 
   if (go.valid_object ())
-      base_properties::remove_child (h);
+    base_properties::remove_child (h, from_root);
 
 }
 
@@ -6116,7 +6150,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));
@@ -7192,31 +7228,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),
@@ -7610,18 +7650,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;
     }
 
@@ -9152,7 +9191,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
@@ -9398,6 +9442,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)
 {
@@ -9441,53 +9583,37 @@
 
   // check coplanarity for 3D-faces with more than 3 corners
   int fcmax = idx.rows ();
-  if (fcmax > 3 && vert.columns () > 2 && 
+  if (fcmax > 3 && vert.columns () > 2 &&
       ! (facecolor_is ("none") && edgecolor_is ("none")))
     {
       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));
         }
     }
 
@@ -10105,17 +10231,17 @@
 // ---------------------------------------------------------------------
 
 void
-hggroup::properties::remove_child (const graphics_handle& h)
+hggroup::properties::remove_child (const graphics_handle& h, bool from_root)
 {
   graphics_object go = gh_manager::get_object (h);
-  if (go.isa ("light") && go.get_properties ().is_visible ())
+  if (! from_root && go.isa ("light") && go.get_properties ().is_visible ())
     {
       axes::properties& ax_props =
         dynamic_cast<axes::properties&>
         (go.get_ancestor ("axes").get_properties ());
       ax_props.decrease_num_lights ();
     }
-  base_properties::remove_child (h);
+  base_properties::remove_child (h, from_root);
   update_limits ();
 }
 
@@ -11224,9 +11350,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
@@ -11585,6 +11709,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 ();
@@ -11609,8 +11734,10 @@
       // Copy CB because "function_value" method is non-const.
       octave_value cb = cb_arg;
 
-      if (cb.is_function () || cb.is_function_handle ())
+      if (cb.is_function ())
         fcn = cb.function_value ();
+      else if (cb.is_function_handle ())
+        ov_fcn = cb;
       else if (cb.is_string ())
         {
           int status;
@@ -11638,7 +11765,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);
@@ -11650,10 +11777,13 @@
                  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&)
           {
@@ -11839,8 +11969,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/graphics.in.h	Mon Mar 25 10:56:14 2019 +0000
@@ -1759,9 +1759,9 @@
     return octave_value (get_children ());
   }
 
-  void delete_children (bool clear = false)
-  {
-    do_delete_children (clear);
+  void delete_children (bool clear = false, bool from_root = false)
+  {
+    do_delete_children (clear, from_root);
   }
 
   void renumber (graphics_handle old_gh, graphics_handle new_gh)
@@ -1885,7 +1885,7 @@
     children_list.push_front (val);
   }
 
-  void do_delete_children (bool clear);
+  void do_delete_children (bool clear, bool from_root);
 };
 
 // ---------------------------------------------------------------------
@@ -2234,7 +2234,7 @@
 
   bool is_modified (void) const { return is___modified__ (); }
 
-  virtual void remove_child (const graphics_handle& h)
+  virtual void remove_child (const graphics_handle& h, bool = false)
   {
     if (children.remove_child (h.value ()))
       {
@@ -2306,9 +2306,9 @@
 
   virtual void update_uicontextmenu (void) const;
 
-  virtual void delete_children (bool clear = false)
-  {
-    children.delete_children (clear);
+  virtual void delete_children (bool clear = false, bool from_root = false)
+  {
+    children.delete_children (clear, from_root);
   }
 
   void renumber_child (graphics_handle old_gh, graphics_handle new_gh)
@@ -2468,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");
@@ -2538,12 +2541,12 @@
     return get_properties ().get___myhandle__ ();
   }
 
-  virtual void remove_child (const graphics_handle& h)
+  virtual void remove_child (const graphics_handle& h, bool from_root = false)
   {
     if (! valid_object ())
       error ("base_graphics_object::remove_child: invalid graphics object");
 
-    get_properties ().remove_child (h);
+    get_properties ().remove_child (h, from_root);
   }
 
   virtual void adopt (const graphics_handle& h)
@@ -2892,7 +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 = false);
 
     Matrix get_boundingbox (bool internal = false,
                             const Matrix& parent_pix_size = Matrix ()) const;
@@ -3073,7 +3076,7 @@
       integerhandle = val;
     }
 
-    void remove_child (const graphics_handle& h);
+    void remove_child (const graphics_handle& h, bool from_root = false);
 
     void set_visible (const octave_value& val);
 
@@ -3187,16 +3190,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:
@@ -3408,7 +3401,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 = false);
 
     void adopt (const graphics_handle& h);
 
@@ -3606,7 +3599,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 = false);
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -3637,16 +3630,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
@@ -3680,7 +3672,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"
@@ -3697,7 +3689,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"
@@ -3712,7 +3704,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"
@@ -3979,6 +3971,10 @@
       update_font ("fontsize");
       sync_positions ();
     }
+    void update_fontsmoothing (void)
+    {
+      update_font ("fontsmoothing");
+    }
     void update_fontangle (void)
     {
       update_font ("fontangle");
@@ -4257,12 +4253,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:
@@ -4280,11 +4276,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:
@@ -4354,7 +4346,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)
@@ -4362,8 +4354,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"
@@ -4416,19 +4409,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);
         }
@@ -4444,21 +4441,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 (); }
@@ -4555,9 +4561,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));
@@ -4857,6 +4868,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));
@@ -5109,6 +5132,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");
@@ -5231,7 +5264,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 = false);
 
     void adopt (const graphics_handle& h);
 
@@ -5305,9 +5338,9 @@
   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 = false)
     {
-      base_properties::remove_child (h);
+      base_properties::remove_child (h, from_root);
     }
 
     void adopt (const graphics_handle& h)
@@ -5464,7 +5497,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 ()
@@ -5507,17 +5540,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);
 
@@ -5577,7 +5609,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 ()
@@ -5610,15 +5642,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);
@@ -5677,7 +5701,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 ()
@@ -5705,14 +5729,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:
@@ -5779,7 +5795,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 ()
@@ -5813,18 +5829,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:
@@ -5973,6 +5987,7 @@
       string_property tooltipstring , ""
 
       // Octave-specific properties
+      string_property __named_icon__ , ""
       any_property __object__ h , Matrix ()
     END_PROPERTIES
 
@@ -6036,6 +6051,7 @@
       string_property tooltipstring , ""
 
       // Octave-specific properties
+      string_property __named_icon__ , ""
       any_property __object__ h , Matrix ()
     END_PROPERTIES
 
@@ -6208,10 +6224,10 @@
            : graphics_handle ();
   }
 
-  static void free (const graphics_handle& h)
+  static void free (const graphics_handle& h, bool from_root = false)
   {
     if (instance_ok ())
-      instance->do_free (h);
+      instance->do_free (h, from_root);
   }
 
   static void renumber_figure (const graphics_handle& old_gh,
@@ -6463,7 +6479,7 @@
 
   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,
                            const graphics_handle& new_gh);
--- a/libinterp/corefcn/help.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/help.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -319,7 +319,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 ();
@@ -841,10 +841,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 +858,7 @@
 %!   assert (d{2} (3), 6);
 %! unwind_protect_cleanup
 %!   unlink (f);
+%!   path (save_path);
 %! end_unwind_protect
 */
 
--- a/libinterp/corefcn/input.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/input.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -150,23 +150,6 @@
     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)
@@ -201,9 +184,7 @@
       octave::interpreter& interp
         = octave::__get_interpreter__ ("generate_struct_completions");
 
-      octave::symbol_table& symtab = interp.get_symbol_table ();
-
-      if (is_variable (symtab, base_name))
+      if (interp.is_variable (base_name))
         {
           int parse_status;
 
@@ -1264,8 +1245,8 @@
   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);
+  // Go up to the nearest user code frame.
+  cs.goto_frame_relative (-1);
 
   octave::tree_evaluator& tw = interp.get_evaluator ();
 
--- a/libinterp/corefcn/interpreter-private.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/interpreter-private.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -24,10 +24,12 @@
 #  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 +40,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"
 
@@ -178,4 +181,44 @@
 
     return interp.get_gtk_manager ();
   }
+
+  octave_value
+  get_function_handle (octave::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 (octave::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 ();
+
+        octave::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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/interpreter-private.h	Mon Mar 25 10:56:14 2019 +0000
@@ -25,16 +25,16 @@
 
 #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 gtk_manager;
@@ -83,6 +83,24 @@
   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 (octave::interpreter& interp, const octave_value& arg,
+                       const std::string& parameter_name);
+
+  octave_value
+  get_function_handle (octave::interpreter& interp, const octave_value& arg,
+                       const std::list<std::string>& parameter_names
+                         = std::list<std::string> ());
 }
 
 #endif
--- a/libinterp/corefcn/interpreter.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/interpreter.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -367,7 +367,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 (),
@@ -417,7 +417,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 +539,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 +714,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 +761,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.
@@ -1062,13 +1089,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 ();
 
@@ -1150,6 +1183,170 @@
     return m_evaluator.eval_string (arg, silent, parse_status, 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);
+  }
+
+  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 ();
+  }
+
   void interpreter::recover_from_exception (void)
   {
     can_interrupt = true;
--- a/libinterp/corefcn/interpreter.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/interpreter.h	Mon Mar 25 10:56:14 2019 +0000
@@ -25,12 +25,14 @@
 
 #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 "gtk-manager.h"
@@ -40,7 +42,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"
@@ -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);
@@ -194,24 +195,25 @@
       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;
-    }
-
-    symbol_scope get_current_scope (void);
-    symbol_scope require_current_scope (const std::string& who);
+    tree_evaluator& get_evaluator (void);
 
     call_stack& get_call_stack (void);
 
-    profiler& get_profiler (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;
 
-    tree_evaluator& get_evaluator (void);
+    profiler& get_profiler (void);
 
     stream_list& get_stream_list (void);
 
@@ -247,6 +249,76 @@
     octave_value_list eval_string (const octave_value& arg, bool silent,
                                    int& parse_status, int nargout);
 
+    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 ());
+
+    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);
+
     static void recover_from_exception (void);
 
     static void add_atexit_function (const std::string& fname);
@@ -271,7 +343,7 @@
 
     void display_startup_message (void) const;
 
-    int execute_startup_files (void) const;
+    int execute_startup_files (void);
 
     int execute_eval_option_code (void);
 
@@ -340,29 +412,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/load-path.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/load-path.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -1225,7 +1225,7 @@
   }
 
   void
-  load_path::dir_info::initialize (void)
+  load_path::dir_info::initialize (const std::string& parent_package)
   {
     is_relative = ! sys::env::absolute_pathname (dir_name);
 
@@ -1241,7 +1241,7 @@
         dir_mtime = fs.mtime ();
         dir_time_last_checked = sys::time ();
 
-        get_file_list (dir_name);
+        get_file_list (dir_name, parent_package);
 
         try
           {
@@ -1269,7 +1269,8 @@
   }
 
   void
-  load_path::dir_info::get_file_list (const std::string& d)
+  load_path::dir_info::get_file_list (const std::string& d,
+                                      const std::string& parent_package)
   {
     sys::dir_entry dir (d);
 
@@ -1302,7 +1303,14 @@
                     else if (fname[0] == '@')
                       get_method_file_map (full_name, fname.substr (1));
                     else if (fname[0] == '+')
-                      get_package_dir (full_name, fname.substr (1));
+                      {
+                        std::string pkg_name = fname.substr (1);
+
+                        if (! parent_package.empty ())
+                          pkg_name = parent_package + "." + pkg_name;
+
+                        get_package_dir (full_name, pkg_name);
+                      }
                   }
                 else
                   {
@@ -1360,7 +1368,12 @@
   load_path::dir_info::get_package_dir (const std::string& d,
                                         const std::string& package_name)
   {
-    package_dir_map[package_name] = dir_info (d);
+    symbol_table& symtab
+      = __get_symbol_table__ ("load_path::dir_info::get_package_dir");
+
+    symtab.install_package (package_name);
+
+    package_dir_map[package_name] = dir_info (d, package_name);
   }
 
   void
--- a/libinterp/corefcn/load-path.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/load-path.h	Mon Mar 25 10:56:14 2019 +0000
@@ -262,12 +262,12 @@
       // constructor for any other purpose.
       dir_info (void) = default;
 
-      dir_info (const std::string& d)
+      dir_info (const std::string& d, const std::string& parent_package = "")
         : dir_name (d), abs_dir_name (), is_relative (false),
           dir_mtime (), dir_time_last_checked (), all_files (), fcn_files (),
           private_file_map (), method_file_map (), package_dir_map ()
       {
-        initialize ();
+        initialize (parent_package);
       }
 
       dir_info (const dir_info&) = default;
@@ -293,9 +293,10 @@
 
     private:
 
-      void initialize (void);
+      void initialize (const std::string& parent_package = "");
 
-      void get_file_list (const std::string& d);
+      void get_file_list (const std::string& d,
+                          const std::string& parent_package);
 
       void get_private_file_map (const std::string& d);
 
--- a/libinterp/corefcn/load-save.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/load-save.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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 ());
@@ -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-mat5.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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,14 +976,11 @@
             // 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);
+
+            octave::symbol_scope local_scope ("read_mat5_binary_element$dummy_scope");
+
+            cs.push (local_scope);
             frame.add_method (cs, &octave::call_stack::pop);
 
             if (m2.nfields () > 0)
@@ -995,7 +992,7 @@
                     std::string key = m2.key (p0);
                     octave_value val = m2.contents (p0);
 
-                    local_scope.assign (key, val, 0);
+                    interp.assign (key, val);
                   }
               }
 
@@ -1191,7 +1188,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 +1492,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/ls-oct-text.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/lsode.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/mappers.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/mex.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -50,6 +50,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"
@@ -3484,13 +3485,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 +3505,14 @@
 
           if (base)
             {
-              octave::call_stack& cs
-                = octave::__get_call_stack__ ("mexGetVariable");
+              octave::call_stack& cs = interp.get_call_stack ();
 
               cs.goto_base_frame ();
 
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          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 +3549,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 +3569,14 @@
 
           if (base)
             {
-              octave::call_stack& cs
-                = octave::__get_call_stack__ ("mexPutVariable");
+              octave::call_stack& cs = interp.get_call_stack ();
 
               cs.goto_base_frame ();
 
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -82,7 +82,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 \
@@ -232,6 +235,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/oct-errno.in.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-errno.in.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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-map.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-map.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-prcstrm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-prcstrm.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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:
 
--- a/libinterp/corefcn/oct-stdstrm.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-stdstrm.h	Mon Mar 25 10:56:14 2019 +0000
@@ -40,8 +40,9 @@
                        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),
+    : octave::base_stream (m, ff, encoding), nm (n), md (m),
       s (f ? new STREAM_T (f, cf) : nullptr), fnum (fid)
   { }
 
@@ -108,18 +109,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 +148,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-stream.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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"
@@ -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
@@ -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.
@@ -4529,6 +4545,8 @@
 #define FINISH_CHARACTER_CONVERSION()                                   \
   do                                                                    \
     {                                                                   \
+      if (encoding ().compare ("utf-8"))                                \
+        tmp = octave::string::u8_from_encoding (who, tmp, encoding ()); \
       width = tmp.length ();                                            \
                                                                         \
       if (is)                                                           \
@@ -5306,7 +5324,7 @@
       invalid_operation (who, "reading");
     else
       {
-        textscan scanner (who);
+        textscan scanner (who, encoding ());
 
         retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
       }
@@ -5557,7 +5575,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 +5586,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;
   }
@@ -5846,7 +5871,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,
@@ -5886,10 +5912,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)
@@ -7470,7 +7499,7 @@
 
   string_vector stream_list::get_info (int fid) const
   {
-    string_vector retval (3);
+    string_vector retval (4);
 
     if (fid < 0)
       return retval;
@@ -7495,6 +7524,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;
   }
--- a/libinterp/corefcn/oct-stream.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-stream.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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")
+      : count (0), md (arg_md), flt_fmt (ff), mencoding (encoding),
+        fail (false), open_state (true), errmsg ()
     { }
 
     // No copying!
@@ -152,6 +153,8 @@
 
     mach_info::float_format float_format (void) const { return flt_fmt; }
 
+    std::string encoding (void) const { return mencoding; }
+
     // Set current error state and set fail to TRUE.
 
     void error (const std::string& msg);
@@ -177,6 +180,9 @@
     // Data format.
     mach_info::float_format flt_fmt;
 
+    // Code page
+    std::string mencoding;
+
     // TRUE if an error has occurred.
     bool fail;
 
@@ -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" */);
@@ -362,6 +368,11 @@
     mach_info::float_format float_format (void) const;
 
     static std::string mode_as_string (int mode);
+    
+    std::string encoding (void)
+    {
+      return rep ? rep->encoding () : std::string ();
+    }
 
     std::istream * input_stream (void)
     {
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-strstrm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/oct-strstrm.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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), is (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), is (data) { }
 
   // No copying!
 
@@ -104,12 +107,14 @@
   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.
 
@@ -139,8 +144,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), os () { }
 
   // No copying!
 
@@ -157,7 +163,8 @@
   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.
 
--- a/libinterp/corefcn/octave-link.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/octave-link.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -37,7 +37,6 @@
 #include "ovl.h"
 #include "pager.h"
 #include "syminfo.h"
-#include "symtab.h"
 
 static int
 octave_readline_hook (void)
@@ -69,13 +68,10 @@
 {
   if (enabled ())
     {
-      octave::symbol_table& symtab
-         = octave::__get_symbol_table__ ("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 (cs.at_top_level (),
                                   instance->debugging,
                                   cs.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/pager.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/pager.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -426,13 +426,10 @@
       {
         m_external_pager = new oprocstream (pgr.c_str ());
 
-        if (m_external_pager)
-          {
-            octave::child_list& kids = m_interpreter.get_child_list ();
+        octave::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);
       }
   }
 
--- a/libinterp/corefcn/pager.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/pager.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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-output.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/pr-output.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -3163,17 +3163,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/quad.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/quad.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/quadcc.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,1497 @@
+/*
+
+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 "call-stack.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 "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_call_stack.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_call_stack.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 (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 << "prev: " << m_prev << 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 (call_stack& cs,
+                                          octave_user_script *script,
+                                          unwind_protect *up_frame,
+                                          size_t prev,
+                                          stack_frame *static_link)
+    : stack_frame (cs, prev, 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);
+        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);
+        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_call_stack.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_call_stack.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_call_stack.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_call_stack.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_call_stack.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_call_stack.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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,1051 @@
+/*
+
+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 "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 call stack that contains the frame
+//
+//    Global variables are now stored in the call stack 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 call_stack;
+  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 call_stack 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 (call_stack& cs, size_t prev, stack_frame *static_link,
+                 stack_frame *access_link)
+      : m_call_stack (cs), m_line (-1), m_column (-1), m_prev (prev),
+        m_static_link (static_link), m_access_link (access_link)
+    { }
+
+    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 previous (void) const { return m_prev; }
+
+    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);
+
+    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.
+    call_stack& m_call_stack;
+
+    // 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;
+
+    // FIXME: We could probably eliminate this variable.  Now that we
+    // maintain the static and access links to previous frames, this
+    // index should not be necessary.
+    size_t m_prev;
+
+    // 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;
+  };
+
+  class compiled_fcn_stack_frame : public stack_frame
+  {
+  public:
+
+    compiled_fcn_stack_frame (void) = delete;
+
+    compiled_fcn_stack_frame (call_stack& cs, octave_function *fcn,
+                              size_t prev, stack_frame *static_link)
+      : stack_frame (cs, prev, 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 (call_stack& cs, octave_user_script *script,
+                        unwind_protect *up_frame, size_t prev,
+                        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 (call_stack& cs, size_t num_symbols,
+                            size_t prev, stack_frame *static_link,
+                            stack_frame *access_link)
+      : stack_frame (cs, prev, 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 call_stack 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 (call_stack& cs, octave_user_function *fcn,
+                          unwind_protect *up_frame, size_t prev,
+                          stack_frame *static_link,
+                          stack_frame *access_link = nullptr)
+      : base_value_stack_frame (cs, get_num_symbols (fcn), prev, 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 (call_stack& cs, size_t prev, const symbol_scope& scope,
+                       stack_frame *static_link)
+      : base_value_stack_frame (cs, scope.num_symbols (), prev,
+                                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/svd.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/svd.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,291 @@
+/*
+
+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;
+
+    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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/syminfo.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -105,14 +105,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 +172,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
@@ -314,7 +323,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 +355,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/syminfo.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symrec.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -37,85 +37,25 @@
 #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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symrec.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symscope.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symscope.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symtab.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -25,6 +25,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include <sstream>
 
 #include "file-ops.h"
@@ -33,6 +35,10 @@
 #include "oct-time.h"
 
 #include "bp-table.h"
+#include "call-stack.h"
+#include "cdef-manager.h"
+#include "cdef-package.h"
+#include "cdef-utils.h"
 #include "defun.h"
 #include "dirfns.h"
 #include "fcn-info.h"
@@ -57,9 +63,635 @@
 
 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)
+  {
+    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);
+
+    if (p != m_fcn_table.end ())
+      return p->second.find_method (dispatch_type);
+    else
+      {
+        fcn_info finfo (name);
+
+        octave_value fcn = finfo.find_method (dispatch_type);
+
+        if (fcn.is_defined ())
+          m_fcn_table[name] = finfo;
+
+        return fcn;
+      }
+  }
+
+  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 ());
+  }
+
+  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);
+
+    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;
+      }
+
+    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 (name[0] == '@')
+      {
+        size_t pos = name.find_first_of ('/');
+
+        if (pos == std::string::npos)
+          return octave_value ();
+
+        std::string method = name.substr (pos+1);
+        std::string dispatch_type = name.substr (1, pos-1);
+
+        return find_method (method, dispatch_type);
+      }
+    else
+      {
+        symbol_scope search_scope
+          = (search_scope_arg ? search_scope_arg : current_scope ());
+
+        return find_function (name, ovl (), search_scope);
+      }
+  }
+
+  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 ());
+  }
+
+  octave_value symbol_table::find_cmdline_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_cmdline_function () : octave_value ());
+  }
+
+  void symbol_table::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;
+      }
+  }
+
+  // Install local function FCN named NAME.  FILE_NAME is the name of
+  // the file containing the local function.
+
+  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 (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;
+      }
+  }
+
+  void symbol_table::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;
+      }
+  }
+
+  // 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)
+  {
+    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_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)
+  {
+    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)
+  {
+    if (is_superiorto (inf_class, sup_class))
+      return false;
+
+    // If sup_class doesn't have an entry in the precedence table,
+    // this will automatically create it, and associate to it a
+    // singleton set {inf_class} of inferior classes.
+    m_class_precedence_table[sup_class].insert (inf_class);
+
+    return true;
+  }
+
+  // Has class A been marked as superior to class B?  Also returns
+  // TRUE if B has been marked as inferior to A, since we only keep
+  // one table, and convert inferiorto information to a superiorto
+  // relationship.  Two calls are required to determine whether there
+  // is no relationship between two classes:
+  //
+  //  if (symbol_table::is_superiorto (a, b))
+  //    // A is superior to B, or B has been marked inferior to A.
+  //  else if (symbol_table::is_superiorto (b, a))
+  //    // B is superior to A, or A has been marked inferior to B.
+  //  else
+  //    // No relation.
+
+  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
+    if (p == m_class_precedence_table.end ())
+      return false;
+
+    const std::set<std::string>& inferior_classes = p->second;
+    std::set<std::string>::const_iterator q = inferior_classes.find (b);
+    return (q != inferior_classes.end ());
+  }
+
+  void symbol_table::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 ());
+  }
+
+  void symbol_table::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 ());
+  }
+
+  // Install a +package directory object in the function table.
+  void symbol_table::install_package (const std::string& name)
+  {
+    auto p = m_fcn_table.find (name);
+
+    bool found_in_fcn_table = (p != m_fcn_table.end ());
+
+    if (found_in_fcn_table)
+      {
+        fcn_info& finfo = p->second;
+
+        if (finfo.is_package_defined ())
+          return;
+      }
+
+    cdef_manager& cdm = m_interpreter.get_cdef_manager ();
+
+    octave_function *tmp = cdm.make_package_symbol (name);
+
+    if (! tmp)
+      return;
+
+    octave_value pack = tmp;
+
+    if (found_in_fcn_table)
+      {
+        fcn_info& finfo = p->second;
+
+        finfo.install_package (pack);
+      }
+    else
+      {
+        fcn_info finfo (name);
+
+        finfo.install_package (pack);
+
+        m_fcn_table[name] = finfo;
+      }
+  }
+
+  std::list<std::string> symbol_table::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> symbol_table::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> symbol_table::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;
+  }
+
+  template <template <typename, typename...> class C, typename V,
+            typename... A>
+  static octave_value
+  dump_container_map (const std::map<std::string, C<V, A...>>& container_map)
+  {
+    if (container_map.empty ())
+      return octave_value (Matrix ());
+
+    std::map<std::string, octave_value> info_map;
+
+    for (const auto& nm_container : container_map)
+      {
+        std::string nm = nm_container.first;
+        const C<V, A...>& container = nm_container.second;
+        info_map[nm] = Cell (container);
+      }
+
+    return octave_value (info_map);
+  }
+
+  octave_value symbol_table::dump (void) const
+  {
+    std::map<std::string, octave_value> m
+      = {{ "function_info", dump_fcn_table_map () },
+         { "precedence_table", dump_container_map (m_class_precedence_table) },
+         { "parent_classes", dump_container_map (m_parent_map) }};
+
+    return octave_value (m);
+  }
+
+  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)
+  {
+    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 ();
+  }
+
+  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 ());
+
+    std::map<std::string, octave_value> info_map;
+
+    for (const auto& nm_finfo : m_fcn_table)
+      {
+        std::string nm = nm_finfo.first;
+        const fcn_info& finfo = nm_finfo.second;
+        info_map[nm] = finfo.dump ();
+      }
+
+    return octave_value (info_map);
+  }
+
+  static void split_name_with_package (const std::string& name,
+                                       std::string& fname, std::string& pname)
   {
     size_t pos = name.rfind ('.');
 
@@ -98,7 +730,7 @@
 
     octave_value ov_fcn
       = load_fcn_from_file (ff, dir_name, dispatch_type,
-                                    package_name);
+                            package_name);
 
     if (ov_fcn.is_defined ())
       {
@@ -112,10 +744,9 @@
     return retval;
   }
 
-  bool
-  out_of_date_check (octave_value& function,
-                     const std::string& dispatch_type,
-                     bool check_relative)
+  bool out_of_date_check (octave_value& function,
+                          const std::string& dispatch_type,
+                          bool check_relative)
   {
     bool retval = false;
 
@@ -125,7 +756,7 @@
       {
         // FIXME: we need to handle subfunctions properly here.
 
-        if (! fcn->is_subfunction ())
+        if (! (fcn->is_subfunction () || fcn->is_anonymous_function ()))
           {
             std::string ff = fcn->fcn_file_name ();
 
@@ -298,229 +929,6 @@
 
     return retval;
   }
-
-  void
-  symbol_table::clear_global (const std::string& name)
-  {
-    m_global_scope.clear_variable (name);
-  }
-
-  void
-  symbol_table::clear_global_pattern (const std::string& pattern)
-  {
-    m_global_scope.clear_variable_pattern (pattern);
-  }
-
-  // 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)
-  {
-    if (is_superiorto (inf_class, sup_class))
-      return false;
-
-    // If sup_class doesn't have an entry in the precedence table,
-    // this will automatically create it, and associate to it a
-    // singleton set {inf_class} of inferior classes.
-    m_class_precedence_table[sup_class].insert (inf_class);
-
-    return true;
-  }
-
-  // Has class A been marked as superior to class B?  Also returns
-  // TRUE if B has been marked as inferior to A, since we only keep
-  // one table, and convert inferiorto information to a superiorto
-  // relationship.  Two calls are required to determine whether there
-  // is no relationship between two classes:
-  //
-  //  if (symbol_table::is_superiorto (a, b))
-  //    // A is superior to B, or B has been marked inferior to A.
-  //  else if (symbol_table::is_superiorto (b, a))
-  //    // B is superior to A, or A has been marked inferior to B.
-  //  else
-  //    // No relation.
-
-  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
-    if (p == m_class_precedence_table.end ())
-      return false;
-
-    const std::set<std::string>& inferior_classes = p->second;
-    std::set<std::string>::const_iterator q = inferior_classes.find (b);
-    return (q != inferior_classes.end ());
-  }
-
-  octave_value
-  symbol_table::builtin_find (const std::string& name)
-  {
-    fcn_table_iterator p = m_fcn_table.find (name);
-
-    if (p != m_fcn_table.end ())
-      return p->second.builtin_find ();
-    else
-      {
-        fcn_info finfo (name);
-
-        octave_value fcn = finfo.builtin_find ();
-
-        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)
-  {
-    fcn_table_iterator 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);
-
-        if (fcn.is_defined ())
-          m_fcn_table[name] = finfo;
-
-        return fcn;
-      }
-
-    return octave_value ();
-  }
-
-  octave_value symbol_table::find_function (const std::string& name)
-  {
-    if (name.empty ())
-      return octave_value ();
-
-    if (name[0] == '@')
-      {
-        size_t pos = name.find_first_of ('/');
-
-        if (pos == std::string::npos)
-          return octave_value ();
-
-        std::string method = name.substr (pos+1);
-        std::string dispatch_type = name.substr (1, pos-1);
-
-        return find_method (method, dispatch_type);
-      }
-    else
-      return find_function (name, ovl ());
-  }
-
-  octave_value
-  symbol_table::find_function (const std::string& name,
-                               const octave_value_list& args)
-  {
-    octave_value fcn;
-
-    if (m_current_scope)
-      {
-        fcn = m_current_scope.find_subfunction (name);
-
-        if (fcn.is_defined ())
-          return fcn;
-      }
-
-    return fcn_table_find (name, args);
-  }
-
-  // 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)
-  {
-    fcn_table_const_iterator p = m_fcn_table.find (name);
-
-    if (p != m_fcn_table.end ())
-      return p->second.find_method (dispatch_type);
-    else
-      {
-        fcn_info finfo (name);
-
-        octave_value fcn = finfo.find_method (dispatch_type);
-
-        if (fcn.is_defined ())
-          m_fcn_table[name] = finfo;
-
-        return fcn;
-      }
-  }
-
-  template <template <typename, typename...> class C, typename V,
-            typename... A>
-  static octave_value
-  dump_container_map (const std::map<std::string, C<V, A...>>& container_map)
-  {
-    if (container_map.empty ())
-      return octave_value (Matrix ());
-
-    std::map<std::string, octave_value> info_map;
-
-    for (const auto& nm_container : container_map)
-      {
-        std::string nm = nm_container.first;
-        const C<V, A...>& container = nm_container.second;
-        info_map[nm] = Cell (container);
-      }
-
-    return octave_value (info_map);
-  }
-
-  octave_value
-  symbol_table::dump (void) const
-  {
-    std::map<std::string, octave_value> m
-      = {{ "function_info", dump_fcn_table_map () },
-         { "precedence_table", dump_container_map (m_class_precedence_table) },
-         { "parent_classes", dump_container_map (m_parent_map) }};
-
-    return octave_value (m);
-  }
-
-  void
-  symbol_table::cleanup (void)
-  {
-    clear_all (true);
-
-    m_fcn_table.clear ();
-    m_class_precedence_table.clear ();
-    m_parent_map.clear ();
-  }
-
-  octave_value
-  symbol_table::dump_fcn_table_map (void) const
-  {
-    if (m_fcn_table.empty ())
-      return octave_value (Matrix ());
-
-    std::map<std::string, octave_value> info_map;
-
-    for (const auto& nm_finfo : m_fcn_table)
-      {
-        std::string nm = nm_finfo.first;
-        const fcn_info& finfo = nm_finfo.second;
-        info_map[nm] = finfo.dump ();
-      }
-
-    return octave_value (info_map);
-  }
 }
 
 DEFUN (ignore_function_time_stamp, args, nargout,
@@ -602,28 +1010,11 @@
 %!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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/symtab.h	Mon Mar 25 10:56:14 2019 +0000
@@ -50,17 +50,10 @@
   {
   public:
 
-    typedef octave::symbol_record symbol_record;
     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 +63,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 +91,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 +152,36 @@
     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;
-    }
+    void install_package (const std::string& name);
 
-    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> user_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> built_in_function_names (void);
 
-    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,11 +215,6 @@
     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.
--- a/libinterp/corefcn/syscalls.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/syscalls.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/sysdep.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -320,6 +320,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 = octave::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.
--- a/libinterp/corefcn/sysdep.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/sysdep.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/text-renderer.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/text-renderer.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/toplev.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/toplev.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -285,6 +285,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/variables.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/variables.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -29,6 +29,7 @@
 #include <cstring>
 
 #include <iomanip>
+#include <list>
 #include <set>
 #include <string>
 
@@ -62,6 +63,7 @@
 #include "parse.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 ()
@@ -284,6 +271,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 +477,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
@@ -973,76 +964,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 +1026,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 +1083,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 +1219,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 +1242,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 +1303,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 +1313,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);
                 }
             }
         }
@@ -1476,9 +1428,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::call_stack& cs = interp.get_call_stack ();
+
+      return cs.get_auto_fcn_var (octave::stack_frame::ARG_NAMES);
+    }
+
+  return interp.varval (nm);
 }
 
 static std::string Vmissing_component_hook;
@@ -1514,131 +1475,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/corefcn/variables.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/dldfcn/__eigs__.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/dldfcn/__init_fltk__.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/dldfcn/__ode15__.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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,21 +41,73 @@
 
 #if defined (HAVE_SUNDIALS)
 
+#  if defined (HAVE_NVECTOR_NVECTOR_SERIAL_H)
+#    include <nvector/nvector_serial.h>
+#  endif
+
 #  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_IDA_IDA_DENSE_H)
-#    include <ida/ida_dense.h>
+#  if defined (HAVE_SUNLINSOL_SUNLINSOL_DENSE_H)
+#    include <sunlinsol/sunlinsol_dense.h>
 #  endif
 
-#  if defined (HAVE_IDA_IDA_KLU_H)
-#    include <ida/ida_klu.h>
-#    include <sundials/sundials_sparse.h>
+#  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
+
+#  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_NVECTOR_NVECTOR_SERIAL_H)
-#    include <nvector/nvector_serial.h>
+#  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 *
@@ -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,
@@ -109,27 +162,34 @@
     //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),
+        havejacsparse (false), mem (nullptr), num (), ida_fun (),
+        ida_jac (), dfdy (nullptr), dfdyp (nullptr), spdfdy (nullptr),
         spdfdyp (nullptr), fun (nullptr), jacfun (nullptr), jacspfun (nullptr),
-        jacdcell (nullptr), jacspcell (nullptr)
+        jacdcell (nullptr), jacspcell (nullptr),
+        sunJacMatrix (nullptr), sunLinearSolver (nullptr)
     { }
 
 
     IDA (realtype t, ColumnVector y, ColumnVector yp,
-         octave_function *ida_fcn, DAERHSFuncIDA daefun)
+         const octave_value& 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),
+        ida_jac (), dfdy (nullptr), dfdyp (nullptr), spdfdy (nullptr),
         spdfdyp (nullptr), fun (daefun), jacfun (nullptr), jacspfun (nullptr),
-        jacdcell (nullptr), jacspcell (nullptr)
+        jacdcell (nullptr), jacspcell (nullptr),
+        sunJacMatrix (nullptr), sunLinearSolver (nullptr)
     { }
 
 
-    ~IDA (void) { IDAFree (&mem); }
+    ~IDA (void)
+    {
+      IDAFree (&mem);
+      SUNLinSolFree(sunLinearSolver);
+      SUNMatDestroy(sunJacMatrix);
+    }
 
     IDA&
-    set_jacobian (octave_function *jac, DAEJacFuncDense j)
+    set_jacobian (const octave_value& jac, DAEJacFuncDense j)
     {
       jacfun = j;
       ida_jac = jac;
@@ -140,7 +200,7 @@
     }
 
     IDA&
-    set_jacobian (octave_function *jac, DAEJacFuncSparse j)
+    set_jacobian (const octave_value& jac, DAEJacFuncSparse j)
     {
       jacspfun = j;
       ida_jac = jac;
@@ -184,7 +244,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 +259,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 +286,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 +296,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,9 +323,9 @@
     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);
 
@@ -280,8 +339,8 @@
     bool havejacsparse;
     void *mem;
     int num;
-    octave_function *ida_fun;
-    octave_function *ida_jac;
+    octave_value ida_fun;
+    octave_value ida_jac;
     Matrix *dfdy;
     Matrix *dfdyp;
     SparseMatrix *spdfdy;
@@ -291,6 +350,8 @@
     DAEJacFuncSparse jacspfun;
     DAEJacCellDense jacdcell;
     DAEJacCellSparse jacspcell;
+    SUNMatrix sunJacMatrix;
+    SUNLinearSolver sunLinearSolver;
   };
 
   int
@@ -323,36 +384,63 @@
   }
 
   void
-  IDA::set_up (void)
+  IDA::set_up (const ColumnVector& y)
   {
+    N_Vector yy = ColToNVec(y, num);
+
     if (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.
+        sunJacMatrix = SUNSparseMatrix (num, num, num*num, CSC_MAT);
+        if (! sunJacMatrix)
+          error ("Unable to create sparse Jacobian for Sundials");
 
-        IDASlsSetSparseJacFn (mem, IDA::jacsparse);
+        sunLinearSolver = SUNLinSol_KLU (yy, sunJacMatrix);
+        if (! sunLinearSolver)
+          error ("Unable to create KLU sparse solver");
+
+        if (IDASetLinearSolver (mem, sunLinearSolver, sunJacMatrix))
+          error ("Unable to set sparse linear solver");
+
+        IDASetJacFn (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");
+
+        sunJacMatrix = SUNDenseMatrix (num, num);
+        if (! sunJacMatrix)
+          error ("Unable to create dense Jacobian for Sundials");
 
-        if (havejac && IDADlsSetDenseJacFn (mem, IDA::jacdense) != 0)
-          error ("Dense Jacobian not set");
+        sunLinearSolver = SUNLinSol_Dense (yy, sunJacMatrix);
+        if (! sunLinearSolver)
+          error ("Unable to create dense linear solver");
+
+        if (IDASetLinearSolver (mem, sunLinearSolver, sunJacMatrix))
+          error ("Unable to set dense linear solver");
+
+        if (havejac && IDASetJacFn (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);
 
     ColumnVector yp = NVecToCol (yyp, Neq);
@@ -366,15 +454,15 @@
 
     std::copy (jac.fortran_vec (),
                jac.fortran_vec () + jac.numel (),
-               JJ->data);
+      SUNDenseMatrix_Data(JJ));
 
     END_INTERRUPT_WITH_EXCEPTIONS;
   }
 
-#  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;
@@ -390,22 +478,23 @@
     else
       jac = (*jacspcell) (spdfdy, 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++)
       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)
@@ -479,9 +568,9 @@
   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 ());
@@ -567,7 +656,7 @@
 
         //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)
@@ -642,7 +731,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,
@@ -692,7 +781,7 @@
             // 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));
@@ -717,7 +806,7 @@
                 // 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);
@@ -744,9 +833,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)
@@ -810,7 +899,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)
@@ -901,7 +990,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 +1008,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 +1026,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 +1056,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,
@@ -989,14 +1078,14 @@
 
     Matrix ida_dfdy, ida_dfdyp, *dfdy, *dfdyp;
     SparseMatrix ida_spdfdy, ida_spdfdyp, *spdfdy, *spdfdyp;
-    octave_function *ida_jac;
+    octave_value ida_jac;
     Cell jaccell;
 
     if (havejac)
       {
         if (havejacfun)
           {
-            ida_jac = options.getfield ("Jacobian").function_value ();
+            ida_jac = options.getfield ("Jacobian");
 
             if (havejacsparse)
               dae.set_jacobian (ida_jac, ida_sparse_jac);
@@ -1070,7 +1159,7 @@
 
     bool haverefine = (refine > 1);
 
-    octave_function *output_fcn = nullptr;
+    octave_value output_fcn;
     ColumnVector outputsel;
 
     // OutputFcn
@@ -1078,7 +1167,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 +1175,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 +1221,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 +1271,8 @@
 
 #endif
 }
+
+/*
+## No test needed for internal helper function.
+%!assert (1)
+*/
--- a/libinterp/dldfcn/audiodevinfo.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/dldfcn/audiodevinfo.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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 ());
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-class.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,1136 @@
+/*
+
+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"
+
+// Define to 1 to enable debugging statements.
+#define DEBUG_TRACE 0
+
+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::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
+
+    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
+
+    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);
+          }
+      }
+
+    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 (*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;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-class.h	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,446 @@
+/*
+
+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 "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 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_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	Mon Mar 25 10:56:14 2019 +0000
@@ -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))
+          retval = make_package (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;
+  }
+
+  octave_function *
+  cdef_manager::make_package_symbol (const std::string& pack_name)
+  {
+    octave_function *retval = nullptr;
+
+    cdef_package pack = make_package (pack_name);
+
+    if (pack.ok ())
+      retval = new octave_classdef_meta (pack);
+
+    return retval;
+  }
+
+  cdef_class
+  cdef_manager::make_class (const std::string& name,
+                            const std::list<octave::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& package_name)
+  {
+    cdef_package pack (package_name);
+
+    std::string parent;
+
+    size_t pos = package_name.rfind ('.');
+
+    if (pos != std::string::npos)
+      parent = package_name.substr (0, pos);
+
+    pack.set_class (meta_package ());
+
+    if (parent.empty ())
+      pack.put ("ContainingPackage", Matrix ());
+    else
+      pack.put ("ContainingPackage", to_ov (find_package (parent)));
+
+    if (! package_name.empty ())
+      register_package (pack);
+
+    return pack;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-manager.h	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,154 @@
+/*
+
+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);
+
+    octave_function * make_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& package_name);
+
+  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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,222 @@
+/*
+
+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
+{
+  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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,763 @@
+/*
+
+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 "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&)
+          {
+            std::string msg = 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 ("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_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
+  {
+    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;
+  }
+
+  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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,698 @@
+/*
+
+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 "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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,203 @@
+/*
+
+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"
+
+// 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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,245 @@
+/*
+
+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
+{
+  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 bool
+  is_method_executing (const octave_value& ov, const cdef_object& obj)
+  {
+    tree_evaluator& tw = __get_evaluator__ ("is_method_executing");
+
+    call_stack& cs = __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.
+
+            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)
+  {
+    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 = 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 = 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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,176 @@
+/*
+
+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 "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 = "");
+
+      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)
+      {
+        m_count++;
+        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 ());
+    }
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/cdef-utils.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,387 @@
+/*
+
+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 "call-stack.h"
+#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"
+
+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)
+  {
+    cdef_class cls;
+
+    call_stack& cs = __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;
+  }
+
+  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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-diag.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-int.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-int.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-scalar.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base-sparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -191,7 +191,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 +941,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 ());
 }
--- a/libinterp/octave-value/ov-base.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-base.h	Mon Mar 25 10:56:14 2019 +0000
@@ -278,7 +278,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 +334,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 +674,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 +721,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool-sparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-bool.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-builtin.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cell.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -887,7 +887,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cell.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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-class.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-class.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -332,10 +332,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 +362,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 +466,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 +1023,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 +1257,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 ();
 
@@ -1937,66 +1924,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)
 {
--- a/libinterp/octave-value/ov-class.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-class.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -25,825 +25,35 @@
 #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 "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 +73,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 +96,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 +116,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 +137,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 +152,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 ())
         {
@@ -993,15 +203,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 +233,7 @@
         }
     }
 
-  retval = octave_base_value::numel (idx);
+  retval = octave_base_value::xnumel (idx);
 
   return retval;
 }
@@ -1037,32 +247,56 @@
 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 ())
+    {
+      indent (os);
+      os << class_name () << " object";
+      if (object.is_array ())
+        os << " array";
+      os << " with properties:";
+      newline (os);
+      newline (os);
+
+      std::map<std::string, octave::cdef_property> props;
+
+      props = cls.get_property_map ();
+
+      size_t max_len = 0;
+      for (const auto& nm_prop : props)
+        {
+          const std::string& nm = nm_prop.first;
 
-bool
-octave_classdef::print_name_tag (std::ostream& os,
-                                 const std::string& name) const
-{
-  return octave_base_value::print_name_tag (os, name);
-}
+          size_t sz = nm.size ();
+
+          if (sz > max_len)
+            max_len = sz;
+        }
 
-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);
+      for (auto& nm_prop : props)
+        {
+          const std::string& nm = nm_prop.first;
+          octave::cdef_property& prop = nm_prop.second;
+          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);
+        }
+    }
 }
 
 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 +304,168 @@
   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)
+bool octave_classdef_superclass_ref::is_constructed_object (octave::tree_evaluator& tw,
+                                                            const std::string& nm)
 {
-  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
-{
-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; }
+  octave::call_stack& cs = tw.get_call_stack ();
 
-  // 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 = cs.current ();
 
-  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 +477,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 +489,140 @@
   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)
+    {
+      std::string nm = pname_prop.second.get_name ();
+
+      octave_value acc = pname_prop.second.get ("GetAccess");
+
+      if (! acc.is_string () || acc.string_value () != "public")
+        continue;
+
+      property_names.push_back (nm);
+    }
+
+  if (nargout > 0)
+    return octave_value (Cell (string_vector (property_names)));
+
+  octave_stdout << "properties for class " << class_name << ":\n\n";
 
-  return to_ov (obj.get_class ());
+  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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-classdef.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-complex.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-complex.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cs-list.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-diag.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-diag.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-cx-sparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -30,6 +30,7 @@
 #include <list>
 #include <ostream>
 #include <sstream>
+#include <string>
 #include <vector>
 
 #include "file-ops.h"
@@ -54,7 +55,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 +63,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 +82,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)
 {
-  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)
+{
+  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)
+{
+  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 +210,182 @@
   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)
+  if (! fcn_to_call.is_defined ())
     {
-      // Possibly overloaded function.
-      octave_value ov_fcn;
+      // The following code is similar to part of
+      // tree_evaluator::visit_index_expression but simpler because it
+      // handles a more restricted case.
 
-      // Compute dispatch type.
-      builtin_type_t btyp;
-      std::string dispatch_type = octave::get_dispatch_type (args, btyp);
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::call");
 
-      // 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
+    = octave::__get_evaluator__ ("octave_fcn_handle::call");
+
+  octave_function *of = fcn_to_call.function_value ();
+
+  return of->call (tw, nargout, args, closure_context);
 }
 
 dim_vector
@@ -231,25 +395,126 @@
   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::call_stack& main_cs = tw.get_call_stack ();
+
+  octave::stack_frame& curr_frame = main_cs.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 +539,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 +566,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 +583,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 +616,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 +652,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 +676,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 +717,9 @@
       is.clear ();
     }
 
-  is >> nm;
+  is >> m_name;
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       skip_preceeding_newline (is);
 
@@ -483,17 +741,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::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_ascii");
+
+      octave::call_stack& cs = interp.get_call_stack ();
 
       octave::symbol_scope local_scope (buf);
-
-      symtab.set_scope (local_scope);
-
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_ascii");
-
-      cs.push (local_scope, 0);
+      cs.push (local_scope);
       frame.add_method (cs, &octave::call_stack::pop);
 
       octave_idx_type len = 0;
@@ -513,7 +767,7 @@
                   if (! is)
                     error ("load: failed to load anonymous function handle");
 
-                  local_scope.assign (name, t2, 0);
+                  interp.assign (name, t2);
                 }
             }
         }
@@ -535,29 +789,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 +824,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 +839,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 +867,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,17 +901,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::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_binary");
+
+      octave::call_stack& cs = interp.get_call_stack ();
 
       octave::symbol_scope local_scope (ctmp2);
-
-      symtab.set_scope (local_scope);
-
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_binary");
-
-      cs.push (local_scope, 0);
+      cs.push (local_scope);
       frame.add_method (cs, &octave::call_stack::pop);
 
       if (len > 0)
@@ -681,7 +925,7 @@
               if (! is)
                 error ("load: failed to load anonymous function handle");
 
-              local_scope.force_assign (name, t2);
+              interp.assign (name, t2);
             }
         }
 
@@ -695,13 +939,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 +977,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 +1004,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 +1013,7 @@
     }
   H5Dclose (data_hid);
 
-  if (nm == anonymous)
+  if (m_name == anonymous)
     {
       std::ostringstream buf;
       print_raw (buf, true);
@@ -804,15 +1048,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 +1098,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 +1282,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,17 +1397,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::interpreter& interp
+        = octave::__get_interpreter__ ("octave_fcn_handle::load_hdf5");
+
+      octave::call_stack& cs = interp.get_call_stack ();
 
       octave::symbol_scope local_scope (fcn_tmp);
-
-      symtab.set_scope (local_scope);
-
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_fcn_handle::load_hdf5");
-
-      cs.push (local_scope, 0);
+      cs.push (local_scope);
       frame.add_method (cs, &octave::call_stack::pop);
 
       if (len > 0 && success)
@@ -1196,7 +1428,7 @@
                                     &dsub) <= 0)
                 error ("load: failed to load anonymous function handle");
 
-              local_scope.force_assign (dsub.name, dsub.tc);
+              interp.assign (dsub.name, dsub.tc);
             }
         }
 
@@ -1411,14 +1643,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 +1686,157 @@
     }
 
   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 = "ge";
-              break;
+              case '/':
+                tnm = "rdivide";
+                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 = "power";
+                break;
 
-        case '\'':
-          tnm = "ctranspose";
-          break;
+              case '\\':
+                tnm = "ldivide";
+                break;
+              }
+          }
+        else if (nm[1] == '=')
+          {
+            switch (nm[0])
+              {
+              case '<':
+                tnm = "le";
+                break;
 
-        case '+':
-          tnm = "plus";
-          break;
+              case '=':
+                tnm = "eq";
+                break;
 
-        case '-':
-          tnm = "minus";
-          break;
-
-        case '*':
-          tnm = "mtimes";
-          break;
-
-        case '/':
-          tnm = "mrdivide";
-          break;
-
-        case '^':
-          tnm = "mpower";
-          break;
-
-        case '\\':
-          tnm = "mldivide";
-          break;
+              case '>':
+                tnm = "ge";
+                break;
 
-        case '<':
-          tnm = "lt";
-          break;
-
-        case '>':
-          tnm = "gt";
-          break;
-
-        case '&':
-          tnm = "and";
-          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 = "or";
-          break;
-        }
-    }
+          case '\'':
+            tnm = "ctranspose";
+            break;
+
+          case '+':
+            tnm = "plus";
+            break;
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ("make_fcn_handle");
+          case '-':
+            tnm = "minus";
+            break;
 
-  octave_value f = symtab.find_function (tnm, octave_value_list ());
-
-  octave_function *fptr = f.function_value (true);
+          case '*':
+            tnm = "mtimes";
+            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 = "mrdivide";
+            break;
+
+          case '^':
+            tnm = "mpower";
+            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 = "mldivide";
+            break;
+
+          case '<':
+            tnm = "lt";
+            break;
 
-      if (! any_match)
-        error ("@%s: no function and no method found", tnm.c_str ());
+          case '>':
+            tnm = "gt";
+            break;
 
-      octave_fcn_handle *fh = new octave_fcn_handle (f, tnm);
-      retval = fh;
-
-      for (auto& cls : classes)
-        {
-          std::string class_name = cls;
-          octave_value fmeth = symtab.find_method (tnm, class_name);
+          case '&':
+            tnm = "and";
+            break;
 
-          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);
-                }
-            }
+          case '|':
+            tnm = "or";
+            break;
+          }
+      }
 
-          if (! is_builtin)
-            fh->set_overload (class_name, fmeth);
-        }
-    }
+    octave::tree_evaluator& tw = interp.get_evaluator ();
+
+    octave::symbol_scope curr_scope = tw.get_current_scope ();
 
-  return retval;
+    return new octave_fcn_handle (curr_scope, tnm);
+
+    return retval;
+  }
 }
 
 /*
@@ -1718,6 +1906,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 +1960,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 +1972,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 +2056,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 +2121,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-handle.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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)
+  { }
 
-  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,24 @@
 
   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 nm; }
+  std::string fcn_name (void) const { return m_name; }
 
-  void set_overload (builtin_type_t btyp, const octave_value& ov_fcn)
-  {
-    if (btyp != btyp_unknown)
-      {
-        has_overloads = true;
-        builtin_overloads[btyp] = ov_fcn;
-      }
+  void push_closure_context (octave::tree_evaluator& tw);
 
-  }
-
-  void set_overload (const std::string& dispatch_type,
-                     const octave_value& ov_fcn)
-  {
-    has_overloads = true;
-    overloads[dispatch_type] = ov_fcn;
-  }
+  octave_value workspace (void) const;
 
   bool is_equal_to (const octave_fcn_handle&) const;
 
@@ -137,7 +126,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 +140,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 +150,44 @@
 
 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;
 
-  // Whether the function is overloaded at all.
-  bool has_overloads;
+  // 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;
+
+  // The name of the handle, not including the "@".
+  std::string m_name;
 
-  // Overloads for builtin types.  We use array to make lookup faster.
-  octave_value builtin_overloads[btyp_num_types];
+  // The scope where this object was defined.
+  octave::symbol_scope m_scope;
 
-  // Overloads for other classes.
-  str_ov_map overloads;
+  // TRUE means this is a handle to a nested function.
+  bool m_is_nested;
+
+  // 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;
 
   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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -64,7 +64,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 +72,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,9 +95,9 @@
 
       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)
             {
@@ -119,7 +119,7 @@
         }
     }
 
-  if (fcn.is_undefined ())
+  if (m_fcn.is_undefined ())
     error ("inline: unable to define function");
 }
 
@@ -152,15 +152,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 +170,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 +189,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 +201,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 +235,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 +245,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 +258,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 +270,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 +300,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 +313,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 +336,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 +361,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 +385,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 +395,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 +411,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 +471,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 +488,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 +551,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 +614,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 +643,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn-inline.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-fcn.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-float.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-float.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-complex.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-complex.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-diag.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-cx-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-diag.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-flt-re-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-java.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -2340,7 +2340,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-java.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-lazy-idx.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-lazy-idx.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-mex-fcn.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-oncleanup.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -64,49 +64,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 +92,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 +141,57 @@
   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&)
+    {
+      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");
+    }
+}
+
 DEFUN (onCleanup, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{obj} =} onCleanup (@var{function})
--- a/libinterp/octave-value/ov-oncleanup.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-oncleanup.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-perm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-perm.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-range.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-range.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-diag.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-diag.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-sparse.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-re-sparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-scalar.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-scalar.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-str-mat.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-str-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-struct.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -791,7 +791,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 +1451,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-struct.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-typeinfo.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -770,112 +770,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-typeinfo.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -128,8 +128,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 +184,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 +451,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 +517,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 +585,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::call_stack& cs = interp.get_call_stack ();
+
+  octave_value val
+    = cs.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 +606,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 +651,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 +689,9 @@
     }
   else
     {
-      octave::symbol_scope scope = symtab.require_current_scope ("nargin");
-      retval = scope.varval (".nargin.");
+      octave::call_stack& cs = interp.get_call_stack ();
+
+      retval = cs.get_auto_fcn_var (octave::stack_frame::NARGIN);
 
       if (retval.is_undefined ())
         retval = 0;
@@ -729,14 +762,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 +813,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::call_stack& cs = interp.get_call_stack ();
+
+      retval = cs.get_auto_fcn_var (octave::stack_frame::NARGOUT);
 
       if (retval.is_undefined ())
         retval = 0;
@@ -851,17 +885,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::call_stack& cs = interp.get_call_stack ();
+
+  octave_value tmp;
 
-  int nargout1 = scope.varval (".nargout.").int_value ();
+  int nargout1 = 0;
+  tmp = cs.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 = cs.get_auto_fcn_var (octave::stack_frame::IGNORED);
   if (tmp.is_defined ())
     ignored = tmp.matrix_value ();
 
--- a/libinterp/octave-value/ov-usr-fcn.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave-value/ov.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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) \
--- a/libinterp/octave.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/octave.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/op-kw-docs	Mon Mar 25 10:56:14 2019 +0000
@@ -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-cm-cs.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cm-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cm-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cm-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cm-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-cm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-m.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-cs-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-dm-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-dm-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-dms-template.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcm-fcs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcm-fs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcs-fcm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcs-fcs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcs-fm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fcs-fs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fm-fcs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fm-fs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fs-fcm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fs-fcs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fs-fm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-fs-fs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-int.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-m-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-m-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-m-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-m-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-cm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-m.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-s-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-cm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-m.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-scm-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-cm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-cs.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-m.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-s.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-scm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/op-sm-sm.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/operators/ops.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/bp-table.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -252,29 +252,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 +324,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 +343,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 ();
+                  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 +384,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 ())
                   {
--- a/libinterp/parse-tree/bp-table.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/bp-table.h	Mon Mar 25 10:56:14 2019 +0000
@@ -121,9 +121,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:
 
--- a/libinterp/parse-tree/comment-list.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/comment-list.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/lex.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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;
--- a/libinterp/parse-tree/lex.ll	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/lex.ll	Mon Mar 25 10:56:14 2019 +0000
@@ -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,7 @@
 %}
 
 <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 ();
@@ -1099,6 +1111,8 @@
   }
 
 <FQ_IDENT_START>. {
+    // If input doesn't match FQIDENT, return char and go to previous
+    // start state.
     yyless (0);
     curr_lexer->pop_start_state ();
   }
@@ -1245,8 +1259,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 +1269,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 +1303,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 +1325,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 +1337,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 +1351,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 +2152,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 +2164,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 +2267,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;
   }
@@ -2449,7 +2522,7 @@
   {
     int c = text_yyinput ();
     xunput (c);
-    return (c == ' ' || c == '\t');
+    return is_space_or_tab (c);
   }
 
   bool
@@ -2471,9 +2544,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 +2927,7 @@
     while (offset < yylng)
       {
         char c = yytxt[offset];
-        if (c == ' ' || c == '\t')
+        if (is_space_or_tab (c))
           {
             have_space = true;
             offset++;
@@ -2947,6 +3021,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 +3034,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 +3070,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 +3099,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 +3116,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 +3155,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 +3521,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 +3540,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 +3579,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 +3616,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 +3696,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/oct-lvalue.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/oct-lvalue.h	Mon Mar 25 10:56:14 2019 +0000
@@ -28,6 +28,7 @@
 #include <string>
 
 #include "ovl.h"
+#include "call-stack.h"
 #include "symrec.h"
 
 namespace octave
@@ -36,13 +37,8 @@
   {
   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)
     { }
 
@@ -56,19 +52,14 @@
 
     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); }
+    // OCTAVE_DEPRECATED (5, "foobar, for sure!")
+    void define (const octave_value& v);
 
     void assign (octave_value::assign_op, const octave_value&);
 
@@ -92,7 +83,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/oct-parse.yy	Mon Mar 25 10:56:14 2019 +0000
@@ -75,7 +75,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"
@@ -150,7 +149,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 +248,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 +326,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 +486,7 @@
                         // make_index_expression deleted $1 and $2.
                         YYABORT;
                       }
+                    $$->mark_word_list_cmd ();
                   }
                 ;
 
@@ -502,26 +505,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 +604,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
@@ -1650,6 +1654,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 +1721,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;
                   }
                 ;
@@ -3343,14 +3350,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 +3400,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 +3484,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 +3563,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
@@ -3901,8 +3880,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 +3910,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 +3941,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);
 
@@ -4317,6 +4298,12 @@
   }
 
   void
+  base_parser::disallow_command_syntax (void)
+  {
+    m_lexer.m_allow_command_syntax = false;
+  }
+
+  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;
@@ -4981,14 +4968,15 @@
       {
         call_stack& cs = __get_call_stack__ ("source_file");
 
+        frame.add_method (cs, &octave::call_stack::restore_frame,
+                          cs.current_frame ());
+
         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.
@@ -5004,8 +4992,8 @@
     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);
+    symbol_table& symtab = __get_symbol_table__ ("source_file");
+    octave_value ov_code = symtab.fcn_table_find (symbol);
 
     // For compatibility with Matlab, accept both scripts and
     // functions.
@@ -5182,6 +5170,12 @@
   //!         necessarily the same as @c nargout.
 
   octave_value_list
+  feval (const char *name, const octave_value_list& args, int nargout)
+  {
+    return feval (std::string (name), args, nargout);
+  }
+
+  octave_value_list
   feval (const std::string& name, const octave_value_list& args, int nargout)
   {
     octave_value_list retval;
@@ -5220,8 +5214,17 @@
   }
 
   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)
   {
+    // 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);
@@ -5234,7 +5237,14 @@
         std::list<octave_value_list> arg_list;
         arg_list.push_back (args);
 
-        return val.subsref ("(", arg_list, nargout);
+        // 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 ())
       {
@@ -5402,23 +5412,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})
@@ -5576,6 +5569,9 @@
 
   octave::call_stack& cs = interp.get_call_stack ();
 
+  frame.add_method (cs, &octave::call_stack::restore_frame,
+                    cs.current_frame ());
+
   if (context == "caller")
     cs.goto_caller_frame ();
   else if (context == "base")
@@ -5583,8 +5579,6 @@
   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))
@@ -5596,10 +5590,7 @@
       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));
+      interp.assign (nm, args(2));
     }
   else
     error ("assignin: invalid variable name in argument VARNAME");
@@ -5635,6 +5626,9 @@
 
   octave::call_stack& cs = interp.get_call_stack ();
 
+  frame.add_method (cs, &octave::call_stack::restore_frame,
+                    cs.current_frame ());
+
   if (context == "caller")
     cs.goto_caller_frame ();
   else if (context == "base")
@@ -5642,8 +5636,6 @@
   else
     error ("evalin: CONTEXT must be \"caller\" or \"base\"");
 
-  frame.add_method (cs, &octave::call_stack::pop);
-
   if (nargin > 2)
     {
       frame.protect_var (buffer_error_messages);
@@ -5784,7 +5776,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 +5800,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;"), "");
--- a/libinterp/parse-tree/parse.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/parse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
 
@@ -567,6 +564,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 +579,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 +598,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-all.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-anon-scopes.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-anon-scopes.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-array-list.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-assign.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-binop.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-bp.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-bp.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-cbinop.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-cell.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-check.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-check.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-classdef.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-classdef.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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:
--- a/libinterp/parse-tree/pt-cmd.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-cmd.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-colon.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-const.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-decl.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-decl.h	Mon Mar 25 10:56:14 2019 +0000
@@ -55,8 +55,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 +65,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 +85,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 +215,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -42,12 +42,15 @@
 #include "input.h"
 #include "interpreter-private.h"
 #include "interpreter.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,6 +65,11 @@
 {
   // Normal evaluator.
 
+  bool tree_evaluator::at_top_level (void) const
+  {
+    return m_call_stack.at_top_level ();
+  }
+
   void
   tree_evaluator::reset (void)
   {
@@ -84,8 +92,6 @@
                         ? new lexer (m_interpreter)
                         : new lexer (stdin, m_interpreter));
 
-    symbol_table& symtab = m_interpreter.get_symbol_table ();
-
     do
       {
         try
@@ -94,7 +100,7 @@
 
             repl_parser.reset ();
 
-            if (symtab.at_top_level ())
+            if (at_top_level ())
               reset_debug_state ();
 
             retval = repl_parser.run ();
@@ -206,6 +212,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 +238,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 ());
@@ -298,19 +303,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 +314,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 +326,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 +356,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);
   }
@@ -751,6 +769,148 @@
     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);
+  }
+
+  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::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)
@@ -949,17 +1109,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 +1196,148 @@
     return false;
   }
 
-  symbol_scope
-  tree_evaluator::get_current_scope (void)
+  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 ();
+  }
+
+  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.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 ();
 
-    return symtab.current_scope ();
+    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,
@@ -1161,60 +1453,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");
 
@@ -1478,12 +1719,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);
@@ -1503,10 +1739,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);
 
@@ -1531,7 +1763,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;
 
@@ -1565,56 +1798,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.
@@ -1634,32 +1842,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);
@@ -1669,6 +1862,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);
 
@@ -1709,7 +1904,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");
@@ -1719,6 +1914,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;
   }
 
@@ -1752,10 +1966,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);
       }
   }
 
@@ -1764,13 +1975,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 ())
       {
@@ -1967,11 +2181,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;
 
@@ -1994,10 +2211,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);
 
@@ -2031,6 +2257,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;
                   }
@@ -2218,6 +2450,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);
   }
 
@@ -2487,44 +2732,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 ();
@@ -2780,19 +2993,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 ()
@@ -3232,6 +3435,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";
@@ -3247,9 +3489,7 @@
           }
         else
           {
-            symbol_scope scope = get_current_scope ();
-
-            scope.force_assign (ans, val);
+            assign (ans, val);
 
             if (print)
               {
@@ -3462,10 +3702,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 ();
 
@@ -3768,46 +4005,30 @@
     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);
   }
 }
 
@@ -3864,8 +4085,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-eval.h	Mon Mar 25 10:56:14 2019 +0000
@@ -129,7 +129,7 @@
       : 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_nargout_stack (), m_bp_table (*this), m_call_stack (*this),
         m_profiler (), m_current_frame (0), m_debug_mode (false),
         m_quiet_breakpoint_flag (false), m_max_recursion_depth (256),
         m_whos_line_format ("  %a:4; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;\n"),
@@ -138,8 +138,9 @@
         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,6 +150,8 @@
 
     ~tree_evaluator (void) = default;
 
+    bool at_top_level (void) const;
+
     void reset (void);
 
     int repl (bool interactive);
@@ -197,8 +200,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 +232,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 +263,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);
@@ -366,6 +371,45 @@
 
     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;
+
+    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 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);
 
@@ -390,9 +434,52 @@
 
     call_stack& get_call_stack (void) { return m_call_stack; }
 
+    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 ();
+    }
+
     profiler& get_profiler (void) { return m_profiler; }
 
-    symbol_scope get_current_scope (void);
+    symbol_scope get_top_scope (void) const;
+    symbol_scope get_current_scope (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 = "");
 
@@ -570,11 +657,12 @@
 
     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);
+
     interpreter& m_interpreter;
 
     // The context for the current evaluation.
@@ -662,11 +750,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-except.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-exp.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-id.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-id.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-idx.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-idx.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-jit.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-jit.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-jump.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-loop.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-mat.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-misc.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-misc.h	Mon Mar 25 10:56:14 2019 +0000
@@ -77,8 +77,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-pr-code.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-pr-code.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-select.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-stmt.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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-unop.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-unop.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt-walk.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/pt.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/token.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/parse-tree/token.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/libinterp/template-inst/Array-tc.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/Array.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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; }
   //@}
@@ -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/CMatrix.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/CMatrix.h	Mon Mar 25 10:56:14 2019 +0000
@@ -111,10 +111,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/CSparse.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/CSparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/MatrixType.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/PermMatrix.h	Mon Mar 25 10:56:14 2019 +0000
@@ -60,9 +60,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/Range.h	Mon Mar 25 10:56:14 2019 +0000
@@ -80,9 +80,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 +87,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 +105,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/Sparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -231,11 +231,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 (); }
 
@@ -246,12 +241,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); }
 
@@ -471,16 +460,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/boolNDArray.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/boolNDArray.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/boolNDArray.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/dMatrix.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/dMatrix.h	Mon Mar 25 10:56:14 2019 +0000
@@ -98,10 +98,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/dSparse.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/dSparse.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/dim-vector.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/fCMatrix.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/fCMatrix.h	Mon Mar 25 10:56:14 2019 +0000
@@ -116,10 +116,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/fMatrix.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/fMatrix.h	Mon Mar 25 10:56:14 2019 +0000
@@ -98,10 +98,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/idx-vector.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/array/idx-vector.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/numeric/chol.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/chol.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -71,7 +71,7 @@
                                v, n, info
                                F77_CHAR_ARG_LEN (1)));
 
-  // FIXME: Should we check info exit value and possible report an error?
+  // 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!
@@ -119,7 +119,7 @@
                                v, n, info
                                F77_CHAR_ARG_LEN (1)));
 
-  // FIXME: Should we check info exit value and possible report an error?
+  // 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!
--- a/liboctave/numeric/chol.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/chol.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/lo-mappers.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/lo-mappers.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/oct-fftw.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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;
   }
 
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/oct-fftw.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/oct-rand.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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;
   }
 
--- a/liboctave/numeric/oct-rand.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/oct-rand.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/oct-spparms.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/randgamma.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/randmtzig.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/randpoisson.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/numeric/svd.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/mach-info.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/system/mach-info.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/system/oct-env.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/action-container.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/f77-fcn.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/f77-fcn.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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/oct-base64.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-base64.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-base64.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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-mutex.h	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-mutex.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-refcount.h	Mon Mar 25 10:56:14 2019 +0000
@@ -122,7 +122,4 @@
   };
 }
 
-template <typename T>
-using octave_refcount OCTAVE_DEPRECATED (4.4, "use 'octave::refcount' instead") = octave::refcount<T>;
-
 #endif
--- a/liboctave/util/oct-shlib.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-shlib.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-sort.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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-string.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-string.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/oct-string.h	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/liboctave/util/singleton-cleanup.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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/m4/acinclude.m4	Sun Mar 24 21:50:07 2019 -0700
+++ b/m4/acinclude.m4	Mon Mar 25 10:56:14 2019 +0000
@@ -2215,14 +2215,11 @@
 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>
         ]], [[
@@ -2238,61 +2235,94 @@
   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 SUNLINSOL_KLU library],
+    [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; 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_sunlinsol_dense="SUNDIALS IDA library does not include the SUNLINSOL_DENSE linear solver, ode15i and ode15s will be disabled"
+    OCTAVE_CONFIGURE_WARNING([warn_sundials_sunlinsol_dense])
   fi
 ])
 dnl
--- a/scripts/+containers/Map.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/+containers/Map.m	Mon Mar 25 10:56:14 2019 +0000
@@ -785,9 +785,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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/deprecated/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -1,15 +1,7 @@
 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%/output_max_field_width.m
 
 %canon_reldir%dir = $(fcnfiledir)/deprecated
 
--- a/scripts/deprecated/paren.m	Sun Mar 24 21:50:07 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)
--- a/scripts/deprecated/semicolon.m	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/elfun/asech.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/general/gradient.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/general/quadgk.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/general/quadv.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/gui/uimenu.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/gui/uimenu.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/help/__makeinfo__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/help/__unimplemented__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -968,7 +968,6 @@
   "libisloaded",
   "libpointer",
   "libstruct",
-  "lightangle",
   "linkdata",
   "listfonts",
   "loadlibrary",
@@ -1328,7 +1327,6 @@
   "varfun",
   "vartype",
   "verctrl",
-  "verLessThan",
   "vertexAttachments",
   "vertexNormal",
   "VideoReader",
--- a/scripts/help/print_usage.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/help/print_usage.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/help/warning_ids.m	Mon Mar 25 10:56:14 2019 +0000
@@ -158,11 +158,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
@@ -200,6 +195,13 @@
 ## @item Octave:glyph-render
 ## By default, the @code{Octave:glyph-render} warning is enabled.
 ##
+## @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:imag-to-real
 ## If the @code{Octave:imag-to-real} warning is enabled, a warning is
 ## printed for implicit conversions of complex numbers to real numbers.
--- a/scripts/image/imshow.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/image/imshow.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/java/org/octave/ClassHelper.java	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/java/org/octave/ClassHelper.java	Mon Mar 25 10:56:14 2019 +0000
@@ -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/linear-algebra/ishermitian.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/linear-algebra/ishermitian.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/linear-algebra/issymmetric.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/clearvars.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/dir.m	Mon Mar 25 10:56:14 2019 +0000
@@ -175,23 +175,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/edit.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/ismethod.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/methods.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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,18 +27,25 @@
 ## @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)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  showsigs = (nargin > 1 && ischar (opt) && strcmp (opt, "-full"));
+  havesigs = false;
+
   if (isobject (obj))
     ## Call internal C++ function for Octave objects
     mtds_list = __methods__ (obj);
@@ -48,19 +56,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)
@@ -81,6 +109,24 @@
 
 ## test Java classname
 %!testif HAVE_JAVA; usejava ("jvm")
-%! mtds = methods ("java.lang.Double");
+%! mtds = methods ("java.lang.Double", "-full");
 %! search = strfind (mtds, "java.lang.Double valueOf");
 %! assert (! isempty ([search{:}]));
+
+## test Java classname
+%!testif HAVE_JAVA; usejava ("jvm")
+%! mtds = methods ("java.lang.Double");
+%! search = strfind (mtds, "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"))
+
+## classdef
+%!assert (methods ("inputParser"),
+%!        {"addOptional"; "addParamValue"; "addParameter";
+%!         "addRequired"; "addSwitch"; "add_missing"; "delete";
+%!         "disp"; "error"; "is_argname"; "parse"; "validate_arg";
+%!         "validate_name"});
--- a/scripts/miscellaneous/module.mk	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/miscellaneous/perl.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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.
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/verLessThan.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/ode/ode15i.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/ode/ode15i.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/ode/ode15s.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/qp.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/optimization/qp.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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)));
@@ -407,10 +410,10 @@
       x0 = xbar;
     endif
   endif
-
+  
   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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/optimization/sqp.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/pkg/pkg.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/plot/appearance/annotation.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/appearance/annotation.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
--- a/scripts/plot/appearance/axis.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/appearance/axis.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/legend.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/appearance/legend.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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
@@ -627,6 +610,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.
@@ -1084,6 +1072,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 +1128,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;
--- a/scripts/plot/draw/comet.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/comet.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/comet3.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/ezplot3.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/isosurface.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/isosurface.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/light.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/plotyy.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/polar.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/private/__bar__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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))
--- a/scripts/plot/draw/private/__ezplot__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/private/__ezplot__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/private/__line__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/__stem__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/private/__stem__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
 
--- a/scripts/plot/draw/private/__unite_shared_vertices__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/private/__unite_shared_vertices__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/draw/reducepatch.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/util/allchild.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/allchild.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/clf.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/copyobj.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/findall.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/graphics_toolkit.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/graphics_toolkit.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/print.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/print.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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
@@ -675,6 +659,9 @@
     ## 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 +714,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 +730,6 @@
   if (isfigure (orig_figure))
     set (0, "currentfigure", orig_figure);
   endif
-
 endfunction
 
 function cmd = epstool (opts, filein, fileout)
@@ -800,8 +789,8 @@
   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)
 
@@ -1061,9 +1050,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__add_default_menu__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/__gnuplot_draw_axes__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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_has_feature__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_has_feature__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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_version__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__gnuplot_version__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__opengl_print__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -125,10 +125,6 @@
       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
--- a/scripts/plot/util/private/__print_parse_opts__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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;
@@ -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))
@@ -485,7 +495,7 @@
   if (warn_on_missing_ghostscript)
     if (isempty (arg_st.ghostscript.binary))
       warning ("octave:print:missing_gs", ...
-               ["print.m: Ghostscript binary is not available.  ", ...
+               ["print: Ghostscript binary is not available.  ", ...
                 "Only eps output is possible"]);
     endif
     warn_on_missing_ghostscript = false;
@@ -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
--- a/scripts/polynomial/deconv.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/polynomial/deconv.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/polynomial/poly.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/prefs/addpref.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/prefs/addpref.m	Mon Mar 25 10:56:14 2019 +0000
@@ -77,6 +77,7 @@
 
 %!test
 %! HOME = getenv ("HOME");
+%! save_default_options ("-binary", "local");
 %! unwind_protect
 %!   setenv ("HOME", P_tmpdir ());
 %!
--- a/scripts/prefs/getpref.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/prefs/getpref.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/prefs/ispref.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/prefs/rmpref.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/signal/detrend.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/signal/detrend.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/specfun/betainc.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/specfun/expint.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/specfun/gammainc.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/specfun/legendre.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/specfun/perms.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/startup/__finish__.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/startup/__finish__.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/startup/version-rcfile	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/kurtosis.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/mean.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/movmax.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/movmin.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/movprod.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/movsum.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/quantile.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/statistics/skewness.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/strings/native2unicode.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/strings/str2num.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/testfun/assert.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/testfun/assert.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/private/dump_demos.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/testfun/private/dump_demos.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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/test.m	Sun Mar 24 21:50:07 2019 -0700
+++ b/scripts/testfun/test.m	Mon Mar 25 10:56:14 2019 +0000
@@ -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)))
--- a/src/main.in.cc	Sun Mar 24 21:50:07 2019 -0700
+++ b/src/main.in.cc	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/bug-38236/bug-38236.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/bug-45969.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/bug-50716/bug-50716.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -0,0 +1,5 @@
+bug_55758_TEST_FILES = \
+  %reldir%/bug-55758.tst \
+  %reldir%/class_bug_55758.m
+
+TEST_FILES += $(bug_55758_TEST_FILES)
--- a/test/classdef/classdef.tst	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/classdef/classdef.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -48,12 +48,13 @@
 %!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
+%!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)
--- a/test/classes/classes.tst	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/classes/classes.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -394,27 +394,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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/deprecate-props.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/eval-command.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Sun Mar 24 21:50:07 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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/for.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/io.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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);
 %!
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/jit.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/mk-sparse-tst.sh	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/nest/module.mk	Mon Mar 25 10:56:14 2019 +0000
@@ -1,6 +1,7 @@
 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 \
--- a/test/nest/nest.tst	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/nest/nest.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/pkg/pkg.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/prefer.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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	Sun Mar 24 21:50:07 2019 -0700
+++ b/test/struct.tst	Mon Mar 25 10:56:14 2019 +0000
@@ -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;