changeset 32167:59681cc864e7

maint: Merge stable to default.
author Markus Mützel <markus.muetzel@gmx.de>
date Fri, 23 Jun 2023 20:51:51 +0200
parents 98c550c374ef (diff) e8497a0fb249 (current diff)
children 69723478e84d
files
diffstat 1184 files changed, 52598 insertions(+), 36792 deletions(-) [+]
line wrap: on
line diff
--- a/.github/workflows/make.yaml	Fri Jun 23 20:51:15 2023 +0200
+++ b/.github/workflows/make.yaml	Fri Jun 23 20:51:51 2023 +0200
@@ -86,7 +86,7 @@
           key: ${{ steps.ccache-prepare.outputs.key }}
           restore-keys: |
             ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}
-            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable
+            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default
 
       - name: configure ccache
         env:
@@ -252,7 +252,7 @@
           key: ${{ steps.ccache-prepare.outputs.key }}
           restore-keys: |
             ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}
-            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable
+            ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default
 
       - name: configure ccache
         # The cache doesn't seem to compress well on macOS. Is it already compressed?
@@ -358,6 +358,8 @@
   mingw:
     runs-on: ${{ matrix.os }}
 
+    name: mingw-w64 ${{ matrix.msystem }}
+
     defaults:
       run:
         # Use MSYS2 as default shell
@@ -370,29 +372,37 @@
       matrix:
         # For available GitHub-hosted runners, see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
         os: [windows-latest]
-        msystem: [MINGW64, MINGW32]
+        msystem: [MINGW64, CLANG64]
         include:
           - msystem: MINGW64
             mingw-prefix: mingw64
-            target-triplet: x86_64-w64-mingw32
             target-prefix: mingw-w64-x86_64
             cc: gcc
             cxx: g++
             f77: gfortran
-          - msystem: MINGW32
-            mingw-prefix: mingw32
-            target-triplet: i686-w64-mingw32
-            target-prefix: mingw-w64-i686
-            cc: gcc
-            cxx: g++
-            f77: gfortran
+            extra-config-flags: ""
+            ccache-max: 0.9G
+          - msystem: CLANG64
+            mingw-prefix: clang64
+            target-prefix: mingw-w64-clang-x86_64
+            cc: clang
+            # It looks like we and graphicsmagick++ aren't ready for C++17 yet.
+            cxx: "clang++ -std=gnu++14"
+            f77: flang
+            # Clang seems to require a different set of dllexport attributes than GCC.
+            # autoconf and libtool still need help to correctly invoke flang.
+            extra-config-flags:
+              --disable-lib-visibility-flags
+              --enable-fortran-calling-convention=gfortran
+              ac_cv_f77_compiler_gnu=yes
+              lt_cv_prog_gnu_ld=yes
+            ccache-max: 400M
 
     env:
       CHERE_INVOKING: 1
       CC:  ${{ matrix.cc }}
       CXX:  ${{ matrix.cxx }}
       F77:  ${{ matrix.f77 }}
-      TARGET_TRIPLET:  ${{ matrix.target-triplet }}
       # perl uses cmd shell by default
       PERL5SHELL: bash -l -c
 
@@ -423,9 +433,8 @@
             base-devel
             ${{ matrix.target-prefix }}-autotools
             ${{ matrix.target-prefix }}-cc
-            ${{ matrix.target-prefix }}-gcc-fortran
+            ${{ matrix.target-prefix }}-fc
             ${{ matrix.target-prefix }}-gperf
-            ${{ matrix.target-prefix }}-lapack
             ${{ matrix.target-prefix }}-openblas
             ${{ matrix.target-prefix }}-pcre2
 
@@ -494,14 +503,14 @@
           key: ${{ steps.ccache-prepare.outputs.key }}
           restore-keys: |
             ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}
-            ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/stable
+            ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/default
 
       - name: configure ccache
         # Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota.
         run: |
           which ccache
           test -d ${{ steps.ccache-prepare.outputs.ccachedir }} || mkdir -p ${{ steps.ccache-prepare.outputs.ccachedir }}
-          echo "max_size = 0.9G" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
+          echo "max_size = ${{ matrix.ccache-max }}" > ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
           echo "compression = true" >> ${{ steps.ccache-prepare.outputs.ccachedir }}/ccache.conf
           ccache -p
           ccache -s
@@ -523,9 +532,9 @@
           which $CC
           echo $CC --version
           $CC --version
-          which $CXX
-          echo $CXX --version
-          $CXX --version
+          which ${CXX% *}
+          echo ${CXX% *} --version
+          ${CXX% *} --version
           which $F77
           echo $F77 --version
           $F77 --version
@@ -533,6 +542,7 @@
           cd .build && ../configure \
             JAVA_HOME="" \
             --disable-docs \
+            ${{ matrix.extra-config-flags }} \
             gl_cv_have_weak=no
 
       - name: build
@@ -742,7 +752,7 @@
           key: ${{ steps.ccache-prepare.outputs.key }}
           restore-keys: |
             ccache:${{ matrix.os }}:cygwin:${{ github.ref }}
-            ccache:${{ matrix.os }}:cygwin:refs/heads/stable
+            ccache:${{ matrix.os }}:cygwin:refs/heads/default
 
       - name: configure ccache
         run: |
--- a/.hgignore	Fri Jun 23 20:51:15 2023 +0200
+++ b/.hgignore	Fri Jun 23 20:51:51 2023 +0200
@@ -42,6 +42,8 @@
 (^|/)build-aux/check-subst-vars\.sh$
 ^build-aux/compile$
 ^build-aux/depcomp$
+(^|/)build-aux/find-defun-files\.sh$
+(^|/)build-aux/find-files-with-tests\.sh$
 ^build-aux/install-sh$
 ^build-aux/ltmain\.sh$
 ^build-aux/mdate-sh$
--- a/Makefile.am	Fri Jun 23 20:51:15 2023 +0200
+++ b/Makefile.am	Fri Jun 23 20:51:51 2023 +0200
@@ -302,12 +302,6 @@
   run-octave \
   $(DIRSTAMP_FILES)
 
-if AMCOND_HAVE_BROKEN_STL_ALGO_H
-  BUILT_SOURCES += bits/stl_algo.h
-else
-  BUILT_SOURCES += nonexistent-file
-endif
-
 noinst_SCRIPTS = run-octave
 
 CLEANFILES += \
@@ -359,10 +353,6 @@
 	$(AM_V_GEN)$(SHELL) $(srcdir)/build-aux/mk-octave-config-h.sh $< > $@-t && \
 	$(simple_move_if_change_rule)
 
-bits/stl_algo.h: build-aux/stl_algo.h-fixed
-	$(AM_V_GEN)$(MKDIR_P) bits && \
-	$(INSTALL_HEADER) $< $@
-
 config-vars: $(GEN_CONFIG_SHELL)
 	$(AM_V_GEN)rm -f $@-t $@ && \
 	$(SED) -n 's/  *"$$/"/; s/^\([A-Za-z_][A-Za-z0-9_]*\)=" *\(.*\)" *$$/\1 \2/p' $^ | sort -u > $@-t && \
@@ -380,13 +370,6 @@
 	@$(SHELL) -f build-aux/check-subst-vars.sh make-vars config-vars
 .PHONY: check-subst-vars
 
-## If we aren't trying to fix stl_algo.h, then try to ensure that
-## there isn't a stray copy sitting in the build tree.
-
-nonexistent-file:
-	$(AM_V_at)rm -f bits/stl_algo.h
-.PHONY: nonexistent-file
-
 .gdbinit: etc/gdbinit
 	$(AM_V_GEN)$(gdbinit-install-rule)
 
--- a/bootstrap.conf	Fri Jun 23 20:51:15 2023 +0200
+++ b/bootstrap.conf	Fri Jun 23 20:51:51 2023 +0200
@@ -56,6 +56,7 @@
   getopt-gnu
   getrusage
   gettimeofday
+  gethrxtime
   glob
   intprops
   isatty
@@ -105,6 +106,8 @@
   uname
   unicase/u8-tolower
   unicase/u8-toupper
+  uniconv/u16-conv-from-enc
+  uniconv/u16-conv-to-enc
   uniconv/u32-conv-to-enc
   uniconv/u8-conv-from-enc
   uniconv/u8-conv-to-enc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build-aux/find-defun-files.in.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,56 @@
+#! /bin/sh
+
+########################################################################
+##
+## Copyright (C) 2009-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## 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/>.
+##
+########################################################################
+
+set -e
+
+: ${SED=@SED@}
+: ${EGREP=@EGREP@}
+
+# Some stupid egreps don't like empty elements in alternation patterns,
+# so we have to repeat ourselves because some stupid egreps don't like
+# empty elements in alternation patterns.
+
+DEFUN_PATTERN="^[ \t]*DEF(CONSTFUN|CONSTMETHOD|METHOD|METHOD(_|_STATIC_)DLD|METHODX|METHODX(_|_STATIC_)DLD|UN|UN(_|_STATIC_)DLD|UNX|UNX(_|_STATIC_)DLD)[ \t]*\\("
+
+srcdir="$1"
+if [ "$1" ]; then
+  shift
+fi
+
+for arg
+do
+  if [ -f "$arg" ]; then
+    file="$arg"
+  else
+    file="$srcdir/$arg"
+  fi
+  if [ -f "$file" ]; then
+    if [ "`$EGREP -l "$DEFUN_PATTERN" $file`" ]; then
+      echo "$file" | $SED "s,\\$srcdir/,,"
+    fi
+  fi
+done
--- a/build-aux/find-defun-files.sh	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-#! /bin/sh
-
-########################################################################
-##
-## Copyright (C) 2009-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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/>.
-##
-########################################################################
-
-set -e
-
-SED=${SED:-sed}
-EGREP=${EGREP:-egrep}
-
-# Some stupid egreps don't like empty elements in alternation patterns,
-# so we have to repeat ourselves because some stupid egreps don't like
-# empty elements in alternation patterns.
-
-DEFUN_PATTERN="^[ \t]*DEF(CONSTFUN|CONSTMETHOD|METHOD|METHOD(_|_STATIC_)DLD|METHODX|METHODX(_|_STATIC_)DLD|UN|UN(_|_STATIC_)DLD|UNX|UNX(_|_STATIC_)DLD)[ \t]*\\("
-
-srcdir="$1"
-if [ "$1" ]; then
-  shift
-fi
-
-for arg
-do
-  if [ -f "$arg" ]; then
-    file="$arg"
-  else
-    file="$srcdir/$arg"
-  fi
-  if [ -f "$file" ]; then
-    if [ "`$EGREP -l "$DEFUN_PATTERN" $file`" ]; then
-      echo "$file" | $SED "s,\\$srcdir/,,"
-    fi
-  fi
-done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build-aux/find-files-with-tests.in.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,50 @@
+#! /bin/sh
+
+########################################################################
+##
+## Copyright (C) 2013-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## 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/>.
+##
+########################################################################
+
+set -e
+
+: ${GREP=@GREP@}
+: ${SED=@SED@}
+
+srcdir="$1"
+if [ "$1" ]; then
+  shift
+fi
+
+for arg
+do
+  if [ -f "$arg" ]; then
+    file="$arg"
+  else
+    file="$srcdir/$arg"
+  fi
+  if [ -f "$file" ]; then
+    if [ "`$GREP -l '^%!' $file`" ]; then
+      echo "$file" | $SED "s,\\$srcdir/,,"
+    fi
+  fi
+done
--- a/build-aux/find-files-with-tests.sh	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#! /bin/sh
-
-########################################################################
-##
-## Copyright (C) 2013-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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/>.
-##
-########################################################################
-
-set -e
-
-GREP=${GREP:-grep}
-SED=${SED:-sed}
-
-srcdir="$1"
-if [ "$1" ]; then
-  shift
-fi
-
-for arg
-do
-  if [ -f "$arg" ]; then
-    file="$arg"
-  else
-    file="$srcdir/$arg"
-  fi
-  if [ -f "$file" ]; then
-    if [ "`$GREP -l '^%!' $file`" ]; then
-      echo "$file" | $SED "s,\\$srcdir/,,"
-    fi
-  fi
-done
--- a/build-aux/mk-octave-config-h.sh	Fri Jun 23 20:51:15 2023 +0200
+++ b/build-aux/mk-octave-config-h.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -105,6 +105,7 @@
 $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_64.*$\)/#  \1/p' $config_h_file
 $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_BOUNDS_CHECK.*$\)/#  \1/p' $config_h_file
 $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_FLOAT_TRUNCATE.*$\)/#  \1/p' $config_h_file
+$SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_INTERNAL_CHECKS.*$\)/#  \1/p' $config_h_file
 $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_LIB_VISIBILITY_FLAGS.*$\)/#  \1/p' $config_h_file
 $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_OPENMP.*$\)/#  \1/p' $config_h_file
 $SED -n 's/#\(\(undef\|define\) OCTAVE_F77_INT_TYPE.*$\)/#  \1/p' $config_h_file
--- a/build-aux/mk-opts.pl	Fri Jun 23 20:51:15 2023 +0200
+++ b/build-aux/mk-opts.pl	Fri Jun 23 20:51:51 2023 +0200
@@ -392,7 +392,7 @@
 {
 public:
 
-  $CLASS_NAME (void)
+  $CLASS_NAME ()
 _END_EMIT_OPT_CLASS_HEADER_
 
   print '    : ';
@@ -421,9 +421,9 @@
       return *this;
     }
 
-  ~$CLASS_NAME (void) { }\n";
+  ~$CLASS_NAME () { }\n";
 
-  print "\n  void init (void)\n    {\n";
+  print "\n  void init ()\n    {\n";
 
   for ($i = 0; $i < $OPT_NUM; $i++)
     {
@@ -452,7 +452,7 @@
 
   emit_copy_body ('      ', 'opt');
 
-  print "    }\n\n  void set_default_options (void) { init (); }\n";
+  print "    }\n\n  void set_default_options () { init (); }\n";
 
   for ($i = 0; $i < $OPT_NUM; $i++)
     {
@@ -484,7 +484,7 @@
 
   for ($i = 0; $i < $OPT_NUM; $i++)
     {
-      print "  $TYPE[$i] $OPT[$i] (void) const\n    { return $OPTVAR[$i]; }\n\n";
+      print "  $TYPE[$i] $OPT[$i] () const\n    { return $OPTVAR[$i]; }\n\n";
     }
 
   print "private:\n\n";
--- a/build-aux/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/build-aux/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -3,8 +3,8 @@
   %reldir%/OctJavaQry.java \
   %reldir%/changelog.tmpl \
   %reldir%/check-subst-vars.in.sh \
-  %reldir%/find-defun-files.sh \
-  %reldir%/find-files-with-tests.sh \
+  %reldir%/find-defun-files.in.sh \
+  %reldir%/find-files-with-tests.in.sh \
   %reldir%/get-source-mtime.sh \
   %reldir%/inplace_edit.pl \
   %reldir%/mk-hg-id.sh \
@@ -12,7 +12,6 @@
   %reldir%/mk-opts.pl \
   %reldir%/mk-pkg-add.sh \
   %reldir%/move-if-change \
-  %reldir%/stl_algo.h-fixed \
   %reldir%/subst-config-vals.in.sh \
   %reldir%/subst-cross-config-vals.in.sh \
   %reldir%/subst-script-vals.in.sh \
--- a/build-aux/stl_algo.h-fixed	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6322 +0,0 @@
-// Algorithm implementation -*- C++ -*-
-
-// Copyright (C) 2001-2013 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <https://www.gnu.org/licenses/>.
-
-/*
- *
- * Copyright (c) 1994
- * Hewlett-Packard Company
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  Hewlett-Packard Company makes no
- * representations about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty.
- *
- *
- * Copyright (c) 1996
- * Silicon Graphics Computer Systems, Inc.
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  Silicon Graphics makes no
- * representations about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty.
- */
-
-/** @file bits/stl_algo.h
- *  This is an internal header file, included by other library headers.
- *  Do not attempt to use it directly. @headername{algorithm}
- */
-
-#ifndef _STL_ALGO_H
-#define _STL_ALGO_H 1
-
-#include <cstdlib>             // for rand
-#include <bits/algorithmfwd.h>
-#include <bits/stl_heap.h>
-#include <bits/stl_tempbuf.h>  // for _Temporary_buffer
-
-#if __cplusplus >= 201103L
-#include <random>     // for std::uniform_int_distribution
-#include <functional> // for std::bind
-#endif
-
-// See concept_check.h for the __glibcxx_*_requires macros.
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  /// Swaps the median value of *__a, *__b and *__c to *__result
-  template<typename _Iterator>
-    void
-    __move_median_to_first(_Iterator __result, _Iterator __a,
-			   _Iterator __b, _Iterator __c)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_Iterator>::value_type>)
-
-      if (*__a < *__b)
-	{
-	  if (*__b < *__c)
-	    std::iter_swap(__result, __b);
-	  else if (*__a < *__c)
-	    std::iter_swap(__result, __c);
-	  else
-	    std::iter_swap(__result, __a);
-	}
-      else if (*__a < *__c)
-      	std::iter_swap(__result, __a);
-      else if (*__b < *__c)
-	std::iter_swap(__result, __c);
-      else
-	std::iter_swap(__result, __b);
-    }
-
-  /// Swaps the median value of *__a, *__b and *__c under __comp to *__result
-  template<typename _Iterator, typename _Compare>
-    void
-    __move_median_to_first(_Iterator __result, _Iterator __a,
-			   _Iterator __b, _Iterator __c,
-			   _Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool,
-	    typename iterator_traits<_Iterator>::value_type,
-	    typename iterator_traits<_Iterator>::value_type>)
-
-      if (__comp(*__a, *__b))
-	{
-	  if (__comp(*__b, *__c))
-	    std::iter_swap(__result, __b);
-	  else if (__comp(*__a, *__c))
-	    std::iter_swap(__result, __c);
-	  else
-	    std::iter_swap(__result, __a);
-	}
-      else if (__comp(*__a, *__c))
-	std::iter_swap(__result, __a);
-      else if (__comp(*__b, *__c))
-	std::iter_swap(__result, __c);
-      else
-	std::iter_swap(__result, __b);
-    }
-
-  // for_each
-
-  /// This is an overload used by find() for the Input Iterator case.
-  template<typename _InputIterator, typename _Tp>
-    inline _InputIterator
-    __find(_InputIterator __first, _InputIterator __last,
-	   const _Tp& __val, input_iterator_tag)
-    {
-      while (__first != __last && !(*__first == __val))
-	++__first;
-      return __first;
-    }
-
-  /// This is an overload used by find_if() for the Input Iterator case.
-  template<typename _InputIterator, typename _Predicate>
-    inline _InputIterator
-    __find_if(_InputIterator __first, _InputIterator __last,
-	      _Predicate __pred, input_iterator_tag)
-    {
-      while (__first != __last && !bool(__pred(*__first)))
-	++__first;
-      return __first;
-    }
-
-  /// This is an overload used by find() for the RAI case.
-  template<typename _RandomAccessIterator, typename _Tp>
-    _RandomAccessIterator
-    __find(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	   const _Tp& __val, random_access_iterator_tag)
-    {
-      typename iterator_traits<_RandomAccessIterator>::difference_type
-	__trip_count = (__last - __first) >> 2;
-
-      for (; __trip_count > 0; --__trip_count)
-	{
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-	}
-
-      switch (__last - __first)
-	{
-	case 3:
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-	case 2:
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-	case 1:
-	  if (*__first == __val)
-	    return __first;
-	  ++__first;
-	case 0:
-	default:
-	  return __last;
-	}
-    }
-
-  /// This is an overload used by find_if() for the RAI case.
-  template<typename _RandomAccessIterator, typename _Predicate>
-    _RandomAccessIterator
-    __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	      _Predicate __pred, random_access_iterator_tag)
-    {
-      typename iterator_traits<_RandomAccessIterator>::difference_type
-	__trip_count = (__last - __first) >> 2;
-
-      for (; __trip_count > 0; --__trip_count)
-	{
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-	}
-
-      switch (__last - __first)
-	{
-	case 3:
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-	case 2:
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-	case 1:
-	  if (__pred(*__first))
-	    return __first;
-	  ++__first;
-	case 0:
-	default:
-	  return __last;
-	}
-    }
-
-  /// This is an overload used by find_if_not() for the Input Iterator case.
-  template<typename _InputIterator, typename _Predicate>
-    inline _InputIterator
-    __find_if_not(_InputIterator __first, _InputIterator __last,
-		  _Predicate __pred, input_iterator_tag)
-    {
-      while (__first != __last && bool(__pred(*__first)))
-	++__first;
-      return __first;
-    }
-
-  /// This is an overload used by find_if_not() for the RAI case.
-  template<typename _RandomAccessIterator, typename _Predicate>
-    _RandomAccessIterator
-    __find_if_not(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		  _Predicate __pred, random_access_iterator_tag)
-    {
-      typename iterator_traits<_RandomAccessIterator>::difference_type
-	__trip_count = (__last - __first) >> 2;
-
-      for (; __trip_count > 0; --__trip_count)
-	{
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-	}
-
-      switch (__last - __first)
-	{
-	case 3:
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-	case 2:
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-	case 1:
-	  if (!bool(__pred(*__first)))
-	    return __first;
-	  ++__first;
-	case 0:
-	default:
-	  return __last;
-	}
-    }
-
-  /// Provided for stable_partition to use.
-  template<typename _InputIterator, typename _Predicate>
-    inline _InputIterator
-    __find_if_not(_InputIterator __first, _InputIterator __last,
-		  _Predicate __pred)
-    {
-      return std::__find_if_not(__first, __last, __pred,
-				std::__iterator_category(__first));
-    }
-
-  /// Like find_if_not(), but uses and updates a count of the
-  /// remaining range length instead of comparing against an end
-  /// iterator.
-  template<typename _InputIterator, typename _Predicate, typename _Distance>
-    _InputIterator
-    __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
-    {
-      for (; __len; --__len, ++__first)
-	if (!bool(__pred(*__first)))
-	  break;
-      return __first;
-    }
-
-  // set_difference
-  // set_intersection
-  // set_symmetric_difference
-  // set_union
-  // for_each
-  // find
-  // find_if
-  // find_first_of
-  // adjacent_find
-  // count
-  // count_if
-  // search
-
-  /**
-   *  This is an uglified
-   *  search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
-   *  overloaded for forward iterators.
-  */
-  template<typename _ForwardIterator, typename _Integer, typename _Tp>
-    _ForwardIterator
-    __search_n(_ForwardIterator __first, _ForwardIterator __last,
-	       _Integer __count, const _Tp& __val,
-	       std::forward_iterator_tag)
-    {
-      __first = _GLIBCXX_STD_A::find(__first, __last, __val);
-      while (__first != __last)
-	{
-	  typename iterator_traits<_ForwardIterator>::difference_type
-	    __n = __count;
-	  _ForwardIterator __i = __first;
-	  ++__i;
-	  while (__i != __last && __n != 1 && *__i == __val)
-	    {
-	      ++__i;
-	      --__n;
-	    }
-	  if (__n == 1)
-	    return __first;
-	  if (__i == __last)
-	    return __last;
-	  __first = _GLIBCXX_STD_A::find(++__i, __last, __val);
-	}
-      return __last;
-    }
-
-  /**
-   *  This is an uglified
-   *  search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
-   *  overloaded for random access iterators.
-  */
-  template<typename _RandomAccessIter, typename _Integer, typename _Tp>
-    _RandomAccessIter
-    __search_n(_RandomAccessIter __first, _RandomAccessIter __last,
-	       _Integer __count, const _Tp& __val,
-	       std::random_access_iterator_tag)
-    {
-
-      typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
-	_DistanceType;
-
-      _DistanceType __tailSize = __last - __first;
-      _DistanceType __remainder = __count;
-
-      while (__remainder <= __tailSize) // the main loop...
-	{
-	  __first += __remainder;
-	  __tailSize -= __remainder;
-	  // __first here is always pointing to one past the last element of
-	  // next possible match.
-	  _RandomAccessIter __backTrack = __first;
-	  while (*--__backTrack == __val)
-	    {
-	      if (--__remainder == 0)
-	        return (__first - __count); // Success
-	    }
-	  __remainder = __count + 1 - (__first - __backTrack);
-	}
-      return __last; // Failure
-    }
-
-  // search_n
-
-  /**
-   *  This is an uglified
-   *  search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&,
-   *	       _BinaryPredicate)
-   *  overloaded for forward iterators.
-  */
-  template<typename _ForwardIterator, typename _Integer, typename _Tp,
-           typename _BinaryPredicate>
-    _ForwardIterator
-    __search_n(_ForwardIterator __first, _ForwardIterator __last,
-	       _Integer __count, const _Tp& __val,
-	       _BinaryPredicate __binary_pred, std::forward_iterator_tag)
-    {
-      while (__first != __last && !bool(__binary_pred(*__first, __val)))
-        ++__first;
-
-      while (__first != __last)
-	{
-	  typename iterator_traits<_ForwardIterator>::difference_type
-	    __n = __count;
-	  _ForwardIterator __i = __first;
-	  ++__i;
-	  while (__i != __last && __n != 1 && bool(__binary_pred(*__i, __val)))
-	    {
-	      ++__i;
-	      --__n;
-	    }
-	  if (__n == 1)
-	    return __first;
-	  if (__i == __last)
-	    return __last;
-	  __first = ++__i;
-	  while (__first != __last
-		 && !bool(__binary_pred(*__first, __val)))
-	    ++__first;
-	}
-      return __last;
-    }
-
-  /**
-   *  This is an uglified
-   *  search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&,
-   *	       _BinaryPredicate)
-   *  overloaded for random access iterators.
-  */
-  template<typename _RandomAccessIter, typename _Integer, typename _Tp,
-	   typename _BinaryPredicate>
-    _RandomAccessIter
-    __search_n(_RandomAccessIter __first, _RandomAccessIter __last,
-	       _Integer __count, const _Tp& __val,
-	       _BinaryPredicate __binary_pred, std::random_access_iterator_tag)
-    {
-
-      typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
-	_DistanceType;
-
-      _DistanceType __tailSize = __last - __first;
-      _DistanceType __remainder = __count;
-
-      while (__remainder <= __tailSize) // the main loop...
-	{
-	  __first += __remainder;
-	  __tailSize -= __remainder;
-	  // __first here is always pointing to one past the last element of
-	  // next possible match.
-	  _RandomAccessIter __backTrack = __first;
-	  while (__binary_pred(*--__backTrack, __val))
-	    {
-	      if (--__remainder == 0)
-	        return (__first - __count); // Success
-	    }
-	  __remainder = __count + 1 - (__first - __backTrack);
-	}
-      return __last; // Failure
-    }
-
-  // find_end for forward iterators.
-  template<typename _ForwardIterator1, typename _ForwardIterator2>
-    _ForwardIterator1
-    __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	       forward_iterator_tag, forward_iterator_tag)
-    {
-      if (__first2 == __last2)
-	return __last1;
-      else
-	{
-	  _ForwardIterator1 __result = __last1;
-	  while (1)
-	    {
-	      _ForwardIterator1 __new_result
-		= _GLIBCXX_STD_A::search(__first1, __last1, __first2, __last2);
-	      if (__new_result == __last1)
-		return __result;
-	      else
-		{
-		  __result = __new_result;
-		  __first1 = __new_result;
-		  ++__first1;
-		}
-	    }
-	}
-    }
-
-  template<typename _ForwardIterator1, typename _ForwardIterator2,
-	   typename _BinaryPredicate>
-    _ForwardIterator1
-    __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	       forward_iterator_tag, forward_iterator_tag,
-	       _BinaryPredicate __comp)
-    {
-      if (__first2 == __last2)
-	return __last1;
-      else
-	{
-	  _ForwardIterator1 __result = __last1;
-	  while (1)
-	    {
-	      _ForwardIterator1 __new_result
-		= _GLIBCXX_STD_A::search(__first1, __last1, __first2,
-					 __last2, __comp);
-	      if (__new_result == __last1)
-		return __result;
-	      else
-		{
-		  __result = __new_result;
-		  __first1 = __new_result;
-		  ++__first1;
-		}
-	    }
-	}
-    }
-
-  // find_end for bidirectional iterators (much faster).
-  template<typename _BidirectionalIterator1, typename _BidirectionalIterator2>
-    _BidirectionalIterator1
-    __find_end(_BidirectionalIterator1 __first1,
-	       _BidirectionalIterator1 __last1,
-	       _BidirectionalIterator2 __first2,
-	       _BidirectionalIterator2 __last2,
-	       bidirectional_iterator_tag, bidirectional_iterator_tag)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator1>)
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator2>)
-
-      typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1;
-      typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2;
-
-      _RevIterator1 __rlast1(__first1);
-      _RevIterator2 __rlast2(__first2);
-      _RevIterator1 __rresult = _GLIBCXX_STD_A::search(_RevIterator1(__last1),
-						       __rlast1,
-						       _RevIterator2(__last2),
-						       __rlast2);
-
-      if (__rresult == __rlast1)
-	return __last1;
-      else
-	{
-	  _BidirectionalIterator1 __result = __rresult.base();
-	  std::advance(__result, -std::distance(__first2, __last2));
-	  return __result;
-	}
-    }
-
-  template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
-	   typename _BinaryPredicate>
-    _BidirectionalIterator1
-    __find_end(_BidirectionalIterator1 __first1,
-	       _BidirectionalIterator1 __last1,
-	       _BidirectionalIterator2 __first2,
-	       _BidirectionalIterator2 __last2,
-	       bidirectional_iterator_tag, bidirectional_iterator_tag,
-	       _BinaryPredicate __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator1>)
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator2>)
-
-      typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1;
-      typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2;
-
-      _RevIterator1 __rlast1(__first1);
-      _RevIterator2 __rlast2(__first2);
-      _RevIterator1 __rresult = std::search(_RevIterator1(__last1), __rlast1,
-					    _RevIterator2(__last2), __rlast2,
-					    __comp);
-
-      if (__rresult == __rlast1)
-	return __last1;
-      else
-	{
-	  _BidirectionalIterator1 __result = __rresult.base();
-	  std::advance(__result, -std::distance(__first2, __last2));
-	  return __result;
-	}
-    }
-
-  /**
-   *  @brief  Find last matching subsequence in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of range to search.
-   *  @param  __last1   End of range to search.
-   *  @param  __first2  Start of sequence to match.
-   *  @param  __last2   End of sequence to match.
-   *  @return   The last iterator @c i in the range
-   *  @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) ==
-   *  @p *(__first2+N) for each @c N in the range @p
-   *  [0,__last2-__first2), or @p __last1 if no such iterator exists.
-   *
-   *  Searches the range @p [__first1,__last1) for a sub-sequence that
-   *  compares equal value-by-value with the sequence given by @p
-   *  [__first2,__last2) and returns an iterator to the __first
-   *  element of the sub-sequence, or @p __last1 if the sub-sequence
-   *  is not found.  The sub-sequence will be the last such
-   *  subsequence contained in [__first,__last1).
-   *
-   *  Because the sub-sequence must lie completely within the range @p
-   *  [__first1,__last1) it must start at a position less than @p
-   *  __last1-(__last2-__first2) where @p __last2-__first2 is the
-   *  length of the sub-sequence.  This means that the returned
-   *  iterator @c i will be in the range @p
-   *  [__first1,__last1-(__last2-__first2))
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2>
-    inline _ForwardIterator1
-    find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	     _ForwardIterator2 __first2, _ForwardIterator2 __last2)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_ForwardIterator1>::value_type,
-	    typename iterator_traits<_ForwardIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      return std::__find_end(__first1, __last1, __first2, __last2,
-			     std::__iterator_category(__first1),
-			     std::__iterator_category(__first2));
-    }
-
-  /**
-   *  @brief  Find last matching subsequence in a sequence using a predicate.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of range to search.
-   *  @param  __last1   End of range to search.
-   *  @param  __first2  Start of sequence to match.
-   *  @param  __last2   End of sequence to match.
-   *  @param  __comp    The predicate to use.
-   *  @return The last iterator @c i in the range @p
-   *  [__first1,__last1-(__last2-__first2)) such that @c
-   *  predicate(*(i+N), @p (__first2+N)) is true for each @c N in the
-   *  range @p [0,__last2-__first2), or @p __last1 if no such iterator
-   *  exists.
-   *
-   *  Searches the range @p [__first1,__last1) for a sub-sequence that
-   *  compares equal value-by-value with the sequence given by @p
-   *  [__first2,__last2) using comp as a predicate and returns an
-   *  iterator to the first element of the sub-sequence, or @p __last1
-   *  if the sub-sequence is not found.  The sub-sequence will be the
-   *  last such subsequence contained in [__first,__last1).
-   *
-   *  Because the sub-sequence must lie completely within the range @p
-   *  [__first1,__last1) it must start at a position less than @p
-   *  __last1-(__last2-__first2) where @p __last2-__first2 is the
-   *  length of the sub-sequence.  This means that the returned
-   *  iterator @c i will be in the range @p
-   *  [__first1,__last1-(__last2-__first2))
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2,
-	   typename _BinaryPredicate>
-    inline _ForwardIterator1
-    find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	     _BinaryPredicate __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	    typename iterator_traits<_ForwardIterator1>::value_type,
-	    typename iterator_traits<_ForwardIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      return std::__find_end(__first1, __last1, __first2, __last2,
-			     std::__iterator_category(__first1),
-			     std::__iterator_category(__first2),
-			     __comp);
-    }
-
-#if __cplusplus >= 201103L
-  /**
-   *  @brief  Checks that a predicate is true for all the elements
-   *          of a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __pred    A predicate.
-   *  @return  True if the check is true, false otherwise.
-   *
-   *  Returns true if @p __pred is true for each element in the range
-   *  @p [__first,__last), and false otherwise.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline bool
-    all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return __last == std::find_if_not(__first, __last, __pred); }
-
-  /**
-   *  @brief  Checks that a predicate is false for all the elements
-   *          of a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __pred    A predicate.
-   *  @return  True if the check is true, false otherwise.
-   *
-   *  Returns true if @p __pred is false for each element in the range
-   *  @p [__first,__last), and false otherwise.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline bool
-    none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); }
-
-  /**
-   *  @brief  Checks that a predicate is false for at least an element
-   *          of a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __pred    A predicate.
-   *  @return  True if the check is true, false otherwise.
-   *
-   *  Returns true if an element exists in the range @p
-   *  [__first,__last) such that @p __pred is true, and false
-   *  otherwise.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline bool
-    any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return !std::none_of(__first, __last, __pred); }
-
-  /**
-   *  @brief  Find the first element in a sequence for which a
-   *          predicate is false.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __pred   A predicate.
-   *  @return   The first iterator @c i in the range @p [__first,__last)
-   *  such that @p __pred(*i) is false, or @p __last if no such iterator exists.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline _InputIterator
-    find_if_not(_InputIterator __first, _InputIterator __last,
-		_Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	      typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-      return std::__find_if_not(__first, __last, __pred);
-    }
-
-  /**
-   *  @brief  Checks whether the sequence is partitioned.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __pred   A predicate.
-   *  @return  True if the range @p [__first,__last) is partitioned by @p __pred,
-   *  i.e. if all elements that satisfy @p __pred appear before those that
-   *  do not.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline bool
-    is_partitioned(_InputIterator __first, _InputIterator __last,
-		   _Predicate __pred)
-    {
-      __first = std::find_if_not(__first, __last, __pred);
-      return std::none_of(__first, __last, __pred);
-    }
-
-  /**
-   *  @brief  Find the partition point of a partitioned range.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __pred    A predicate.
-   *  @return  An iterator @p mid such that @p all_of(__first, mid, __pred)
-   *           and @p none_of(mid, __last, __pred) are both true.
-  */
-  template<typename _ForwardIterator, typename _Predicate>
-    _ForwardIterator
-    partition_point(_ForwardIterator __first, _ForwardIterator __last,
-		    _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	      typename iterator_traits<_ForwardIterator>::value_type>)
-
-      // A specific debug-mode test will be necessary...
-      __glibcxx_requires_valid_range(__first, __last);
-
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      _DistanceType __len = std::distance(__first, __last);
-      _DistanceType __half;
-      _ForwardIterator __middle;
-
-      while (__len > 0)
-	{
-	  __half = __len >> 1;
-	  __middle = __first;
-	  std::advance(__middle, __half);
-	  if (__pred(*__middle))
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	  else
-	    __len = __half;
-	}
-      return __first;
-    }
-#endif
-
-
-  /**
-   *  @brief Copy a sequence, removing elements of a given value.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __result  An output iterator.
-   *  @param  __value   The value to be removed.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies each element in the range @p [__first,__last) not equal
-   *  to @p __value to the range beginning at @p __result.
-   *  remove_copy() is stable, so the relative order of elements that
-   *  are copied is unchanged.
-  */
-  template<typename _InputIterator, typename _OutputIterator, typename _Tp>
-    _OutputIterator
-    remove_copy(_InputIterator __first, _InputIterator __last,
-		_OutputIterator __result, const _Tp& __value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_InputIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (!(*__first == __value))
-	  {
-	    *__result = *__first;
-	    ++__result;
-	  }
-      return __result;
-    }
-
-  /**
-   *  @brief Copy a sequence, removing elements for which a predicate is true.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __result  An output iterator.
-   *  @param  __pred    A predicate.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies each element in the range @p [__first,__last) for which
-   *  @p __pred returns false to the range beginning at @p __result.
-   *
-   *  remove_copy_if() is stable, so the relative order of elements that are
-   *  copied is unchanged.
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _Predicate>
-    _OutputIterator
-    remove_copy_if(_InputIterator __first, _InputIterator __last,
-		   _OutputIterator __result, _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (!bool(__pred(*__first)))
-	  {
-	    *__result = *__first;
-	    ++__result;
-	  }
-      return __result;
-    }
-
-#if __cplusplus >= 201103L
-  /**
-   *  @brief Copy the elements of a sequence for which a predicate is true.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __result  An output iterator.
-   *  @param  __pred    A predicate.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies each element in the range @p [__first,__last) for which
-   *  @p __pred returns true to the range beginning at @p __result.
-   *
-   *  copy_if() is stable, so the relative order of elements that are
-   *  copied is unchanged.
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _Predicate>
-    _OutputIterator
-    copy_if(_InputIterator __first, _InputIterator __last,
-	    _OutputIterator __result, _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (__pred(*__first))
-	  {
-	    *__result = *__first;
-	    ++__result;
-	  }
-      return __result;
-    }
-
-
-  template<typename _InputIterator, typename _Size, typename _OutputIterator>
-    _OutputIterator
-    __copy_n(_InputIterator __first, _Size __n,
-	     _OutputIterator __result, input_iterator_tag)
-    {
-      if (__n > 0)
-	{
-	  while (true)
-	    {
-	      *__result = *__first;
-	      ++__result;
-	      if (--__n > 0)
-		++__first;
-	      else
-		break;
-	    }
-	}
-      return __result;
-    }
-
-  template<typename _RandomAccessIterator, typename _Size,
-	   typename _OutputIterator>
-    inline _OutputIterator
-    __copy_n(_RandomAccessIterator __first, _Size __n,
-	     _OutputIterator __result, random_access_iterator_tag)
-    { return std::copy(__first, __first + __n, __result); }
-
-  /**
-   *  @brief Copies the range [first,first+n) into [result,result+n).
-   *  @ingroup mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __n      The number of elements to copy.
-   *  @param  __result An output iterator.
-   *  @return  result+n.
-   *
-   *  This inline function will boil down to a call to @c memmove whenever
-   *  possible.  Failing that, if random access iterators are passed, then the
-   *  loop count will be known (and therefore a candidate for compiler
-   *  optimizations such as unrolling).
-  */
-  template<typename _InputIterator, typename _Size, typename _OutputIterator>
-    inline _OutputIterator
-    copy_n(_InputIterator __first, _Size __n, _OutputIterator __result)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-
-      return std::__copy_n(__first, __n, __result,
-			   std::__iterator_category(__first));
-    }
-
-  /**
-   *  @brief Copy the elements of a sequence to separate output sequences
-   *         depending on the truth value of a predicate.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __out_true   An output iterator.
-   *  @param  __out_false  An output iterator.
-   *  @param  __pred    A predicate.
-   *  @return   A pair designating the ends of the resulting sequences.
-   *
-   *  Copies each element in the range @p [__first,__last) for which
-   *  @p __pred returns true to the range beginning at @p out_true
-   *  and each element for which @p __pred returns false to @p __out_false.
-  */
-  template<typename _InputIterator, typename _OutputIterator1,
-	   typename _OutputIterator2, typename _Predicate>
-    pair<_OutputIterator1, _OutputIterator2>
-    partition_copy(_InputIterator __first, _InputIterator __last,
-		   _OutputIterator1 __out_true, _OutputIterator2 __out_false,
-		   _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (__pred(*__first))
-	  {
-	    *__out_true = *__first;
-	    ++__out_true;
-	  }
-	else
-	  {
-	    *__out_false = *__first;
-	    ++__out_false;
-	  }
-
-      return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false);
-    }
-#endif
-
-  /**
-   *  @brief Remove elements from a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __value  The value to be removed.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  All elements equal to @p __value are removed from the range
-   *  @p [__first,__last).
-   *
-   *  remove() is stable, so the relative order of elements that are
-   *  not removed is unchanged.
-   *
-   *  Elements between the end of the resulting sequence and @p __last
-   *  are still present, but their value is unspecified.
-  */
-  template<typename _ForwardIterator, typename _Tp>
-    _ForwardIterator
-    remove(_ForwardIterator __first, _ForwardIterator __last,
-	   const _Tp& __value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      __first = _GLIBCXX_STD_A::find(__first, __last, __value);
-      if(__first == __last)
-        return __first;
-      _ForwardIterator __result = __first;
-      ++__first;
-      for(; __first != __last; ++__first)
-        if(!(*__first == __value))
-          {
-            *__result = _GLIBCXX_MOVE(*__first);
-            ++__result;
-          }
-      return __result;
-    }
-
-  /**
-   *  @brief Remove elements from a sequence using a predicate.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __last   A forward iterator.
-   *  @param  __pred   A predicate.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  All elements for which @p __pred returns true are removed from the range
-   *  @p [__first,__last).
-   *
-   *  remove_if() is stable, so the relative order of elements that are
-   *  not removed is unchanged.
-   *
-   *  Elements between the end of the resulting sequence and @p __last
-   *  are still present, but their value is unspecified.
-  */
-  template<typename _ForwardIterator, typename _Predicate>
-    _ForwardIterator
-    remove_if(_ForwardIterator __first, _ForwardIterator __last,
-	      _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      __first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
-      if(__first == __last)
-        return __first;
-      _ForwardIterator __result = __first;
-      ++__first;
-      for(; __first != __last; ++__first)
-        if(!bool(__pred(*__first)))
-          {
-            *__result = _GLIBCXX_MOVE(*__first);
-            ++__result;
-          }
-      return __result;
-    }
-
-  /**
-   *  @brief Remove consecutive duplicate values from a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __last   A forward iterator.
-   *  @return  An iterator designating the end of the resulting sequence.
-   *
-   *  Removes all but the first element from each group of consecutive
-   *  values that compare equal.
-   *  unique() is stable, so the relative order of elements that are
-   *  not removed is unchanged.
-   *  Elements between the end of the resulting sequence and @p __last
-   *  are still present, but their value is unspecified.
-  */
-  template<typename _ForwardIterator>
-    _ForwardIterator
-    unique(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_EqualityComparableConcept<
-		     typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      // Skip the beginning, if already unique.
-      __first = _GLIBCXX_STD_A::adjacent_find(__first, __last);
-      if (__first == __last)
-	return __last;
-
-      // Do the real copy work.
-      _ForwardIterator __dest = __first;
-      ++__first;
-      while (++__first != __last)
-	if (!(*__dest == *__first))
-	  *++__dest = _GLIBCXX_MOVE(*__first);
-      return ++__dest;
-    }
-
-  /**
-   *  @brief Remove consecutive values from a sequence using a predicate.
-   *  @ingroup mutating_algorithms
-   *  @param  __first        A forward iterator.
-   *  @param  __last         A forward iterator.
-   *  @param  __binary_pred  A binary predicate.
-   *  @return  An iterator designating the end of the resulting sequence.
-   *
-   *  Removes all but the first element from each group of consecutive
-   *  values for which @p __binary_pred returns true.
-   *  unique() is stable, so the relative order of elements that are
-   *  not removed is unchanged.
-   *  Elements between the end of the resulting sequence and @p __last
-   *  are still present, but their value is unspecified.
-  */
-  template<typename _ForwardIterator, typename _BinaryPredicate>
-    _ForwardIterator
-    unique(_ForwardIterator __first, _ForwardIterator __last,
-           _BinaryPredicate __binary_pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-		typename iterator_traits<_ForwardIterator>::value_type,
-		typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      // Skip the beginning, if already unique.
-      __first = _GLIBCXX_STD_A::adjacent_find(__first, __last, __binary_pred);
-      if (__first == __last)
-	return __last;
-
-      // Do the real copy work.
-      _ForwardIterator __dest = __first;
-      ++__first;
-      while (++__first != __last)
-	if (!bool(__binary_pred(*__dest, *__first)))
-	  *++__dest = _GLIBCXX_MOVE(*__first);
-      return ++__dest;
-    }
-
-  /**
-   *  This is an uglified unique_copy(_InputIterator, _InputIterator,
-   *                                  _OutputIterator)
-   *  overloaded for forward iterators and output iterator as result.
-  */
-  template<typename _ForwardIterator, typename _OutputIterator>
-    _OutputIterator
-    __unique_copy(_ForwardIterator __first, _ForwardIterator __last,
-		  _OutputIterator __result,
-		  forward_iterator_tag, output_iterator_tag)
-    {
-      // concept requirements -- taken care of in dispatching function
-      _ForwardIterator __next = __first;
-      *__result = *__first;
-      while (++__next != __last)
-	if (!(*__first == *__next))
-	  {
-	    __first = __next;
-	    *++__result = *__first;
-	  }
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified unique_copy(_InputIterator, _InputIterator,
-   *                                  _OutputIterator)
-   *  overloaded for input iterators and output iterator as result.
-  */
-  template<typename _InputIterator, typename _OutputIterator>
-    _OutputIterator
-    __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _OutputIterator __result,
-		  input_iterator_tag, output_iterator_tag)
-    {
-      // concept requirements -- taken care of in dispatching function
-      typename iterator_traits<_InputIterator>::value_type __value = *__first;
-      *__result = __value;
-      while (++__first != __last)
-	if (!(__value == *__first))
-	  {
-	    __value = *__first;
-	    *++__result = __value;
-	  }
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified unique_copy(_InputIterator, _InputIterator,
-   *                                  _OutputIterator)
-   *  overloaded for input iterators and forward iterator as result.
-  */
-  template<typename _InputIterator, typename _ForwardIterator>
-    _ForwardIterator
-    __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _ForwardIterator __result,
-		  input_iterator_tag, forward_iterator_tag)
-    {
-      // concept requirements -- taken care of in dispatching function
-      *__result = *__first;
-      while (++__first != __last)
-	if (!(*__result == *__first))
-	  *++__result = *__first;
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified
-   *  unique_copy(_InputIterator, _InputIterator, _OutputIterator,
-   *              _BinaryPredicate)
-   *  overloaded for forward iterators and output iterator as result.
-  */
-  template<typename _ForwardIterator, typename _OutputIterator,
-	   typename _BinaryPredicate>
-    _OutputIterator
-    __unique_copy(_ForwardIterator __first, _ForwardIterator __last,
-		  _OutputIterator __result, _BinaryPredicate __binary_pred,
-		  forward_iterator_tag, output_iterator_tag)
-    {
-      // concept requirements -- iterators already checked
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	  typename iterator_traits<_ForwardIterator>::value_type,
-	  typename iterator_traits<_ForwardIterator>::value_type>)
-
-      _ForwardIterator __next = __first;
-      *__result = *__first;
-      while (++__next != __last)
-	if (!bool(__binary_pred(*__first, *__next)))
-	  {
-	    __first = __next;
-	    *++__result = *__first;
-	  }
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified
-   *  unique_copy(_InputIterator, _InputIterator, _OutputIterator,
-   *              _BinaryPredicate)
-   *  overloaded for input iterators and output iterator as result.
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _BinaryPredicate>
-    _OutputIterator
-    __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _OutputIterator __result, _BinaryPredicate __binary_pred,
-		  input_iterator_tag, output_iterator_tag)
-    {
-      // concept requirements -- iterators already checked
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	  typename iterator_traits<_InputIterator>::value_type,
-	  typename iterator_traits<_InputIterator>::value_type>)
-
-      typename iterator_traits<_InputIterator>::value_type __value = *__first;
-      *__result = __value;
-      while (++__first != __last)
-	if (!bool(__binary_pred(__value, *__first)))
-	  {
-	    __value = *__first;
-	    *++__result = __value;
-	  }
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified
-   *  unique_copy(_InputIterator, _InputIterator, _OutputIterator,
-   *              _BinaryPredicate)
-   *  overloaded for input iterators and forward iterator as result.
-  */
-  template<typename _InputIterator, typename _ForwardIterator,
-	   typename _BinaryPredicate>
-    _ForwardIterator
-    __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _ForwardIterator __result, _BinaryPredicate __binary_pred,
-		  input_iterator_tag, forward_iterator_tag)
-    {
-      // concept requirements -- iterators already checked
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	  typename iterator_traits<_ForwardIterator>::value_type,
-	  typename iterator_traits<_InputIterator>::value_type>)
-
-      *__result = *__first;
-      while (++__first != __last)
-	if (!bool(__binary_pred(*__result, *__first)))
-	  *++__result = *__first;
-      return ++__result;
-    }
-
-  /**
-   *  This is an uglified reverse(_BidirectionalIterator,
-   *                              _BidirectionalIterator)
-   *  overloaded for bidirectional iterators.
-  */
-  template<typename _BidirectionalIterator>
-    void
-    __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last,
-	      bidirectional_iterator_tag)
-    {
-      while (true)
-	if (__first == __last || __first == --__last)
-	  return;
-	else
-	  {
-	    std::iter_swap(__first, __last);
-	    ++__first;
-	  }
-    }
-
-  /**
-   *  This is an uglified reverse(_BidirectionalIterator,
-   *                              _BidirectionalIterator)
-   *  overloaded for random access iterators.
-  */
-  template<typename _RandomAccessIterator>
-    void
-    __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	      random_access_iterator_tag)
-    {
-      if (__first == __last)
-	return;
-      --__last;
-      while (__first < __last)
-	{
-	  std::iter_swap(__first, __last);
-	  ++__first;
-	  --__last;
-	}
-    }
-
-  /**
-   *  @brief Reverse a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  A bidirectional iterator.
-   *  @param  __last   A bidirectional iterator.
-   *  @return   reverse() returns no value.
-   *
-   *  Reverses the order of the elements in the range @p [__first,__last),
-   *  so that the first element becomes the last etc.
-   *  For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse()
-   *  swaps @p *(__first+i) and @p *(__last-(i+1))
-  */
-  template<typename _BidirectionalIterator>
-    inline void
-    reverse(_BidirectionalIterator __first, _BidirectionalIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
-      std::__reverse(__first, __last, std::__iterator_category(__first));
-    }
-
-  /**
-   *  @brief Copy a sequence, reversing its elements.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A bidirectional iterator.
-   *  @param  __last    A bidirectional iterator.
-   *  @param  __result  An output iterator.
-   *  @return  An iterator designating the end of the resulting sequence.
-   *
-   *  Copies the elements in the range @p [__first,__last) to the
-   *  range @p [__result,__result+(__last-__first)) such that the
-   *  order of the elements is reversed.  For every @c i such that @p
-   *  0<=i<=(__last-__first), @p reverse_copy() performs the
-   *  assignment @p *(__result+(__last-__first)-1-i) = *(__first+i).
-   *  The ranges @p [__first,__last) and @p
-   *  [__result,__result+(__last-__first)) must not overlap.
-  */
-  template<typename _BidirectionalIterator, typename _OutputIterator>
-    _OutputIterator
-    reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last,
-		 _OutputIterator __result)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-		typename iterator_traits<_BidirectionalIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      while (__first != __last)
-	{
-	  --__last;
-	  *__result = *__last;
-	  ++__result;
-	}
-      return __result;
-    }
-
-  /**
-   *  This is a helper function for the rotate algorithm specialized on RAIs.
-   *  It returns the greatest common divisor of two integer values.
-  */
-  template<typename _EuclideanRingElement>
-    _EuclideanRingElement
-    __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n)
-    {
-      while (__n != 0)
-	{
-	  _EuclideanRingElement __t = __m % __n;
-	  __m = __n;
-	  __n = __t;
-	}
-      return __m;
-    }
-
-  /// This is a helper function for the rotate algorithm.
-  template<typename _ForwardIterator>
-    void
-    __rotate(_ForwardIterator __first,
-	     _ForwardIterator __middle,
-	     _ForwardIterator __last,
-	     forward_iterator_tag)
-    {
-      if (__first == __middle || __last  == __middle)
-	return;
-
-      _ForwardIterator __first2 = __middle;
-      do
-	{
-	  std::iter_swap(__first, __first2);
-	  ++__first;
-	  ++__first2;
-	  if (__first == __middle)
-	    __middle = __first2;
-	}
-      while (__first2 != __last);
-
-      __first2 = __middle;
-
-      while (__first2 != __last)
-	{
-	  std::iter_swap(__first, __first2);
-	  ++__first;
-	  ++__first2;
-	  if (__first == __middle)
-	    __middle = __first2;
-	  else if (__first2 == __last)
-	    __first2 = __middle;
-	}
-    }
-
-   /// This is a helper function for the rotate algorithm.
-  template<typename _BidirectionalIterator>
-    void
-    __rotate(_BidirectionalIterator __first,
-	     _BidirectionalIterator __middle,
-	     _BidirectionalIterator __last,
-	      bidirectional_iterator_tag)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-
-      if (__first == __middle || __last  == __middle)
-	return;
-
-      std::__reverse(__first,  __middle, bidirectional_iterator_tag());
-      std::__reverse(__middle, __last,   bidirectional_iterator_tag());
-
-      while (__first != __middle && __middle != __last)
-	{
-	  std::iter_swap(__first, --__last);
-	  ++__first;
-	}
-
-      if (__first == __middle)
-	std::__reverse(__middle, __last,   bidirectional_iterator_tag());
-      else
-	std::__reverse(__first,  __middle, bidirectional_iterator_tag());
-    }
-
-  /// This is a helper function for the rotate algorithm.
-  template<typename _RandomAccessIterator>
-    void
-    __rotate(_RandomAccessIterator __first,
-	     _RandomAccessIterator __middle,
-	     _RandomAccessIterator __last,
-	     random_access_iterator_tag)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-				  _RandomAccessIterator>)
-
-      if (__first == __middle || __last  == __middle)
-	return;
-
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_Distance;
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      _Distance __n = __last   - __first;
-      _Distance __k = __middle - __first;
-
-      if (__k == __n - __k)
-	{
-	  std::swap_ranges(__first, __middle, __middle);
-	  return;
-	}
-
-      _RandomAccessIterator __p = __first;
-
-      for (;;)
-	{
-	  if (__k < __n - __k)
-	    {
-	      if (__is_pod(_ValueType) && __k == 1)
-		{
-		  _ValueType __t = _GLIBCXX_MOVE(*__p);
-		  _GLIBCXX_MOVE3(__p + 1, __p + __n, __p);
-		  *(__p + __n - 1) = _GLIBCXX_MOVE(__t);
-		  return;
-		}
-	      _RandomAccessIterator __q = __p + __k;
-	      for (_Distance __i = 0; __i < __n - __k; ++ __i)
-		{
-		  std::iter_swap(__p, __q);
-		  ++__p;
-		  ++__q;
-		}
-	      __n %= __k;
-	      if (__n == 0)
-		return;
-	      std::swap(__n, __k);
-	      __k = __n - __k;
-	    }
-	  else
-	    {
-	      __k = __n - __k;
-	      if (__is_pod(_ValueType) && __k == 1)
-		{
-		  _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1));
-		  _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n);
-		  *__p = _GLIBCXX_MOVE(__t);
-		  return;
-		}
-	      _RandomAccessIterator __q = __p + __n;
-	      __p = __q - __k;
-	      for (_Distance __i = 0; __i < __n - __k; ++ __i)
-		{
-		  --__p;
-		  --__q;
-		  std::iter_swap(__p, __q);
-		}
-	      __n %= __k;
-	      if (__n == 0)
-		return;
-	      std::swap(__n, __k);
-	    }
-	}
-    }
-
-  /**
-   *  @brief Rotate the elements of a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __middle  A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @return  Nothing.
-   *
-   *  Rotates the elements of the range @p [__first,__last) by
-   *  @p (__middle - __first) positions so that the element at @p __middle
-   *  is moved to @p __first, the element at @p __middle+1 is moved to
-   *  @p __first+1 and so on for each element in the range
-   *  @p [__first,__last).
-   *
-   *  This effectively swaps the ranges @p [__first,__middle) and
-   *  @p [__middle,__last).
-   *
-   *  Performs
-   *   @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n)
-   *  for each @p n in the range @p [0,__last-__first).
-  */
-  template<typename _ForwardIterator>
-    inline void
-    rotate(_ForwardIterator __first, _ForwardIterator __middle,
-	   _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_requires_valid_range(__first, __middle);
-      __glibcxx_requires_valid_range(__middle, __last);
-
-      typedef typename iterator_traits<_ForwardIterator>::iterator_category
-	_IterType;
-      std::__rotate(__first, __middle, __last, _IterType());
-    }
-
-  /**
-   *  @brief Copy a sequence, rotating its elements.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __middle  A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @param  __result  An output iterator.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies the elements of the range @p [__first,__last) to the
-   *  range beginning at @result, rotating the copied elements by
-   *  @p (__middle-__first) positions so that the element at @p __middle
-   *  is moved to @p __result, the element at @p __middle+1 is moved
-   *  to @p __result+1 and so on for each element in the range @p
-   *  [__first,__last).
-   *
-   *  Performs
-   *  @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n)
-   *  for each @p n in the range @p [0,__last-__first).
-  */
-  template<typename _ForwardIterator, typename _OutputIterator>
-    _OutputIterator
-    rotate_copy(_ForwardIterator __first, _ForwardIterator __middle,
-                _ForwardIterator __last, _OutputIterator __result)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-		typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __middle);
-      __glibcxx_requires_valid_range(__middle, __last);
-
-      return std::copy(__first, __middle,
-                       std::copy(__middle, __last, __result));
-    }
-
-  /// This is a helper function...
-  template<typename _ForwardIterator, typename _Predicate>
-    _ForwardIterator
-    __partition(_ForwardIterator __first, _ForwardIterator __last,
-		_Predicate __pred, forward_iterator_tag)
-    {
-      if (__first == __last)
-	return __first;
-
-      while (__pred(*__first))
-	if (++__first == __last)
-	  return __first;
-
-      _ForwardIterator __next = __first;
-
-      while (++__next != __last)
-	if (__pred(*__next))
-	  {
-	    std::iter_swap(__first, __next);
-	    ++__first;
-	  }
-
-      return __first;
-    }
-
-  /// This is a helper function...
-  template<typename _BidirectionalIterator, typename _Predicate>
-    _BidirectionalIterator
-    __partition(_BidirectionalIterator __first, _BidirectionalIterator __last,
-		_Predicate __pred, bidirectional_iterator_tag)
-    {
-      while (true)
-	{
-	  while (true)
-	    if (__first == __last)
-	      return __first;
-	    else if (__pred(*__first))
-	      ++__first;
-	    else
-	      break;
-	  --__last;
-	  while (true)
-	    if (__first == __last)
-	      return __first;
-	    else if (!bool(__pred(*__last)))
-	      --__last;
-	    else
-	      break;
-	  std::iter_swap(__first, __last);
-	  ++__first;
-	}
-    }
-
-  // partition
-
-  /// This is a helper function...
-  /// Requires __len != 0 and !__pred(*__first),
-  /// same as __stable_partition_adaptive.
-  template<typename _ForwardIterator, typename _Predicate, typename _Distance>
-    _ForwardIterator
-    __inplace_stable_partition(_ForwardIterator __first,
-			       _Predicate __pred, _Distance __len)
-    {
-      if (__len == 1)
-	return __first;
-      _ForwardIterator __middle = __first;
-      std::advance(__middle, __len / 2);
-      _ForwardIterator __left_split =
-	std::__inplace_stable_partition(__first, __pred, __len / 2);
-      // Advance past true-predicate values to satisfy this
-      // function's preconditions.
-      _Distance __right_len = __len - __len / 2;
-      _ForwardIterator __right_split =
-	std::__find_if_not_n(__middle, __right_len, __pred);
-      if (__right_len)
-	__right_split = std::__inplace_stable_partition(__middle,
-							__pred,
-							__right_len);
-      std::rotate(__left_split, __middle, __right_split);
-      std::advance(__left_split, std::distance(__middle, __right_split));
-      return __left_split;
-    }
-
-  /// This is a helper function...
-  /// Requires __first != __last and !__pred(*__first)
-  /// and __len == distance(__first, __last).
-  ///
-  /// !__pred(*__first) allows us to guarantee that we don't
-  /// move-assign an element onto itself.
-  template<typename _ForwardIterator, typename _Pointer, typename _Predicate,
-	   typename _Distance>
-    _ForwardIterator
-    __stable_partition_adaptive(_ForwardIterator __first,
-				_ForwardIterator __last,
-				_Predicate __pred, _Distance __len,
-				_Pointer __buffer,
-				_Distance __buffer_size)
-    {
-      if (__len <= __buffer_size)
-	{
-	  _ForwardIterator __result1 = __first;
-	  _Pointer __result2 = __buffer;
-	  // The precondition guarantees that !__pred(*__first), so
-	  // move that element to the buffer before starting the loop.
-	  // This ensures that we only call __pred once per element.
-	  *__result2 = _GLIBCXX_MOVE(*__first);
-	  ++__result2;
-	  ++__first;
-	  for (; __first != __last; ++__first)
-	    if (__pred(*__first))
-	      {
-		*__result1 = _GLIBCXX_MOVE(*__first);
-		++__result1;
-	      }
-	    else
-	      {
-		*__result2 = _GLIBCXX_MOVE(*__first);
-		++__result2;
-	      }
-	  _GLIBCXX_MOVE3(__buffer, __result2, __result1);
-	  return __result1;
-	}
-      else
-	{
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __len / 2);
-	  _ForwardIterator __left_split =
-	    std::__stable_partition_adaptive(__first, __middle, __pred,
-					     __len / 2, __buffer,
-					     __buffer_size);
-	  // Advance past true-predicate values to satisfy this
-	  // function's preconditions.
-	  _Distance __right_len = __len - __len / 2;
-	  _ForwardIterator __right_split =
-	    std::__find_if_not_n(__middle, __right_len, __pred);
-	  if (__right_len)
-	    __right_split =
-	      std::__stable_partition_adaptive(__right_split, __last, __pred,
-					       __right_len,
-					       __buffer, __buffer_size);
-	  std::rotate(__left_split, __middle, __right_split);
-	  std::advance(__left_split, std::distance(__middle, __right_split));
-	  return __left_split;
-	}
-    }
-
-  /**
-   *  @brief Move elements for which a predicate is true to the beginning
-   *         of a sequence, preserving relative ordering.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @param  __pred    A predicate functor.
-   *  @return  An iterator @p middle such that @p __pred(i) is true for each
-   *  iterator @p i in the range @p [first,middle) and false for each @p i
-   *  in the range @p [middle,last).
-   *
-   *  Performs the same function as @p partition() with the additional
-   *  guarantee that the relative ordering of elements in each group is
-   *  preserved, so any two elements @p x and @p y in the range
-   *  @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same
-   *  relative ordering after calling @p stable_partition().
-  */
-  template<typename _ForwardIterator, typename _Predicate>
-    _ForwardIterator
-    stable_partition(_ForwardIterator __first, _ForwardIterator __last,
-		     _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      __first = std::__find_if_not(__first, __last, __pred);
-
-      if (__first == __last)
-	return __first;
-      else
-	{
-	  typedef typename iterator_traits<_ForwardIterator>::value_type
-	    _ValueType;
-	  typedef typename iterator_traits<_ForwardIterator>::difference_type
-	    _DistanceType;
-
-	  _Temporary_buffer<_ForwardIterator, _ValueType> __buf(__first,
-								__last);
-	if (__buf.size() > 0)
-	  return
-	    std::__stable_partition_adaptive(__first, __last, __pred,
-					  _DistanceType(__buf.requested_size()),
-					  __buf.begin(),
-					  _DistanceType(__buf.size()));
-	else
-	  return
-	    std::__inplace_stable_partition(__first, __pred,
-					 _DistanceType(__buf.requested_size()));
-	}
-    }
-
-  /// This is a helper function for the sort routines.
-  template<typename _RandomAccessIterator>
-    void
-    __heap_select(_RandomAccessIterator __first,
-		  _RandomAccessIterator __middle,
-		  _RandomAccessIterator __last)
-    {
-      std::make_heap(__first, __middle);
-      for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
-	if (*__i < *__first)
-	  std::__pop_heap(__first, __middle, __i);
-    }
-
-  /// This is a helper function for the sort routines.
-  template<typename _RandomAccessIterator, typename _Compare>
-    void
-    __heap_select(_RandomAccessIterator __first,
-		  _RandomAccessIterator __middle,
-		  _RandomAccessIterator __last, _Compare __comp)
-    {
-      std::make_heap(__first, __middle, __comp);
-      for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
-	if (__comp(*__i, *__first))
-	  std::__pop_heap(__first, __middle, __i, __comp);
-    }
-
-  // partial_sort
-
-  /**
-   *  @brief Copy the smallest elements of a sequence.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __result_first   A random-access iterator.
-   *  @param  __result_last    Another random-access iterator.
-   *  @return   An iterator indicating the end of the resulting sequence.
-   *
-   *  Copies and sorts the smallest N values from the range @p [__first,__last)
-   *  to the range beginning at @p __result_first, where the number of
-   *  elements to be copied, @p N, is the smaller of @p (__last-__first) and
-   *  @p (__result_last-__result_first).
-   *  After the sort if @e i and @e j are iterators in the range
-   *  @p [__result_first,__result_first+N) such that i precedes j then
-   *  *j<*i is false.
-   *  The value returned is @p __result_first+N.
-  */
-  template<typename _InputIterator, typename _RandomAccessIterator>
-    _RandomAccessIterator
-    partial_sort_copy(_InputIterator __first, _InputIterator __last,
-		      _RandomAccessIterator __result_first,
-		      _RandomAccessIterator __result_last)
-    {
-      typedef typename iterator_traits<_InputIterator>::value_type
-	_InputValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_OutputValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_ConvertibleConcept<_InputValueType,
-				  _OutputValueType>)
-      __glibcxx_function_requires(_LessThanOpConcept<_InputValueType,
-				                     _OutputValueType>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-      __glibcxx_requires_valid_range(__result_first, __result_last);
-
-      if (__result_first == __result_last)
-	return __result_last;
-      _RandomAccessIterator __result_real_last = __result_first;
-      while(__first != __last && __result_real_last != __result_last)
-	{
-	  *__result_real_last = *__first;
-	  ++__result_real_last;
-	  ++__first;
-	}
-      std::make_heap(__result_first, __result_real_last);
-      while (__first != __last)
-	{
-	  if (*__first < *__result_first)
-	    std::__adjust_heap(__result_first, _DistanceType(0),
-			       _DistanceType(__result_real_last
-					     - __result_first),
-			       _InputValueType(*__first));
-	  ++__first;
-	}
-      std::sort_heap(__result_first, __result_real_last);
-      return __result_real_last;
-    }
-
-  /**
-   *  @brief Copy the smallest elements of a sequence using a predicate for
-   *         comparison.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    Another input iterator.
-   *  @param  __result_first   A random-access iterator.
-   *  @param  __result_last    Another random-access iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return   An iterator indicating the end of the resulting sequence.
-   *
-   *  Copies and sorts the smallest N values from the range @p [__first,__last)
-   *  to the range beginning at @p result_first, where the number of
-   *  elements to be copied, @p N, is the smaller of @p (__last-__first) and
-   *  @p (__result_last-__result_first).
-   *  After the sort if @e i and @e j are iterators in the range
-   *  @p [__result_first,__result_first+N) such that i precedes j then
-   *  @p __comp(*j,*i) is false.
-   *  The value returned is @p __result_first+N.
-  */
-  template<typename _InputIterator, typename _RandomAccessIterator, typename _Compare>
-    _RandomAccessIterator
-    partial_sort_copy(_InputIterator __first, _InputIterator __last,
-		      _RandomAccessIterator __result_first,
-		      _RandomAccessIterator __result_last,
-		      _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator>::value_type
-	_InputValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_OutputValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-				  _RandomAccessIterator>)
-      __glibcxx_function_requires(_ConvertibleConcept<_InputValueType,
-				  _OutputValueType>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _InputValueType, _OutputValueType>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _OutputValueType, _OutputValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-      __glibcxx_requires_valid_range(__result_first, __result_last);
-
-      if (__result_first == __result_last)
-	return __result_last;
-      _RandomAccessIterator __result_real_last = __result_first;
-      while(__first != __last && __result_real_last != __result_last)
-	{
-	  *__result_real_last = *__first;
-	  ++__result_real_last;
-	  ++__first;
-	}
-      std::make_heap(__result_first, __result_real_last, __comp);
-      while (__first != __last)
-	{
-	  if (__comp(*__first, *__result_first))
-	    std::__adjust_heap(__result_first, _DistanceType(0),
-			       _DistanceType(__result_real_last
-					     - __result_first),
-			       _InputValueType(*__first),
-			       __comp);
-	  ++__first;
-	}
-      std::sort_heap(__result_first, __result_real_last, __comp);
-      return __result_real_last;
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator>
-    void
-    __unguarded_linear_insert(_RandomAccessIterator __last)
-    {
-      typename iterator_traits<_RandomAccessIterator>::value_type
-	__val = _GLIBCXX_MOVE(*__last);
-      _RandomAccessIterator __next = __last;
-      --__next;
-      while (__val < *__next)
-	{
-	  *__last = _GLIBCXX_MOVE(*__next);
-	  __last = __next;
-	  --__next;
-	}
-      *__last = _GLIBCXX_MOVE(__val);
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Compare>
-    void
-    __unguarded_linear_insert(_RandomAccessIterator __last,
-			      _Compare __comp)
-    {
-      typename iterator_traits<_RandomAccessIterator>::value_type
-	__val = _GLIBCXX_MOVE(*__last);
-      _RandomAccessIterator __next = __last;
-      --__next;
-      while (__comp(__val, *__next))
-	{
-	  *__last = _GLIBCXX_MOVE(*__next);
-	  __last = __next;
-	  --__next;
-	}
-      *__last = _GLIBCXX_MOVE(__val);
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator>
-    void
-    __insertion_sort(_RandomAccessIterator __first,
-		     _RandomAccessIterator __last)
-    {
-      if (__first == __last)
-	return;
-
-      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
-	{
-	  if (*__i < *__first)
-	    {
-	      typename iterator_traits<_RandomAccessIterator>::value_type
-		__val = _GLIBCXX_MOVE(*__i);
-	      _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
-	      *__first = _GLIBCXX_MOVE(__val);
-	    }
-	  else
-	    std::__unguarded_linear_insert(__i);
-	}
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Compare>
-    void
-    __insertion_sort(_RandomAccessIterator __first,
-		     _RandomAccessIterator __last, _Compare __comp)
-    {
-      if (__first == __last) return;
-
-      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
-	{
-	  if (__comp(*__i, *__first))
-	    {
-	      typename iterator_traits<_RandomAccessIterator>::value_type
-		__val = _GLIBCXX_MOVE(*__i);
-	      _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
-	      *__first = _GLIBCXX_MOVE(__val);
-	    }
-	  else
-	    std::__unguarded_linear_insert(__i, __comp);
-	}
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator>
-    inline void
-    __unguarded_insertion_sort(_RandomAccessIterator __first,
-			       _RandomAccessIterator __last)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
-	std::__unguarded_linear_insert(__i);
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline void
-    __unguarded_insertion_sort(_RandomAccessIterator __first,
-			       _RandomAccessIterator __last, _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
-	std::__unguarded_linear_insert(__i, __comp);
-    }
-
-  /**
-   *  @doctodo
-   *  This controls some aspect of the sort routines.
-  */
-  enum { _S_threshold = 16 };
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator>
-    void
-    __final_insertion_sort(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last)
-    {
-      if (__last - __first > int(_S_threshold))
-	{
-	  std::__insertion_sort(__first, __first + int(_S_threshold));
-	  std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
-	}
-      else
-	std::__insertion_sort(__first, __last);
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Compare>
-    void
-    __final_insertion_sort(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last, _Compare __comp)
-    {
-      if (__last - __first > int(_S_threshold))
-	{
-	  std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
-	  std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
-					  __comp);
-	}
-      else
-	std::__insertion_sort(__first, __last, __comp);
-    }
-
-  /// This is a helper function...
-  template<typename _RandomAccessIterator, typename _Tp>
-    _RandomAccessIterator
-    __unguarded_partition(_RandomAccessIterator __first,
-			  _RandomAccessIterator __last, const _Tp& __pivot)
-    {
-      while (true)
-	{
-	  while (*__first < __pivot)
-	    ++__first;
-	  --__last;
-	  while (__pivot < *__last)
-	    --__last;
-	  if (!(__first < __last))
-	    return __first;
-	  std::iter_swap(__first, __last);
-	  ++__first;
-	}
-    }
-
-  /// This is a helper function...
-  template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
-    _RandomAccessIterator
-    __unguarded_partition(_RandomAccessIterator __first,
-			  _RandomAccessIterator __last,
-			  const _Tp& __pivot, _Compare __comp)
-    {
-      while (true)
-	{
-	  while (__comp(*__first, __pivot))
-	    ++__first;
-	  --__last;
-	  while (__comp(__pivot, *__last))
-	    --__last;
-	  if (!(__first < __last))
-	    return __first;
-	  std::iter_swap(__first, __last);
-	  ++__first;
-	}
-    }
-
-  /// This is a helper function...
-  template<typename _RandomAccessIterator>
-    inline _RandomAccessIterator
-    __unguarded_partition_pivot(_RandomAccessIterator __first,
-				_RandomAccessIterator __last)
-    {
-      _RandomAccessIterator __mid = __first + (__last - __first) / 2;
-      std::__move_median_to_first(__first, __first + 1, __mid, __last - 1);
-      return std::__unguarded_partition(__first + 1, __last, *__first);
-    }
-
-
-  /// This is a helper function...
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline _RandomAccessIterator
-    __unguarded_partition_pivot(_RandomAccessIterator __first,
-				_RandomAccessIterator __last, _Compare __comp)
-    {
-      _RandomAccessIterator __mid = __first + (__last - __first) / 2;
-      std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
-				  __comp);
-      return std::__unguarded_partition(__first + 1, __last, *__first, __comp);
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Size>
-    void
-    __introsort_loop(_RandomAccessIterator __first,
-		     _RandomAccessIterator __last,
-		     _Size __depth_limit)
-    {
-      while (__last - __first > int(_S_threshold))
-	{
-	  if (__depth_limit == 0)
-	    {
-	      _GLIBCXX_STD_A::partial_sort(__first, __last, __last);
-	      return;
-	    }
-	  --__depth_limit;
-	  _RandomAccessIterator __cut =
-	    std::__unguarded_partition_pivot(__first, __last);
-	  std::__introsort_loop(__cut, __last, __depth_limit);
-	  __last = __cut;
-	}
-    }
-
-  /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Size, typename _Compare>
-    void
-    __introsort_loop(_RandomAccessIterator __first,
-		     _RandomAccessIterator __last,
-		     _Size __depth_limit, _Compare __comp)
-    {
-      while (__last - __first > int(_S_threshold))
-	{
-	  if (__depth_limit == 0)
-	    {
-	      _GLIBCXX_STD_A::partial_sort(__first, __last, __last, __comp);
-	      return;
-	    }
-	  --__depth_limit;
-	  _RandomAccessIterator __cut =
-	    std::__unguarded_partition_pivot(__first, __last, __comp);
-	  std::__introsort_loop(__cut, __last, __depth_limit, __comp);
-	  __last = __cut;
-	}
-    }
-
-  // sort
-
-  template<typename _RandomAccessIterator, typename _Size>
-    void
-    __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
-		  _RandomAccessIterator __last, _Size __depth_limit)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      while (__last - __first > 3)
-	{
-	  if (__depth_limit == 0)
-	    {
-	      std::__heap_select(__first, __nth + 1, __last);
-
-	      // Place the nth largest element in its final position.
-	      std::iter_swap(__first, __nth);
-	      return;
-	    }
-	  --__depth_limit;
-	  _RandomAccessIterator __cut =
-	    std::__unguarded_partition_pivot(__first, __last);
-	  if (__cut <= __nth)
-	    __first = __cut;
-	  else
-	    __last = __cut;
-	}
-      std::__insertion_sort(__first, __last);
-    }
-
-  template<typename _RandomAccessIterator, typename _Size, typename _Compare>
-    void
-    __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
-		  _RandomAccessIterator __last, _Size __depth_limit,
-		  _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      while (__last - __first > 3)
-	{
-	  if (__depth_limit == 0)
-	    {
-	      std::__heap_select(__first, __nth + 1, __last, __comp);
-	      // Place the nth largest element in its final position.
-	      std::iter_swap(__first, __nth);
-	      return;
-	    }
-	  --__depth_limit;
-	  _RandomAccessIterator __cut =
-	    std::__unguarded_partition_pivot(__first, __last, __comp);
-	  if (__cut <= __nth)
-	    __first = __cut;
-	  else
-	    __last = __cut;
-	}
-      std::__insertion_sort(__first, __last, __comp);
-    }
-
-  // nth_element
-
-  // lower_bound moved to stl_algobase.h
-
-  /**
-   *  @brief Finds the first position in which @p __val could be inserted
-   *         without changing the ordering.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return An iterator pointing to the first element <em>not less
-   *           than</em> @p __val, or end() if every element is less
-   *           than @p __val.
-   *  @ingroup binary_search_algorithms
-   *
-   *  The comparison function should have the same effects on ordering as
-   *  the function used for the initial sort.
-  */
-  template<typename _ForwardIterator, typename _Tp, typename _Compare>
-    _ForwardIterator
-    lower_bound(_ForwardIterator __first, _ForwardIterator __last,
-		const _Tp& __val, _Compare __comp)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType, _Tp>)
-      __glibcxx_requires_partitioned_lower_pred(__first, __last,
-						__val, __comp);
-
-      _DistanceType __len = std::distance(__first, __last);
-
-      while (__len > 0)
-	{
-	  _DistanceType __half = __len >> 1;
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __half);
-	  if (__comp(*__middle, __val))
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	  else
-	    __len = __half;
-	}
-      return __first;
-    }
-
-  /**
-   *  @brief Finds the last position in which @p __val could be inserted
-   *         without changing the ordering.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @return  An iterator pointing to the first element greater than @p __val,
-   *           or end() if no elements are greater than @p __val.
-   *  @ingroup binary_search_algorithms
-  */
-  template<typename _ForwardIterator, typename _Tp>
-    _ForwardIterator
-    upper_bound(_ForwardIterator __first, _ForwardIterator __last,
-		const _Tp& __val)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
-      __glibcxx_requires_partitioned_upper(__first, __last, __val);
-
-      _DistanceType __len = std::distance(__first, __last);
-
-      while (__len > 0)
-	{
-	  _DistanceType __half = __len >> 1;
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __half);
-	  if (__val < *__middle)
-	    __len = __half;
-	  else
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	}
-      return __first;
-    }
-
-  /**
-   *  @brief Finds the last position in which @p __val could be inserted
-   *         without changing the ordering.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return  An iterator pointing to the first element greater than @p __val,
-   *           or end() if no elements are greater than @p __val.
-   *  @ingroup binary_search_algorithms
-   *
-   *  The comparison function should have the same effects on ordering as
-   *  the function used for the initial sort.
-  */
-  template<typename _ForwardIterator, typename _Tp, typename _Compare>
-    _ForwardIterator
-    upper_bound(_ForwardIterator __first, _ForwardIterator __last,
-		const _Tp& __val, _Compare __comp)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _Tp, _ValueType>)
-      __glibcxx_requires_partitioned_upper_pred(__first, __last,
-						__val, __comp);
-
-      _DistanceType __len = std::distance(__first, __last);
-
-      while (__len > 0)
-	{
-	  _DistanceType __half = __len >> 1;
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __half);
-	  if (__comp(__val, *__middle))
-	    __len = __half;
-	  else
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	}
-      return __first;
-    }
-
-  /**
-   *  @brief Finds the largest subrange in which @p __val could be inserted
-   *         at any place in it without changing the ordering.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @return  An pair of iterators defining the subrange.
-   *  @ingroup binary_search_algorithms
-   *
-   *  This is equivalent to
-   *  @code
-   *    std::make_pair(lower_bound(__first, __last, __val),
-   *                   upper_bound(__first, __last, __val))
-   *  @endcode
-   *  but does not actually call those functions.
-  */
-  template<typename _ForwardIterator, typename _Tp>
-    pair<_ForwardIterator, _ForwardIterator>
-    equal_range(_ForwardIterator __first, _ForwardIterator __last,
-		const _Tp& __val)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
-      __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)	
-      __glibcxx_requires_partitioned_lower(__first, __last, __val);
-      __glibcxx_requires_partitioned_upper(__first, __last, __val);
-
-      _DistanceType __len = std::distance(__first, __last);
-
-      while (__len > 0)
-	{
-	  _DistanceType __half = __len >> 1;
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __half);
-	  if (*__middle < __val)
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	  else if (__val < *__middle)
-	    __len = __half;
-	  else
-	    {
-	      _ForwardIterator __left = std::lower_bound(__first, __middle,
-							 __val);
-	      std::advance(__first, __len);
-	      _ForwardIterator __right = std::upper_bound(++__middle, __first,
-							  __val);
-	      return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
-	    }
-	}
-      return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
-    }
-
-  /**
-   *  @brief Finds the largest subrange in which @p __val could be inserted
-   *         at any place in it without changing the ordering.
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return  An pair of iterators defining the subrange.
-   *  @ingroup binary_search_algorithms
-   *
-   *  This is equivalent to
-   *  @code
-   *    std::make_pair(lower_bound(__first, __last, __val, __comp),
-   *                   upper_bound(__first, __last, __val, __comp))
-   *  @endcode
-   *  but does not actually call those functions.
-  */
-  template<typename _ForwardIterator, typename _Tp, typename _Compare>
-    pair<_ForwardIterator, _ForwardIterator>
-    equal_range(_ForwardIterator __first, _ForwardIterator __last,
-		const _Tp& __val, _Compare __comp)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_ForwardIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType, _Tp>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _Tp, _ValueType>)
-      __glibcxx_requires_partitioned_lower_pred(__first, __last,
-						__val, __comp);
-      __glibcxx_requires_partitioned_upper_pred(__first, __last,
-						__val, __comp);
-
-      _DistanceType __len = std::distance(__first, __last);
-
-      while (__len > 0)
-	{
-	  _DistanceType __half = __len >> 1;
-	  _ForwardIterator __middle = __first;
-	  std::advance(__middle, __half);
-	  if (__comp(*__middle, __val))
-	    {
-	      __first = __middle;
-	      ++__first;
-	      __len = __len - __half - 1;
-	    }
-	  else if (__comp(__val, *__middle))
-	    __len = __half;
-	  else
-	    {
-	      _ForwardIterator __left = std::lower_bound(__first, __middle,
-							 __val, __comp);
-	      std::advance(__first, __len);
-	      _ForwardIterator __right = std::upper_bound(++__middle, __first,
-							  __val, __comp);
-	      return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
-	    }
-	}
-      return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
-    }
-
-  /**
-   *  @brief Determines whether an element exists in a range.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @return True if @p __val (or its equivalent) is in [@p
-   *  __first,@p __last ].
-   *
-   *  Note that this does not actually return an iterator to @p __val.  For
-   *  that, use std::find or a container's specialized find member functions.
-  */
-  template<typename _ForwardIterator, typename _Tp>
-    bool
-    binary_search(_ForwardIterator __first, _ForwardIterator __last,
-                  const _Tp& __val)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
-      __glibcxx_requires_partitioned_lower(__first, __last, __val);
-      __glibcxx_requires_partitioned_upper(__first, __last, __val);
-
-      _ForwardIterator __i = std::lower_bound(__first, __last, __val);
-      return __i != __last && !(__val < *__i);
-    }
-
-  /**
-   *  @brief Determines whether an element exists in a range.
-   *  @ingroup binary_search_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __val     The search term.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return  True if @p __val (or its equivalent) is in @p [__first,__last].
-   *
-   *  Note that this does not actually return an iterator to @p __val.  For
-   *  that, use std::find or a container's specialized find member functions.
-   *
-   *  The comparison function should have the same effects on ordering as
-   *  the function used for the initial sort.
-  */
-  template<typename _ForwardIterator, typename _Tp, typename _Compare>
-    bool
-    binary_search(_ForwardIterator __first, _ForwardIterator __last,
-                  const _Tp& __val, _Compare __comp)
-    {
-      typedef typename iterator_traits<_ForwardIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _Tp, _ValueType>)
-      __glibcxx_requires_partitioned_lower_pred(__first, __last,
-						__val, __comp);
-      __glibcxx_requires_partitioned_upper_pred(__first, __last,
-						__val, __comp);
-
-      _ForwardIterator __i = std::lower_bound(__first, __last, __val, __comp);
-      return __i != __last && !bool(__comp(__val, *__i));
-    }
-
-  // merge
-
-  /// This is a helper function for the __merge_adaptive routines.
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    void
-    __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
-			  _InputIterator2 __first2, _InputIterator2 __last2,
-			  _OutputIterator __result)
-    {
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (*__first2 < *__first1)
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first2);
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first1);
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      if (__first1 != __last1)
-	_GLIBCXX_MOVE3(__first1, __last1, __result);
-    }
-
-  /// This is a helper function for the __merge_adaptive routines.
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    void
-    __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
-			  _InputIterator2 __first2, _InputIterator2 __last2,
-			  _OutputIterator __result, _Compare __comp)
-    {
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (__comp(*__first2, *__first1))
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first2);
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first1);
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      if (__first1 != __last1)
-	_GLIBCXX_MOVE3(__first1, __last1, __result);
-    }
-
-  /// This is a helper function for the __merge_adaptive routines.
-  template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
-	   typename _BidirectionalIterator3>
-    void
-    __move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
-				   _BidirectionalIterator1 __last1,
-				   _BidirectionalIterator2 __first2,
-				   _BidirectionalIterator2 __last2,
-				   _BidirectionalIterator3 __result)
-    {
-      if (__first1 == __last1)
-	{
-	  _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result);
-	  return;
-	}
-      else if (__first2 == __last2)
-	return;
-
-      --__last1;
-      --__last2;
-      while (true)
-	{
-	  if (*__last2 < *__last1)
-	    {
-	      *--__result = _GLIBCXX_MOVE(*__last1);
-	      if (__first1 == __last1)
-		{
-		  _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result);
-		  return;
-		}
-	      --__last1;
-	    }
-	  else
-	    {
-	      *--__result = _GLIBCXX_MOVE(*__last2);
-	      if (__first2 == __last2)
-		return;
-	      --__last2;
-	    }
-	}
-    }
-
-  /// This is a helper function for the __merge_adaptive routines.
-  template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
-	   typename _BidirectionalIterator3, typename _Compare>
-    void
-    __move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
-				   _BidirectionalIterator1 __last1,
-				   _BidirectionalIterator2 __first2,
-				   _BidirectionalIterator2 __last2,
-				   _BidirectionalIterator3 __result,
-				   _Compare __comp)
-    {
-      if (__first1 == __last1)
-	{
-	  _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result);
-	  return;
-	}
-      else if (__first2 == __last2)
-	return;
-
-      --__last1;
-      --__last2;
-      while (true)
-	{
-	  if (__comp(*__last2, *__last1))
-	    {
-	      *--__result = _GLIBCXX_MOVE(*__last1);
-	      if (__first1 == __last1)
-		{
-		  _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result);
-		  return;
-		}
-	      --__last1;
-	    }
-	  else
-	    {
-	      *--__result = _GLIBCXX_MOVE(*__last2);
-	      if (__first2 == __last2)
-		return;
-	      --__last2;
-	    }
-	}
-    }
-
-  /// This is a helper function for the merge routines.
-  template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
-	   typename _Distance>
-    _BidirectionalIterator1
-    __rotate_adaptive(_BidirectionalIterator1 __first,
-		      _BidirectionalIterator1 __middle,
-		      _BidirectionalIterator1 __last,
-		      _Distance __len1, _Distance __len2,
-		      _BidirectionalIterator2 __buffer,
-		      _Distance __buffer_size)
-    {
-      _BidirectionalIterator2 __buffer_end;
-      if (__len1 > __len2 && __len2 <= __buffer_size)
-	{
-	  if (__len2)
-	    {
-	      __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
-	      _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last);
-	      return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first);
-	    }
-	  else
-	    return __first;
-	}
-      else if (__len1 <= __buffer_size)
-	{
-	  if (__len1)
-	    {
-	      __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
-	      _GLIBCXX_MOVE3(__middle, __last, __first);
-	      return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last);
-	    }
-	  else
-	    return __last;
-	}
-      else
-	{
-	  std::rotate(__first, __middle, __last);
-	  std::advance(__first, std::distance(__middle, __last));
-	  return __first;
-	}
-    }
-
-  /// This is a helper function for the merge routines.
-  template<typename _BidirectionalIterator, typename _Distance,
-	   typename _Pointer>
-    void
-    __merge_adaptive(_BidirectionalIterator __first,
-                     _BidirectionalIterator __middle,
-		     _BidirectionalIterator __last,
-		     _Distance __len1, _Distance __len2,
-		     _Pointer __buffer, _Distance __buffer_size)
-    {
-      if (__len1 <= __len2 && __len1 <= __buffer_size)
-	{
-	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
-	  std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
-				     __first);
-	}
-      else if (__len2 <= __buffer_size)
-	{
-	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
-	  std::__move_merge_adaptive_backward(__first, __middle, __buffer,
-					      __buffer_end, __last);
-	}
-      else
-	{
-	  _BidirectionalIterator __first_cut = __first;
-	  _BidirectionalIterator __second_cut = __middle;
-	  _Distance __len11 = 0;
-	  _Distance __len22 = 0;
-	  if (__len1 > __len2)
-	    {
-	      __len11 = __len1 / 2;
-	      std::advance(__first_cut, __len11);
-	      __second_cut = std::lower_bound(__middle, __last,
-					      *__first_cut);
-	      __len22 = std::distance(__middle, __second_cut);
-	    }
-	  else
-	    {
-	      __len22 = __len2 / 2;
-	      std::advance(__second_cut, __len22);
-	      __first_cut = std::upper_bound(__first, __middle,
-					     *__second_cut);
-	      __len11 = std::distance(__first, __first_cut);
-	    }
-	  _BidirectionalIterator __new_middle =
-	    std::__rotate_adaptive(__first_cut, __middle, __second_cut,
-				   __len1 - __len11, __len22, __buffer,
-				   __buffer_size);
-	  std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
-				__len22, __buffer, __buffer_size);
-	  std::__merge_adaptive(__new_middle, __second_cut, __last,
-				__len1 - __len11,
-				__len2 - __len22, __buffer, __buffer_size);
-	}
-    }
-
-  /// This is a helper function for the merge routines.
-  template<typename _BidirectionalIterator, typename _Distance,
-	   typename _Pointer, typename _Compare>
-    void
-    __merge_adaptive(_BidirectionalIterator __first,
-                     _BidirectionalIterator __middle,
-		     _BidirectionalIterator __last,
-		     _Distance __len1, _Distance __len2,
-		     _Pointer __buffer, _Distance __buffer_size,
-		     _Compare __comp)
-    {
-      if (__len1 <= __len2 && __len1 <= __buffer_size)
-	{
-	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
-	  std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
-				     __first, __comp);
-	}
-      else if (__len2 <= __buffer_size)
-	{
-	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
-	  std::__move_merge_adaptive_backward(__first, __middle, __buffer,
-					      __buffer_end, __last, __comp);
-	}
-      else
-	{
-	  _BidirectionalIterator __first_cut = __first;
-	  _BidirectionalIterator __second_cut = __middle;
-	  _Distance __len11 = 0;
-	  _Distance __len22 = 0;
-	  if (__len1 > __len2)
-	    {
-	      __len11 = __len1 / 2;
-	      std::advance(__first_cut, __len11);
-	      __second_cut = std::lower_bound(__middle, __last, *__first_cut,
-					      __comp);
-	      __len22 = std::distance(__middle, __second_cut);
-	    }
-	  else
-	    {
-	      __len22 = __len2 / 2;
-	      std::advance(__second_cut, __len22);
-	      __first_cut = std::upper_bound(__first, __middle, *__second_cut,
-					     __comp);
-	      __len11 = std::distance(__first, __first_cut);
-	    }
-	  _BidirectionalIterator __new_middle =
-	    std::__rotate_adaptive(__first_cut, __middle, __second_cut,
-				   __len1 - __len11, __len22, __buffer,
-				   __buffer_size);
-	  std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
-				__len22, __buffer, __buffer_size, __comp);
-	  std::__merge_adaptive(__new_middle, __second_cut, __last,
-				__len1 - __len11,
-				__len2 - __len22, __buffer,
-				__buffer_size, __comp);
-	}
-    }
-
-  /// This is a helper function for the merge routines.
-  template<typename _BidirectionalIterator, typename _Distance>
-    void
-    __merge_without_buffer(_BidirectionalIterator __first,
-			   _BidirectionalIterator __middle,
-			   _BidirectionalIterator __last,
-			   _Distance __len1, _Distance __len2)
-    {
-      if (__len1 == 0 || __len2 == 0)
-	return;
-      if (__len1 + __len2 == 2)
-	{
-	  if (*__middle < *__first)
-	    std::iter_swap(__first, __middle);
-	  return;
-	}
-      _BidirectionalIterator __first_cut = __first;
-      _BidirectionalIterator __second_cut = __middle;
-      _Distance __len11 = 0;
-      _Distance __len22 = 0;
-      if (__len1 > __len2)
-	{
-	  __len11 = __len1 / 2;
-	  std::advance(__first_cut, __len11);
-	  __second_cut = std::lower_bound(__middle, __last, *__first_cut);
-	  __len22 = std::distance(__middle, __second_cut);
-	}
-      else
-	{
-	  __len22 = __len2 / 2;
-	  std::advance(__second_cut, __len22);
-	  __first_cut = std::upper_bound(__first, __middle, *__second_cut);
-	  __len11 = std::distance(__first, __first_cut);
-	}
-      std::rotate(__first_cut, __middle, __second_cut);
-      _BidirectionalIterator __new_middle = __first_cut;
-      std::advance(__new_middle, std::distance(__middle, __second_cut));
-      std::__merge_without_buffer(__first, __first_cut, __new_middle,
-				  __len11, __len22);
-      std::__merge_without_buffer(__new_middle, __second_cut, __last,
-				  __len1 - __len11, __len2 - __len22);
-    }
-
-  /// This is a helper function for the merge routines.
-  template<typename _BidirectionalIterator, typename _Distance,
-	   typename _Compare>
-    void
-    __merge_without_buffer(_BidirectionalIterator __first,
-                           _BidirectionalIterator __middle,
-			   _BidirectionalIterator __last,
-			   _Distance __len1, _Distance __len2,
-			   _Compare __comp)
-    {
-      if (__len1 == 0 || __len2 == 0)
-	return;
-      if (__len1 + __len2 == 2)
-	{
-	  if (__comp(*__middle, *__first))
-	    std::iter_swap(__first, __middle);
-	  return;
-	}
-      _BidirectionalIterator __first_cut = __first;
-      _BidirectionalIterator __second_cut = __middle;
-      _Distance __len11 = 0;
-      _Distance __len22 = 0;
-      if (__len1 > __len2)
-	{
-	  __len11 = __len1 / 2;
-	  std::advance(__first_cut, __len11);
-	  __second_cut = std::lower_bound(__middle, __last, *__first_cut,
-					  __comp);
-	  __len22 = std::distance(__middle, __second_cut);
-	}
-      else
-	{
-	  __len22 = __len2 / 2;
-	  std::advance(__second_cut, __len22);
-	  __first_cut = std::upper_bound(__first, __middle, *__second_cut,
-					 __comp);
-	  __len11 = std::distance(__first, __first_cut);
-	}
-      std::rotate(__first_cut, __middle, __second_cut);
-      _BidirectionalIterator __new_middle = __first_cut;
-      std::advance(__new_middle, std::distance(__middle, __second_cut));
-      std::__merge_without_buffer(__first, __first_cut, __new_middle,
-				  __len11, __len22, __comp);
-      std::__merge_without_buffer(__new_middle, __second_cut, __last,
-				  __len1 - __len11, __len2 - __len22, __comp);
-    }
-
-  /**
-   *  @brief Merges two sorted ranges in place.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __middle  Another iterator.
-   *  @param  __last    Another iterator.
-   *  @return  Nothing.
-   *
-   *  Merges two sorted and consecutive ranges, [__first,__middle) and
-   *  [__middle,__last), and puts the result in [__first,__last).  The
-   *  output will be sorted.  The sort is @e stable, that is, for
-   *  equivalent elements in the two ranges, elements from the first
-   *  range will always come before elements from the second.
-   *
-   *  If enough additional memory is available, this takes (__last-__first)-1
-   *  comparisons.  Otherwise an NlogN algorithm is used, where N is
-   *  distance(__first,__last).
-  */
-  template<typename _BidirectionalIterator>
-    void
-    inplace_merge(_BidirectionalIterator __first,
-		  _BidirectionalIterator __middle,
-		  _BidirectionalIterator __last)
-    {
-      typedef typename iterator_traits<_BidirectionalIterator>::value_type
-          _ValueType;
-      typedef typename iterator_traits<_BidirectionalIterator>::difference_type
-          _DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
-	    _BidirectionalIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
-      __glibcxx_requires_sorted(__first, __middle);
-      __glibcxx_requires_sorted(__middle, __last);
-
-      if (__first == __middle || __middle == __last)
-	return;
-
-      _DistanceType __len1 = std::distance(__first, __middle);
-      _DistanceType __len2 = std::distance(__middle, __last);
-
-      _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
-								  __last);
-      if (__buf.begin() == 0)
-	std::__merge_without_buffer(__first, __middle, __last, __len1, __len2);
-      else
-	std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
-			      __buf.begin(), _DistanceType(__buf.size()));
-    }
-
-  /**
-   *  @brief Merges two sorted ranges in place.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __middle  Another iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return  Nothing.
-   *
-   *  Merges two sorted and consecutive ranges, [__first,__middle) and
-   *  [middle,last), and puts the result in [__first,__last).  The output will
-   *  be sorted.  The sort is @e stable, that is, for equivalent
-   *  elements in the two ranges, elements from the first range will always
-   *  come before elements from the second.
-   *
-   *  If enough additional memory is available, this takes (__last-__first)-1
-   *  comparisons.  Otherwise an NlogN algorithm is used, where N is
-   *  distance(__first,__last).
-   *
-   *  The comparison function should have the same effects on ordering as
-   *  the function used for the initial sort.
-  */
-  template<typename _BidirectionalIterator, typename _Compare>
-    void
-    inplace_merge(_BidirectionalIterator __first,
-		  _BidirectionalIterator __middle,
-		  _BidirectionalIterator __last,
-		  _Compare __comp)
-    {
-      typedef typename iterator_traits<_BidirectionalIterator>::value_type
-          _ValueType;
-      typedef typename iterator_traits<_BidirectionalIterator>::difference_type
-          _DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
-	    _BidirectionalIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    _ValueType, _ValueType>)
-      __glibcxx_requires_sorted_pred(__first, __middle, __comp);
-      __glibcxx_requires_sorted_pred(__middle, __last, __comp);
-
-      if (__first == __middle || __middle == __last)
-	return;
-
-      const _DistanceType __len1 = std::distance(__first, __middle);
-      const _DistanceType __len2 = std::distance(__middle, __last);
-
-      _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
-								  __last);
-      if (__buf.begin() == 0)
-	std::__merge_without_buffer(__first, __middle, __last, __len1,
-				    __len2, __comp);
-      else
-	std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
-			      __buf.begin(), _DistanceType(__buf.size()),
-			      __comp);
-    }
-
-
-  /// This is a helper function for the __merge_sort_loop routines.
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
-		 _InputIterator2 __first2, _InputIterator2 __last2,
-		 _OutputIterator __result)
-    {
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (*__first2 < *__first1)
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first2);
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first1);
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      return _GLIBCXX_MOVE3(__first2, __last2,
-			    _GLIBCXX_MOVE3(__first1, __last1,
-					   __result));
-    }
-
-  /// This is a helper function for the __merge_sort_loop routines.
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
-		 _InputIterator2 __first2, _InputIterator2 __last2,
-		 _OutputIterator __result, _Compare __comp)
-    {
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (__comp(*__first2, *__first1))
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first2);
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = _GLIBCXX_MOVE(*__first1);
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      return _GLIBCXX_MOVE3(__first2, __last2,
-			    _GLIBCXX_MOVE3(__first1, __last1,
-					   __result));
-    }
-
-  template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
-	   typename _Distance>
-    void
-    __merge_sort_loop(_RandomAccessIterator1 __first,
-		      _RandomAccessIterator1 __last,
-		      _RandomAccessIterator2 __result,
-		      _Distance __step_size)
-    {
-      const _Distance __two_step = 2 * __step_size;
-
-      while (__last - __first >= __two_step)
-	{
-	  __result = std::__move_merge(__first, __first + __step_size,
-				       __first + __step_size,
-				       __first + __two_step, __result);
-	  __first += __two_step;
-	}
-
-      __step_size = std::min(_Distance(__last - __first), __step_size);
-      std::__move_merge(__first, __first + __step_size,
-			__first + __step_size, __last, __result);
-    }
-
-  template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
-	   typename _Distance, typename _Compare>
-    void
-    __merge_sort_loop(_RandomAccessIterator1 __first,
-		      _RandomAccessIterator1 __last,
-		      _RandomAccessIterator2 __result, _Distance __step_size,
-		      _Compare __comp)
-    {
-      const _Distance __two_step = 2 * __step_size;
-
-      while (__last - __first >= __two_step)
-	{
-	  __result = std::__move_merge(__first, __first + __step_size,
-				       __first + __step_size,
-				       __first + __two_step,
-				       __result, __comp);
-	  __first += __two_step;
-	}
-      __step_size = std::min(_Distance(__last - __first), __step_size);
-
-      std::__move_merge(__first,__first + __step_size,
-			__first + __step_size, __last, __result, __comp);
-    }
-
-  template<typename _RandomAccessIterator, typename _Distance>
-    void
-    __chunk_insertion_sort(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last,
-			   _Distance __chunk_size)
-    {
-      while (__last - __first >= __chunk_size)
-	{
-	  std::__insertion_sort(__first, __first + __chunk_size);
-	  __first += __chunk_size;
-	}
-      std::__insertion_sort(__first, __last);
-    }
-
-  template<typename _RandomAccessIterator, typename _Distance,
-	   typename _Compare>
-    void
-    __chunk_insertion_sort(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last,
-			   _Distance __chunk_size, _Compare __comp)
-    {
-      while (__last - __first >= __chunk_size)
-	{
-	  std::__insertion_sort(__first, __first + __chunk_size, __comp);
-	  __first += __chunk_size;
-	}
-      std::__insertion_sort(__first, __last, __comp);
-    }
-
-  enum { _S_chunk_size = 7 };
-
-  template<typename _RandomAccessIterator, typename _Pointer>
-    void
-    __merge_sort_with_buffer(_RandomAccessIterator __first,
-			     _RandomAccessIterator __last,
-                             _Pointer __buffer)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_Distance;
-
-      const _Distance __len = __last - __first;
-      const _Pointer __buffer_last = __buffer + __len;
-
-      _Distance __step_size = _S_chunk_size;
-      std::__chunk_insertion_sort(__first, __last, __step_size);
-
-      while (__step_size < __len)
-	{
-	  std::__merge_sort_loop(__first, __last, __buffer, __step_size);
-	  __step_size *= 2;
-	  std::__merge_sort_loop(__buffer, __buffer_last, __first, __step_size);
-	  __step_size *= 2;
-	}
-    }
-
-  template<typename _RandomAccessIterator, typename _Pointer, typename _Compare>
-    void
-    __merge_sort_with_buffer(_RandomAccessIterator __first,
-			     _RandomAccessIterator __last,
-                             _Pointer __buffer, _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_Distance;
-
-      const _Distance __len = __last - __first;
-      const _Pointer __buffer_last = __buffer + __len;
-
-      _Distance __step_size = _S_chunk_size;
-      std::__chunk_insertion_sort(__first, __last, __step_size, __comp);
-
-      while (__step_size < __len)
-	{
-	  std::__merge_sort_loop(__first, __last, __buffer,
-				 __step_size, __comp);
-	  __step_size *= 2;
-	  std::__merge_sort_loop(__buffer, __buffer_last, __first,
-				 __step_size, __comp);
-	  __step_size *= 2;
-	}
-    }
-
-  template<typename _RandomAccessIterator, typename _Pointer,
-	   typename _Distance>
-    void
-    __stable_sort_adaptive(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last,
-                           _Pointer __buffer, _Distance __buffer_size)
-    {
-      const _Distance __len = (__last - __first + 1) / 2;
-      const _RandomAccessIterator __middle = __first + __len;
-      if (__len > __buffer_size)
-	{
-	  std::__stable_sort_adaptive(__first, __middle,
-				      __buffer, __buffer_size);
-	  std::__stable_sort_adaptive(__middle, __last,
-				      __buffer, __buffer_size);
-	}
-      else
-	{
-	  std::__merge_sort_with_buffer(__first, __middle, __buffer);
-	  std::__merge_sort_with_buffer(__middle, __last, __buffer);
-	}
-      std::__merge_adaptive(__first, __middle, __last,
-			    _Distance(__middle - __first),
-			    _Distance(__last - __middle),
-			    __buffer, __buffer_size);
-    }
-
-  template<typename _RandomAccessIterator, typename _Pointer,
-	   typename _Distance, typename _Compare>
-    void
-    __stable_sort_adaptive(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last,
-                           _Pointer __buffer, _Distance __buffer_size,
-                           _Compare __comp)
-    {
-      const _Distance __len = (__last - __first + 1) / 2;
-      const _RandomAccessIterator __middle = __first + __len;
-      if (__len > __buffer_size)
-	{
-	  std::__stable_sort_adaptive(__first, __middle, __buffer,
-				      __buffer_size, __comp);
-	  std::__stable_sort_adaptive(__middle, __last, __buffer,
-				      __buffer_size, __comp);
-	}
-      else
-	{
-	  std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp);
-	  std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp);
-	}
-      std::__merge_adaptive(__first, __middle, __last,
-			    _Distance(__middle - __first),
-			    _Distance(__last - __middle),
-			    __buffer, __buffer_size,
-			    __comp);
-    }
-
-  /// This is a helper function for the stable sorting routines.
-  template<typename _RandomAccessIterator>
-    void
-    __inplace_stable_sort(_RandomAccessIterator __first,
-			  _RandomAccessIterator __last)
-    {
-      if (__last - __first < 15)
-	{
-	  std::__insertion_sort(__first, __last);
-	  return;
-	}
-      _RandomAccessIterator __middle = __first + (__last - __first) / 2;
-      std::__inplace_stable_sort(__first, __middle);
-      std::__inplace_stable_sort(__middle, __last);
-      std::__merge_without_buffer(__first, __middle, __last,
-				  __middle - __first,
-				  __last - __middle);
-    }
-
-  /// This is a helper function for the stable sorting routines.
-  template<typename _RandomAccessIterator, typename _Compare>
-    void
-    __inplace_stable_sort(_RandomAccessIterator __first,
-			  _RandomAccessIterator __last, _Compare __comp)
-    {
-      if (__last - __first < 15)
-	{
-	  std::__insertion_sort(__first, __last, __comp);
-	  return;
-	}
-      _RandomAccessIterator __middle = __first + (__last - __first) / 2;
-      std::__inplace_stable_sort(__first, __middle, __comp);
-      std::__inplace_stable_sort(__middle, __last, __comp);
-      std::__merge_without_buffer(__first, __middle, __last,
-				  __middle - __first,
-				  __last - __middle,
-				  __comp);
-    }
-
-  // stable_sort
-
-  // Set algorithms: includes, set_union, set_intersection, set_difference,
-  // set_symmetric_difference.  All of these algorithms have the precondition
-  // that their input ranges are sorted and the postcondition that their output
-  // ranges are sorted.
-
-  /**
-   *  @brief Determines whether all elements of a sequence exists in a range.
-   *  @param  __first1  Start of search range.
-   *  @param  __last1   End of search range.
-   *  @param  __first2  Start of sequence
-   *  @param  __last2   End of sequence.
-   *  @return  True if each element in [__first2,__last2) is contained in order
-   *  within [__first1,__last1).  False otherwise.
-   *  @ingroup set_algorithms
-   *
-   *  This operation expects both [__first1,__last1) and
-   *  [__first2,__last2) to be sorted.  Searches for the presence of
-   *  each element in [__first2,__last2) within [__first1,__last1).
-   *  The iterators over each range only move forward, so this is a
-   *  linear algorithm.  If an element in [__first2,__last2) is not
-   *  found before the search iterator reaches @p __last2, false is
-   *  returned.
-  */
-  template<typename _InputIterator1, typename _InputIterator2>
-    bool
-    includes(_InputIterator1 __first1, _InputIterator1 __last1,
-	     _InputIterator2 __first2, _InputIterator2 __last2)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (*__first2 < *__first1)
-	  return false;
-	else if(*__first1 < *__first2)
-	  ++__first1;
-	else
-	  ++__first1, ++__first2;
-
-      return __first2 == __last2;
-    }
-
-  /**
-   *  @brief Determines whether all elements of a sequence exists in a range
-   *  using comparison.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of search range.
-   *  @param  __last1   End of search range.
-   *  @param  __first2  Start of sequence
-   *  @param  __last2   End of sequence.
-   *  @param  __comp    Comparison function to use.
-   *  @return True if each element in [__first2,__last2) is contained
-   *  in order within [__first1,__last1) according to comp.  False
-   *  otherwise.  @ingroup set_algorithms
-   *
-   *  This operation expects both [__first1,__last1) and
-   *  [__first2,__last2) to be sorted.  Searches for the presence of
-   *  each element in [__first2,__last2) within [__first1,__last1),
-   *  using comp to decide.  The iterators over each range only move
-   *  forward, so this is a linear algorithm.  If an element in
-   *  [__first2,__last2) is not found before the search iterator
-   *  reaches @p __last2, false is returned.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _Compare>
-    bool
-    includes(_InputIterator1 __first1, _InputIterator1 __last1,
-	     _InputIterator2 __first2, _InputIterator2 __last2,
-	     _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(*__first2, *__first1))
-	  return false;
-	else if(__comp(*__first1, *__first2))
-	  ++__first1;
-	else
-	  ++__first1, ++__first2;
-
-      return __first2 == __last2;
-    }
-
-  // nth_element
-  // merge
-  // set_difference
-  // set_intersection
-  // set_union
-  // stable_sort
-  // set_symmetric_difference
-  // min_element
-  // max_element
-
-  /**
-   *  @brief  Permute range into the next @e dictionary ordering.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @return  False if wrapped to first permutation, true otherwise.
-   *
-   *  Treats all permutations of the range as a set of @e dictionary sorted
-   *  sequences.  Permutes the current sequence into the next one of this set.
-   *  Returns true if there are more sequences to generate.  If the sequence
-   *  is the largest of the set, the smallest is generated and false returned.
-  */
-  template<typename _BidirectionalIterator>
-    bool
-    next_permutation(_BidirectionalIterator __first,
-		     _BidirectionalIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_BidirectionalIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return false;
-      _BidirectionalIterator __i = __first;
-      ++__i;
-      if (__i == __last)
-	return false;
-      __i = __last;
-      --__i;
-
-      for(;;)
-	{
-	  _BidirectionalIterator __ii = __i;
-	  --__i;
-	  if (*__i < *__ii)
-	    {
-	      _BidirectionalIterator __j = __last;
-	      while (!(*__i < *--__j))
-		{}
-	      std::iter_swap(__i, __j);
-	      std::reverse(__ii, __last);
-	      return true;
-	    }
-	  if (__i == __first)
-	    {
-	      std::reverse(__first, __last);
-	      return false;
-	    }
-	}
-    }
-
-  /**
-   *  @brief  Permute range into the next @e dictionary ordering using
-   *          comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @param  __comp   A comparison functor.
-   *  @return  False if wrapped to first permutation, true otherwise.
-   *
-   *  Treats all permutations of the range [__first,__last) as a set of
-   *  @e dictionary sorted sequences ordered by @p __comp.  Permutes the current
-   *  sequence into the next one of this set.  Returns true if there are more
-   *  sequences to generate.  If the sequence is the largest of the set, the
-   *  smallest is generated and false returned.
-  */
-  template<typename _BidirectionalIterator, typename _Compare>
-    bool
-    next_permutation(_BidirectionalIterator __first,
-		     _BidirectionalIterator __last, _Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_BidirectionalIterator>::value_type,
-	    typename iterator_traits<_BidirectionalIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return false;
-      _BidirectionalIterator __i = __first;
-      ++__i;
-      if (__i == __last)
-	return false;
-      __i = __last;
-      --__i;
-
-      for(;;)
-	{
-	  _BidirectionalIterator __ii = __i;
-	  --__i;
-	  if (__comp(*__i, *__ii))
-	    {
-	      _BidirectionalIterator __j = __last;
-	      while (!bool(__comp(*__i, *--__j)))
-		{}
-	      std::iter_swap(__i, __j);
-	      std::reverse(__ii, __last);
-	      return true;
-	    }
-	  if (__i == __first)
-	    {
-	      std::reverse(__first, __last);
-	      return false;
-	    }
-	}
-    }
-
-  /**
-   *  @brief  Permute range into the previous @e dictionary ordering.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @return  False if wrapped to last permutation, true otherwise.
-   *
-   *  Treats all permutations of the range as a set of @e dictionary sorted
-   *  sequences.  Permutes the current sequence into the previous one of this
-   *  set.  Returns true if there are more sequences to generate.  If the
-   *  sequence is the smallest of the set, the largest is generated and false
-   *  returned.
-  */
-  template<typename _BidirectionalIterator>
-    bool
-    prev_permutation(_BidirectionalIterator __first,
-		     _BidirectionalIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_BidirectionalIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return false;
-      _BidirectionalIterator __i = __first;
-      ++__i;
-      if (__i == __last)
-	return false;
-      __i = __last;
-      --__i;
-
-      for(;;)
-	{
-	  _BidirectionalIterator __ii = __i;
-	  --__i;
-	  if (*__ii < *__i)
-	    {
-	      _BidirectionalIterator __j = __last;
-	      while (!(*--__j < *__i))
-		{}
-	      std::iter_swap(__i, __j);
-	      std::reverse(__ii, __last);
-	      return true;
-	    }
-	  if (__i == __first)
-	    {
-	      std::reverse(__first, __last);
-	      return false;
-	    }
-	}
-    }
-
-  /**
-   *  @brief  Permute range into the previous @e dictionary ordering using
-   *          comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @param  __comp   A comparison functor.
-   *  @return  False if wrapped to last permutation, true otherwise.
-   *
-   *  Treats all permutations of the range [__first,__last) as a set of
-   *  @e dictionary sorted sequences ordered by @p __comp.  Permutes the current
-   *  sequence into the previous one of this set.  Returns true if there are
-   *  more sequences to generate.  If the sequence is the smallest of the set,
-   *  the largest is generated and false returned.
-  */
-  template<typename _BidirectionalIterator, typename _Compare>
-    bool
-    prev_permutation(_BidirectionalIterator __first,
-		     _BidirectionalIterator __last, _Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_BidirectionalIteratorConcept<
-				  _BidirectionalIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_BidirectionalIterator>::value_type,
-	    typename iterator_traits<_BidirectionalIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return false;
-      _BidirectionalIterator __i = __first;
-      ++__i;
-      if (__i == __last)
-	return false;
-      __i = __last;
-      --__i;
-
-      for(;;)
-	{
-	  _BidirectionalIterator __ii = __i;
-	  --__i;
-	  if (__comp(*__ii, *__i))
-	    {
-	      _BidirectionalIterator __j = __last;
-	      while (!bool(__comp(*--__j, *__i)))
-		{}
-	      std::iter_swap(__i, __j);
-	      std::reverse(__ii, __last);
-	      return true;
-	    }
-	  if (__i == __first)
-	    {
-	      std::reverse(__first, __last);
-	      return false;
-	    }
-	}
-    }
-
-  // replace
-  // replace_if
-
-  /**
-   *  @brief Copy a sequence, replacing each element of one value with another
-   *         value.
-   *  @param  __first      An input iterator.
-   *  @param  __last       An input iterator.
-   *  @param  __result     An output iterator.
-   *  @param  __old_value  The value to be replaced.
-   *  @param  __new_value  The replacement value.
-   *  @return   The end of the output sequence, @p result+(last-first).
-   *
-   *  Copies each element in the input range @p [__first,__last) to the
-   *  output range @p [__result,__result+(__last-__first)) replacing elements
-   *  equal to @p __old_value with @p __new_value.
-  */
-  template<typename _InputIterator, typename _OutputIterator, typename _Tp>
-    _OutputIterator
-    replace_copy(_InputIterator __first, _InputIterator __last,
-		 _OutputIterator __result,
-		 const _Tp& __old_value, const _Tp& __new_value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_InputIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first, ++__result)
-	if (*__first == __old_value)
-	  *__result = __new_value;
-	else
-	  *__result = *__first;
-      return __result;
-    }
-
-  /**
-   *  @brief Copy a sequence, replacing each value for which a predicate
-   *         returns true with another value.
-   *  @ingroup mutating_algorithms
-   *  @param  __first      An input iterator.
-   *  @param  __last       An input iterator.
-   *  @param  __result     An output iterator.
-   *  @param  __pred       A predicate.
-   *  @param  __new_value  The replacement value.
-   *  @return   The end of the output sequence, @p __result+(__last-__first).
-   *
-   *  Copies each element in the range @p [__first,__last) to the range
-   *  @p [__result,__result+(__last-__first)) replacing elements for which
-   *  @p __pred returns true with @p __new_value.
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _Predicate, typename _Tp>
-    _OutputIterator
-    replace_copy_if(_InputIterator __first, _InputIterator __last,
-		    _OutputIterator __result,
-		    _Predicate __pred, const _Tp& __new_value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first, ++__result)
-	if (__pred(*__first))
-	  *__result = __new_value;
-	else
-	  *__result = *__first;
-      return __result;
-    }
-
-#if __cplusplus >= 201103L
-  /**
-   *  @brief  Determines whether the elements of a sequence are sorted.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @return  True if the elements are sorted, false otherwise.
-  */
-  template<typename _ForwardIterator>
-    inline bool
-    is_sorted(_ForwardIterator __first, _ForwardIterator __last)
-    { return std::is_sorted_until(__first, __last) == __last; }
-
-  /**
-   *  @brief  Determines whether the elements of a sequence are sorted
-   *          according to a comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  True if the elements are sorted, false otherwise.
-  */
-  template<typename _ForwardIterator, typename _Compare>
-    inline bool
-    is_sorted(_ForwardIterator __first, _ForwardIterator __last,
-	      _Compare __comp)
-    { return std::is_sorted_until(__first, __last, __comp) == __last; }
-
-  /**
-   *  @brief  Determines the end of a sorted sequence.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @return  An iterator pointing to the last iterator i in [__first, __last)
-   *           for which the range [__first, i) is sorted.
-  */
-  template<typename _ForwardIterator>
-    _ForwardIterator
-    is_sorted_until(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __last;
-
-      _ForwardIterator __next = __first;
-      for (++__next; __next != __last; __first = __next, ++__next)
-	if (*__next < *__first)
-	  return __next;
-      return __next;
-    }
-
-  /**
-   *  @brief  Determines the end of a sorted sequence using comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  An iterator pointing to the last iterator i in [__first, __last)
-   *           for which the range [__first, i) is sorted.
-  */
-  template<typename _ForwardIterator, typename _Compare>
-    _ForwardIterator
-    is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
-		    _Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_ForwardIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __last;
-
-      _ForwardIterator __next = __first;
-      for (++__next; __next != __last; __first = __next, ++__next)
-	if (__comp(*__next, *__first))
-	  return __next;
-      return __next;
-    }
-
-  /**
-   *  @brief  Determines min and max at once as an ordered pair.
-   *  @ingroup sorting_algorithms
-   *  @param  __a  A thing of arbitrary type.
-   *  @param  __b  Another thing of arbitrary type.
-   *  @return A pair(__b, __a) if __b is smaller than __a, pair(__a,
-   *  __b) otherwise.
-  */
-  template<typename _Tp>
-    inline pair<const _Tp&, const _Tp&>
-    minmax(const _Tp& __a, const _Tp& __b)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
-
-      return __b < __a ? pair<const _Tp&, const _Tp&>(__b, __a)
-	               : pair<const _Tp&, const _Tp&>(__a, __b);
-    }
-
-  /**
-   *  @brief  Determines min and max at once as an ordered pair.
-   *  @ingroup sorting_algorithms
-   *  @param  __a  A thing of arbitrary type.
-   *  @param  __b  Another thing of arbitrary type.
-   *  @param  __comp  A @link comparison_functors comparison functor @endlink.
-   *  @return A pair(__b, __a) if __b is smaller than __a, pair(__a,
-   *  __b) otherwise.
-  */
-  template<typename _Tp, typename _Compare>
-    inline pair<const _Tp&, const _Tp&>
-    minmax(const _Tp& __a, const _Tp& __b, _Compare __comp)
-    {
-      return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a)
-	                      : pair<const _Tp&, const _Tp&>(__a, __b);
-    }
-
-  /**
-   *  @brief  Return a pair of iterators pointing to the minimum and maximum
-   *          elements in a range.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @return  make_pair(m, M), where m is the first iterator i in
-   *           [__first, __last) such that no other element in the range is
-   *           smaller, and where M is the last iterator i in [__first, __last)
-   *           such that no other element in the range is larger.
-  */
-  template<typename _ForwardIterator>
-    pair<_ForwardIterator, _ForwardIterator>
-    minmax_element(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      _ForwardIterator __next = __first;
-      if (__first == __last
-	  || ++__next == __last)
-	return std::make_pair(__first, __first);
-
-      _ForwardIterator __min, __max;
-      if (*__next < *__first)
-	{
-	  __min = __next;
-	  __max = __first;
-	}
-      else
-	{
-	  __min = __first;
-	  __max = __next;
-	}
-
-      __first = __next;
-      ++__first;
-
-      while (__first != __last)
-	{
-	  __next = __first;
-	  if (++__next == __last)
-	    {
-	      if (*__first < *__min)
-		__min = __first;
-	      else if (!(*__first < *__max))
-		__max = __first;
-	      break;
-	    }
-
-	  if (*__next < *__first)
-	    {
-	      if (*__next < *__min)
-		__min = __next;
-	      if (!(*__first < *__max))
-		__max = __first;
-	    }
-	  else
-	    {
-	      if (*__first < *__min)
-		__min = __first;
-	      if (!(*__next < *__max))
-		__max = __next;
-	    }
-
-	  __first = __next;
-	  ++__first;
-	}
-
-      return std::make_pair(__min, __max);
-    }
-
-  /**
-   *  @brief  Return a pair of iterators pointing to the minimum and maximum
-   *          elements in a range.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @param  __comp   Comparison functor.
-   *  @return  make_pair(m, M), where m is the first iterator i in
-   *           [__first, __last) such that no other element in the range is
-   *           smaller, and where M is the last iterator i in [__first, __last)
-   *           such that no other element in the range is larger.
-  */
-  template<typename _ForwardIterator, typename _Compare>
-    pair<_ForwardIterator, _ForwardIterator>
-    minmax_element(_ForwardIterator __first, _ForwardIterator __last,
-		   _Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_ForwardIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      _ForwardIterator __next = __first;
-      if (__first == __last
-	  || ++__next == __last)
-	return std::make_pair(__first, __first);
-
-      _ForwardIterator __min, __max;
-      if (__comp(*__next, *__first))
-	{
-	  __min = __next;
-	  __max = __first;
-	}
-      else
-	{
-	  __min = __first;
-	  __max = __next;
-	}
-
-      __first = __next;
-      ++__first;
-
-      while (__first != __last)
-	{
-	  __next = __first;
-	  if (++__next == __last)
-	    {
-	      if (__comp(*__first, *__min))
-		__min = __first;
-	      else if (!__comp(*__first, *__max))
-		__max = __first;
-	      break;
-	    }
-
-	  if (__comp(*__next, *__first))
-	    {
-	      if (__comp(*__next, *__min))
-		__min = __next;
-	      if (!__comp(*__first, *__max))
-		__max = __first;
-	    }
-	  else
-	    {
-	      if (__comp(*__first, *__min))
-		__min = __first;
-	      if (!__comp(*__next, *__max))
-		__max = __next;
-	    }
-
-	  __first = __next;
-	  ++__first;
-	}
-
-      return std::make_pair(__min, __max);
-    }
-
-  // N2722 + DR 915.
-  template<typename _Tp>
-    inline _Tp
-    min(initializer_list<_Tp> __l)
-    { return *std::min_element(__l.begin(), __l.end()); }
-
-  template<typename _Tp, typename _Compare>
-    inline _Tp
-    min(initializer_list<_Tp> __l, _Compare __comp)
-    { return *std::min_element(__l.begin(), __l.end(), __comp); }
-
-  template<typename _Tp>
-    inline _Tp
-    max(initializer_list<_Tp> __l)
-    { return *std::max_element(__l.begin(), __l.end()); }
-
-  template<typename _Tp, typename _Compare>
-    inline _Tp
-    max(initializer_list<_Tp> __l, _Compare __comp)
-    { return *std::max_element(__l.begin(), __l.end(), __comp); }
-
-  template<typename _Tp>
-    inline pair<_Tp, _Tp>
-    minmax(initializer_list<_Tp> __l)
-    {
-      pair<const _Tp*, const _Tp*> __p =
-	std::minmax_element(__l.begin(), __l.end());
-      return std::make_pair(*__p.first, *__p.second);
-    }
-
-  template<typename _Tp, typename _Compare>
-    inline pair<_Tp, _Tp>
-    minmax(initializer_list<_Tp> __l, _Compare __comp)
-    {
-      pair<const _Tp*, const _Tp*> __p =
-	std::minmax_element(__l.begin(), __l.end(), __comp);
-      return std::make_pair(*__p.first, *__p.second);
-    }
-
-  /**
-   *  @brief  Checks whether a permutation of the second sequence is equal
-   *          to the first sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @return true if there exists a permutation of the elements in the range
-   *          [__first2, __first2 + (__last1 - __first1)), beginning with
-   *          ForwardIterator2 begin, such that equal(__first1, __last1, begin)
-   *          returns true; otherwise, returns false.
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2>
-    bool
-    is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-		   _ForwardIterator2 __first2)
-    {
-      // Efficiently compare identical prefixes:  O(N) if sequences
-      // have the same elements in the same order.
-      for (; __first1 != __last1; ++__first1, ++__first2)
-	if (!(*__first1 == *__first2))
-	  break;
-
-      if (__first1 == __last1)
-	return true;
-
-      // Establish __last2 assuming equal ranges by iterating over the
-      // rest of the list.
-      _ForwardIterator2 __last2 = __first2;
-      std::advance(__last2, std::distance(__first1, __last1));
-      for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
-	{
-	  if (__scan != _GLIBCXX_STD_A::find(__first1, __scan, *__scan))
-	    continue; // We've seen this one before.
-
-	  auto __matches = std::count(__first2, __last2, *__scan);
-	  if (0 == __matches
-	      || std::count(__scan, __last1, *__scan) != __matches)
-	    return false;
-	}
-      return true;
-    }
-
-  /**
-   *  @brief  Checks whether a permutation of the second sequence is equal
-   *          to the first sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __pred    A binary predicate.
-   *  @return true if there exists a permutation of the elements in
-   *          the range [__first2, __first2 + (__last1 - __first1)),
-   *          beginning with ForwardIterator2 begin, such that
-   *          equal(__first1, __last1, __begin, __pred) returns true;
-   *          otherwise, returns false.
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2,
-	   typename _BinaryPredicate>
-    bool
-    is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-		   _ForwardIterator2 __first2, _BinaryPredicate __pred)
-    {
-      // Efficiently compare identical prefixes:  O(N) if sequences
-      // have the same elements in the same order.
-      for (; __first1 != __last1; ++__first1, ++__first2)
-	if (!bool(__pred(*__first1, *__first2)))
-	  break;
-
-      if (__first1 == __last1)
-	return true;
-
-      // Establish __last2 assuming equal ranges by iterating over the
-      // rest of the list.
-      _ForwardIterator2 __last2 = __first2;
-      std::advance(__last2, std::distance(__first1, __last1));
-      for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
-	{
-	  using std::placeholders::_1;
-
-	  if (__scan != _GLIBCXX_STD_A::find_if(__first1, __scan,
-						std::bind(__pred, _1, *__scan)))
-	    continue; // We've seen this one before.
-	
-	  auto __matches = std::count_if(__first2, __last2,
-					 std::bind(__pred, _1, *__scan));
-	  if (0 == __matches
-	      || std::count_if(__scan, __last1,
-			       std::bind(__pred, _1, *__scan)) != __matches)
-	    return false;
-	}
-      return true;
-    }
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-  /**
-   *  @brief Shuffle the elements of a sequence using a uniform random
-   *         number generator.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @param  __g       A UniformRandomNumberGenerator (26.5.1.3).
-   *  @return  Nothing.
-   *
-   *  Reorders the elements in the range @p [__first,__last) using @p __g to
-   *  provide random numbers.
-  */
-  template<typename _RandomAccessIterator,
-	   typename _UniformRandomNumberGenerator>
-    void
-    shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	    _UniformRandomNumberGenerator&& __g)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return;
-
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_DistanceType;
-
-      typedef typename std::make_unsigned<_DistanceType>::type __ud_type;
-      typedef typename std::uniform_int_distribution<__ud_type> __distr_type;
-      typedef typename __distr_type::param_type __p_type;
-      __distr_type __d;
-
-      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
-	std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first)));
-    }
-#endif
-
-#endif // C++11
-
-_GLIBCXX_END_NAMESPACE_VERSION
-
-_GLIBCXX_BEGIN_NAMESPACE_ALGO
-
-  /**
-   *  @brief Apply a function to every element of a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __f      A unary function object.
-   *  @return   @p __f (std::move(@p __f) in C++0x).
-   *
-   *  Applies the function object @p __f to each element in the range
-   *  @p [first,last).  @p __f must not modify the order of the sequence.
-   *  If @p __f has a return value it is ignored.
-  */
-  template<typename _InputIterator, typename _Function>
-    _Function
-    for_each(_InputIterator __first, _InputIterator __last, _Function __f)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
-      for (; __first != __last; ++__first)
-	__f(*__first);
-      return _GLIBCXX_MOVE(__f);
-    }
-
-  /**
-   *  @brief Find the first occurrence of a value in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __val    The value to find.
-   *  @return   The first iterator @c i in the range @p [__first,__last)
-   *  such that @c *i == @p __val, or @p __last if no such iterator exists.
-  */
-  template<typename _InputIterator, typename _Tp>
-    inline _InputIterator
-    find(_InputIterator __first, _InputIterator __last,
-	 const _Tp& __val)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-		typename iterator_traits<_InputIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-      return std::__find(__first, __last, __val,
-		         std::__iterator_category(__first));
-    }
-
-  /**
-   *  @brief Find the first element in a sequence for which a
-   *         predicate is true.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __pred   A predicate.
-   *  @return   The first iterator @c i in the range @p [__first,__last)
-   *  such that @p __pred(*i) is true, or @p __last if no such iterator exists.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    inline _InputIterator
-    find_if(_InputIterator __first, _InputIterator __last,
-	    _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	      typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-      return std::__find_if(__first, __last, __pred,
-			    std::__iterator_category(__first));
-    }
-
-  /**
-   *  @brief  Find element from a set in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of range to search.
-   *  @param  __last1   End of range to search.
-   *  @param  __first2  Start of match candidates.
-   *  @param  __last2   End of match candidates.
-   *  @return   The first iterator @c i in the range
-   *  @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an
-   *  iterator in [__first2,__last2), or @p __last1 if no such iterator exists.
-   *
-   *  Searches the range @p [__first1,__last1) for an element that is
-   *  equal to some element in the range [__first2,__last2).  If
-   *  found, returns an iterator in the range [__first1,__last1),
-   *  otherwise returns @p __last1.
-  */
-  template<typename _InputIterator, typename _ForwardIterator>
-    _InputIterator
-    find_first_of(_InputIterator __first1, _InputIterator __last1,
-		  _ForwardIterator __first2, _ForwardIterator __last2)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_InputIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      for (; __first1 != __last1; ++__first1)
-	for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter)
-	  if (*__first1 == *__iter)
-	    return __first1;
-      return __last1;
-    }
-
-  /**
-   *  @brief  Find element from a set in a sequence using a predicate.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  Start of range to search.
-   *  @param  __last1   End of range to search.
-   *  @param  __first2  Start of match candidates.
-   *  @param  __last2   End of match candidates.
-   *  @param  __comp    Predicate to use.
-   *  @return   The first iterator @c i in the range
-   *  @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true
-   *  and i2 is an iterator in [__first2,__last2), or @p __last1 if no
-   *  such iterator exists.
-   *
-
-   *  Searches the range @p [__first1,__last1) for an element that is
-   *  equal to some element in the range [__first2,__last2).  If
-   *  found, returns an iterator in the range [__first1,__last1),
-   *  otherwise returns @p __last1.
-  */
-  template<typename _InputIterator, typename _ForwardIterator,
-	   typename _BinaryPredicate>
-    _InputIterator
-    find_first_of(_InputIterator __first1, _InputIterator __last1,
-		  _ForwardIterator __first2, _ForwardIterator __last2,
-		  _BinaryPredicate __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	    typename iterator_traits<_InputIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      for (; __first1 != __last1; ++__first1)
-	for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter)
-	  if (__comp(*__first1, *__iter))
-	    return __first1;
-      return __last1;
-    }
-
-  /**
-   *  @brief Find two adjacent values in a sequence that are equal.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __last   A forward iterator.
-   *  @return   The first iterator @c i such that @c i and @c i+1 are both
-   *  valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1),
-   *  or @p __last if no such iterator exists.
-  */
-  template<typename _ForwardIterator>
-    _ForwardIterator
-    adjacent_find(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_EqualityComparableConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-      if (__first == __last)
-	return __last;
-      _ForwardIterator __next = __first;
-      while(++__next != __last)
-	{
-	  if (*__first == *__next)
-	    return __first;
-	  __first = __next;
-	}
-      return __last;
-    }
-
-  /**
-   *  @brief Find two adjacent values in a sequence using a predicate.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first         A forward iterator.
-   *  @param  __last          A forward iterator.
-   *  @param  __binary_pred   A binary predicate.
-   *  @return   The first iterator @c i such that @c i and @c i+1 are both
-   *  valid iterators in @p [__first,__last) and such that
-   *  @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator
-   *  exists.
-  */
-  template<typename _ForwardIterator, typename _BinaryPredicate>
-    _ForwardIterator
-    adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
-		  _BinaryPredicate __binary_pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	    typename iterator_traits<_ForwardIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-      if (__first == __last)
-	return __last;
-      _ForwardIterator __next = __first;
-      while(++__next != __last)
-	{
-	  if (__binary_pred(*__first, *__next))
-	    return __first;
-	  __first = __next;
-	}
-      return __last;
-    }
-
-  /**
-   *  @brief Count the number of copies of a value in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __value  The value to be counted.
-   *  @return   The number of iterators @c i in the range @p [__first,__last)
-   *  for which @c *i == @p __value
-  */
-  template<typename _InputIterator, typename _Tp>
-    typename iterator_traits<_InputIterator>::difference_type
-    count(_InputIterator __first, _InputIterator __last, const _Tp& __value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	typename iterator_traits<_InputIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-      typename iterator_traits<_InputIterator>::difference_type __n = 0;
-      for (; __first != __last; ++__first)
-	if (*__first == __value)
-	  ++__n;
-      return __n;
-    }
-
-  /**
-   *  @brief Count the elements of a sequence for which a predicate is true.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __pred   A predicate.
-   *  @return   The number of iterators @c i in the range @p [__first,__last)
-   *  for which @p __pred(*i) is true.
-  */
-  template<typename _InputIterator, typename _Predicate>
-    typename iterator_traits<_InputIterator>::difference_type
-    count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-      typename iterator_traits<_InputIterator>::difference_type __n = 0;
-      for (; __first != __last; ++__first)
-	if (__pred(*__first))
-	  ++__n;
-      return __n;
-    }
-
-  /**
-   *  @brief Search a sequence for a matching sub-sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1  A forward iterator.
-   *  @param  __last1   A forward iterator.
-   *  @param  __first2  A forward iterator.
-   *  @param  __last2   A forward iterator.
-   *  @return The first iterator @c i in the range @p
-   *  [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p
-   *  *(__first2+N) for each @c N in the range @p
-   *  [0,__last2-__first2), or @p __last1 if no such iterator exists.
-   *
-   *  Searches the range @p [__first1,__last1) for a sub-sequence that
-   *  compares equal value-by-value with the sequence given by @p
-   *  [__first2,__last2) and returns an iterator to the first element
-   *  of the sub-sequence, or @p __last1 if the sub-sequence is not
-   *  found.
-   *
-   *  Because the sub-sequence must lie completely within the range @p
-   *  [__first1,__last1) it must start at a position less than @p
-   *  __last1-(__last2-__first2) where @p __last2-__first2 is the
-   *  length of the sub-sequence.
-   *
-   *  This means that the returned iterator @c i will be in the range
-   *  @p [__first1,__last1-(__last2-__first2))
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2>
-    _ForwardIterator1
-    search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	   _ForwardIterator2 __first2, _ForwardIterator2 __last2)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_ForwardIterator1>::value_type,
-	    typename iterator_traits<_ForwardIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      // Test for empty ranges
-      if (__first1 == __last1 || __first2 == __last2)
-	return __first1;
-
-      // Test for a pattern of length 1.
-      _ForwardIterator2 __p1(__first2);
-      if (++__p1 == __last2)
-	return _GLIBCXX_STD_A::find(__first1, __last1, *__first2);
-
-      // General case.
-      _ForwardIterator2 __p;
-      _ForwardIterator1 __current = __first1;
-
-      for (;;)
-	{
-	  __first1 = _GLIBCXX_STD_A::find(__first1, __last1, *__first2);
-	  if (__first1 == __last1)
-	    return __last1;
-
-	  __p = __p1;
-	  __current = __first1;
-	  if (++__current == __last1)
-	    return __last1;
-
-	  while (*__current == *__p)
-	    {
-	      if (++__p == __last2)
-		return __first1;
-	      if (++__current == __last1)
-		return __last1;
-	    }
-	  ++__first1;
-	}
-      return __first1;
-    }
-
-  /**
-   *  @brief Search a sequence for a matching sub-sequence using a predicate.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first1     A forward iterator.
-   *  @param  __last1      A forward iterator.
-   *  @param  __first2     A forward iterator.
-   *  @param  __last2      A forward iterator.
-   *  @param  __predicate  A binary predicate.
-   *  @return   The first iterator @c i in the range
-   *  @p [__first1,__last1-(__last2-__first2)) such that
-   *  @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range
-   *  @p [0,__last2-__first2), or @p __last1 if no such iterator exists.
-   *
-   *  Searches the range @p [__first1,__last1) for a sub-sequence that
-   *  compares equal value-by-value with the sequence given by @p
-   *  [__first2,__last2), using @p __predicate to determine equality,
-   *  and returns an iterator to the first element of the
-   *  sub-sequence, or @p __last1 if no such iterator exists.
-   *
-   *  @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2)
-  */
-  template<typename _ForwardIterator1, typename _ForwardIterator2,
-	   typename _BinaryPredicate>
-    _ForwardIterator1
-    search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
-	   _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	   _BinaryPredicate  __predicate)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	    typename iterator_traits<_ForwardIterator1>::value_type,
-	    typename iterator_traits<_ForwardIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
-
-      // Test for empty ranges
-      if (__first1 == __last1 || __first2 == __last2)
-	return __first1;
-
-      // Test for a pattern of length 1.
-      _ForwardIterator2 __p1(__first2);
-      if (++__p1 == __last2)
-	{
-	  while (__first1 != __last1
-		 && !bool(__predicate(*__first1, *__first2)))
-	    ++__first1;
-	  return __first1;
-	}
-
-      // General case.
-      _ForwardIterator2 __p;
-      _ForwardIterator1 __current = __first1;
-
-      for (;;)
-	{
-	  while (__first1 != __last1
-		 && !bool(__predicate(*__first1, *__first2)))
-	    ++__first1;
-	  if (__first1 == __last1)
-	    return __last1;
-
-	  __p = __p1;
-	  __current = __first1;
-	  if (++__current == __last1)
-	    return __last1;
-
-	  while (__predicate(*__current, *__p))
-	    {
-	      if (++__p == __last2)
-		return __first1;
-	      if (++__current == __last1)
-		return __last1;
-	    }
-	  ++__first1;
-	}
-      return __first1;
-    }
-
-
-  /**
-   *  @brief Search a sequence for a number of consecutive values.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __last   A forward iterator.
-   *  @param  __count  The number of consecutive values.
-   *  @param  __val    The value to find.
-   *  @return The first iterator @c i in the range @p
-   *  [__first,__last-__count) such that @c *(i+N) == @p __val for
-   *  each @c N in the range @p [0,__count), or @p __last if no such
-   *  iterator exists.
-   *
-   *  Searches the range @p [__first,__last) for @p count consecutive elements
-   *  equal to @p __val.
-  */
-  template<typename _ForwardIterator, typename _Integer, typename _Tp>
-    _ForwardIterator
-    search_n(_ForwardIterator __first, _ForwardIterator __last,
-	     _Integer __count, const _Tp& __val)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__count <= 0)
-	return __first;
-      if (__count == 1)
-	return _GLIBCXX_STD_A::find(__first, __last, __val);
-      return std::__search_n(__first, __last, __count, __val,
-			     std::__iterator_category(__first));
-    }
-
-
-  /**
-   *  @brief Search a sequence for a number of consecutive values using a
-   *         predicate.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first        A forward iterator.
-   *  @param  __last         A forward iterator.
-   *  @param  __count        The number of consecutive values.
-   *  @param  __val          The value to find.
-   *  @param  __binary_pred  A binary predicate.
-   *  @return The first iterator @c i in the range @p
-   *  [__first,__last-__count) such that @p
-   *  __binary_pred(*(i+N),__val) is true for each @c N in the range
-   *  @p [0,__count), or @p __last if no such iterator exists.
-   *
-   *  Searches the range @p [__first,__last) for @p __count
-   *  consecutive elements for which the predicate returns true.
-  */
-  template<typename _ForwardIterator, typename _Integer, typename _Tp,
-           typename _BinaryPredicate>
-    _ForwardIterator
-    search_n(_ForwardIterator __first, _ForwardIterator __last,
-	     _Integer __count, const _Tp& __val,
-	     _BinaryPredicate __binary_pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
-	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__count <= 0)
-	return __first;
-      if (__count == 1)
-	{
-	  while (__first != __last && !bool(__binary_pred(*__first, __val)))
-	    ++__first;
-	  return __first;
-	}
-      return std::__search_n(__first, __last, __count, __val, __binary_pred,
-			     std::__iterator_category(__first));
-    }
-
-
-  /**
-   *  @brief Perform an operation on a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first     An input iterator.
-   *  @param  __last      An input iterator.
-   *  @param  __result    An output iterator.
-   *  @param  __unary_op  A unary operator.
-   *  @return   An output iterator equal to @p __result+(__last-__first).
-   *
-   *  Applies the operator to each element in the input range and assigns
-   *  the results to successive elements of the output sequence.
-   *  Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the
-   *  range @p [0,__last-__first).
-   *
-   *  @p unary_op must not alter its argument.
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _UnaryOperation>
-    _OutputIterator
-    transform(_InputIterator __first, _InputIterator __last,
-	      _OutputIterator __result, _UnaryOperation __unary_op)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-            // "the type returned by a _UnaryOperation"
-            __typeof__(__unary_op(*__first))>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first, ++__result)
-	*__result = __unary_op(*__first);
-      return __result;
-    }
-
-  /**
-   *  @brief Perform an operation on corresponding elements of two sequences.
-   *  @ingroup mutating_algorithms
-   *  @param  __first1     An input iterator.
-   *  @param  __last1      An input iterator.
-   *  @param  __first2     An input iterator.
-   *  @param  __result     An output iterator.
-   *  @param  __binary_op  A binary operator.
-   *  @return   An output iterator equal to @p result+(last-first).
-   *
-   *  Applies the operator to the corresponding elements in the two
-   *  input ranges and assigns the results to successive elements of the
-   *  output sequence.
-   *  Evaluates @p
-   *  *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each
-   *  @c N in the range @p [0,__last1-__first1).
-   *
-   *  @p binary_op must not alter either of its arguments.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _BinaryOperation>
-    _OutputIterator
-    transform(_InputIterator1 __first1, _InputIterator1 __last1,
-	      _InputIterator2 __first2, _OutputIterator __result,
-	      _BinaryOperation __binary_op)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-            // "the type returned by a _BinaryOperation"
-            __typeof__(__binary_op(*__first1,*__first2))>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-
-      for (; __first1 != __last1; ++__first1, ++__first2, ++__result)
-	*__result = __binary_op(*__first1, *__first2);
-      return __result;
-    }
-
-  /**
-   *  @brief Replace each occurrence of one value in a sequence with another
-   *         value.
-   *  @ingroup mutating_algorithms
-   *  @param  __first      A forward iterator.
-   *  @param  __last       A forward iterator.
-   *  @param  __old_value  The value to be replaced.
-   *  @param  __new_value  The replacement value.
-   *  @return   replace() returns no value.
-   *
-   *  For each iterator @c i in the range @p [__first,__last) if @c *i ==
-   *  @p __old_value then the assignment @c *i = @p __new_value is performed.
-  */
-  template<typename _ForwardIterator, typename _Tp>
-    void
-    replace(_ForwardIterator __first, _ForwardIterator __last,
-	    const _Tp& __old_value, const _Tp& __new_value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_EqualOpConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
-      __glibcxx_function_requires(_ConvertibleConcept<_Tp,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (*__first == __old_value)
-	  *__first = __new_value;
-    }
-
-  /**
-   *  @brief Replace each value in a sequence for which a predicate returns
-   *         true with another value.
-   *  @ingroup mutating_algorithms
-   *  @param  __first      A forward iterator.
-   *  @param  __last       A forward iterator.
-   *  @param  __pred       A predicate.
-   *  @param  __new_value  The replacement value.
-   *  @return   replace_if() returns no value.
-   *
-   *  For each iterator @c i in the range @p [__first,__last) if @p __pred(*i)
-   *  is true then the assignment @c *i = @p __new_value is performed.
-  */
-  template<typename _ForwardIterator, typename _Predicate, typename _Tp>
-    void
-    replace_if(_ForwardIterator __first, _ForwardIterator __last,
-	       _Predicate __pred, const _Tp& __new_value)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_ConvertibleConcept<_Tp,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	if (__pred(*__first))
-	  *__first = __new_value;
-    }
-
-  /**
-   *  @brief Assign the result of a function object to each value in a
-   *         sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __last   A forward iterator.
-   *  @param  __gen    A function object taking no arguments and returning
-   *                 std::iterator_traits<_ForwardIterator>::value_type
-   *  @return   generate() returns no value.
-   *
-   *  Performs the assignment @c *i = @p __gen() for each @c i in the range
-   *  @p [__first,__last).
-  */
-  template<typename _ForwardIterator, typename _Generator>
-    void
-    generate(_ForwardIterator __first, _ForwardIterator __last,
-	     _Generator __gen)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_GeneratorConcept<_Generator,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      for (; __first != __last; ++__first)
-	*__first = __gen();
-    }
-
-  /**
-   *  @brief Assign the result of a function object to each value in a
-   *         sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first  A forward iterator.
-   *  @param  __n      The length of the sequence.
-   *  @param  __gen    A function object taking no arguments and returning
-   *                 std::iterator_traits<_ForwardIterator>::value_type
-   *  @return   The end of the sequence, @p __first+__n
-   *
-   *  Performs the assignment @c *i = @p __gen() for each @c i in the range
-   *  @p [__first,__first+__n).
-   *
-   *  _GLIBCXX_RESOLVE_LIB_DEFECTS
-   *  DR 865. More algorithms that throw away information
-  */
-  template<typename _OutputIterator, typename _Size, typename _Generator>
-    _OutputIterator
-    generate_n(_OutputIterator __first, _Size __n, _Generator __gen)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-            // "the type returned by a _Generator"
-            __typeof__(__gen())>)
-
-      for (__decltype(__n + 0) __niter = __n;
-	   __niter > 0; --__niter, ++__first)
-	*__first = __gen();
-      return __first;
-    }
-
-
-  /**
-   *  @brief Copy a sequence, removing consecutive duplicate values.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   An input iterator.
-   *  @param  __last    An input iterator.
-   *  @param  __result  An output iterator.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies each element in the range @p [__first,__last) to the range
-   *  beginning at @p __result, except that only the first element is copied
-   *  from groups of consecutive elements that compare equal.
-   *  unique_copy() is stable, so the relative order of elements that are
-   *  copied is unchanged.
-   *
-   *  _GLIBCXX_RESOLVE_LIB_DEFECTS
-   *  DR 241. Does unique_copy() require CopyConstructible and Assignable?
-   *
-   *  _GLIBCXX_RESOLVE_LIB_DEFECTS
-   *  DR 538. 241 again: Does unique_copy() require CopyConstructible and
-   *  Assignable?
-  */
-  template<typename _InputIterator, typename _OutputIterator>
-    inline _OutputIterator
-    unique_copy(_InputIterator __first, _InputIterator __last,
-		_OutputIterator __result)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_function_requires(_EqualityComparableConcept<
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __result;
-      return std::__unique_copy(__first, __last, __result,
-				std::__iterator_category(__first),
-				std::__iterator_category(__result));
-    }
-
-  /**
-   *  @brief Copy a sequence, removing consecutive values using a predicate.
-   *  @ingroup mutating_algorithms
-   *  @param  __first        An input iterator.
-   *  @param  __last         An input iterator.
-   *  @param  __result       An output iterator.
-   *  @param  __binary_pred  A binary predicate.
-   *  @return   An iterator designating the end of the resulting sequence.
-   *
-   *  Copies each element in the range @p [__first,__last) to the range
-   *  beginning at @p __result, except that only the first element is copied
-   *  from groups of consecutive elements for which @p __binary_pred returns
-   *  true.
-   *  unique_copy() is stable, so the relative order of elements that are
-   *  copied is unchanged.
-   *
-   *  _GLIBCXX_RESOLVE_LIB_DEFECTS
-   *  DR 241. Does unique_copy() require CopyConstructible and Assignable?
-  */
-  template<typename _InputIterator, typename _OutputIterator,
-	   typename _BinaryPredicate>
-    inline _OutputIterator
-    unique_copy(_InputIterator __first, _InputIterator __last,
-		_OutputIterator __result,
-		_BinaryPredicate __binary_pred)
-    {
-      // concept requirements -- predicates checked later
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-	    typename iterator_traits<_InputIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __result;
-      return std::__unique_copy(__first, __last, __result, __binary_pred,
-				std::__iterator_category(__first),
-				std::__iterator_category(__result));
-    }
-
-
-  /**
-   *  @brief Randomly shuffle the elements of a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @return  Nothing.
-   *
-   *  Reorder the elements in the range @p [__first,__last) using a random
-   *  distribution, so that every possible ordering of the sequence is
-   *  equally likely.
-  */
-  template<typename _RandomAccessIterator>
-    inline void
-    random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first != __last)
-	for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
-	  std::iter_swap(__i, __first + (std::rand() % ((__i - __first) + 1)));
-    }
-
-  /**
-   *  @brief Shuffle the elements of a sequence using a random number
-   *         generator.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @param  __rand    The RNG functor or function.
-   *  @return  Nothing.
-   *
-   *  Reorders the elements in the range @p [__first,__last) using @p __rand to
-   *  provide a random distribution. Calling @p __rand(N) for a positive
-   *  integer @p N should return a randomly chosen integer from the
-   *  range [0,N).
-  */
-  template<typename _RandomAccessIterator, typename _RandomNumberGenerator>
-    void
-    random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
-#if __cplusplus >= 201103L
-		   _RandomNumberGenerator&& __rand)
-#else
-		   _RandomNumberGenerator& __rand)
-#endif
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return;
-      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
-	std::iter_swap(__i, __first + __rand((__i - __first) + 1));
-    }
-
-
-  /**
-   *  @brief Move elements for which a predicate is true to the beginning
-   *         of a sequence.
-   *  @ingroup mutating_algorithms
-   *  @param  __first   A forward iterator.
-   *  @param  __last    A forward iterator.
-   *  @param  __pred    A predicate functor.
-   *  @return  An iterator @p middle such that @p __pred(i) is true for each
-   *  iterator @p i in the range @p [__first,middle) and false for each @p i
-   *  in the range @p [middle,__last).
-   *
-   *  @p __pred must not modify its operand. @p partition() does not preserve
-   *  the relative ordering of elements in each group, use
-   *  @p stable_partition() if this is needed.
-  */
-  template<typename _ForwardIterator, typename _Predicate>
-    inline _ForwardIterator
-    partition(_ForwardIterator __first, _ForwardIterator __last,
-	      _Predicate   __pred)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
-				  _ForwardIterator>)
-      __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      return std::__partition(__first, __last, __pred,
-			      std::__iterator_category(__first));
-    }
-
-  /**
-   *  @brief Sort the smallest elements of a sequence.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __middle  Another iterator.
-   *  @param  __last    Another iterator.
-   *  @return  Nothing.
-   *
-   *  Sorts the smallest @p (__middle-__first) elements in the range
-   *  @p [first,last) and moves them to the range @p [__first,__middle). The
-   *  order of the remaining elements in the range @p [__middle,__last) is
-   *  undefined.
-   *  After the sort if @e i and @e j are iterators in the range
-   *  @p [__first,__middle) such that i precedes j and @e k is an iterator in
-   *  the range @p [__middle,__last) then *j<*i and *k<*i are both false.
-  */
-  template<typename _RandomAccessIterator>
-    inline void
-    partial_sort(_RandomAccessIterator __first,
-		 _RandomAccessIterator __middle,
-		 _RandomAccessIterator __last)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
-      __glibcxx_requires_valid_range(__first, __middle);
-      __glibcxx_requires_valid_range(__middle, __last);
-
-      std::__heap_select(__first, __middle, __last);
-      std::sort_heap(__first, __middle);
-    }
-
-  /**
-   *  @brief Sort the smallest elements of a sequence using a predicate
-   *         for comparison.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __middle  Another iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  Nothing.
-   *
-   *  Sorts the smallest @p (__middle-__first) elements in the range
-   *  @p [__first,__last) and moves them to the range @p [__first,__middle). The
-   *  order of the remaining elements in the range @p [__middle,__last) is
-   *  undefined.
-   *  After the sort if @e i and @e j are iterators in the range
-   *  @p [__first,__middle) such that i precedes j and @e k is an iterator in
-   *  the range @p [__middle,__last) then @p *__comp(j,*i) and @p __comp(*k,*i)
-   *  are both false.
-  */
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline void
-    partial_sort(_RandomAccessIterator __first,
-		 _RandomAccessIterator __middle,
-		 _RandomAccessIterator __last,
-		 _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType, _ValueType>)
-      __glibcxx_requires_valid_range(__first, __middle);
-      __glibcxx_requires_valid_range(__middle, __last);
-
-      std::__heap_select(__first, __middle, __last, __comp);
-      std::sort_heap(__first, __middle, __comp);
-    }
-
-  /**
-   *  @brief Sort a sequence just enough to find a particular position.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __nth     Another iterator.
-   *  @param  __last    Another iterator.
-   *  @return  Nothing.
-   *
-   *  Rearranges the elements in the range @p [__first,__last) so that @p *__nth
-   *  is the same element that would have been in that position had the
-   *  whole sequence been sorted. The elements either side of @p *__nth are
-   *  not completely sorted, but for any iterator @e i in the range
-   *  @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it
-   *  holds that *j < *i is false.
-  */
-  template<typename _RandomAccessIterator>
-    inline void
-    nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
-		_RandomAccessIterator __last)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-				  _RandomAccessIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
-      __glibcxx_requires_valid_range(__first, __nth);
-      __glibcxx_requires_valid_range(__nth, __last);
-
-      if (__first == __last || __nth == __last)
-	return;
-
-      std::__introselect(__first, __nth, __last,
-			 std::__lg(__last - __first) * 2);
-    }
-
-  /**
-   *  @brief Sort a sequence just enough to find a particular position
-   *         using a predicate for comparison.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __nth     Another iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  Nothing.
-   *
-   *  Rearranges the elements in the range @p [__first,__last) so that @p *__nth
-   *  is the same element that would have been in that position had the
-   *  whole sequence been sorted. The elements either side of @p *__nth are
-   *  not completely sorted, but for any iterator @e i in the range
-   *  @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it
-   *  holds that @p __comp(*j,*i) is false.
-  */
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline void
-    nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
-		_RandomAccessIterator __last, _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-				  _RandomAccessIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType, _ValueType>)
-      __glibcxx_requires_valid_range(__first, __nth);
-      __glibcxx_requires_valid_range(__nth, __last);
-
-      if (__first == __last || __nth == __last)
-	return;
-
-      std::__introselect(__first, __nth, __last,
-			 std::__lg(__last - __first) * 2, __comp);
-    }
-
-
-  /**
-   *  @brief Sort the elements of a sequence.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @return  Nothing.
-   *
-   *  Sorts the elements in the range @p [__first,__last) in ascending order,
-   *  such that for each iterator @e i in the range @p [__first,__last-1),
-   *  *(i+1)<*i is false.
-   *
-   *  The relative ordering of equivalent elements is not preserved, use
-   *  @p stable_sort() if this is needed.
-  */
-  template<typename _RandomAccessIterator>
-    inline void
-    sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first != __last)
-	{
-	  std::__introsort_loop(__first, __last,
-				std::__lg(__last - __first) * 2);
-	  std::__final_insertion_sort(__first, __last);
-	}
-    }
-
-  /**
-   *  @brief Sort the elements of a sequence using a predicate for comparison.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  Nothing.
-   *
-   *  Sorts the elements in the range @p [__first,__last) in ascending order,
-   *  such that @p __comp(*(i+1),*i) is false for every iterator @e i in the
-   *  range @p [__first,__last-1).
-   *
-   *  The relative ordering of equivalent elements is not preserved, use
-   *  @p stable_sort() if this is needed.
-  */
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline void
-    sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	 _Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, _ValueType,
-				  _ValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first != __last)
-	{
-	  std::__introsort_loop(__first, __last,
-				std::__lg(__last - __first) * 2, __comp);
-	  std::__final_insertion_sort(__first, __last, __comp);
-	}
-    }
-
-  /**
-   *  @brief Merges two sorted ranges.
-   *  @ingroup sorting_algorithms
-   *  @param  __first1  An iterator.
-   *  @param  __first2  Another iterator.
-   *  @param  __last1   Another iterator.
-   *  @param  __last2   Another iterator.
-   *  @param  __result  An iterator pointing to the end of the merged range.
-   *  @return         An iterator pointing to the first element <em>not less
-   *                  than</em> @e val.
-   *
-   *  Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into
-   *  the sorted range @p [__result, __result + (__last1-__first1) +
-   *  (__last2-__first2)).  Both input ranges must be sorted, and the
-   *  output range must not overlap with either of the input ranges.
-   *  The sort is @e stable, that is, for equivalent elements in the
-   *  two ranges, elements from the first range will always come
-   *  before elements from the second.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    merge(_InputIterator1 __first1, _InputIterator1 __last1,
-	  _InputIterator2 __first2, _InputIterator2 __last2,
-	  _OutputIterator __result)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)	
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (*__first2 < *__first1)
-	    {
-	      *__result = *__first2;
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      return std::copy(__first2, __last2, std::copy(__first1, __last1,
-						    __result));
-    }
-
-  /**
-   *  @brief Merges two sorted ranges.
-   *  @ingroup sorting_algorithms
-   *  @param  __first1  An iterator.
-   *  @param  __first2  Another iterator.
-   *  @param  __last1   Another iterator.
-   *  @param  __last2   Another iterator.
-   *  @param  __result  An iterator pointing to the end of the merged range.
-   *  @param  __comp    A functor to use for comparisons.
-   *  @return         An iterator pointing to the first element "not less
-   *                  than" @e val.
-   *
-   *  Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into
-   *  the sorted range @p [__result, __result + (__last1-__first1) +
-   *  (__last2-__first2)).  Both input ranges must be sorted, and the
-   *  output range must not overlap with either of the input ranges.
-   *  The sort is @e stable, that is, for equivalent elements in the
-   *  two ranges, elements from the first range will always come
-   *  before elements from the second.
-   *
-   *  The comparison function should have the same effects on ordering as
-   *  the function used for the initial sort.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    merge(_InputIterator1 __first1, _InputIterator1 __last1,
-	  _InputIterator2 __first2, _InputIterator2 __last2,
-	  _OutputIterator __result, _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (__comp(*__first2, *__first1))
-	    {
-	      *__result = *__first2;
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	    }
-	  ++__result;
-	}
-      return std::copy(__first2, __last2, std::copy(__first1, __last1,
-						    __result));
-    }
-
-
-  /**
-   *  @brief Sort the elements of a sequence, preserving the relative order
-   *         of equivalent elements.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @return  Nothing.
-   *
-   *  Sorts the elements in the range @p [__first,__last) in ascending order,
-   *  such that for each iterator @p i in the range @p [__first,__last-1),
-   *  @p *(i+1)<*i is false.
-   *
-   *  The relative ordering of equivalent elements is preserved, so any two
-   *  elements @p x and @p y in the range @p [__first,__last) such that
-   *  @p x<y is false and @p y<x is false will have the same relative
-   *  ordering after calling @p stable_sort().
-  */
-  template<typename _RandomAccessIterator>
-    inline void
-    stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
-								 __last);
-      if (__buf.begin() == 0)
-	std::__inplace_stable_sort(__first, __last);
-      else
-	std::__stable_sort_adaptive(__first, __last, __buf.begin(),
-				    _DistanceType(__buf.size()));
-    }
-
-  /**
-   *  @brief Sort the elements of a sequence using a predicate for comparison,
-   *         preserving the relative order of equivalent elements.
-   *  @ingroup sorting_algorithms
-   *  @param  __first   An iterator.
-   *  @param  __last    Another iterator.
-   *  @param  __comp    A comparison functor.
-   *  @return  Nothing.
-   *
-   *  Sorts the elements in the range @p [__first,__last) in ascending order,
-   *  such that for each iterator @p i in the range @p [__first,__last-1),
-   *  @p __comp(*(i+1),*i) is false.
-   *
-   *  The relative ordering of equivalent elements is preserved, so any two
-   *  elements @p x and @p y in the range @p [__first,__last) such that
-   *  @p __comp(x,y) is false and @p __comp(y,x) is false will have the same
-   *  relative ordering after calling @p stable_sort().
-  */
-  template<typename _RandomAccessIterator, typename _Compare>
-    inline void
-    stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		_Compare __comp)
-    {
-      typedef typename iterator_traits<_RandomAccessIterator>::value_type
-	_ValueType;
-      typedef typename iterator_traits<_RandomAccessIterator>::difference_type
-	_DistanceType;
-
-      // concept requirements
-      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
-	    _RandomAccessIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType,
-				  _ValueType>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
-								 __last);
-      if (__buf.begin() == 0)
-	std::__inplace_stable_sort(__first, __last, __comp);
-      else
-	std::__stable_sort_adaptive(__first, __last, __buf.begin(),
-				    _DistanceType(__buf.size()), __comp);
-    }
-
-
-  /**
-   *  @brief Return the union of two sorted ranges.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  each range in order to the output range.  Iterators increment for each
-   *  range.  When the current element of one range is less than the other,
-   *  that element is copied and the iterator advanced.  If an element is
-   *  contained in both ranges, the element from the first range is copied and
-   *  both ranges advance.  The output range may not overlap either input
-   *  range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    set_union(_InputIterator1 __first1, _InputIterator1 __last1,
-	      _InputIterator2 __first2, _InputIterator2 __last2,
-	      _OutputIterator __result)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (*__first1 < *__first2)
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	    }
-	  else if (*__first2 < *__first1)
-	    {
-	      *__result = *__first2;
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	      ++__first2;
-	    }
-	  ++__result;
-	}
-      return std::copy(__first2, __last2, std::copy(__first1, __last1,
-						    __result));
-    }
-
-  /**
-   *  @brief Return the union of two sorted ranges using a comparison functor.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @param  __comp    The comparison functor.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  each range in order to the output range.  Iterators increment for each
-   *  range.  When the current element of one range is less than the other
-   *  according to @p __comp, that element is copied and the iterator advanced.
-   *  If an equivalent element according to @p __comp is contained in both
-   *  ranges, the element from the first range is copied and both ranges
-   *  advance.  The output range may not overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    set_union(_InputIterator1 __first1, _InputIterator1 __last1,
-	      _InputIterator2 __first2, _InputIterator2 __last2,
-	      _OutputIterator __result, _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	{
-	  if (__comp(*__first1, *__first2))
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	    }
-	  else if (__comp(*__first2, *__first1))
-	    {
-	      *__result = *__first2;
-	      ++__first2;
-	    }
-	  else
-	    {
-	      *__result = *__first1;
-	      ++__first1;
-	      ++__first2;
-	    }
-	  ++__result;
-	}
-      return std::copy(__first2, __last2, std::copy(__first1, __last1,
-						    __result));
-    }
-
-  /**
-   *  @brief Return the intersection of two sorted ranges.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  both ranges in order to the output range.  Iterators increment for each
-   *  range.  When the current element of one range is less than the other,
-   *  that iterator advances.  If an element is contained in both ranges, the
-   *  element from the first range is copied and both ranges advance.  The
-   *  output range may not overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
-		     _InputIterator2 __first2, _InputIterator2 __last2,
-		     _OutputIterator __result)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (*__first1 < *__first2)
-	  ++__first1;
-	else if (*__first2 < *__first1)
-	  ++__first2;
-	else
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__first2;
-	    ++__result;
-	  }
-      return __result;
-    }
-
-  /**
-   *  @brief Return the intersection of two sorted ranges using comparison
-   *  functor.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @param  __comp    The comparison functor.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  both ranges in order to the output range.  Iterators increment for each
-   *  range.  When the current element of one range is less than the other
-   *  according to @p __comp, that iterator advances.  If an element is
-   *  contained in both ranges according to @p __comp, the element from the
-   *  first range is copied and both ranges advance.  The output range may not
-   *  overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
-		     _InputIterator2 __first2, _InputIterator2 __last2,
-		     _OutputIterator __result, _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(*__first1, *__first2))
-	  ++__first1;
-	else if (__comp(*__first2, *__first1))
-	  ++__first2;
-	else
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__first2;
-	    ++__result;
-	  }
-      return __result;
-    }
-
-  /**
-   *  @brief Return the difference of two sorted ranges.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  the first range but not the second in order to the output range.
-   *  Iterators increment for each range.  When the current element of the
-   *  first range is less than the second, that element is copied and the
-   *  iterator advances.  If the current element of the second range is less,
-   *  the iterator advances, but no element is copied.  If an element is
-   *  contained in both ranges, no elements are copied and both ranges
-   *  advance.  The output range may not overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
-		   _InputIterator2 __first2, _InputIterator2 __last2,
-		   _OutputIterator __result)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)	
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (*__first1 < *__first2)
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__result;
-	  }
-	else if (*__first2 < *__first1)
-	  ++__first2;
-	else
-	  {
-	    ++__first1;
-	    ++__first2;
-	  }
-      return std::copy(__first1, __last1, __result);
-    }
-
-  /**
-   *  @brief  Return the difference of two sorted ranges using comparison
-   *  functor.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @param  __comp    The comparison functor.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  the first range but not the second in order to the output range.
-   *  Iterators increment for each range.  When the current element of the
-   *  first range is less than the second according to @p __comp, that element
-   *  is copied and the iterator advances.  If the current element of the
-   *  second range is less, no element is copied and the iterator advances.
-   *  If an element is contained in both ranges according to @p __comp, no
-   *  elements are copied and both ranges advance.  The output range may not
-   *  overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
-		   _InputIterator2 __first2, _InputIterator2 __last2,
-		   _OutputIterator __result, _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(*__first1, *__first2))
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__result;
-	  }
-	else if (__comp(*__first2, *__first1))
-	  ++__first2;
-	else
-	  {
-	    ++__first1;
-	    ++__first2;
-	  }
-      return std::copy(__first1, __last1, __result);
-    }
-
-  /**
-   *  @brief  Return the symmetric difference of two sorted ranges.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  one range but not the other in order to the output range.  Iterators
-   *  increment for each range.  When the current element of one range is less
-   *  than the other, that element is copied and the iterator advances.  If an
-   *  element is contained in both ranges, no elements are copied and both
-   *  ranges advance.  The output range may not overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator>
-    _OutputIterator
-    set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
-			     _InputIterator2 __first2, _InputIterator2 __last2,
-			     _OutputIterator __result)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)	
-      __glibcxx_requires_sorted_set(__first1, __last1, __first2);
-      __glibcxx_requires_sorted_set(__first2, __last2, __first1);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (*__first1 < *__first2)
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__result;
-	  }
-	else if (*__first2 < *__first1)
-	  {
-	    *__result = *__first2;
-	    ++__first2;
-	    ++__result;
-	  }
-	else
-	  {
-	    ++__first1;
-	    ++__first2;
-	  }
-      return std::copy(__first2, __last2, std::copy(__first1,
-						    __last1, __result));
-    }
-
-  /**
-   *  @brief  Return the symmetric difference of two sorted ranges using
-   *  comparison functor.
-   *  @ingroup set_algorithms
-   *  @param  __first1  Start of first range.
-   *  @param  __last1   End of first range.
-   *  @param  __first2  Start of second range.
-   *  @param  __last2   End of second range.
-   *  @param  __comp    The comparison functor.
-   *  @return  End of the output range.
-   *  @ingroup set_algorithms
-   *
-   *  This operation iterates over both ranges, copying elements present in
-   *  one range but not the other in order to the output range.  Iterators
-   *  increment for each range.  When the current element of one range is less
-   *  than the other according to @p comp, that element is copied and the
-   *  iterator advances.  If an element is contained in both ranges according
-   *  to @p __comp, no elements are copied and both ranges advance.  The output
-   *  range may not overlap either input range.
-  */
-  template<typename _InputIterator1, typename _InputIterator2,
-	   typename _OutputIterator, typename _Compare>
-    _OutputIterator
-    set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
-			     _InputIterator2 __first2, _InputIterator2 __last2,
-			     _OutputIterator __result,
-			     _Compare __comp)
-    {
-      typedef typename iterator_traits<_InputIterator1>::value_type
-	_ValueType1;
-      typedef typename iterator_traits<_InputIterator2>::value_type
-	_ValueType2;
-
-      // concept requirements
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
-      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType1>)
-      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
-				  _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType1, _ValueType2>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-				  _ValueType2, _ValueType1>)
-      __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
-      __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
-
-      while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(*__first1, *__first2))
-	  {
-	    *__result = *__first1;
-	    ++__first1;
-	    ++__result;
-	  }
-	else if (__comp(*__first2, *__first1))
-	  {
-	    *__result = *__first2;
-	    ++__first2;
-	    ++__result;
-	  }
-	else
-	  {
-	    ++__first1;
-	    ++__first2;
-	  }
-      return std::copy(__first2, __last2,
-		       std::copy(__first1, __last1, __result));
-    }
-
-
-  /**
-   *  @brief  Return the minimum element in a range.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @return  Iterator referencing the first instance of the smallest value.
-  */
-  template<typename _ForwardIterator>
-    _ForwardIterator
-    min_element(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __first;
-      _ForwardIterator __result = __first;
-      while (++__first != __last)
-	if (*__first < *__result)
-	  __result = __first;
-      return __result;
-    }
-
-  /**
-   *  @brief  Return the minimum element in a range using comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @param  __comp   Comparison functor.
-   *  @return  Iterator referencing the first instance of the smallest value
-   *  according to __comp.
-  */
-  template<typename _ForwardIterator, typename _Compare>
-    _ForwardIterator
-    min_element(_ForwardIterator __first, _ForwardIterator __last,
-		_Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_ForwardIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __first;
-      _ForwardIterator __result = __first;
-      while (++__first != __last)
-	if (__comp(*__first, *__result))
-	  __result = __first;
-      return __result;
-    }
-
-  /**
-   *  @brief  Return the maximum element in a range.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @return  Iterator referencing the first instance of the largest value.
-  */
-  template<typename _ForwardIterator>
-    _ForwardIterator
-    max_element(_ForwardIterator __first, _ForwardIterator __last)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_LessThanComparableConcept<
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last)
-	return __first;
-      _ForwardIterator __result = __first;
-      while (++__first != __last)
-	if (*__result < *__first)
-	  __result = __first;
-      return __result;
-    }
-
-  /**
-   *  @brief  Return the maximum element in a range using comparison functor.
-   *  @ingroup sorting_algorithms
-   *  @param  __first  Start of range.
-   *  @param  __last   End of range.
-   *  @param  __comp   Comparison functor.
-   *  @return  Iterator referencing the first instance of the largest value
-   *  according to __comp.
-  */
-  template<typename _ForwardIterator, typename _Compare>
-    _ForwardIterator
-    max_element(_ForwardIterator __first, _ForwardIterator __last,
-		_Compare __comp)
-    {
-      // concept requirements
-      __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
-      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
-	    typename iterator_traits<_ForwardIterator>::value_type,
-	    typename iterator_traits<_ForwardIterator>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
-
-      if (__first == __last) return __first;
-      _ForwardIterator __result = __first;
-      while (++__first != __last)
-	if (__comp(*__result, *__first))
-	  __result = __first;
-      return __result;
-    }
-
-_GLIBCXX_END_NAMESPACE_ALGO
-} // namespace std
-
-#endif /* _STL_ALGO_H */
--- a/build-aux/subst-config-vals.in.sh	Fri Jun 23 20:51:15 2023 +0200
+++ b/build-aux/subst-config-vals.in.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -210,7 +210,6 @@
 QT_CPPFLAGS="@QT_CPPFLAGS@"
 QT_LDFLAGS="@QT_LDFLAGS@"
 QT_LIBS="@QT_LIBS@"
-QT_OPENGL_LIBS="@QT_OPENGL_LIBS@"
 RANLIB="@RANLIB@"
 RDYNAMIC_FLAG="@RDYNAMIC_FLAG@"
 READLINE_LIBS="@LIBREADLINE@"
@@ -372,7 +371,6 @@
   -e "s|%OCTAVE_CONF_QT_CPPFLAGS%|\"${QT_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_QT_LDFLAGS%|\"${QT_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_QT_LIBS%|\"${QT_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_QT_OPENGL_LIBS%|\"${QT_OPENGL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_RANLIB%|\"${RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" | \
--- a/build-aux/subst-cross-config-vals.in.sh	Fri Jun 23 20:51:15 2023 +0200
+++ b/build-aux/subst-cross-config-vals.in.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -214,7 +214,6 @@
 QT_CPPFLAGS="@QT_CPPFLAGS@"
 QT_LDFLAGS="@QT_LDFLAGS@"
 QT_LIBS="@QT_LIBS@"
-QT_OPENGL_LIBS="@QT_OPENGL_LIBS@"
 RANLIB="@RANLIB@"
 RDYNAMIC_FLAG="@RDYNAMIC_FLAG@"
 READLINE_LIBS="@LIBREADLINE@"
@@ -376,7 +375,6 @@
   -e "s|%OCTAVE_CONF_QT_CPPFLAGS%|\"${QT_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_QT_LDFLAGS%|\"${QT_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_QT_LIBS%|\"${QT_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_QT_OPENGL_LIBS%|\"${QT_OPENGL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_RANLIB%|\"${RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" | \
--- a/configure.ac	Fri Jun 23 20:51:15 2023 +0200
+++ b/configure.ac	Fri Jun 23 20:51:51 2023 +0200
@@ -27,7 +27,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [8.2.1], [https://octave.org/bugs.html], [octave],
+AC_INIT([GNU Octave], [9.0.0], [https://octave.org/bugs.html], [octave],
         [https://www.gnu.org/software/octave/])
 
 ### Declare version numbers
@@ -39,9 +39,9 @@
 ## explains how to update these numbers for release and development
 ## versions.
 
-OCTAVE_MAJOR_VERSION=8
-OCTAVE_MINOR_VERSION=2
-OCTAVE_PATCH_VERSION=1
+OCTAVE_MAJOR_VERSION=9
+OCTAVE_MINOR_VERSION=0
+OCTAVE_PATCH_VERSION=0
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -389,16 +389,6 @@
 fi
 AC_SUBST(GXX_VERSION)
 
-## Workaround for broken STL algorithm library.
-OCTAVE_CHECK_BROKEN_STL_ALGO_H
-AM_CONDITIONAL([AMCOND_HAVE_BROKEN_STL_ALGO_H],
-  [test $octave_cv_broken_stl_algo_h = yes])
-
-if test $octave_cv_broken_stl_algo_h = yes; then
-  warn_stl_algo_h="Found nth_element broken in g++ $GXX_VERSION.  Attempting to repair by using local patched version of bits/stl_algo.h."
-  OCTAVE_CONFIGURE_WARNING([warn_stl_algo_h])
-fi
-
 ### Check version number when using gcc.
 dnl It might be different from the g++ version number.
 
@@ -940,6 +930,20 @@
     [Define to 1 to truncate intermediate FP results.])
 fi
 
+### Enable internal checks
+
+## The checks slow down the execution and are redundant,
+## but useful for debugging or verifying GNU Octave.
+ENABLE_INTERNAL_CHECKS=no
+AC_ARG_ENABLE([internal-checks],
+  [AS_HELP_STRING([--enable-internal-checks],
+    [Enable internal checks that are redundant but useful to debug or verify GNU Octave])],
+  [if test "$enableval" = yes; then ENABLE_INTERNAL_CHECKS=yes; fi], [])
+if test $ENABLE_INTERNAL_CHECKS = yes; then
+  AC_DEFINE(OCTAVE_ENABLE_INTERNAL_CHECKS, 1,
+    [Define to 1 to enable internal checks.])
+fi
+
 ### Determine extra CFLAGS, CXXFLAGS that may be necessary for Octave.
 
 ## On Intel systems with gcc, we need to compile with -mieee-fp to get full
@@ -998,6 +1002,7 @@
 
 AC_SUBST(XTRA_CFLAGS)
 AC_SUBST(XTRA_CXXFLAGS)
+AC_SUBST(XTRA_LDFLAGS)
 
 ### Defaults for cross compiling.
 dnl BUILD_CC and BUILD_CXX are the compilers that we use for building tools
@@ -1492,6 +1497,12 @@
 
 OCTAVE_ENABLE_READLINE
 
+### Check whether functions from libiconv are available.
+
+OCTAVE_CHECK_ICONVLIST
+
+OCTAVE_CHECK_ICONV_CANONICALIZE
+
 ### Check for ZLIB library.
 
 OCTAVE_CHECK_LIB(z, ZLIB,
@@ -1853,7 +1864,7 @@
 
 ### GUI/Qt related tests.
 
-QT_VERSIONS="5"
+QT_VERSIONS="5 6"
 
 AC_ARG_WITH([qt],
   [AS_HELP_STRING([--with-qt=VER], [use the Qt major version VER])
@@ -2008,8 +2019,11 @@
 AC_SUBST(FLTK_LDFLAGS)
 AC_SUBST(FLTK_LIBS)
 
-### Final determination of whether OpenGL graphics can be built.
-if test $build_qt_graphics = no && test $build_fltk_graphics = no; then
+### Final determination of whether OpenGL graphics features should
+### be built.  Note that there is no longer a way to build the Qt GUI
+### without also building a Qt widget that uses OpenGL graphics so we
+### check $build_qt_gui instead of $build_qt_graphics here.
+if test $build_qt_gui = no && test $build_fltk_graphics = no; then
   opengl_graphics=no
 else
   opengl_graphics=yes
@@ -2676,7 +2690,7 @@
    fi], [])
 
 if test $ENABLE_DOCS = yes; then
-  if test $opengl_graphics = no || test "$have_qt_opengl_offscreen" = no; then
+  if test $opengl_graphics = no; then
     if test -n "$warn_gnuplot"; then
       ENABLE_DOCS=no
       warn_docs_graphics="building documentation disabled because no suitable graphics toolkit is available; make dist will fail."
@@ -2730,10 +2744,10 @@
 
 ### Determine whether libraries should be linked with visibility attributes.
 
-ENABLE_LIB_VISIBILITY_FLAGS=no
+ENABLE_LIB_VISIBILITY_FLAGS=yes
 AC_ARG_ENABLE(lib-visibility-flags,
-  [AS_HELP_STRING([--enable-lib-visibility-flags],
-    [build libraries with visibility flags (export only symbols from API)])],
+  [AS_HELP_STRING([--disable-lib-visibility-flags],
+    [don't build libraries with visibility flags (export all symbols)])],
   [case $enableval in
      yes) ENABLE_LIB_VISIBILITY_FLAGS=yes ;;
      no) ENABLE_LIB_VISIBILITY_FLAGS=no ;;
@@ -2881,19 +2895,19 @@
   ADDRESS_SANITIZER_ENABLED=yes
   for flag in $GCC_ADDRESS_SANITIZER_FLAGS; do
     OCTAVE_CC_FLAG([$flag], [
-      WARN_CFLAGS="$WARN_CFLAGS $flag";
-      AC_MSG_RESULT([adding $flag to WARN_CFLAGS])])
+      XTRA_CFLAGS="$XTRA_CFLAGS $flag";
+      AC_MSG_RESULT([adding $flag to XTRA_CFLAGS])])
   done
   for flag in $GXX_ADDRESS_SANITIZER_FLAGS; do
     OCTAVE_CXX_FLAG([$flag], [
-      WARN_CXXFLAGS="$WARN_CXXFLAGS $flag";
-      AC_MSG_RESULT([adding $flag to WARN_CXXFLAGS])])
+      XTRA_CXXFLAGS="$XTRA_CXXFLAGS $flag";
+      AC_MSG_RESULT([adding $flag to XTRA_CXXFLAGS])])
   done
   dnl FIXME: do we really need an LD-specific test, or is this good enough?
   for flag in $LD_ADDRESS_SANITIZER_FLAGS; do
     OCTAVE_CC_FLAG([$flag], [
-      WARN_LDFLAGS="$WARN_LDFLAGS $flag";
-      AC_MSG_RESULT([adding $flag to WARN_LDFLAGS])])
+      XTRA_LDFLAGS="$XTRA_LDFLAGS $flag";
+      AC_MSG_RESULT([adding $flag to XTRA_LDFLAGS])])
   done
 fi
 AC_SUBST(ADDRESS_SANITIZER_ENABLED)
@@ -3041,8 +3055,8 @@
 OCTAVE_GUI_LINK_OPTS=""
 
 if test $build_qt_gui = yes; then
-  LIBOCTGUI_LINK_DEPS="$QT_LIBS $QT_OPENGL_LIBS"
-  LIBOCTGUI_LINK_OPTS="$QT_LDFLAGS $QT_OPENGL_LDFLAGS"
+  LIBOCTGUI_LINK_DEPS="$QT_LIBS"
+  LIBOCTGUI_LINK_OPTS="$QT_LDFLAGS"
 
   if test $link_all_deps = yes || test -n "$QT_LDFLAGS"; then
     LIBOCTGUI_LINK_DEPS="$LIBOCTGUI_LINK_DEPS $LIBOCTINTERP_LINK_DEPS"
@@ -3161,6 +3175,8 @@
 AC_CONFIG_FILES([
   Makefile
   build-aux/check-subst-vars.sh:build-aux/check-subst-vars.in.sh
+  build-aux/find-defun-files.sh:build-aux/find-defun-files.in.sh
+  build-aux/find-files-with-tests.sh:build-aux/find-files-with-tests.in.sh
   doc/doxyhtml/Doxyfile
   libgnu/Makefile
   test/Makefile
@@ -3207,7 +3223,7 @@
   Lex libraries:                 $LEXLIB
   LIBS:                          $LIBS
   LDFLAGS:                       $LDFLAGS
-  Extra LDFLAGS:                 $WARN_LDFLAGS
+  Extra LDFLAGS:                 $XTRA_LDFLAGS $WARN_LDFLAGS
 
   AMD CPPFLAGS:                  $AMD_CPPFLAGS
   AMD LDFLAGS:                   $AMD_LDFLAGS
@@ -3287,7 +3303,6 @@
   Qt CPPFLAGS:                   $QT_CPPFLAGS
   Qt LDFLAGS:                    $QT_LDFLAGS
   Qt GUI libraries:              $QT_LIBS
-  Qt OpenGL libraries:           $QT_OPENGL_LIBS
   Qt moc:                        $MOC $MOCFLAGS
   Qt uic:                        $UIC $UICFLAGS
   Qt rcc:                        $RCC $RCCFLAGS
--- a/doc/interpreter/basics.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/basics.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -391,11 +391,11 @@
 properties).  In other words, the system's locale charset is in effect until a
 user manually sets the m-file encoding (e.g., in one of the startup files) and
 triggers re-parsing of any relevant m-files.  Octave can be forced to use a
-new encoding with the undocumented function @code{__mfile_encoding__}:
+new encoding with the function @code{mfile_encoding}:
 
 @example
 @group
-__mfile_encoding__ ("utf-8");  # set new encoding
+mfile_encoding ("utf-8");  # set new encoding
 clear ("functions");  # re-parse all .m files in the new encoding
 @end group
 @end example
--- a/doc/interpreter/contributors.in	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/contributors.in	Fri Jun 23 20:51:51 2023 +0200
@@ -101,6 +101,7 @@
 Massimiliano Fasi
 Stephen Fegan
 Ramon Garcia Fernandez
+Kasper H. Filtenborg
 Torsten Finke
 David Finkel
 Guillaume Flandin
--- a/doc/interpreter/external.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/external.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -312,19 +312,19 @@
 circumstances the user might prefer to access the data of the array or matrix
 directly through the @code{fortran_vec} method discussed below.
 
-@deftypefn {Method} {octave_idx_type} numel (void) const
+@deftypefn {Method} {octave_idx_type} numel () const
 The total number of elements in the matrix or array.
 @end deftypefn
 
-@deftypefn {Method} {size_t} byte_size (void) const
+@deftypefn {Method} {size_t} byte_size () const
 The number of bytes used to store the matrix or array.
 @end deftypefn
 
-@deftypefn {Method} {dim_vector} dims (void) const
+@deftypefn {Method} {dim_vector} dims () const
 The dimensions of the matrix or array in value of type @code{dim_vector}.
 @end deftypefn
 
-@deftypefn {Method} {int} ndims (void) const
+@deftypefn {Method} {int} ndims () const
 The number of dimensions of the matrix or array.  Matrices are always 2-D, but
 arrays can be N-dimensional.
 @end deftypefn
@@ -336,7 +336,7 @@
 of rows and columns in the matrix.
 @end deftypefn
 
-@deftypefn {Method} {T*} fortran_vec (void)
+@deftypefn {Method} {T*} fortran_vec ()
 This method returns a pointer to the underlying data of the matrix or array so
 that it can be manipulated directly, either within Octave or by an external
 library.
--- a/doc/interpreter/func.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/func.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -926,6 +926,8 @@
 
 @DOCSTRING(dir_in_loadpath)
 
+@DOCSTRING(mfile_encoding)
+
 @DOCSTRING(dir_encoding)
 
 @node Subfunctions
@@ -1955,7 +1957,7 @@
 
 @example
 @group
-toupper lower_case_arg
+upper lower_case_arg
    @result{} ans = LOWER_CASE_ARG
 @end group
 @end example
@@ -1967,9 +1969,9 @@
 @example
 @group
 strvar = "hello world";
-toupper strvar
+upper strvar
    @result{} ans = STRVAR
-toupper (strvar)
+upper (strvar)
    @result{} ans = HELLO WORLD
 @end group
 @end example
--- a/doc/interpreter/genpropdoc.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/genpropdoc.m	Fri Jun 23 20:51:51 2023 +0200
@@ -859,7 +859,8 @@
 
       case "tickdir"
         s.doc = "Control whether axes tick marks project \"in\" to the plot \
-box or \"out\".  __modemsg__.";
+box or \"out\".  The value \"none\" means no tick marks will be drawn, \
+although tick labels will still be rendered.  __modemsg__.";
 
       case "tickdirmode"
 
--- a/doc/interpreter/geometryimages.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/geometryimages.m	Fri Jun 23 20:51:51 2023 +0200
@@ -154,8 +154,7 @@
 function set_graphics_toolkit ()
   if (isempty (available_graphics_toolkits ()))
     error ("no graphics toolkit available for plotting");
-  elseif (strcmp ("qt", graphics_toolkit ())
-          && __have_feature__ ("QT_OFFSCREEN"))
+  elseif (strcmp ("qt", graphics_toolkit ()))
     ## Use qt with QOffscreenSurface for plot
   elseif (! strcmp ("gnuplot", graphics_toolkit ()))
     if (! any (strcmp ("gnuplot", available_graphics_toolkits ())))
--- a/doc/interpreter/interpimages.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/interpimages.m	Fri Jun 23 20:51:51 2023 +0200
@@ -96,8 +96,7 @@
 function set_graphics_toolkit ()
   if (isempty (available_graphics_toolkits ()))
     error ("no graphics toolkit available for plotting");
-  elseif (strcmp ("qt", graphics_toolkit ())
-          && __have_feature__ ("QT_OFFSCREEN"))
+  elseif (strcmp ("qt", graphics_toolkit ()))
     ## Use qt with QOffscreenSurface for plot
   elseif (! strcmp ("gnuplot", graphics_toolkit ()))
     if (! any (strcmp ("gnuplot", available_graphics_toolkits ())))
--- a/doc/interpreter/linalg.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/linalg.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -211,6 +211,8 @@
 
 @DOCSTRING(kron)
 
+@DOCSTRING(tensorprod)
+
 @DOCSTRING(blkmm)
 
 @DOCSTRING(sylvester)
--- a/doc/interpreter/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -369,7 +369,6 @@
 	@$(GREP) '#define HAVE_CHOLMOD 1' $(top_builddir)/config.h > /dev/null || { echo "Documentation creation requires missing CHOLMOD library.  Cannot package distribution!" ; exit 1; }
 	@$(GREP) '#define HAVE_UMFPACK 1' $(top_builddir)/config.h > /dev/null || { echo "Documentation creation requires missing UMFPACK library.  Cannot package distribution!" ; exit 1; }
 	@$(GREP) '#define HAVE_QHULL 1' $(top_builddir)/config.h > /dev/null || { echo "Documentation creation requires missing QHULL library.  Cannot package distribution!" ; exit 1; }
-	@$(GREP) '#define HAVE_QT_OFFSCREEN 1' $(top_builddir)/config.h > /dev/null || { echo "Documentation creation requires Qt offscreen OpenGL rendering.  Cannot package distribution!" ; exit 1; }
 
 $(MUNGED_TEXI_SRC): $(DOCSTRING_FILES)
 
--- a/doc/interpreter/numbers.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/numbers.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -871,6 +871,8 @@
 
 @DOCSTRING(isprime)
 
+@DOCSTRING(isuniform)
+
 If instead of knowing properties of variables, you wish to know which
 variables are defined and to gather other information about the
 workspace itself, @pxref{Status of Variables}.
--- a/doc/interpreter/plotimages.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/plotimages.m	Fri Jun 23 20:51:51 2023 +0200
@@ -154,8 +154,7 @@
 function set_graphics_toolkit ()
   if (isempty (available_graphics_toolkits ()))
     error ("no graphics toolkit available for plotting");
-  elseif (strcmp ("qt", graphics_toolkit ())
-          && __have_feature__ ("QT_OFFSCREEN"))
+  elseif (strcmp ("qt", graphics_toolkit ()))
     ## Use qt with QOffscreenSurface for plot
   elseif (! strcmp ("gnuplot", graphics_toolkit ()))
     if (! any (strcmp ("gnuplot", available_graphics_toolkits ())))
--- a/doc/interpreter/sparseimages.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/sparseimages.m	Fri Jun 23 20:51:51 2023 +0200
@@ -255,8 +255,7 @@
 function set_graphics_toolkit ()
   if (isempty (available_graphics_toolkits ()))
     error ("no graphics toolkit available for plotting");
-  elseif (strcmp ("qt", graphics_toolkit ())
-          && __have_feature__ ("QT_OFFSCREEN"))
+  elseif (strcmp ("qt", graphics_toolkit ()))
     ## Use qt with QOffscreenSurface for plot
   elseif (! strcmp ("gnuplot", graphics_toolkit ()))
     if (! any (strcmp ("gnuplot", available_graphics_toolkits ())))
--- a/doc/interpreter/splineimages.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/splineimages.m	Fri Jun 23 20:51:51 2023 +0200
@@ -186,8 +186,7 @@
 function set_graphics_toolkit ()
   if (isempty (available_graphics_toolkits ()))
     error ("no graphics toolkit available for plotting");
-  elseif (strcmp ("qt", graphics_toolkit ())
-          && __have_feature__ ("QT_OFFSCREEN"))
+  elseif (strcmp ("qt", graphics_toolkit ()))
     ## Use qt with QOffscreenSurface for plot
   elseif (! strcmp ("gnuplot", graphics_toolkit ()))
     if (! any (strcmp ("gnuplot", available_graphics_toolkits ())))
--- a/doc/interpreter/strings.txi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/interpreter/strings.txi	Fri Jun 23 20:51:51 2023 +0200
@@ -254,9 +254,9 @@
 
 The following functions are useful to perform common String operations.
 
-@DOCSTRING(tolower)
+@DOCSTRING(lower)
 
-@DOCSTRING(toupper)
+@DOCSTRING(upper)
 
 @DOCSTRING(deblank)
 
--- a/doc/liboctave/range.texi	Fri Jun 23 20:51:15 2023 +0200
+++ b/doc/liboctave/range.texi	Fri Jun 23 20:51:51 2023 +0200
@@ -20,35 +20,4 @@
 @chapter Ranges
 @cindex ranges
 
-@deftypefn  {} {} Range (void)
-@deftypefnx  {} {} Range (const Range &@var{r})
-@deftypefnx  {} {} Range (double @var{b}, double @var{l})
-@deftypefnx  {} {} Range (double @var{b}, double @var{l}, double @var{i})
-@end deftypefn
-
-@deftypefn {} double base (void) const
-@deftypefnx {} double limit (void) const
-@deftypefnx {} double inc (void) const
-@end deftypefn
-
-@deftypefn {} void set_base (double @var{b})
-@deftypefnx {} void set_limit (double @var{l})
-@deftypefnx {} void set_inc (double @var{i})
-@end deftypefn
-
-@deftypefn {} int nelem (void) const
-@end deftypefn
-
-@deftypefn {} double min (void) const
-@deftypefnx {} double max (void) const
-@end deftypefn
-
-@deftypefn {} void sort (void)
-@end deftypefn
-
-@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const Range &@var{r})
-@deftypefnx {} {istream&} {operator >>} (istream &@var{is}, Range &@var{r})
-@end deftypefn
-
-@deftypefn {} void print_range (void)
-@end deftypefn
+FIXME: The @code{Range} class is obsolete.
--- a/etc/NEWS.8.md	Fri Jun 23 20:51:15 2023 +0200
+++ b/etc/NEWS.8.md	Fri Jun 23 20:51:51 2023 +0200
@@ -94,7 +94,7 @@
 - Octave is now compatible with PCRE2 (UTF-8).  PCRE2 is preferred over PCRE
   if both are installed.  Configure with `--without-pcre2` if you prefer Octave
   to use PCRE in this case.
-  
+
 - `mean` now internally processes data as type double to reduce likelihood of
 hitting overflow or precision limits with other types (bug #63848).
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.9.md	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,206 @@
+Summary of important user-visible changes for version 9 (yyyy-mm-dd):
+---------------------------------------------------------------------
+
+### General improvements
+
+- `oruntests`: The current directory now changes to the directory
+containing the files with the tests for the duration of the test.  This
+aligns the behavior of this function with Octave's test suite.  This also
+means that the file encoding specified in the `.oct-config` file for the
+respective directory is taken into account for the tests.
+
+- `dec2base`, `dec2bin`, and `dec2hex` have all been overhauled.  All three
+functions now accommodate negative inputs and fractional inputs, and repeated
+code between the functions has been reduced or eliminated.  Previously only
+`dec2bin` and `dec2hex` accepted negative inputs but `dec2base` did not, and
+none of the three accepted fractional inputs.  But now,
+`dec2base (100*pi, 16, 4, 6)` for exampele returns a base-16 string with four
+places for the integer part and six places for the fractional part.  Omitting
+the number of decimal places (the fourth input) retains old behavior for
+backward compatibility, except that non-integer inputs will no longer error.
+
+- `quiver` and `quiver3` now properly plot non-float numeric inputs by
+internally recasting them to 'double' (bug #59695).  Both functions now
+honor a previously ignored scaling factor input when there is only a
+single arrow (bug #39552), and `quiver3` no longer produces an error when a
+scaling factor is input without x and y inputs. Both functions now also
+accept a scale factor of "off" which is equivalent to setting it to 0.
+When a linestyle with a base marker is set suppressing arrowhead display,
+subsequent name-value property pairs in the quiver/quiver3 function call
+will no longer turn arrowhead display back on (bug #64143).  The linewdith
+property now also affect the line width of the base marker.
+
+- The `inputParser` function has been re-architected for a 60% performance
+improvement.
+
+### Graphical User Interface
+
+### Graphics backend
+
+* The `set` function now accepts any combination of name/value pairs,
+cell array of names / cell array of values, or property structures.
+This change is Matlab-compatible.
+
+* When the `hold` function is used without arguments to toggle the current
+state the resulting value is now displayed in the Command Window for
+informational purposes.
+
+* The axes graphics property "TickDir" now accepts the option "none" which
+will not draw tick marks, but will still draw tick labels.
+
+### Matlab compatibility
+
+- The `inputParser` function now implements the `PartialMatching` property
+for `Parameter` and `Switch` names.  For Matlab compatibility,
+`PartialMatching` is now set to true by default which may change the behavior
+of existing code.
+
+- Overhauled `mean`, `median`, `var`, and `std` functions have been imported
+from statistics package v1.5.4 to compatibly implement 'nanflag' (bug #50571),
+'all' (bug #58116), and 'vecdim' (bug #58089) options, preserve output class,
+and match expected output behavior for empty (bug #50583) and sparse inputs
+(bug #63291).  Both `median` and `mean` can handle large int values without
+overflow or precision concerns (bug #54567), and `mean` avoids errors due to
+limits of single precision by processing as doubles (bug #63848).  `median`
+has also adopted the 'outtype' option from `mean`.
+
+- `mad` function now produces Matlab compatible output using improved `mean`
+and `median` functions.  'vecdim' and 'all' options are now supported.  `mad`
+ignores all NaN values (using 'omitnan' mean/median option) and produces
+expected output behavior for empty inputs.
+
+- `mode` now produces Matlab compatible output for empty inputs (bug #50583).
+
+- `normalize` now produces Matlab compatible output for inputs containing NaN
+values (bug #50571).
+
+- `cov` now processes the input form cov(x,y) with two separate data arrays
+x and y, as cov(x(:),y(:)) to maintain Matlab compatibility.  It also accepts
+a NANFLAG option to allow ignoring NaN entries in input data (bug #50571)
+and produces Matlab compatible outputs for empty inputs (bug #50583).  `corr`
+and `corrcoef` internal code has been adapted to the new `cov` behavior with
+no change to user interface.  Packages using the octave core's `cov` that rely
+on the previous calling form may need to make similar adaptations.  Calls for
+cov(x) with a vector x expecting a scalar return can get the previous results
+from `cov(x)(2)`, and calls to cov(x,y) with x and y matrices expecting
+columnwise covariance calculation can obtain the previous results using
+`cov([x,y])(1:nx, nx+1:end)`, where nx = columns(x).
+
+- `qz` now handles input and output arguments in a Matlab compatible
+way. It always computes the complex QZ decomposition if there are only
+two input arguments, and it accepts an optional third input argument
+'real' or 'complex' to select the type of decomposition. The output
+arguments are always in the same order independently of the input
+arguments, and the generalized eigenvalues are no longer returned (one
+can use the `ordeig` function for that purpose). The optional reordering
+of the generalized eigenvalues has been removed (one can use the `ordqz`
+function for that purpose).
+
+- `pcolor` now sets the axes limits to be just large enough to display the
+plotted data (equivalent of `axis tight`).
+
+- `xlim`, `ylim`, `zlim` functions can now query or set the limit calculation
+method which is one of "tickaligned", "tight", or "padded".
+
+### Alphabetical list of new functions added in Octave 9
+
+* `isuniform`
+* `tensorprod`
+
+### Deprecated functions, properties, and operators
+
+The following functions and properties have been deprecated in Octave 9
+and will be removed from Octave 11 (or whatever version is the second
+major release after 9):
+
+- Functions
+
+        Function               | Replacement
+        -----------------------|------------------
+
+- Properties
+
+  The following property names are discouraged, but there is no fixed
+  date for their removal.
+
+        Object           | Property    | Replacement
+        -----------------|-------------|------------
+
+- Core
+
+    * The `idx_vector::bool()` function is obsolete and always returns true.
+Any uses can simply be removed from existing code with no loss of function.
+
+    * The `all_ok(const Array<octave::idx_vector>&)` function in `Array-util.h`
+is obsolete and always returns true.  Any uses can simply be removed from
+existing code with no loss of function.
+
+    * The member variable `octave_base_value::count` is deprecated and will be removed from Octave 11.  Replace all instances with the new name `m_count`.
+
+The following features were deprecated in Octave 7 and have been removed
+from Octave 9.
+
+- Functions
+
+        Function                   | Replacement
+        ---------------------------|------------------
+        disable_diagonal_matrix    | optimize_diagonal_matrix
+        disable_permutation_matrix | optimize_permutation_matrix
+        disable_range              | optimize_range
+
+- Operators
+
+        Operator | Replacement
+        ---------|------------
+        .+       | +
+        .+=      | +=
+        .-       | -
+        .-=      | -=
+        **       | ^
+        **=      | ^=
+        .**      | .^
+        .**=     | .^=
+
+- Interpreter
+
+    * The use of `'...'` for line continuations *inside* double-quoted
+    strings has been removed.  Use `'\'` for line continuations inside strings
+    instead.
+
+    * The use of `'\'` as a line continuation *outside* of double-quoted
+    strings has been removed.  Use `'...'` for line continuations instead.
+
+    * Support for trailing whitespace after a `'\'` line continuation has been
+    removed.  Delete unnecessary trailing whitespace.
+
+- For plot functions, the use of numbers to select line colors in
+  shorthand formats was an undocumented feature that was removed in Octave 9.
+
+- The environment variable used by `mkoctfile` for linker flags is now
+  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6
+  and has been removed.
+
+Summary of bugs fixed for version 9.1.0 (yyyy-mm-dd):
+----------------------------------------------------
+
+- Bugfixes to `whos -file`, `urlread`, `mat2cell`, `set`.
+
+- Memory usage reduced for `movfun` by eliminating temporary copies.
+
+- Memory usage reduced when saving to file, preventing OOM and data loss.
+
+- Several race conditions removed in signal handler.
+
+- Performance improvements: avoid unnecessary string construction, use
+  static casts instead of dynamic casts where possible.
+
+### Old release news
+
+- [Octave 8.x](etc/NEWS.8)
+- [Octave 7.x](etc/NEWS.7)
+- [Octave 6.x](etc/NEWS.6)
+- [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/etc/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/etc/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -13,6 +13,7 @@
   %reldir%/NEWS.6.md \
   %reldir%/NEWS.7.md \
   %reldir%/NEWS.8.md \
+  %reldir%/NEWS.9.md \
   %reldir%/gdbinit
 
 %canon_reldir%_EXTRA_DIST += \
--- a/examples/code/embedded.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/examples/code/embedded.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -5,7 +5,7 @@
 #include <octave/interpreter.h>
 
 int
-main (void)
+main ()
 {
   // Create interpreter.
 
--- a/examples/code/make_int.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/examples/code/make_int.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  octave_integer (void)
+  octave_integer ()
     : octave_base_dld_value (), scalar (0) { }
 
   octave_integer (int i)
@@ -46,40 +46,35 @@
   octave_integer (const octave_integer& s)
     : octave_base_dld_value (), scalar (s.scalar) { }
 
-  ~octave_integer (void) = default;
-
-  octave_base_value * clone (void) { return new octave_integer (*this); }
+  ~octave_integer () = default;
 
-#if 0
-  void *operator new (std::size_t size);
-  void operator delete (void *p, std::size_t size);
-#endif
+  octave_base_value * clone () { return new octave_integer (*this); }
 
   octave::idx_vector index_vector (bool) const
   { return octave::idx_vector ((double) scalar); }
 
-  int rows (void) const { return 1; }
-  int columns (void) const { return 1; }
+  int rows () const { return 1; }
+  int columns () const { return 1; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_defined (void) const { return true; }
-  bool is_real_scalar (void) const { return true; }
+  bool is_defined () const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  octave_value all (void) const { return (double) (scalar != 0); }
-  octave_value any (void) const { return (double) (scalar != 0); }
+  octave_value all () const { return (double) (scalar != 0); }
+  octave_value any () const { return (double) (scalar != 0); }
 
-  bool is_real_type (void) const { return true; }
-  bool is_scalar_type (void) const { return true; }
-  bool isnumeric (void) const { return true; }
+  bool is_real_type () const { return true; }
+  bool is_scalar_type () const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool valid_as_scalar_index (void) const
+  bool valid_as_scalar_index () const
   { return scalar == 1; }
 
-  bool valid_as_zero_index (void) const
+  bool valid_as_zero_index () const
   { return scalar == 0; }
 
-  bool is_true (void) const { return (scalar != 0); }
+  bool is_true () const { return (scalar != 0); }
 
   double double_value (bool = false) const { return (double) scalar; }
 
@@ -92,17 +87,17 @@
   ComplexMatrix complex_matrix_value (bool = false) const
   { return ComplexMatrix (1, 1, Complex (scalar)); }
 
-  octave_value gnot (void) const { return octave_value ((double) ! scalar); }
+  octave_value gnot () const { return octave_value ((double) ! scalar); }
 
-  octave_value uminus (void) const { return new octave_integer (- scalar); }
+  octave_value uminus () const { return new octave_integer (- scalar); }
 
-  octave_value transpose (void) const { return new octave_integer (scalar); }
+  octave_value transpose () const { return new octave_integer (scalar); }
 
-  octave_value hermitian (void) const { return new octave_integer (scalar); }
+  octave_value hermitian () const { return new octave_integer (scalar); }
 
-  void increment (void) { ++scalar; }
+  void increment () { ++scalar; }
 
-  void decrement (void) { --scalar; }
+  void decrement () { --scalar; }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false);
 
--- a/examples/code/standalone.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/examples/code/standalone.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -2,7 +2,7 @@
 #include <octave/oct.h>
 
 int
-main (void)
+main ()
 {
   std::cout << "Hello Octave world!\n";
 
--- a/examples/code/standalonebuiltin.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/examples/code/standalonebuiltin.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -3,7 +3,7 @@
 #include <octave/builtin-defun-decls.h>
 
 int
-main (void)
+main ()
 {
   int n = 2;
   Matrix a_matrix = Matrix (n, n);
--- a/libgui/graphics/BaseControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/BaseControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -72,8 +72,8 @@
       QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
       QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
       QString qss = QString (":enabled { background: %1 none;\n"
-                             "color: %2; }")
-        .arg(bcol.name ()).arg (fcol.name ());
+                                        "color: %2; }")
+                    .arg(bcol.name ()).arg (fcol.name ());
       w->setStyleSheet(qss);
       return;
     }
@@ -95,8 +95,8 @@
       QColor bcol = Utils::fromRgb (props.get_backgroundcolor_rgb ());
       QColor fcol = Utils::fromRgb (props.get_foregroundcolor_rgb ());
       QString qss = QString (":enabled { background: %1 none;\n"
-                             "color: %2; }")
-        .arg(bcol.name ()).arg (fcol.name ());
+                                        "color: %2; }")
+                    .arg(bcol.name ()).arg (fcol.name ());
       w->setStyleSheet(qss);
       return;
     }
@@ -115,10 +115,9 @@
   w->setPalette (p);
 }
 
-BaseControl::BaseControl (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+BaseControl::BaseControl (octave::interpreter& interp,
                           const graphics_object& go, QWidget *w)
-  : Object (oct_qobj, interp, go, w), m_normalizedFont (false),
+  : Object (interp, go, w), m_normalizedFont (false),
     m_keyPressHandlerDefined (false)
 {
   qObject ()->setObjectName ("UIControl");
@@ -151,11 +150,11 @@
   m_normalizedFont = up.fontunits_is ("normalized");
 }
 
-BaseControl::~BaseControl (void)
+BaseControl::~BaseControl ()
 { }
 
 void
-BaseControl::redraw (void)
+BaseControl::redraw ()
 {
   update (uicontrol::properties::ID_POSITION);
 }
--- a/libgui/graphics/BaseControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/BaseControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,23 +33,22 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class BaseControl : public Object
 {
 public:
-  BaseControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  BaseControl (octave::interpreter& interp,
                const graphics_object& go, QWidget *w);
-  ~BaseControl (void);
+  ~BaseControl ();
 
-  Container * innerContainer (void) { return nullptr; }
+  Container * innerContainer () { return nullptr; }
 
   bool eventFilter (QObject *watched, QEvent *e);
 
 protected:
   void init (QWidget *w, bool callBase = false);
-  void redraw (void);
+  void redraw ();
   void update (int pId);
 
 private:
--- a/libgui/graphics/ButtonControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ButtonControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,11 +39,10 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-ButtonControl::ButtonControl (octave::base_qobject& oct_qobj,
-                              octave::interpreter& interp,
+ButtonControl::ButtonControl (octave::interpreter& interp,
                               const graphics_object& go,
                               QAbstractButton *btn)
-: BaseControl (oct_qobj, interp, go, btn), m_blockCallback (false)
+  : BaseControl (interp, go, btn), m_blockCallback (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -64,7 +63,7 @@
   connect (btn, &QAbstractButton::toggled, this, &ButtonControl::toggled);
 }
 
-ButtonControl::~ButtonControl (void)
+ButtonControl::~ButtonControl ()
 { }
 
 void
@@ -144,7 +143,7 @@
 }
 
 void
-ButtonControl::clicked (void)
+ButtonControl::clicked ()
 {
   QAbstractButton *btn = qWidget<QAbstractButton> ();
 
--- a/libgui/graphics/ButtonControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ButtonControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class ButtonControl : public BaseControl
@@ -40,15 +39,15 @@
   Q_OBJECT
 
 public:
-  ButtonControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ButtonControl (octave::interpreter& interp,
                  const graphics_object& go, QAbstractButton *btn);
-  ~ButtonControl (void);
+  ~ButtonControl ();
 
 protected:
   void update (int pId);
 
 private slots:
-  void clicked (void);
+  void clicked ();
   void toggled (bool checked);
 
 private:
--- a/libgui/graphics/ButtonGroup.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ButtonGroup.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -45,9 +45,6 @@
 #include "QtHandlesUtils.h"
 #include "qt-graphics-toolkit.h"
 
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
-
 #include "interpreter.h"
 #include "oct-map.h"
 
@@ -99,8 +96,7 @@
 }
 
 ButtonGroup *
-ButtonGroup::create (octave::base_qobject& oct_qobj,
-                     octave::interpreter& interp, const graphics_object& go)
+ButtonGroup::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
 
@@ -111,7 +107,7 @@
       if (container)
         {
           QFrame *frame = new QFrame (container);
-          return new ButtonGroup (oct_qobj, interp, go,
+          return new ButtonGroup (interp, go,
                                   new QButtonGroup (frame), frame);
         }
     }
@@ -119,11 +115,10 @@
   return nullptr;
 }
 
-ButtonGroup::ButtonGroup (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+ButtonGroup::ButtonGroup (octave::interpreter& interp,
                           const graphics_object& go,
                           QButtonGroup *buttongroup, QFrame *frame)
-  : Object (oct_qobj, interp, go, frame), m_hiddenbutton (nullptr),
+  : Object (interp, go, frame), m_hiddenbutton (nullptr),
     m_container (nullptr), m_title (nullptr), m_blockUpdates (false)
 {
   uibuttongroup::properties& pp = properties<uibuttongroup> ();
@@ -143,7 +138,7 @@
   m_hiddenbutton->hide ();
   m_buttongroup->addButton (m_hiddenbutton);
 
-  m_container = new Container (frame, oct_qobj, interp);
+  m_container = new Container (frame, interp);
   m_container->canvas (m_handle);
 
   connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)),
@@ -178,7 +173,7 @@
       QTimer::singleShot (0, frame, &QFrame::show);
       // FIXME: What is the intent here?  QButtonGroup::show is not a
       // member of QButtonGroup.
-      QTimer::singleShot (0, buttongroup, SLOT (show (void)));
+      QTimer::singleShot (0, buttongroup, SLOT (show ()));
     }
   else
     frame->hide ();
@@ -188,7 +183,7 @@
            this, &ButtonGroup::buttonClicked);
 }
 
-ButtonGroup::~ButtonGroup (void)
+ButtonGroup::~ButtonGroup ()
 { }
 
 bool
@@ -379,7 +374,7 @@
 
         Object *selectedObject = qt_graphics_toolkit::toolkitObject (go);
         ToggleButtonControl *toggle = static_cast<ToggleButtonControl *>
-          (selectedObject);
+                                      (selectedObject);
         RadioButtonControl *radio = static_cast<RadioButtonControl *>(selectedObject);
         if (toggle)
           {
@@ -404,7 +399,7 @@
 }
 
 void
-ButtonGroup::redraw (void)
+ButtonGroup::redraw ()
 {
   update (uibuttongroup::properties::ID_POSITION);
 
@@ -416,7 +411,7 @@
 }
 
 void
-ButtonGroup::updateLayout (void)
+ButtonGroup::updateLayout ()
 {
   uibuttongroup::properties& pp = properties<uibuttongroup> ();
   QFrame *frame = qWidget<QFrame> ();
@@ -457,7 +452,7 @@
 }
 
 void
-ButtonGroup::selectNothing (void)
+ButtonGroup::selectNothing ()
 {
   m_hiddenbutton->setChecked (true);
 }
--- a/libgui/graphics/ButtonGroup.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ButtonGroup.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Container;
@@ -46,33 +45,33 @@
   Q_OBJECT
 
 public:
-  ButtonGroup (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ButtonGroup (octave::interpreter& interp,
                const graphics_object& go, QButtonGroup *buttongroup,
                QFrame *frame);
-  ~ButtonGroup (void);
+  ~ButtonGroup ();
 
-  Container * innerContainer (void) { return m_container; }
+  Container * innerContainer () { return m_container; }
 
   bool eventFilter (QObject *watched, QEvent *event);
 
   static ButtonGroup *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
   void addButton (QAbstractButton *btn);
 
-  void selectNothing (void);
+  void selectNothing ();
 
 protected:
   void update (int pId);
-  void redraw (void);
+  void redraw ();
 
 private slots:
   void buttonToggled (bool toggled);
   void buttonClicked (QAbstractButton *btn);
 
 private:
-  void updateLayout (void);
+  void updateLayout ();
 
 private:
   QButtonGroup *m_buttongroup;
--- a/libgui/graphics/Canvas.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Canvas.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 #include "qt-graphics-toolkit.h"
 
 #include "annotation-dialog.h"
-#include "octave-qobject.h"
+#include "gui-settings.h"
 #include "qt-interpreter-events.h"
 
 #include "builtin-defun-decls.h"
@@ -76,9 +76,9 @@
 QCursor
 Canvas::make_cursor (const QString& name, int hot_x, int hot_y)
 {
-  octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
-  QIcon icon = rmgr.icon (name);
+  QIcon icon = settings.icon (name);
 
   return QCursor (icon.pixmap (22, 22), hot_x, hot_y);
 }
@@ -172,9 +172,9 @@
 }
 
 /*
-  Two updateCurrentPoint() routines are required:
-  1) Used for QMouseEvents where cursor position data is in callback from Qt.
-  2) Used for QKeyEvents where cursor position must be determined.
+   Two updateCurrentPoint() routines are required:
+   1) Used for QMouseEvents where cursor position data is in callback from Qt.
+   2) Used for QKeyEvents where cursor position must be determined.
 */
 void
 Canvas::updateCurrentPoint (const graphics_object& fig,
@@ -272,7 +272,7 @@
 }
 
 void
-Canvas::canvasPaintEvent (void)
+Canvas::canvasPaintEvent ()
 {
   if (! m_redrawBlocked)
     {
@@ -621,9 +621,9 @@
 
       // 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";
+                        && 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)
@@ -868,7 +868,7 @@
 
               octave_value_list props = ovl ("textbox", bb);
 
-              annotation_dialog anno_dlg (m_octave_qobj, w, props);
+              annotation_dialog anno_dlg (w, props);
 
               if (anno_dlg.exec () == QDialog::Accepted)
                 {
@@ -877,13 +877,13 @@
 
                   emit interpreter_event
                     ([=] (octave::interpreter& interp)
-                    {
-                      // INTERPRETER THREAD
+                     {
+                       // INTERPRETER THREAD
 
-                      interp.feval ("annotation", props);
+                       interp.feval ("annotation", props);
 
-                      redraw ();
-                    });
+                       redraw ();
+                     });
                 }
             }
         }
@@ -946,18 +946,14 @@
           if (axesObj.get_properties ().handlevisibility_is ("on"))
             {
               Utils::properties<figure> (figObj)
-                .set_currentaxes (axesObj.get_handle ().as_octave_value ());
+              .set_currentaxes (axesObj.get_handle ().as_octave_value ());
 
               if (zoom_enabled (figObj))
                 {
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
                   if (event->angleDelta().y () > 0)
-#else
-                    if (event->delta () > 0)
-#endif
-                      newMouseMode = ZoomInMode;
-                    else
-                      newMouseMode = ZoomOutMode;
+                    newMouseMode = ZoomInMode;
+                  else
+                    newMouseMode = ZoomOutMode;
 
                   mode = zoom_mode (figObj);
                 }
@@ -996,11 +992,7 @@
               {
                 axes::properties& ap = Utils::properties<axes> (axesObj);
 
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
                 double factor = (event->angleDelta().y () > 0 ? 0.1 : -0.1);
-#else
-                double factor = (event->delta () > 0 ? 0.1 : -0.1);
-#endif
 
                 if (event->modifiers () == Qt::NoModifier
                     && mode != "horizontal")
@@ -1085,12 +1077,12 @@
 }
 
 Canvas *
-Canvas::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Canvas::create (octave::interpreter& interp,
                 const graphics_handle& handle, QWidget *parent,
                 const std::string& /* name */)
 {
   // Only OpenGL
-  return new GLCanvas (oct_qobj, interp, handle, parent);
+  return new GLCanvas (interp, handle, parent);
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/Canvas.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Canvas.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Canvas : public QObject
@@ -52,13 +51,13 @@
 
 public:
   enum EventMask
-    {
-      KeyPress   = 0x01,
-      KeyRelease = 0x02
-    };
+  {
+    KeyPress   = 0x01,
+    KeyRelease = 0x02
+  };
 
 public:
-  virtual ~Canvas (void) = default;
+  virtual ~Canvas () = default;
 
   void redraw (bool sync = false);
   void blockRedraw (bool block = true);
@@ -75,14 +74,13 @@
   void setCursor (MouseMode mode, std::string fallback,
                   QImage cdata, Matrix hotspot);
 
-  virtual QWidget * qWidget (void) = 0;
+  virtual QWidget * qWidget () = 0;
 
   static Canvas *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
-          const graphics_handle& handle, QWidget *parent,
-          const std::string& name);
+  create (octave::interpreter& interp, const graphics_handle& handle,
+          QWidget *parent, const std::string& name);
 
-  virtual uint8NDArray getPixels (void) { return do_getPixels (m_handle); };
+  virtual uint8NDArray getPixels () { return do_getPixels (m_handle); };
 
 signals:
 
@@ -114,22 +112,18 @@
                          const graphics_handle& handle) = 0;
 
 protected:
-  Canvas (octave::base_qobject& oct_qobj, octave::interpreter& interp,
-          const graphics_handle& handle)
-    : m_octave_qobj (oct_qobj),
-      m_interpreter (interp),
-      m_handle (handle),
-      m_redrawBlocked (false),
-      m_mouseMode (NoMode),
-      m_clickMode (false),
-      m_eventMask (0),
-      m_rectMode (false)
+
+  Canvas (octave::interpreter& interp, const graphics_handle& handle)
+    : QObject (), m_interpreter (interp), m_handle (handle),
+      m_redrawBlocked (false), m_mouseMode (NoMode), m_clickMode (false),
+      m_eventMask (0), m_rectMode (false)
   { }
 
+public:
   void canvasToggleAxes (const graphics_handle& handle);
   void canvasToggleGrid (const graphics_handle& handle);
   void canvasAutoAxes (const graphics_handle& handle);
-  void canvasPaintEvent (void);
+  void canvasPaintEvent ();
   void canvasMouseDoubleClickEvent (QMouseEvent *event);
   void canvasMouseMoveEvent (QMouseEvent *event);
   void canvasMousePressEvent (QMouseEvent *event);
@@ -149,12 +143,12 @@
                       std::vector<std::string> omit = std::vector<std::string> ());
 
 protected:
-  octave::base_qobject& m_octave_qobj;
+
   octave::interpreter& m_interpreter;
 
 private:
 
-  QCursor make_cursor (const QString& name, int hot_x  = -1, int hot_y = -1);
+  QCursor make_cursor (const QString& name, int hot_x = -1, int hot_y = -1);
 
   graphics_handle m_handle;
   bool m_redrawBlocked;
--- a/libgui/graphics/CheckBoxControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/CheckBoxControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,13 +32,10 @@
 #include "CheckBoxControl.h"
 #include "Container.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 CheckBoxControl *
-CheckBoxControl::create (octave::base_qobject& oct_qobj,
-                         octave::interpreter& interp,
+CheckBoxControl::create (octave::interpreter& interp,
                          const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -48,17 +45,16 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new CheckBoxControl (oct_qobj, interp, go,
+        return new CheckBoxControl (interp, go,
                                     new QCheckBox (container));
     }
 
   return nullptr;
 }
 
-CheckBoxControl::CheckBoxControl (octave::base_qobject& oct_obj,
-                                  octave::interpreter& interp,
+CheckBoxControl::CheckBoxControl (octave::interpreter& interp,
                                   const graphics_object& go, QCheckBox *box)
-  : ButtonControl (oct_obj, interp, go, box)
+  : ButtonControl (interp, go, box)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -67,7 +63,7 @@
     box->setCheckable (false);
 }
 
-CheckBoxControl::~CheckBoxControl (void)
+CheckBoxControl::~CheckBoxControl ()
 { }
 
 void
--- a/libgui/graphics/CheckBoxControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/CheckBoxControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,19 +32,17 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class CheckBoxControl : public ButtonControl
 {
 public:
-  CheckBoxControl (octave::base_qobject& oct_qobj,
-                   octave::interpreter& interp, const graphics_object& go,
+  CheckBoxControl (octave::interpreter& interp, const graphics_object& go,
                    QCheckBox *box);
-  ~CheckBoxControl (void);
+  ~CheckBoxControl ();
 
   static CheckBoxControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/Container.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Container.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -40,15 +40,13 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-Container::Container (QWidget *xparent, octave::base_qobject& oct_qobj,
-                      octave::interpreter& interp)
-: ContainerBase (xparent), m_octave_qobj (oct_qobj),
-  m_interpreter (interp),  m_canvas (nullptr)
+Container::Container (QWidget *xparent, octave::interpreter& interp)
+  : ContainerBase (xparent), m_interpreter (interp),  m_canvas (nullptr)
 {
   setFocusPolicy (Qt::ClickFocus);
 }
 
-Container::~Container (void)
+Container::~Container ()
 { }
 
 Canvas *
@@ -66,7 +64,7 @@
         {
           graphics_object fig = go.get_ancestor ("figure");
 
-          m_canvas = Canvas::create (m_octave_qobj, m_interpreter, gh, this,
+          m_canvas = Canvas::create (m_interpreter, gh, this,
                                      fig.get ("renderer").string_value ());
 
           connect (m_canvas, QOverload<const octave::fcn_callback&>::of (&Canvas::interpreter_event),
--- a/libgui/graphics/Container.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Container.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,11 +35,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-}
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
 DECLARE_GENERICEVENTNOTIFY_SENDER(ContainerBase, QWidget);
 
 class Canvas;
@@ -49,9 +44,8 @@
   Q_OBJECT
 
 public:
-  Container (QWidget *parent, octave::base_qobject& oct_qobj,
-             octave::interpreter& interp);
-  ~Container (void);
+  Container (QWidget *parent, octave::interpreter& interp);
+  ~Container ();
 
   Canvas * canvas (const graphics_handle& handle, bool create = true);
 
@@ -80,7 +74,6 @@
   void resizeEvent (QResizeEvent *event);
 
 private:
-  octave::base_qobject& m_octave_qobj;
   octave::interpreter& m_interpreter;
   Canvas *m_canvas;
 };
--- a/libgui/graphics/ContextMenu.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ContextMenu.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,15 +33,12 @@
 #include "QtHandlesUtils.h"
 #include "qt-graphics-toolkit.h"
 
-#include "octave-qobject.h"
-
 #include "interpreter.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 ContextMenu *
-ContextMenu::create (octave::base_qobject& oct_qobj,
-                     octave::interpreter& interp, const graphics_object& go)
+ContextMenu::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *xparent = parentObject (interp, go);
 
@@ -49,16 +46,15 @@
     {
       QWidget *w = xparent->qWidget<QWidget> ();
 
-      return new ContextMenu (oct_qobj, interp, go, new QMenu (w));
+      return new ContextMenu (interp, go, new QMenu (w));
     }
 
   return nullptr;
 }
 
-ContextMenu::ContextMenu (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+ContextMenu::ContextMenu (octave::interpreter& interp,
                           const graphics_object& go, QMenu *xmenu)
-  : Object (oct_qobj, interp, go, xmenu)
+  : Object (interp, go, xmenu)
 {
   xmenu->setAutoFillBackground (true);
 
@@ -66,7 +62,7 @@
   connect (xmenu, &QMenu::aboutToHide, this, &ContextMenu::aboutToHide);
 }
 
-ContextMenu::~ContextMenu (void)
+ContextMenu::~ContextMenu ()
 { }
 
 void
@@ -100,20 +96,20 @@
 }
 
 void
-ContextMenu::aboutToShow (void)
+ContextMenu::aboutToShow ()
 {
   emit gh_callback_event (m_handle, "callback");
   emit gh_set_event (m_handle, "visible", "on", false);
 }
 
 void
-ContextMenu::aboutToHide (void)
+ContextMenu::aboutToHide ()
 {
   emit gh_set_event (m_handle, "visible", "off", false);
 }
 
 QWidget *
-ContextMenu::menu (void)
+ContextMenu::menu ()
 {
   return qWidget<QWidget> ();
 }
--- a/libgui/graphics/ContextMenu.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ContextMenu.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class ContextMenu : public Object, public MenuContainer
@@ -43,27 +42,27 @@
   Q_OBJECT
 
 public:
-  ContextMenu (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ContextMenu (octave::interpreter& interp,
                const graphics_object& go, QMenu *menu);
-  ~ContextMenu (void);
+  ~ContextMenu ();
 
   static ContextMenu *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
   static void executeAt (octave::interpreter& interp,
                          const base_properties& props, const QPoint& pt);
 
-  Container * innerContainer (void) { return nullptr; }
+  Container * innerContainer () { return nullptr; }
 
-  QWidget * menu (void);
+  QWidget * menu ();
 
 protected:
   void update (int pId);
 
 private slots:
-  void aboutToShow (void);
-  void aboutToHide (void);
+  void aboutToShow ();
+  void aboutToHide ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/EditControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/EditControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,13 +34,10 @@
 #include "TextEdit.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 EditControl *
-EditControl::create (octave::base_qobject& oct_qobj,
-                     octave::interpreter& interp, const graphics_object& go)
+EditControl::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
 
@@ -53,10 +50,10 @@
           uicontrol::properties& up = Utils::properties<uicontrol> (go);
 
           if ((up.get_max () - up.get_min ()) > 1)
-            return new EditControl (oct_qobj, interp, go,
+            return new EditControl (interp, go,
                                     new TextEdit (container));
           else
-            return new EditControl (oct_qobj, interp, go,
+            return new EditControl (interp, go,
                                     new QLineEdit (container));
         }
     }
@@ -64,10 +61,9 @@
   return nullptr;
 }
 
-EditControl::EditControl (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+EditControl::EditControl (octave::interpreter& interp,
                           const graphics_object& go, QLineEdit *edit)
-  : BaseControl (oct_qobj, interp, go, edit), m_multiLine (false),
+  : BaseControl (interp, go, edit), m_multiLine (false),
     m_textChanged (false)
 {
   init (edit);
@@ -100,10 +96,9 @@
            this, &EditControl::returnPressed);
 }
 
-EditControl::EditControl (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+EditControl::EditControl (octave::interpreter& interp,
                           const graphics_object& go, TextEdit *edit)
-  : BaseControl (oct_qobj, interp, go, edit), m_multiLine (true),
+  : BaseControl (interp, go, edit), m_multiLine (true),
     m_textChanged (false)
 {
   init (edit);
@@ -138,7 +133,7 @@
            this, &EditControl::returnPressed);
 }
 
-EditControl::~EditControl (void)
+EditControl::~EditControl ()
 { }
 
 void
@@ -262,13 +257,13 @@
 }
 
 void
-EditControl::textChanged (void)
+EditControl::textChanged ()
 {
   m_textChanged = true;
 }
 
 void
-EditControl::returnPressed (void)
+EditControl::returnPressed ()
 {
   QString txt = (m_multiLine
                  ? qWidget<TextEdit> ()->toPlainText ()
@@ -291,7 +286,7 @@
 }
 
 void
-EditControl::editingFinished (void)
+EditControl::editingFinished ()
 {
   if (m_textChanged)
     {
--- a/libgui/graphics/EditControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/EditControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class TextEdit;
@@ -43,16 +42,16 @@
   Q_OBJECT
 
 public:
-  EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  EditControl (octave::interpreter& interp,
                const graphics_object& go, QLineEdit *edit);
 
-  EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  EditControl (octave::interpreter& interp,
                const graphics_object& go, TextEdit *edit);
 
-  ~EditControl (void);
+  ~EditControl ();
 
   static EditControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
@@ -66,9 +65,9 @@
   bool updateMultiLine (int pId);
 
 private slots:
-  void textChanged (void);
-  void editingFinished (void);
-  void returnPressed (void);
+  void textChanged ();
+  void editingFinished ();
+  void returnPressed ();
 
 private:
   bool m_multiLine;
--- a/libgui/graphics/Figure.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Figure.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,10 +43,8 @@
 #include <QtDebug>
 #include <QTimer>
 #include <QToolBar>
-#if defined (HAVE_QSCREEN_DEVICEPIXELRATIO)
-#  include <QWindow>
-#  include <QScreen>
-#endif
+#include <QWindow>
+#include <QScreen>
 
 #include "Canvas.h"
 #include "Container.h"
@@ -109,19 +107,19 @@
 }
 
 Figure *
-Figure::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Figure::create (octave::interpreter& interp,
                 const graphics_object& go)
 {
-  return new Figure (oct_qobj, interp, go, new FigureWindow ());
+  return new Figure (interp, go, new FigureWindow ());
 }
 
-Figure::Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Figure::Figure (octave::interpreter& interp,
                 const graphics_object& go, FigureWindow *win)
-  : Object (oct_qobj, interp, go, win), m_blockUpdates (false),
+  : Object (interp, go, win), m_blockUpdates (false),
     m_figureToolBar (nullptr), m_menuBar (nullptr), m_innerRect (),
     m_outerRect (), m_previousHeight (0), m_resizable (true)
 {
-  m_container = new Container (win, oct_qobj, interp);
+  m_container = new Container (win, interp);
   win->setCentralWidget (m_container);
 
   connect (m_container, QOverload<const octave::fcn_callback&>::of (&Container::interpreter_event),
@@ -162,7 +160,9 @@
   update (figure::properties::ID_NUMBERTITLE);
 
   // Decide what keyboard events we listen to
-  m_container->canvas (m_handle)->setEventMask (0);
+  Canvas *canvas = m_container->canvas (m_handle);
+  if (canvas)
+    canvas->setEventMask (0);
   update (figure::properties::ID_KEYPRESSFCN);
   update (figure::properties::ID_KEYRELEASEFCN);
 
@@ -189,11 +189,11 @@
   m_container->addReceiver (this);
 }
 
-Figure::~Figure (void)
+Figure::~Figure ()
 { }
 
 QString
-Figure::fileName (void)
+Figure::fileName ()
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -219,7 +219,7 @@
 }
 
 MouseMode
-Figure::mouseMode (void)
+Figure::mouseMode ()
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -278,13 +278,13 @@
 }
 
 Container *
-Figure::innerContainer (void)
+Figure::innerContainer ()
 {
   return m_container;
 }
 
 void
-Figure::redraw (void)
+Figure::redraw ()
 {
   Canvas *canvas = m_container->canvas (m_handle);
 
@@ -307,7 +307,7 @@
 }
 
 void
-Figure::show (void)
+Figure::show ()
 {
   QWidget *win = qWidget<QWidget> ();
 
@@ -325,7 +325,7 @@
 }
 
 uint8NDArray
-Figure::slotGetPixels (void)
+Figure::slotGetPixels ()
 {
   uint8NDArray retval;
   Canvas *canvas = m_container->canvas (m_handle);
@@ -343,7 +343,7 @@
 }
 
 void
-Figure::beingDeleted (void)
+Figure::beingDeleted ()
 {
   Canvas *canvas = m_container->canvas (m_handle.value (), false);
 
@@ -442,54 +442,69 @@
       break;
 
     case figure::properties::ID_KEYPRESSFCN:
-      if (fp.get_keypressfcn ().isempty ())
-        m_container->canvas (m_handle)->clearEventMask (Canvas::KeyPress);
-      else
-        m_container->canvas (m_handle)->addEventMask (Canvas::KeyPress);
-      // Signal the change to uipanels as well
-      for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())
-        {
-          if (qobj->objectName () == "UIPanel")
-            {
-              Object *obj = Object::fromQObject (qobj);
+      {
+        Canvas *canvas = m_container->canvas (m_handle);
+
+        if (canvas)
+          {
+            if (fp.get_keypressfcn ().isempty ())
+              canvas->clearEventMask (Canvas::KeyPress);
+            else
+              canvas->addEventMask (Canvas::KeyPress);
+          }
 
-              if (obj)
-                {
-                  if (fp.get_keypressfcn ().isempty ())
-                    obj->innerContainer ()->canvas (m_handle)->
-                      clearEventMask (Canvas::KeyPress);
-                  else
-                    obj->innerContainer ()->canvas (m_handle)->
-                      addEventMask (Canvas::KeyPress);
-                }
-            }
-        }
+        // Signal the change to uipanels as well
+        for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())
+          {
+            if (qobj->objectName () == "UIPanel")
+              {
+                Object *obj = Object::fromQObject (qobj);
+
+                if (obj)
+                  {
+                    if (fp.get_keypressfcn ().isempty ())
+                      obj->innerContainer ()->canvas (m_handle)->
+                        clearEventMask (Canvas::KeyPress);
+                    else
+                      obj->innerContainer ()->canvas (m_handle)->
+                        addEventMask (Canvas::KeyPress);
+                  }
+              }
+          }
+      }
       break;
 
     case figure::properties::ID_KEYRELEASEFCN:
-      if (fp.get_keyreleasefcn ().isempty ())
-        m_container->canvas (m_handle)->clearEventMask (Canvas::KeyRelease);
-      else
-        m_container->canvas (m_handle)->addEventMask (Canvas::KeyRelease);
-      break;
-      // Signal the change to uipanels as well
-      for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())
-        {
-          if (qobj->objectName () == "UIPanel")
-            {
-              Object *obj = Object::fromQObject (qobj);
+      {
+        Canvas *canvas = m_container->canvas (m_handle);
 
-              if (obj)
-                {
-                  if (fp.get_keypressfcn ().isempty ())
-                    obj->innerContainer ()->canvas (m_handle)->
-                      clearEventMask (Canvas::KeyRelease);
-                  else
-                    obj->innerContainer ()->canvas (m_handle)->
-                      addEventMask (Canvas::KeyRelease);
-                }
-            }
-        }
+        if (canvas)
+          {
+            if (fp.get_keyreleasefcn ().isempty ())
+              canvas->clearEventMask (Canvas::KeyRelease);
+            else
+              canvas->addEventMask (Canvas::KeyRelease);
+          }
+        break;
+        // Signal the change to uipanels as well
+        for (auto *qobj : qWidget<QWidget> ()->findChildren<QObject *> ())
+          {
+            if (qobj->objectName () == "UIPanel")
+              {
+                Object *obj = Object::fromQObject (qobj);
+
+                if (obj)
+                  {
+                    if (fp.get_keypressfcn ().isempty ())
+                      obj->innerContainer ()->canvas (m_handle)->
+                        clearEventMask (Canvas::KeyRelease);
+                    else
+                      obj->innerContainer ()->canvas (m_handle)->
+                        addEventMask (Canvas::KeyRelease);
+                  }
+              }
+          }
+      }
       break;
 
     case figure::properties::ID_WINDOWSTYLE:
@@ -521,11 +536,14 @@
     case figure::properties::ID_POINTERSHAPEHOTSPOT:
     case figure::properties::ID___MOUSE_MODE__:
     case figure::properties::ID___ZOOM_MODE__:
-      m_container->canvas (m_handle)->setCursor (mouseMode (),
-                                                 fp.get_pointer (),
-                                                 m_pointer_cdata,
-                                                 fp.get_pointershapehotspot ()
-                                                 .matrix_value());
+      {
+        Canvas *canvas = m_container->canvas (m_handle);
+
+        if (canvas)
+          canvas->setCursor (mouseMode (), fp.get_pointer (),
+                             m_pointer_cdata,
+                             fp.get_pointershapehotspot ().matrix_value());
+      }
       break;
 
     default:
@@ -597,7 +615,7 @@
 }
 
 QWidget *
-Figure::menu (void)
+Figure::menu ()
 {
   return qWidget<QMainWindow> ()->menuBar ();
 }
@@ -846,7 +864,7 @@
 }
 
 void
-Figure::updateContainer (void)
+Figure::updateContainer ()
 {
   redraw ();
 }
@@ -854,7 +872,6 @@
 void
 Figure::figureWindowShown ()
 {
-#if defined (HAVE_QSCREEN_DEVICEPIXELRATIO)
   QWindow *window = qWidget<QMainWindow> ()->windowHandle ();
   QScreen *screen = window->screen ();
 
@@ -866,13 +883,11 @@
   fp.set___device_pixel_ratio__ (screen->devicePixelRatio ());
 
   connect (window, &QWindow::screenChanged, this, &Figure::screenChanged);
-#endif
 }
 
 void
 Figure::screenChanged (QScreen *screen)
 {
-#if defined (HAVE_QSCREEN_DEVICEPIXELRATIO)
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
   octave::autolock guard (gh_mgr.graphics_lock ());
@@ -888,17 +903,19 @@
       // from the GUI thread does not necessarily trigger a redraw.  Force it.
       redraw ();
     }
-#else
-  octave_unused_parameter (screen);
-#endif
 }
 
 void
-Figure::enableMouseTracking (void)
+Figure::enableMouseTracking ()
 {
   // Enable mouse tracking on every widgets
   m_container->setMouseTracking (true);
-  m_container->canvas (m_handle)->qWidget ()->setMouseTracking (true);
+
+  Canvas *canvas = m_container->canvas (m_handle);
+
+  if (canvas)
+    canvas->qWidget ()->setMouseTracking (true);
+
   for (auto *w : m_container->findChildren<QWidget *> ())
     w->setMouseTracking (true);
 }
--- a/libgui/graphics/Figure.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Figure.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,19 +39,18 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 enum MouseMode
-  {
-    NoMode,
-    RotateMode,
-    ZoomInMode,
-    ZoomOutMode,
-    PanMode,
-    SelectMode,
-    TextMode
-  };
+{
+  NoMode,
+  RotateMode,
+  ZoomInMode,
+  ZoomOutMode,
+  PanMode,
+  SelectMode,
+  TextMode
+};
 
 class Container;
 class FigureWindow;
@@ -68,21 +67,21 @@
   friend class ToolBar;
 
 public:
-  Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  Figure (octave::interpreter& interp,
           const graphics_object& go, FigureWindow *win);
-  ~Figure (void);
+  ~Figure ();
 
   static Figure *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
-  QString fileName (void);
+  QString fileName ();
   void setFileName (const QString& name);
 
-  MouseMode mouseMode (void);
+  MouseMode mouseMode ();
 
-  Container * innerContainer (void);
-  QWidget * menu (void);
+  Container * innerContainer ();
+  QWidget * menu ();
   void updateStatusBar (ColumnVector pt);
 
   void do_connections (const QObject *receiver,
@@ -93,19 +92,19 @@
 
 protected:
   enum UpdateBoundingBoxFlag
-    {
-      UpdateBoundingBoxPosition = 0x1,
-      UpdateBoundingBoxSize     = 0x2,
-      UpdateBoundingBoxAll      = 0x3
-    };
+  {
+    UpdateBoundingBoxPosition = 0x1,
+    UpdateBoundingBoxSize     = 0x2,
+    UpdateBoundingBoxAll      = 0x3
+  };
 
 protected:
-  void redraw (void);
-  void show (void);
+  void redraw ();
+  void show ();
   void print (const QString& file_cmd, const QString& term);
   void update (int pId);
   void updateBoundingBox (bool internal = false, int flags = 0);
-  void beingDeleted (void);
+  void beingDeleted ();
 
 private:
   void showFigureStatusBar (bool visible);
@@ -113,19 +112,19 @@
   void showCustomToolBar (QToolBar *bar, bool visible);
   void set_geometry (QRect r);
 
-  void enableMouseTracking (void);
+  void enableMouseTracking ();
 
 private slots:
   void updateFigureHeight (int delta_h);
-  void updateContainer (void);
+  void updateContainer ();
   void figureWindowShown ();
   void screenChanged (QScreen *);
 
 public slots:
-  uint8NDArray slotGetPixels (void);
+  uint8NDArray slotGetPixels ();
 
 signals:
-  void asyncUpdate (void);
+  void asyncUpdate ();
   void interpreter_event (const octave::fcn_callback& fcn);
   void interpreter_event (const octave::meth_callback& meth);
 
--- a/libgui/graphics/FigureWindow.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/FigureWindow.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,11 +41,11 @@
   setWindowIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)));
 }
 
-FigureWindow::~FigureWindow (void)
+FigureWindow::~FigureWindow ()
 { }
 
 QMenu *
-FigureWindow::createPopupMenu (void)
+FigureWindow::createPopupMenu ()
 {
   // For the time being, disable menubar/toolbar popup menu
   return nullptr;
--- a/libgui/graphics/FigureWindow.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/FigureWindow.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,9 +40,9 @@
 
 public:
   explicit FigureWindow (QWidget *parent = nullptr);
-  ~FigureWindow (void);
+  ~FigureWindow ();
 
-  QMenu * createPopupMenu (void);
+  QMenu * createPopupMenu ();
 
 protected:
   void showEvent(QShowEvent *ev);
--- a/libgui/graphics/GLCanvas.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/GLCanvas.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,66 +37,54 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-#if defined (HAVE_QOPENGLWIDGET)
-#  define OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS
-#else
-#  if defined (Q_OS_WIN32)
-#    define OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS         \
-  QGLFormat (QGL::SampleBuffers | QGL::AlphaChannel     \
-             | QGL::IndirectRendering),
-#  else
-#    define OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS         \
-  QGLFormat (QGL::SampleBuffers | QGL::AlphaChannel),
-#  endif
-#endif
-
-GLCanvas::GLCanvas (octave::base_qobject& oct_qobj,
-                    octave::interpreter& interp,
-                    const graphics_handle& gh, QWidget *xparent)
-: OCTAVE_QT_OPENGL_WIDGET (OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS xparent),
-  Canvas (oct_qobj, interp, gh), m_glfcns (), m_renderer (m_glfcns)
+GLWidget::GLWidget (Canvas& parent_canvas, QWidget *parent)
+  : QOpenGLWidget (parent), m_parent_canvas (parent_canvas),
+    m_glfcns (), m_renderer (m_glfcns)
 {
   setFocusPolicy (Qt::ClickFocus);
   setFocus ();
 }
 
-GLCanvas::~GLCanvas (void)
-{ }
+GLWidget::~GLWidget () { }
 
 void
-GLCanvas::initializeGL (void)
+GLWidget::initializeGL ()
 {
+  // The qopengl_functions object (part of Octave, not Qt) is just
+  // wrapper around QOpenGLFunctions_1_1.  Does initialization really
+  // need to be deferred until initializeGL is called?
+
   m_glfcns.init ();
+
+  // All other resources we need are currently (supposed to be)
+  // managed by the QOpenGLWidget object so there is else nothing to
+  // do here.  If we used custom shader programs, then we would need
+  // to initialize them here.
 }
 
 void
-GLCanvas::draw (const graphics_handle& gh)
+GLWidget::draw (graphics_object go)
 {
-  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
-
-  octave::autolock guard  (gh_mgr.graphics_lock ());
-
-  graphics_object go = gh_mgr.get_object (gh);
-
   if (go)
     {
+      begin_rendering ();
+
+      unwind_action reset_current ([=] () { end_rendering (); });
+
       graphics_object fig = go.get_ancestor ("figure");
       double dpr = fig.get ("__device_pixel_ratio__").double_value ();
       m_renderer.set_viewport (dpr * width (), dpr * height ());
       m_renderer.set_device_pixel_ratio (dpr);
+
       m_renderer.draw (go);
     }
 }
 
 uint8NDArray
-GLCanvas::do_getPixels (const graphics_handle& gh)
+GLWidget::do_getPixels (graphics_object go)
 {
   uint8NDArray retval;
 
-  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
-
-  graphics_object go = gh_mgr.get_object (gh);
-
   if (go && go.isa ("figure"))
     {
       Matrix pos = go.get ("position").matrix_value ();
@@ -104,9 +92,9 @@
       pos(2) *= dpr;
       pos(3) *= dpr;
 
-      // Make sure we have a valid current context
-      if (! begin_rendering ())
-        return retval;
+      begin_rendering ();
+
+      unwind_action reset_current ([=] () { end_rendering (); });
 
       // When the figure is not visible or its size is frozen for printing,
       // we use a framebuffer object to make sure we are rendering on a
@@ -114,101 +102,84 @@
       if (go.get ("visible").string_value () == "off"
           || go.get ("__printing__").string_value () == "on")
         {
-          OCTAVE_QT_OPENGL_FBO
+          QOpenGLFramebufferObject
             fbo (pos(2), pos(3),
-                 OCTAVE_QT_OPENGL_FBO::Attachment::Depth);
+                 QOpenGLFramebufferObject::Attachment::Depth);
 
           fbo.bind ();
 
+          unwind_action release_fbo ([&] () { fbo.release (); });
+
           m_renderer.set_viewport (pos(2), pos(3));
           m_renderer.set_device_pixel_ratio (dpr);
           m_renderer.draw (go);
+
           retval = m_renderer.get_pixels (pos(2), pos(3));
-
-          fbo.release ();
         }
       else
         {
           m_renderer.set_viewport (pos(2), pos(3));
           m_renderer.set_device_pixel_ratio (dpr);
           m_renderer.draw (go);
+
           retval = m_renderer.get_pixels (pos(2), pos(3));
         }
-
-      end_rendering ();
     }
 
   return retval;
 }
 
 void
-GLCanvas::do_print (const QString& file_cmd, const QString& term,
-                    const graphics_handle& handle)
+GLWidget::do_print (const QString& file_cmd, const QString& term,
+                    graphics_object go)
 {
-  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
-
-  octave::autolock guard  (gh_mgr.graphics_lock ());
-
-  graphics_object go = gh_mgr.get_object (handle);
-
   if (go.valid_object ())
     {
+      begin_rendering ();
+
+      unwind_action reset_current ([=] () { end_rendering (); });
+
       graphics_object fig (go.get_ancestor ("figure"));
 
-      // Make sure we have a valid current context
-      if (! begin_rendering ())
-        error ("print: no valid OpenGL offscreen context");
-
-      try
+      if (fig.get ("visible").string_value () == "on")
+        octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
+                             term.toStdString ());
+      else
         {
-          if (fig.get ("visible").string_value () == "on")
-            octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
-                                 term.toStdString ());
-          else
-            {
-              // When the figure is not visible, we use a framebuffer object
-              // to make sure we are rendering on a suitably large frame.
-              Matrix pos = fig.get ("position").matrix_value ();
-              double dpr = fig.get ("__device_pixel_ratio__").double_value ();
-              pos(2) *= dpr;
-              pos(3) *= dpr;
+          // When the figure is not visible, we use a framebuffer object
+          // to make sure we are rendering on a suitably large frame.
+          Matrix pos = fig.get ("position").matrix_value ();
+          double dpr = fig.get ("__device_pixel_ratio__").double_value ();
+          pos(2) *= dpr;
+          pos(3) *= dpr;
 
-              OCTAVE_QT_OPENGL_FBO
-                fbo (pos(2), pos(3),
-                     OCTAVE_QT_OPENGL_FBO::Attachment::Depth);
-
-              fbo.bind ();
+          QOpenGLFramebufferObject
+            fbo (pos(2), pos(3),
+                 QOpenGLFramebufferObject::Attachment::Depth);
 
-              octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
-                                   term.toStdString ());
+          fbo.bind ();
 
-              fbo.release ();
-            }
+          unwind_action release_fbo ([&] () { fbo.release (); });
+
+          octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
+                               term.toStdString ());
         }
-      catch (octave::execution_exception& ee)
-        {
-          emit interpreter_event
-            ([=] (void)
-            {
-              // INTERPRETER THREAD
-              throw ee;
-            });
-        }
-
-      end_rendering ();
     }
 }
 
 graphics_object
-GLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt)
+GLWidget::selectFromAxes (const graphics_object& ax, const QPoint& pt)
 {
-  makeCurrent ();
-
   if (ax)
     {
+      begin_rendering ();
+
+      unwind_action reset_current ([=] () { end_rendering (); });
+
       octave::opengl_selector s (m_glfcns);
 
       s.set_viewport (width (), height ());
+
       return s.select (ax, pt.x (), height () - pt.y (),
                        octave::select_ignore_hittest);
     }
@@ -217,7 +188,7 @@
 }
 
 void
-GLCanvas::drawZoomBox (const QPoint& p1, const QPoint& p2)
+GLWidget::drawZoomBox (const QPoint& p1, const QPoint& p2)
 {
   Matrix overlaycolor (3, 1);
   overlaycolor(0) = 0.45;
@@ -235,68 +206,72 @@
 }
 
 void
-GLCanvas::paintGL (void)
+GLWidget::paintGL ()
 {
-  canvasPaintEvent ();
+  m_parent_canvas.canvasPaintEvent ();
 }
 
 void
-GLCanvas::mouseDoubleClickEvent (QMouseEvent *xevent)
+GLWidget::mouseDoubleClickEvent (QMouseEvent *xevent)
 {
-  canvasMouseDoubleClickEvent (xevent);
+  m_parent_canvas.canvasMouseDoubleClickEvent (xevent);
 }
 
 void
-GLCanvas::mouseMoveEvent (QMouseEvent *xevent)
+GLWidget::mouseMoveEvent (QMouseEvent *xevent)
 {
-  canvasMouseMoveEvent (xevent);
+  m_parent_canvas.canvasMouseMoveEvent (xevent);
 }
 
 void
-GLCanvas::mousePressEvent (QMouseEvent *xevent)
+GLWidget::mousePressEvent (QMouseEvent *xevent)
 {
-  canvasMousePressEvent (xevent);
+  m_parent_canvas.canvasMousePressEvent (xevent);
 }
 
 void
-GLCanvas::mouseReleaseEvent (QMouseEvent *xevent)
+GLWidget::mouseReleaseEvent (QMouseEvent *xevent)
 {
-  canvasMouseReleaseEvent (xevent);
+  m_parent_canvas.canvasMouseReleaseEvent (xevent);
 }
 
 void
-GLCanvas::wheelEvent (QWheelEvent *xevent)
+GLWidget::wheelEvent (QWheelEvent *xevent)
 {
-  canvasWheelEvent (xevent);
+  m_parent_canvas.canvasWheelEvent (xevent);
 }
 
 void
-GLCanvas::keyPressEvent (QKeyEvent *xevent)
+GLWidget::keyPressEvent (QKeyEvent *xevent)
 {
-  if (! canvasKeyPressEvent (xevent))
-    OCTAVE_QT_OPENGL_WIDGET::keyPressEvent (xevent);
+  if (! m_parent_canvas.canvasKeyPressEvent (xevent))
+    QOpenGLWidget::keyPressEvent (xevent);
 }
 
 void
-GLCanvas::keyReleaseEvent (QKeyEvent *xevent)
+GLWidget::keyReleaseEvent (QKeyEvent *xevent)
 {
-  if (! canvasKeyReleaseEvent (xevent))
-    OCTAVE_QT_OPENGL_WIDGET::keyReleaseEvent (xevent);
+  if (! m_parent_canvas.canvasKeyReleaseEvent (xevent))
+    QOpenGLWidget::keyReleaseEvent (xevent);
 }
 
 bool
-GLCanvas::begin_rendering (void)
+GLWidget::begin_rendering ()
 {
   bool retval = true;
 
   if (! isValid ())
     {
-#  if defined (HAVE_QT_OFFSCREEN)
+      // FIXME: Is this really the right way to manager offscreen
+      // rendering for printing?
+
       static bool os_ctx_ok = true;
+
       if (os_ctx_ok && ! m_os_context.isValid ())
         {
           // Try to initialize offscreen context
           m_os_surface.create ();
+
           if (! m_os_context.create ())
             {
               os_ctx_ok = false;
@@ -305,9 +280,6 @@
         }
 
       retval = m_os_context.makeCurrent (&m_os_surface);
-#  else
-      retval = false;
-#  endif
     }
   else
     makeCurrent ();
@@ -316,9 +288,92 @@
 }
 
 void
-GLCanvas::end_rendering (void)
+GLWidget::end_rendering ()
 {
   doneCurrent ();
 }
 
+GLCanvas::GLCanvas (octave::interpreter& interp,
+                    const graphics_handle& gh, QWidget *parent)
+  : Canvas (interp, gh), m_glwidget (new GLWidget (*this, parent))
+{ }
+
+GLCanvas::~GLCanvas ()
+{
+  delete m_glwidget;
+}
+
+void
+GLCanvas::draw (const graphics_handle& gh)
+{
+  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+  octave::autolock guard  (gh_mgr.graphics_lock ());
+
+  graphics_object go = gh_mgr.get_object (gh);
+
+  m_glwidget->draw (go);
+}
+
+uint8NDArray
+GLCanvas::do_getPixels (const graphics_handle& gh)
+{
+  uint8NDArray retval;
+
+  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+  graphics_object go = gh_mgr.get_object (gh);
+
+  return m_glwidget->do_getPixels (go);
+}
+
+void
+GLCanvas::do_print (const QString& file_cmd, const QString& term,
+                    const graphics_handle& handle)
+{
+  gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
+
+  octave::autolock guard  (gh_mgr.graphics_lock ());
+
+  graphics_object go = gh_mgr.get_object (handle);
+
+  try
+    {
+      m_glwidget->do_print (file_cmd, term, go);
+    }
+  catch (octave::execution_exception& ee)
+    {
+      emit interpreter_event
+        ([=] ()
+        {
+          // INTERPRETER THREAD
+          throw ee;
+        });
+    }
+}
+
+graphics_object
+GLCanvas::selectFromAxes (const graphics_object& ax, const QPoint& pt)
+{
+  return m_glwidget->selectFromAxes (ax, pt);
+}
+
+void
+GLCanvas::drawZoomBox (const QPoint& p1, const QPoint& p2)
+{
+  m_glwidget->drawZoomBox (p1, p2);
+}
+
+bool
+GLCanvas::begin_rendering ()
+{
+  return m_glwidget->begin_rendering ();
+}
+
+void
+GLCanvas::end_rendering ()
+{
+  m_glwidget->end_rendering ();
+}
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/GLCanvas.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/GLCanvas.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,23 +26,10 @@
 #if ! defined (octave_GLCanvas_h)
 #define octave_GLCanvas_h 1
 
-#if defined (HAVE_QOPENGLWIDGET)
-#  include <QOpenGLWidget>
-#  define OCTAVE_QT_OPENGL_WIDGET QOpenGLWidget
-#  include <QOpenGLFramebufferObject>
-#  define OCTAVE_QT_OPENGL_FBO QOpenGLFramebufferObject
-#  if defined (HAVE_QT_OFFSCREEN)
-#    include <QOpenGLContext>
-#    include <QOffscreenSurface>
-#  endif
-#elif defined (HAVE_QGLWIDGET)
-#  include <QGLWidget>
-#  define OCTAVE_QT_OPENGL_WIDGET QGLWidget
-#  include <QGLFramebufferObject>
-#  define OCTAVE_QT_OPENGL_FBO QGLFramebufferObject
-#else
-#  error "configuration error: must have <QOpenGLWidget> or <QGLWidget>."
-#endif
+#include <QOffscreenSurface>
+#include <QOpenGLContext>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLWidget>
 
 #include "Canvas.h"
 
@@ -51,19 +38,61 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-}
+class GLWidget : public QOpenGLWidget
+{
+  Q_OBJECT
+
+public:
+
+  GLWidget (Canvas& parent_canvas, QWidget *parent);
+
+  ~GLWidget ();
+
+  void initializeGL ();
+
+  void draw (graphics_object go);
+  uint8NDArray  do_getPixels (graphics_object go);
+  void do_print (const QString& file_cmd, const QString& term,
+                 graphics_object go);
+  void drawZoomBox (const QPoint& p1, const QPoint& p2);
+  void resize (int /* x */, int /* y */,
+               int /* width */, int /* height */) { }
+  graphics_object selectFromAxes (const graphics_object& ax,
+                                  const QPoint& pt);
 
-OCTAVE_BEGIN_NAMESPACE(octave)
+  bool begin_rendering ();
+  void end_rendering ();
+
+protected:
 
-class GLCanvas : public OCTAVE_QT_OPENGL_WIDGET, public Canvas
+  void paintGL ();
+  void mouseDoubleClickEvent (QMouseEvent *event);
+  void mouseMoveEvent (QMouseEvent *event);
+  void mousePressEvent (QMouseEvent *event);
+  void mouseReleaseEvent (QMouseEvent *event);
+  void wheelEvent (QWheelEvent *event);
+  void keyPressEvent (QKeyEvent *event);
+  void keyReleaseEvent (QKeyEvent *event);
+
+private:
+
+  Canvas& m_parent_canvas;
+
+  qopengl_functions m_glfcns;
+  opengl_renderer m_renderer;
+
+  QOpenGLContext m_os_context;
+  QOffscreenSurface m_os_surface;
+};
+
+class GLCanvas : public Canvas
 {
 public:
-  GLCanvas (octave::base_qobject& oct_qobj, octave::interpreter& interp,
-            const graphics_handle& handle, QWidget *parent);
-  ~GLCanvas (void);
 
-  void initializeGL (void);
+  GLCanvas (octave::interpreter& interp, const graphics_handle& handle,
+            QWidget *parent);
+
+  ~GLCanvas ();
 
   void draw (const graphics_handle& handle);
   uint8NDArray  do_getPixels (const graphics_handle& handle);
@@ -74,30 +103,15 @@
                int /* width */, int /* height */) { }
   graphics_object selectFromAxes (const graphics_object& ax,
                                   const QPoint& pt);
-  QWidget * qWidget (void) { return this; }
 
-protected:
-  void paintGL (void);
-  void mouseDoubleClickEvent (QMouseEvent *event);
-  void mouseMoveEvent (QMouseEvent *event);
-  void mousePressEvent (QMouseEvent *event);
-  void mouseReleaseEvent (QMouseEvent *event);
-  void wheelEvent (QWheelEvent *event);
-  void keyPressEvent (QKeyEvent *event);
-  void keyReleaseEvent (QKeyEvent *event);
+  QWidget * qWidget () { return m_glwidget; }
 
 private:
 
-  bool begin_rendering (void);
-  void end_rendering (void);
+  GLWidget *m_glwidget;
 
-  octave::qopengl_functions m_glfcns;
-  octave::opengl_renderer m_renderer;
-
-#  if defined (HAVE_QT_OFFSCREEN)
-  QOpenGLContext m_os_context;
-  QOffscreenSurface m_os_surface;
-#  endif
+  bool begin_rendering ();
+  void end_rendering ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/GenericEventNotify.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/GenericEventNotify.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,8 +39,8 @@
 class GenericEventNotifySender
 {
 public:
-  GenericEventNotifySender (void) : m_receivers () { }
-  virtual ~GenericEventNotifySender (void) = default;
+  GenericEventNotifySender () : m_receivers () { }
+  virtual ~GenericEventNotifySender () = default;
 
   void addReceiver (GenericEventNotifyReceiver *r)
   { m_receivers.insert (r); }
@@ -59,8 +59,8 @@
 class GenericEventNotifyReceiver
 {
 public:
-  GenericEventNotifyReceiver (void) { }
-  virtual ~GenericEventNotifyReceiver (void) = default;
+  GenericEventNotifyReceiver () { }
+  virtual ~GenericEventNotifyReceiver () = default;
 
   virtual bool eventNotifyBefore (QObject *obj, QEvent *evt) = 0;
   virtual void eventNotifyAfter (QObject *obj, QEvent *evt) = 0;
@@ -92,7 +92,7 @@
 { \
 public: \
   T (QWidget *xparent) : B (xparent), GenericEventNotifySender () { } \
-  ~ T (void) = default; \
+  ~ T () = default; \
 \
   bool event (QEvent *evt) \
     { \
--- a/libgui/graphics/KeyMap.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/KeyMap.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 
 namespace KeyMap
 {
-  QMap<int, std::string> makeKeyMapper (void)
+  QMap<int, std::string> makeKeyMapper ()
   {
     QMap<int, std::string> keyMapper;
 
--- a/libgui/graphics/ListBoxControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ListBoxControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,8 +35,6 @@
 #include "ListBoxControl.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static void
@@ -69,8 +67,7 @@
 }
 
 ListBoxControl *
-ListBoxControl::create (octave::base_qobject& oct_qobj,
-                        octave::interpreter& interp,
+ListBoxControl::create (octave::interpreter& interp,
                         const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -80,17 +77,16 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new ListBoxControl (oct_qobj, interp, go,
+        return new ListBoxControl (interp, go,
                                    new QListWidget (container));
     }
 
   return nullptr;
 }
 
-ListBoxControl::ListBoxControl (octave::base_qobject& oct_qobj,
-                                octave::interpreter& interp,
+ListBoxControl::ListBoxControl (octave::interpreter& interp,
                                 const graphics_object& go, QListWidget *list)
-  : BaseControl (oct_qobj, interp, go, list), m_blockCallback (false),
+  : BaseControl (interp, go, list), m_blockCallback (false),
     m_selectionChanged (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
@@ -131,7 +127,7 @@
            this, &ListBoxControl::itemPressed);
 }
 
-ListBoxControl::~ListBoxControl (void)
+ListBoxControl::~ListBoxControl ()
 { }
 
 void
@@ -201,7 +197,7 @@
 }
 
 void
-ListBoxControl::itemSelectionChanged (void)
+ListBoxControl::itemSelectionChanged ()
 {
   if (! m_blockCallback)
     m_selectionChanged = true;
--- a/libgui/graphics/ListBoxControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ListBoxControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class ListBoxControl : public BaseControl
@@ -42,13 +41,12 @@
   Q_OBJECT
 
 public:
-  ListBoxControl (octave::base_qobject& oct_qobj,
-                  octave::interpreter& interp, const graphics_object& go,
+  ListBoxControl (octave::interpreter& interp, const graphics_object& go,
                   QListWidget *list);
-  ~ListBoxControl (void);
+  ~ListBoxControl ();
 
   static ListBoxControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
@@ -57,7 +55,7 @@
   void sendSelectionChange ();
 
 private slots:
-  void itemSelectionChanged (void);
+  void itemSelectionChanged ();
   void itemActivated (const QModelIndex&);
   void itemPressed (QListWidgetItem *);
 
--- a/libgui/graphics/Logger.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Logger.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 Logger *Logger::s_instance = nullptr;
 QMutex *Logger::s_mutex = nullptr;
 
-Logger::Logger (void)
+Logger::Logger ()
   : m_debugEnabled (false)
 {
   QProcessEnvironment pe (QProcessEnvironment::systemEnvironment ());
@@ -49,11 +49,11 @@
     m_debugEnabled = true;
 }
 
-Logger::~Logger (void)
+Logger::~Logger ()
 { }
 
 Logger *
-Logger::instance (void)
+Logger::instance ()
 {
   if (! s_instance)
     {
--- a/libgui/graphics/Logger.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Logger.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,10 +44,10 @@
   static QMutex *s_mutex;
 
 private:
-  Logger (void);
-  ~Logger (void);
+  Logger ();
+  ~Logger ();
 
-  static Logger * instance (void);
+  static Logger * instance ();
 
   void debugV (const char *fmt, va_list arg);
 };
--- a/libgui/graphics/Menu.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Menu.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,8 +36,6 @@
 #include "Menu.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static QKeySequence
@@ -62,7 +60,7 @@
 }
 
 Menu *
-Menu::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Menu::create (octave::interpreter& interp,
               const graphics_object& go)
 {
   Object *parent_obj = parentObject (interp, go);
@@ -72,16 +70,16 @@
       QObject *qObj = parent_obj->qObject ();
 
       if (qObj)
-        return new Menu (oct_qobj, interp, go, new QAction (qObj),
+        return new Menu (interp, go, new QAction (qObj),
                          parent_obj);
     }
 
   return nullptr;
 }
 
-Menu::Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Menu::Menu (octave::interpreter& interp,
             const graphics_object& go, QAction *action, Object *xparent)
-  : Object (oct_qobj, interp, go, action), m_parent (nullptr),
+  : Object (interp, go, action), m_parent (nullptr),
     m_separator (nullptr)
 {
   uimenu::properties& up = properties<uimenu> ();
@@ -127,7 +125,7 @@
               count++;
 
           up.get_property ("position").set
-            (octave_value (static_cast<double> (count)), true, false);
+          (octave_value (static_cast<double> (count)), true, false);
         }
       else
         {
@@ -156,14 +154,14 @@
             updateSiblingPositions ();
           else
             up.get_property ("position").set
-              (octave_value (static_cast<double> (count+1)), true, false);
+            (octave_value (static_cast<double> (count+1)), true, false);
         }
     }
 
   connect (action, &QAction::triggered, this, &Menu::actionTriggered);
 }
 
-Menu::~Menu (void)
+Menu::~Menu ()
 { }
 
 void
@@ -270,7 +268,7 @@
 }
 
 QWidget *
-Menu::menu (void)
+Menu::menu ()
 {
   QAction *action = qWidget<QAction> ();
   QMenu *action_menu = action->menu ();
@@ -287,7 +285,7 @@
 }
 
 void
-Menu::actionTriggered (void)
+Menu::actionTriggered ()
 {
   QAction *action = qWidget<QAction> ();
 
@@ -297,13 +295,13 @@
 }
 
 void
-Menu::actionHovered (void)
+Menu::actionHovered ()
 {
   emit gh_callback_event (m_handle, "menuselectedfcn");
 }
 
 void
-Menu::updateSiblingPositions (void)
+Menu::updateSiblingPositions ()
 {
   if (m_parent)
     {
@@ -326,7 +324,7 @@
                       uimenu::properties& up = Utils::properties<uimenu> (go);
 
                       up.get_property ("position").set
-                        (octave_value (count), true, false);
+                      (octave_value (count), true, false);
                     }
                 }
 
--- a/libgui/graphics/Menu.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Menu.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Menu : public Object, public MenuContainer
@@ -43,27 +42,27 @@
   Q_OBJECT
 
 public:
-  Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  Menu (octave::interpreter& interp,
         const graphics_object& go, QAction *action, Object *parent);
-  ~Menu (void);
+  ~Menu ();
 
   static Menu *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
-  Container * innerContainer (void) { return nullptr; }
+  Container * innerContainer () { return nullptr; }
 
-  QWidget * menu (void);
+  QWidget * menu ();
 
 protected:
   void update (int pId);
 
 private slots:
-  void actionTriggered (void);
-  void actionHovered (void);
+  void actionTriggered ();
+  void actionHovered ();
 
 private:
-  void updateSiblingPositions (void);
+  void updateSiblingPositions ();
 
 private:
   QWidget *m_parent;
--- a/libgui/graphics/MenuContainer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/MenuContainer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,7 @@
 class MenuContainer
 {
 public:
-  virtual QWidget * menu (void) = 0;
+  virtual QWidget * menu () = 0;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/Object.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Object.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,6 @@
 
 #include "Object.h"
 #include "QtHandlesUtils.h"
-#include "octave-qobject.h"
 #include "qt-graphics-toolkit.h"
 
 #include "graphics.h"
@@ -40,10 +39,10 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-Object::Object (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Object::Object (octave::interpreter& interp,
                 const graphics_object& go, QObject *obj)
-: QObject (), m_octave_qobj (oct_qobj), m_interpreter (interp),
-  m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr)
+  : QObject (), m_interpreter (interp), m_go (go),
+    m_handle (go.get_handle ()), m_qobject (nullptr)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -75,11 +74,11 @@
     }
 }
 
-Object::~Object (void)
+Object::~Object ()
 { }
 
 graphics_object
-Object::object (void) const
+Object::object () const
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -102,9 +101,9 @@
 
   switch (pId)
     {
-      // Special case for objects being deleted, as it's very likely
-      // that the graphics_object already has been destroyed when this
-      // is executed (because of the async behavior).
+    // Special case for objects being deleted, as it's very likely
+    // that the graphics_object already has been destroyed when this
+    // is executed (because of the async behavior).
     case base_properties::ID_BEINGDELETED:
       beingDeleted ();
       break;
@@ -117,7 +116,7 @@
 }
 
 void
-Object::slotFinalize (void)
+Object::slotFinalize ()
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -127,7 +126,7 @@
 }
 
 void
-Object::slotRedraw (void)
+Object::slotRedraw ()
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -138,7 +137,7 @@
 }
 
 void
-Object::slotShow (void)
+Object::slotShow ()
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
@@ -164,7 +163,7 @@
 { }
 
 void
-Object::finalize (void)
+Object::finalize ()
 {
   if (m_qobject)
     {
@@ -175,11 +174,11 @@
 }
 
 void
-Object::redraw (void)
+Object::redraw ()
 { }
 
 void
-Object::show (void)
+Object::show ()
 { }
 
 void
@@ -187,7 +186,7 @@
 { }
 
 void
-Object::beingDeleted (void)
+Object::beingDeleted ()
 { }
 
 void Object::objectDestroyed (QObject *obj)
@@ -204,7 +203,7 @@
   octave::autolock guard (gh_mgr.graphics_lock ());
 
   Object *parent = qt_graphics_toolkit::toolkitObject
-    (gh_mgr.get_object (go.get_parent ()));
+                   (gh_mgr.get_object (go.get_parent ()));
 
   return parent;
 }
--- a/libgui/graphics/Object.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Object.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Container;
@@ -48,39 +47,39 @@
   Q_OBJECT
 
 public:
-  Object (octave::base_qobject& qobj, octave::interpreter& interp,
-          const graphics_object& go, QObject *obj = nullptr);
+  Object (octave::interpreter& interp, const graphics_object& go,
+          QObject *obj = nullptr);
 
-  virtual ~Object (void);
+  virtual ~Object ();
 
-  base_properties& properties (void)
+  base_properties& properties ()
   { return object ().get_properties (); }
 
-  const base_properties& properties (void) const
+  const base_properties& properties () const
   { return object ().get_properties (); }
 
   template <typename T>
-  typename T::properties& properties (void)
+  typename T::properties& properties ()
   {
     return dynamic_cast<typename T::properties&>
-      (object ().get_properties ());
+           (object ().get_properties ());
   }
 
   template <typename T>
-  const typename T::properties& properties (void) const
+  const typename T::properties& properties () const
   {
     return dynamic_cast<const typename T::properties&>
-      (object ().get_properties ());
+           (object ().get_properties ());
   }
 
-  graphics_object object (void) const;
+  graphics_object object () const;
 
-  virtual QObject * qObject (void) { return m_qobject; }
+  virtual QObject * qObject () { return m_qobject; }
 
   template <typename T>
-  T * qWidget (void) { return qobject_cast<T *>(qObject ()); }
+  T * qWidget () { return qobject_cast<T *>(qObject ()); }
 
-  virtual Container * innerContainer (void) = 0;
+  virtual Container * innerContainer () = 0;
 
   static Object * fromQObject (QObject *obj);
 
@@ -109,9 +108,9 @@
 
 public slots:
   void slotUpdate (int pId);
-  void slotFinalize (void);
-  void slotRedraw (void);
-  void slotShow (void);
+  void slotFinalize ();
+  void slotRedraw ();
+  void slotShow ();
   void slotPrint (const QString& file_cmd, const QString& term);
 
   void objectDestroyed (QObject *obj = nullptr);
@@ -123,16 +122,15 @@
   void init (QObject *obj, bool callBase = false);
 
   virtual void update (int pId);
-  virtual void finalize (void);
-  virtual void redraw (void);
-  virtual void show (void);
+  virtual void finalize ();
+  virtual void redraw ();
+  virtual void show ();
   virtual void print (const QString& file_cmd, const QString& term);
 
-  virtual void beingDeleted (void);
+  virtual void beingDeleted ();
 
 protected:
 
-  octave::base_qobject& m_octave_qobj;
   octave::interpreter& m_interpreter;
 
   // Store the graphics object directly so that it will exist when
--- a/libgui/graphics/ObjectProxy.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ObjectProxy.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -91,7 +91,7 @@
 }
 
 void
-ObjectProxy::finalize (void)
+ObjectProxy::finalize ()
 {
   if (! m_object)
     error ("ObjectProxy::finalize: invalid GUI Object");
@@ -106,13 +106,13 @@
 }
 
 void
-ObjectProxy::redraw (void)
+ObjectProxy::redraw ()
 {
   emit sendRedraw ();
 }
 
 void
-ObjectProxy::show (void)
+ObjectProxy::show ()
 {
   emit sendShow ();
 }
@@ -135,7 +135,7 @@
 }
 
 uint8NDArray
-ObjectProxy::get_pixels (void)
+ObjectProxy::get_pixels ()
 {
   if (! m_object)
     error ("ObjectProxy::finalize: invalid GUI Object");
--- a/libgui/graphics/ObjectProxy.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ObjectProxy.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,19 +44,19 @@
   ObjectProxy (Object *obj = nullptr);
 
   void update (int pId);
-  void finalize (void);
-  void redraw (void);
-  void show (void);
+  void finalize ();
+  void redraw ();
+  void show ();
   void print (const QString& file_cmd, const QString& term);
-  uint8NDArray get_pixels (void);
+  uint8NDArray get_pixels ();
 
-  Object * object (void) { return m_object; }
+  Object * object () { return m_object; }
   void setObject (Object *obj);
 
 signals:
   void sendUpdate (int pId);
-  void sendRedraw (void);
-  void sendShow (void);
+  void sendRedraw ();
+  void sendShow ();
 
 private:
   void init (Object *obj);
--- a/libgui/graphics/Panel.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Panel.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,8 +39,6 @@
 #include "Panel.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 #include "graphics.h"
 #include "interpreter.h"
 
@@ -92,7 +90,7 @@
 }
 
 Panel *
-Panel::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Panel::create (octave::interpreter& interp,
                const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -102,15 +100,15 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new Panel (oct_qobj, interp, go, new QFrame (container));
+        return new Panel (interp, go, new QFrame (container));
     }
 
   return nullptr;
 }
 
-Panel::Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Panel::Panel (octave::interpreter& interp,
               const graphics_object& go, QFrame *frame)
-  : Object (oct_qobj, interp, go, frame), m_container (nullptr),
+  : Object (interp, go, frame), m_container (nullptr),
     m_title (nullptr), m_blockUpdates (false),
     m_previous_bbox (Matrix (1, 4, 0))
 {
@@ -127,7 +125,7 @@
   setupPalette (pp, pal);
   frame->setPalette (pal);
 
-  m_container = new Container (frame, oct_qobj, interp);
+  m_container = new Container (frame, interp);
   m_container->canvas (m_handle);
 
   connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)),
@@ -168,7 +166,7 @@
     frame->hide ();
 }
 
-Panel::~Panel (void)
+Panel::~Panel ()
 { }
 
 bool
@@ -368,7 +366,7 @@
 }
 
 void
-Panel::redraw (void)
+Panel::redraw ()
 {
   update (uipanel::properties::ID_POSITION);
 
@@ -379,7 +377,7 @@
 }
 
 void
-Panel::updateLayout (void)
+Panel::updateLayout ()
 {
   uipanel::properties& pp = properties<uipanel> ();
   QFrame *frame = qWidget<QFrame> ();
--- a/libgui/graphics/Panel.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Panel.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Container;
@@ -41,16 +40,16 @@
 class Panel : public Object
 {
 public:
-  Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  Panel (octave::interpreter& interp,
          const graphics_object& go, QFrame *frame);
-  ~Panel (void);
+  ~Panel ();
 
-  Container * innerContainer (void) { return m_container; }
+  Container * innerContainer () { return m_container; }
 
   bool eventFilter (QObject *watched, QEvent *event);
 
   static Panel *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
   void do_connections (const QObject *receiver,
@@ -58,10 +57,10 @@
 
 protected:
   void update (int pId);
-  void redraw (void);
+  void redraw ();
 
 private:
-  void updateLayout (void);
+  void updateLayout ();
 
 private:
   Container *m_container;
--- a/libgui/graphics/PopupMenuControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PopupMenuControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,14 +33,10 @@
 #include "PopupMenuControl.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 PopupMenuControl *
-PopupMenuControl::create (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+PopupMenuControl::create (octave::interpreter& interp,
                           const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -50,18 +46,17 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new PopupMenuControl (oct_qobj, interp, go,
+        return new PopupMenuControl (interp, go,
                                      new QComboBox (container));
     }
 
   return nullptr;
 }
 
-PopupMenuControl::PopupMenuControl (octave::base_qobject& oct_qobj,
-                                    octave::interpreter& interp,
+PopupMenuControl::PopupMenuControl (octave::interpreter& interp,
                                     const graphics_object& go,
                                     QComboBox *box)
-  : BaseControl (oct_qobj, interp, go, box), m_blockUpdate (false)
+  : BaseControl (interp, go, box), m_blockUpdate (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -73,7 +68,7 @@
            this, &PopupMenuControl::currentIndexChanged);
 }
 
-PopupMenuControl::~PopupMenuControl (void)
+PopupMenuControl::~PopupMenuControl ()
 { }
 
 void PopupMenuControl::update (int pId)
--- a/libgui/graphics/PopupMenuControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PopupMenuControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class PopupMenuControl : public BaseControl
@@ -40,13 +39,12 @@
   Q_OBJECT
 
 public:
-  PopupMenuControl (octave::base_qobject& oct_qobj,
-                    octave::interpreter& interp, const graphics_object& go,
+  PopupMenuControl (octave::interpreter& interp, const graphics_object& go,
                     QComboBox *box);
-  ~PopupMenuControl (void);
+  ~PopupMenuControl ();
 
   static PopupMenuControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/PushButtonControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PushButtonControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,13 +34,10 @@
 #include "Container.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 PushButtonControl *
-PushButtonControl::create (octave::base_qobject& oct_qobj,
-                           octave::interpreter& interp,
+PushButtonControl::create (octave::interpreter& interp,
                            const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -50,18 +47,17 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new PushButtonControl (oct_qobj, interp, go,
+        return new PushButtonControl (interp, go,
                                       new QPushButton (container));
     }
 
   return nullptr;
 }
 
-PushButtonControl::PushButtonControl (octave::base_qobject& oct_qobj,
-                                      octave::interpreter& interp,
+PushButtonControl::PushButtonControl (octave::interpreter& interp,
                                       const graphics_object& go,
                                       QPushButton *btn)
-  : ButtonControl (oct_qobj, interp, go, btn)
+  : ButtonControl (interp, go, btn)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -73,7 +69,7 @@
   btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));
 }
 
-PushButtonControl::~PushButtonControl (void)
+PushButtonControl::~PushButtonControl ()
 { }
 
 void
--- a/libgui/graphics/PushButtonControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PushButtonControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,19 +32,17 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class PushButtonControl : public ButtonControl
 {
 public:
-  PushButtonControl (octave::base_qobject& oct_qobj,
-                     octave::interpreter& interp, const graphics_object& go,
+  PushButtonControl (octave::interpreter& interp, const graphics_object& go,
                      QPushButton *btn);
-  ~PushButtonControl (void);
+  ~PushButtonControl ();
 
   static PushButtonControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/PushTool.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PushTool.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -31,13 +31,10 @@
 
 #include "ToolBarButton.cc"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 PushTool *
-PushTool::create (octave::base_qobject& oct_qobj,
-                  octave::interpreter& interp, const graphics_object& go)
+PushTool::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
 
@@ -46,22 +43,21 @@
       QWidget *parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-        return new PushTool (oct_qobj, interp, go,
+        return new PushTool (interp, go,
                              new QAction (parentWidget));
     }
 
   return nullptr;
 }
 
-PushTool::PushTool (octave::base_qobject& oct_qobj,
-                    octave::interpreter& interp,
+PushTool::PushTool (octave::interpreter& interp,
                     const graphics_object& go, QAction *action)
-  : ToolBarButton<uipushtool> (oct_qobj, interp, go, action)
+  : ToolBarButton<uipushtool> (interp, go, action)
 {
   connect (action, &QAction::triggered, this, &PushTool::clicked);
 }
 
-PushTool::~PushTool (void)
+PushTool::~PushTool ()
 { }
 
 void
@@ -76,7 +72,7 @@
 }
 
 void
-PushTool::clicked (void)
+PushTool::clicked ()
 {
   emit gh_callback_event (m_handle, "clickedcallback");
 }
--- a/libgui/graphics/PushTool.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/PushTool.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class PushTool : public ToolBarButton<uipushtool>
@@ -38,19 +37,19 @@
   Q_OBJECT
 
 public:
-  PushTool (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  PushTool (octave::interpreter& interp,
             const graphics_object& go, QAction *action);
-  ~PushTool (void);
+  ~PushTool ();
 
   static PushTool *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
   void update (int pId);
 
 private slots:
-  void clicked (void);
+  void clicked ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/QtHandlesUtils.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/QtHandlesUtils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -161,9 +161,13 @@
     Matrix rgb (1, 3);
     double *rgbData = rgb.fortran_vec ();
 
+#if HAVE_QCOLOR_FLOAT_TYPE
+    float tmp[3];
+#else
     // qreal is a typedef for double except for ARM CPU architectures
     // where it is a typedef for float (Bug #44970).
     qreal tmp[3];
+#endif
     c.getRgbF (tmp, tmp+1, tmp+2);
     rgbData[0] = tmp[0]; rgbData[1] = tmp[1]; rgbData[2] = tmp[2];
 
@@ -401,11 +405,8 @@
 
     // We assume a standard mouse with 15 degree steps and Qt returns
     // 1/8 of a degree.
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
     int ydelta = -(event->angleDelta().y ());
-#else
-    int ydelta = -(event->delta ());
-#endif
+
     retval.setfield ("VerticalScrollCount", octave_value (ydelta / 120));
 
     // FIXME: Is there any way to access the number of lines a scroll step
--- a/libgui/graphics/RadioButtonControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/RadioButtonControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,13 +34,10 @@
 #include "Container.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 RadioButtonControl *
-RadioButtonControl::create (octave::base_qobject& oct_qobj,
-                            octave::interpreter& interp,
+RadioButtonControl::create (octave::interpreter& interp,
                             const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -50,18 +47,17 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new RadioButtonControl (oct_qobj, interp, go,
+        return new RadioButtonControl (interp, go,
                                        new QRadioButton (container));
     }
 
   return nullptr;
 }
 
-RadioButtonControl::RadioButtonControl (octave::base_qobject& oct_qobj,
-                                        octave::interpreter& interp,
+RadioButtonControl::RadioButtonControl (octave::interpreter& interp,
                                         const graphics_object& go,
                                         QRadioButton *radio)
-  : ButtonControl (oct_qobj, interp, go, radio)
+  : ButtonControl (interp, go, radio)
 {
   Object *parent = parentObject (interp, go);
   ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);
@@ -76,7 +72,7 @@
     radio->setCheckable (false);
 }
 
-RadioButtonControl::~RadioButtonControl (void)
+RadioButtonControl::~RadioButtonControl ()
 { }
 
 void
--- a/libgui/graphics/RadioButtonControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/RadioButtonControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,19 +32,16 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class RadioButtonControl : public ButtonControl
 {
 public:
-  RadioButtonControl (octave::base_qobject& oct_qobj,
-                      octave::interpreter& interp, const graphics_object& go,
+  RadioButtonControl (octave::interpreter& interp, const graphics_object& go,
                       QRadioButton *box);
-  ~RadioButtonControl (void);
+  ~RadioButtonControl ();
 
-  static RadioButtonControl * create (octave::base_qobject& oct_qobj,
-                                      octave::interpreter& interp,
+  static RadioButtonControl * create (octave::interpreter& interp,
                                       const graphics_object& go);
 
 protected:
--- a/libgui/graphics/SliderControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/SliderControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,8 +33,6 @@
 #include "SliderControl.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 #include "graphics.h"
 #include "interpreter.h"
 
@@ -43,8 +41,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 SliderControl *
-SliderControl::create (octave::base_qobject& oct_qobj,
-                       octave::interpreter& interp,
+SliderControl::create (octave::interpreter& interp,
                        const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -54,18 +51,17 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new SliderControl (oct_qobj, interp, go,
+        return new SliderControl (interp, go,
                                   new QScrollBar (container));
     }
 
   return nullptr;
 }
 
-SliderControl::SliderControl (octave::base_qobject& oct_qobj,
-                              octave::interpreter& interp,
+SliderControl::SliderControl (octave::interpreter& interp,
                               const graphics_object& go,
                               QAbstractSlider *slider)
-  : BaseControl (oct_qobj, interp, go, slider), m_blockUpdates (false)
+  : BaseControl (interp, go, slider), m_blockUpdates (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -93,7 +89,7 @@
            this, &SliderControl::valueChanged);
 }
 
-SliderControl::~SliderControl (void)
+SliderControl::~SliderControl ()
 { }
 
 void
--- a/libgui/graphics/SliderControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/SliderControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class SliderControl : public BaseControl
@@ -40,12 +39,12 @@
   Q_OBJECT
 
 public:
-  SliderControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  SliderControl (octave::interpreter& interp,
                  const graphics_object& go, QAbstractSlider *slider);
-  ~SliderControl (void);
+  ~SliderControl ();
 
   static SliderControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/Table.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Table.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,6 @@
 #include "Table.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 #include "graphics.h"
 #include "interpreter.h"
 #include "oct-map.h"
@@ -74,43 +72,43 @@
   return QSize (w, h);
 }
 
-#define FORMATNUMBER(type)                                              \
-  static QString formatNumber (type d,                                  \
-                               char format = 'f',                       \
-                               int precision = 4)                       \
-  {                                                                     \
-    type ten = 10;                                                      \
-    if (format == 'n')                                                  \
-      {                                                                 \
-        if (d == floor (d))                                             \
-          return QString::number (d, 'g', precision);                   \
-        else if (d <= pow (ten, precision - 1)                          \
-                 && d > pow (ten, 1 - precision))                       \
-          return QString::number (d, 'f', precision);                   \
-        else                                                            \
-          return QString::number (d, 'e', precision);                   \
-      }                                                                 \
-    else if (format == 'F')                                             \
-      {                                                                 \
-        int exponent = floor (log10 (d) / 3) * 3;                       \
-        d *= pow (ten, -exponent);                                      \
-        return QString::number (d, 'f', precision) + "e" +              \
-          (exponent < 0 ? "-" : "+") +                                  \
-          QString ("%1").arg (abs (exponent), 3, 10, QChar ('0'));      \
-      }                                                                 \
-    else if (format == 'E')                                             \
-      {                                                                 \
-        int exponent = floor (log10 (d) / 3) * 3;                       \
-        d *=  pow (ten, -exponent);                                     \
-        return QString::number (d,                                      \
-                                'f',                                    \
-                                precision - floor (log10 (d)) - 1) +    \
-          "e" + (exponent < 0 ? "-" : "+") +                            \
-          QString ("%1").arg (abs (exponent), 3, 10, QChar ('0'));      \
-      }                                                                 \
-    else                                                                \
-      return QString::number (d, format, precision);                    \
-  }
+#define FORMATNUMBER(type)                                                    \
+static QString formatNumber (type d,                                        \
+                             char format = 'f',                             \
+                             int precision = 4)                             \
+{                                                                           \
+  type ten = 10;                                                            \
+  if (format == 'n')                                                        \
+    {                                                                       \
+      if (d == floor (d))                                                   \
+        return QString::number (d, 'g', precision);                         \
+      else if (d <= pow (ten, precision - 1)                                \
+               && d > pow (ten, 1 - precision))                             \
+        return QString::number (d, 'f', precision);                         \
+      else                                                                  \
+        return QString::number (d, 'e', precision);                         \
+    }                                                                       \
+  else if (format == 'F')                                                   \
+    {                                                                       \
+      int exponent = floor (log10 (d) / 3) * 3;                             \
+      d *= pow (ten, -exponent);                                            \
+      return QString::number (d, 'f', precision) + "e" +                    \
+        (exponent < 0 ? "-" : "+") +                                        \
+        QString ("%1").arg (abs (exponent), 3, 10, QChar ('0'));            \
+    }                                                                       \
+  else if (format == 'E')                                                   \
+    {                                                                       \
+      int exponent = floor (log10 (d) / 3) * 3;                             \
+      d *=  pow (ten, -exponent);                                           \
+      return QString::number (d,                                            \
+                              'f',                                          \
+                              precision - floor (log10 (d)) - 1) +          \
+             "e" + (exponent < 0 ? "-" : "+") +                             \
+             QString ("%1").arg (abs (exponent), 3, 10, QChar ('0'));       \
+    }                                                                       \
+  else                                                                      \
+    return QString::number (d, format, precision);                          \
+}
 
 FORMATNUMBER(double)
 FORMATNUMBER(float)
@@ -120,75 +118,75 @@
 static QString formatComplex (Complex c, char format = 'f', int precision = 4)
 {
   return formatNumber (c.real (), format, precision) + " + "
-    + formatNumber (c.imag (), format, precision) + "i";
+         + formatNumber (c.imag (), format, precision) + "i";
 }
 
-#define FORMAT_VALUE_EXCEPT_RAT(f,l)                            \
-  if (format == "numeric" || format == "short")                 \
-    text = formatNumber (value, 'n', f);                        \
-  else if (format == "short f" || format == "shortf")           \
-    text = formatNumber (value, 'f', f);                        \
-  else if (format == "short e" || format == "shorte")           \
-    text = formatNumber (value, 'e', f);                        \
-  else if (format == "short eng" || format == "shorteng")       \
-    text = formatNumber (value, 'F', f);                        \
-  else if (format == "short g" || format == "shortg")           \
-    text = formatNumber (value, 'g', f + 1);                    \
-  else if (format == "long")                                    \
-    text = formatNumber (value, 'n', l);                        \
-  else if (format == "long f" || format == "longf")             \
-    text = formatNumber (value, 'f', l);                        \
-  else if (format == "long e" || format == "longe")             \
-    text = formatNumber (value, 'e', l);                        \
-  else if (format == "long eng" || format == "longeng")         \
-    text = formatNumber (value, 'E', l);                        \
-  else if (format == "long g" || format == "longg")             \
-    text = formatNumber (value, 'g', l + 1);                    \
-  else if (format == "bank")                                    \
-    text = QString::number (value, 'f', 2);                     \
-  else if (format == "+")                                       \
-    if (value > 0)                                              \
-      text = Utils::fromStdString ("+");                        \
-    else if (value < 0)                                         \
-      text = Utils::fromStdString ("-");                        \
-    else                                                        \
-      text = Utils::fromStdString ("");
+#define FORMAT_VALUE_EXCEPT_RAT(f,l)                      \
+if (format == "numeric" || format == "short")           \
+  text = formatNumber (value, 'n', f);                  \
+else if (format == "short f" || format == "shortf")     \
+  text = formatNumber (value, 'f', f);                  \
+else if (format == "short e" || format == "shorte")     \
+  text = formatNumber (value, 'e', f);                  \
+else if (format == "short eng" || format == "shorteng") \
+  text = formatNumber (value, 'F', f);                  \
+else if (format == "short g" || format == "shortg")     \
+  text = formatNumber (value, 'g', f + 1);              \
+else if (format == "long")                              \
+  text = formatNumber (value, 'n', l);                  \
+else if (format == "long f" || format == "longf")       \
+  text = formatNumber (value, 'f', l);                  \
+else if (format == "long e" || format == "longe")       \
+  text = formatNumber (value, 'e', l);                  \
+else if (format == "long eng" || format == "longeng")   \
+  text = formatNumber (value, 'E', l);                  \
+else if (format == "long g" || format == "longg")       \
+  text = formatNumber (value, 'g', l + 1);              \
+else if (format == "bank")                              \
+  text = QString::number (value, 'f', 2);               \
+else if (format == "+")                                 \
+  if (value > 0)                                        \
+    text = Utils::fromStdString ("+");                  \
+  else if (value < 0)                                   \
+    text = Utils::fromStdString ("-");                  \
+  else                                                  \
+    text = Utils::fromStdString ("");
 
 #define FORMAT_VALUE(f,l)                                               \
-  FORMAT_VALUE_EXCEPT_RAT(f,l)                                          \
-  else if (format == "rat")                                             \
-    text = Utils::fromStdString (rational_approx (double (value), 0));  \
-  else                                                                  \
-    {                                                                   \
-      text = formatNumber (value, 'n', f);                              \
-      flag = Qt::AlignLeft ;                                            \
-    }
+FORMAT_VALUE_EXCEPT_RAT(f,l)                                          \
+else if (format == "rat")                                             \
+  text = Utils::fromStdString (rational_approx (double (value), 0));  \
+else                                                                  \
+  {                                                                   \
+    text = formatNumber (value, 'n', f);                              \
+    flag = Qt::AlignLeft ;                                            \
+  }
 
-#define FORMAT_UINT_VALUE()                     \
-  text = QString::number (value);               \
-  if (format == "char"  || format == "popup")   \
-    flag = Qt::AlignLeft;                       \
-  else if (format == "+")                       \
-    {                                           \
-      if (value > 0)                            \
-        text = Utils::fromStdString ("+");      \
-      else                                      \
-        text = Utils::fromStdString ("");       \
-    }
+#define FORMAT_UINT_VALUE()                    \
+text = QString::number (value);              \
+if (format == "char"  || format == "popup")  \
+  flag = Qt::AlignLeft;                      \
+else if (format == "+")                      \
+  {                                          \
+    if (value > 0)                           \
+      text = Utils::fromStdString ("+");     \
+    else                                     \
+      text = Utils::fromStdString ("");      \
+  }
 
-#define FORMAT_INT_VALUE()                      \
-  text = QString::number (value);               \
-  if (format == "char" || format == "popup")    \
-    flag = Qt::AlignLeft ;                      \
-  else if (format == "+")                       \
-    {                                           \
-      if (value > 0)                            \
-        text = Utils::fromStdString ("+");      \
-      else if (value < 0)                       \
-        text = Utils::fromStdString ("-");      \
-      else                                      \
-        text = Utils::fromStdString ("");       \
-    }
+#define FORMAT_INT_VALUE()                     \
+text = QString::number (value);              \
+if (format == "char" || format == "popup")   \
+  flag = Qt::AlignLeft ;                     \
+else if (format == "+")                      \
+  {                                          \
+    if (value > 0)                           \
+      text = Utils::fromStdString ("+");     \
+    else if (value < 0)                      \
+      text = Utils::fromStdString ("-");     \
+    else                                     \
+      text = Utils::fromStdString ("");      \
+  }
 
 static std::pair<Qt::AlignmentFlag, QString>
 qStringValueFor (octave_value val, std::string format = "")
@@ -238,14 +236,14 @@
         }
       else if (format == "rat")
         text = Utils::fromStdString (rational_approx (c.real (), 0)) + " + "
-          + Utils::fromStdString (rational_approx (c.imag (), 0)) + "i";
+               + Utils::fromStdString (rational_approx (c.imag (), 0)) + "i";
       else if (format == "numeric")
         text = QString::number (c.real (), 'g', 5) + " + "
-          + QString::number (c.imag (), 'g', 5) + "i";
+               + QString::number (c.imag (), 'g', 5) + "i";
       else
         {
           text = QString::number (c.real (), 'g', 5) + " + "
-            + QString::number (c.imag (), 'g', 5) + "i";
+                 + QString::number (c.imag (), 'g', 5) + "i";
           flag = Qt::AlignLeft;
         }
     }
@@ -253,52 +251,52 @@
     {
       double value = val.double_value ();
       FORMAT_VALUE(4, 15)
-        }
+    }
   else if (val.is_single_type ())
     {
       float value = val.float_value ();
       FORMAT_VALUE(4, 7)
-        }
+    }
   else if (val.is_int8_type ())
     {
       short int value = val.short_value ();
       FORMAT_INT_VALUE()
-        }
+    }
   else if (val.is_uint8_type ())
     {
       unsigned short int value = val.ushort_value ();
       FORMAT_UINT_VALUE()
-        }
+    }
   else if (val.is_int16_type ())
     {
       int value = val.int_value ();
       FORMAT_INT_VALUE()
-        }
+    }
   else if (val.is_uint16_type ())
     {
       unsigned int value = val.uint_value ();
       FORMAT_UINT_VALUE()
-        }
+    }
   else if (val.is_int32_type ())
     {
       long int value = val.long_value ();
       FORMAT_INT_VALUE()
-        }
+    }
   else if (val.is_uint32_type ())
     {
       unsigned long int value = val.ulong_value ();
       FORMAT_UINT_VALUE()
-        }
+    }
   else if (val.is_int64_type ())
     {
       int64_t value = val.int64_value ();
       FORMAT_INT_VALUE()
-        }
+    }
   else if (val.is_uint64_type ())
     {
       uint64_t value = val.uint64_value ();
       FORMAT_UINT_VALUE()
-        }
+    }
   else if (val.islogical ())
     {
       bool b = val.bool_value ();
@@ -357,31 +355,31 @@
   // Define a macro to help with the conversion of strings to integers
   // FIXME: these will happily integer overflow in the (u)int64 case
   // - this probably doesn't matter.
-#define SCANF_AND_CONVERT(name,ctype,format)            \
-  else if (old_value.is_ ## name ## _type ())           \
-    {                                                   \
-      ctype val;                                        \
-      int n;                                            \
-      const std::string cxx_str = ov.string_value ();   \
-      const char *c_str = cxx_str.c_str ();             \
-      int error = sscanf (c_str, format, &val, &n);     \
-      if (error != 1 || c_str[n])                       \
-        {                                               \
-          val = 0;                                      \
-        }                                               \
-      retval = octave_value ( octave_ ## name (val));   \
-    }
+#define SCANF_AND_CONVERT(name,ctype,format)           \
+else if (old_value.is_ ## name ## _type ())          \
+  {                                                  \
+    ctype val;                                       \
+    int n;                                           \
+    const std::string cxx_str = ov.string_value ();  \
+    const char *c_str = cxx_str.c_str ();            \
+    int error = sscanf (c_str, format, &val, &n);    \
+    if (error != 1 || c_str[n])                      \
+      {                                              \
+        val = 0;                                     \
+      }                                              \
+    retval = octave_value ( octave_ ## name (val));  \
+  }
 
   if (old_value.is_string ())
     retval = ov;
   SCANF_AND_CONVERT(int8, int64_t, "%" PRId64 " %n")
-    SCANF_AND_CONVERT(uint8, uint64_t, "%" PRIu64 " %n")
-    SCANF_AND_CONVERT(int16, int64_t, "%" PRId64 " %n")
-    SCANF_AND_CONVERT(uint16, uint64_t, "%" PRIu64 " %n")
-    SCANF_AND_CONVERT(int32, int64_t, "%" PRId64 " %n")
-    SCANF_AND_CONVERT(uint32, uint64_t, "%" PRIu64 " %n")
-    SCANF_AND_CONVERT(int64, int64_t, "%" PRId64 " %n")
-    SCANF_AND_CONVERT(uint64, uint64_t, "%" PRIu64 " %n")
+  SCANF_AND_CONVERT(uint8, uint64_t, "%" PRIu64 " %n")
+  SCANF_AND_CONVERT(int16, int64_t, "%" PRId64 " %n")
+  SCANF_AND_CONVERT(uint16, uint64_t, "%" PRIu64 " %n")
+  SCANF_AND_CONVERT(int32, int64_t, "%" PRId64 " %n")
+  SCANF_AND_CONVERT(uint32, uint64_t, "%" PRIu64 " %n")
+  SCANF_AND_CONVERT(int64, int64_t, "%" PRId64 " %n")
+  SCANF_AND_CONVERT(uint64, uint64_t, "%" PRIu64 " %n")
 
 #undef SCANF_AND_CONVERT
 
@@ -432,7 +430,7 @@
 }
 
 Table *
-Table::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Table::create (octave::interpreter& interp,
                const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -442,15 +440,15 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new Table (oct_qobj, interp, go, new QTableWidget (container));
+        return new Table (interp, go, new QTableWidget (container));
     }
 
   return 0;
 }
 
-Table::Table (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+Table::Table (octave::interpreter& interp,
               const graphics_object& go, QTableWidget *tableWidget)
-  : Object (oct_qobj, interp, go, tableWidget), m_tableWidget (tableWidget),
+  : Object (interp, go, tableWidget), m_tableWidget (tableWidget),
     m_curData (), m_blockUpdates (false)
 {
   qObject ()->setObjectName ("UItable");
@@ -487,7 +485,7 @@
            this, &Table::itemSelectionChanged);
 }
 
-Table::~Table (void) { }
+Table::~Table () { }
 
 void
 Table::itemSelectionChanged ()
@@ -538,7 +536,6 @@
                              octave_value edit_data,
                              octave_value error)
 {
-
   if (!(properties<uitable> ().get_celleditcallback ().isempty ()))
     {
       Matrix indices = Matrix (1, 2);
@@ -629,8 +626,8 @@
       else
         {
           octave_value old_data = data.is_matrix_type ()
-            ? data.fast_elem_extract (row + col * data.rows ())
-            : octave_value ();
+                                  ? data.fast_elem_extract (row + col * data.rows ())
+                                  : octave_value ();
           data.fast_elem_insert (row + col * data.rows (),
                                  attempt_type_conversion (edit_data, old_data));
 
@@ -877,7 +874,7 @@
 }
 
 void
-Table::redraw (void)
+Table::redraw ()
 {
   update (uitable::properties::ID_POSITION);
 }
@@ -980,7 +977,7 @@
 }
 
 void
-Table::updateColumnname (void)
+Table::updateColumnname ()
 {
   uitable::properties& tp = properties<uitable> ();
 
@@ -1076,7 +1073,7 @@
 }
 
 void
-Table::updateColumnwidth (void)
+Table::updateColumnwidth ()
 {
   uitable::properties& tp = properties<uitable> ();
 
@@ -1304,7 +1301,7 @@
 }
 
 void
-Table::updateEnable (void)
+Table::updateEnable ()
 {
   uitable::properties& tp = properties<uitable> ();
   bool enabled = tp.is_enable ();
@@ -1362,7 +1359,7 @@
 }
 
 void
-Table::updateExtent (void)
+Table::updateExtent ()
 {
   QSize s = realQSizeForTable (m_tableWidget);
   Matrix extent = Matrix (1, 4);
@@ -1375,7 +1372,7 @@
 }
 
 void
-Table::updatePalette (void)
+Table::updatePalette ()
 {
   uitable::properties& tp = properties<uitable> ();
 
@@ -1392,7 +1389,7 @@
 }
 
 void
-Table::updateRowname (void)
+Table::updateRowname ()
 {
   uitable::properties& tp = properties<uitable> ();
 
@@ -1490,7 +1487,7 @@
 }
 
 void
-Table::updateRearrangeableColumns (void)
+Table::updateRearrangeableColumns ()
 {
   uitable::properties& tp = properties<uitable> ();
 
@@ -1628,12 +1625,12 @@
                         {
                           if (col - 1 >= 0)
                             m_tableWidget->setCurrentCell
-                              (m_tableWidget->rowCount () - 1,
-                               col - 1);
+                            (m_tableWidget->rowCount () - 1,
+                             col - 1);
                           else
                             m_tableWidget->setCurrentCell
-                              (m_tableWidget->rowCount () - 1,
-                               m_tableWidget->columnCount () - 1);
+                            (m_tableWidget->rowCount () - 1,
+                             m_tableWidget->columnCount () - 1);
                         }
                     }
                 }
--- a/libgui/graphics/Table.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/Table.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Container;
@@ -44,35 +43,35 @@
   Q_OBJECT
 
 public:
-  Table (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  Table (octave::interpreter& interp,
          const graphics_object& go, QTableWidget *tableWidget);
-  ~Table (void);
+  ~Table ();
 
-  Container * innerContainer (void) { return m_container; }
+  Container * innerContainer () { return m_container; }
 
   bool eventFilter (QObject *watched, QEvent *event);
 
   static Table *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
   void update (int pId);
-  void redraw (void);
-  void updateColumnname (void);
-  void updateColumnwidth (void);
-  void updateData (void);
-  void updateEnable (void);
-  void updateExtent (void);
-  void updatePalette (void);
-  void updateRearrangeableColumns (void);
-  void updateRowname (void);
+  void redraw ();
+  void updateColumnname ();
+  void updateColumnwidth ();
+  void updateData ();
+  void updateEnable ();
+  void updateExtent ();
+  void updatePalette ();
+  void updateRearrangeableColumns ();
+  void updateRowname ();
 
 private slots:
   void itemChanged (QTableWidgetItem *item);
   void comboBoxCurrentIndexChanged (const QString& value);
   void cellClicked (int row, int col);
-  void itemSelectionChanged (void);
+  void itemSelectionChanged ();
 
 private:
   Container *m_container;
--- a/libgui/graphics/TextControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/TextControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,13 +33,10 @@
 #include "TextControl.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 TextControl *
-TextControl::create (octave::base_qobject& oct_qobj,
-                     octave::interpreter& interp, const graphics_object& go)
+TextControl::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
 
@@ -48,16 +45,15 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new TextControl (oct_qobj, interp, go, new QLabel (container));
+        return new TextControl (interp, go, new QLabel (container));
     }
 
   return nullptr;
 }
 
-TextControl::TextControl (octave::base_qobject& oct_qobj,
-                          octave::interpreter& interp,
+TextControl::TextControl (octave::interpreter& interp,
                           const graphics_object& go, QLabel *label)
-  : BaseControl (oct_qobj, interp, go, label)
+  : BaseControl (interp, go, label)
 {
   uicontrol::properties& up = properties<uicontrol> ();
 
@@ -65,11 +61,11 @@
   label->setTextFormat (Qt::PlainText);
   label->setWordWrap (false);
   label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-                                           up.get_verticalalignment ()));
+                       up.get_verticalalignment ()));
   label->setText (Utils::fromStringVector (up.get_string_vector ()).join ("\n"));
 }
 
-TextControl::~TextControl (void)
+TextControl::~TextControl ()
 { }
 
 void
@@ -87,7 +83,7 @@
     case uicontrol::properties::ID_HORIZONTALALIGNMENT:
     case uicontrol::properties::ID_VERTICALALIGNMENT:
       label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-                                               up.get_verticalalignment ()));
+                           up.get_verticalalignment ()));
       break;
 
     default:
--- a/libgui/graphics/TextControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/TextControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,18 +32,17 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class TextControl : public BaseControl
 {
 public:
-  TextControl (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  TextControl (octave::interpreter& interp,
                const graphics_object& go, QLabel *label);
-  ~TextControl (void);
+  ~TextControl ();
 
   static TextControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/TextEdit.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/TextEdit.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,11 +36,11 @@
 
 public:
   TextEdit (QWidget *xparent) : QTextEdit (xparent) { }
-  ~TextEdit (void) = default;
+  ~TextEdit () = default;
 
 signals:
-  void editingFinished (void);
-  void returnPressed (void);
+  void editingFinished ();
+  void returnPressed ();
 
 protected:
   void focusOutEvent (QFocusEvent *event);
--- a/libgui/graphics/ToggleButtonControl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToggleButtonControl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,13 +34,10 @@
 #include "Container.h"
 #include "QtHandlesUtils.h"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 ToggleButtonControl *
-ToggleButtonControl::create (octave::base_qobject& oct_qobj,
-                             octave::interpreter& interp,
+ToggleButtonControl::create (octave::interpreter& interp,
                              const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -50,18 +47,17 @@
       Container *container = parent->innerContainer ();
 
       if (container)
-        return new ToggleButtonControl (oct_qobj, interp, go,
+        return new ToggleButtonControl (interp, go,
                                         new QPushButton (container));
     }
 
   return nullptr;
 }
 
-ToggleButtonControl::ToggleButtonControl (octave::base_qobject& oct_qobj,
-                                          octave::interpreter& interp,
+ToggleButtonControl::ToggleButtonControl (octave::interpreter& interp,
                                           const graphics_object& go,
                                           QPushButton *btn)
-  : ButtonControl (oct_qobj, interp, go, btn)
+  : ButtonControl (interp, go, btn)
 {
   Object *parent = parentObject (interp, go);
   ButtonGroup *btnGroup = dynamic_cast<ButtonGroup *>(parent);
@@ -79,7 +75,7 @@
   btn->setIconSize (QSize (cdat.columns (), cdat.rows ()));
 }
 
-ToggleButtonControl::~ToggleButtonControl (void)
+ToggleButtonControl::~ToggleButtonControl ()
 { }
 
 void
--- a/libgui/graphics/ToggleButtonControl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToggleButtonControl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,19 +32,17 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class ToggleButtonControl : public ButtonControl
 {
 public:
-  ToggleButtonControl (octave::base_qobject& oct_qobj,
-                       octave::interpreter& interp,
+  ToggleButtonControl (octave::interpreter& interp,
                        const graphics_object& go, QPushButton *box);
-  ~ToggleButtonControl (void);
+  ~ToggleButtonControl ();
 
   static ToggleButtonControl *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/ToggleTool.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToggleTool.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -31,13 +31,10 @@
 
 #include "ToolBarButton.cc"
 
-#include "octave-qobject.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 ToggleTool *
-ToggleTool::create (octave::base_qobject& oct_qobj,
-                    octave::interpreter& interp, const graphics_object& go)
+ToggleTool::create (octave::interpreter& interp, const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
 
@@ -46,17 +43,16 @@
       QWidget *parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-        return new ToggleTool (oct_qobj, interp, go,
+        return new ToggleTool (interp, go,
                                new QAction (parentWidget));
     }
 
   return nullptr;
 }
 
-ToggleTool::ToggleTool (octave::base_qobject& oct_qobj,
-                        octave::interpreter& interp,
+ToggleTool::ToggleTool (octave::interpreter& interp,
                         const graphics_object& go, QAction *action)
-  : ToolBarButton<uitoggletool> (oct_qobj, interp, go, action)
+  : ToolBarButton<uitoggletool> (interp, go, action)
 {
   uitoggletool::properties& tp = properties<uitoggletool> ();
 
@@ -66,7 +62,7 @@
   connect (action, &QAction::toggled, this, &ToggleTool::triggered);
 }
 
-ToggleTool::~ToggleTool (void)
+ToggleTool::~ToggleTool ()
 { }
 
 void
--- a/libgui/graphics/ToggleTool.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToggleTool.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class ToggleTool : public ToolBarButton<uitoggletool>
@@ -38,13 +37,13 @@
   Q_OBJECT
 
 public:
-  ToggleTool (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ToggleTool (octave::interpreter& interp,
               const graphics_object& go,
               QAction *action);
-  ~ToggleTool (void);
+  ~ToggleTool ();
 
   static ToggleTool *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
 protected:
--- a/libgui/graphics/ToolBar.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToolBar.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,11 +42,10 @@
 #include "QtHandlesUtils.h"
 
 #include "gui-preferences-global.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-static QIcon makeEmptyIcon (void)
+static QIcon makeEmptyIcon ()
 {
   QPixmap pix (16, 16);
 
@@ -69,7 +68,7 @@
 }
 
 ToolBar *
-ToolBar::create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+ToolBar::create (octave::interpreter& interp,
                  const graphics_object& go)
 {
   Object *parent = parentObject (interp, go);
@@ -79,16 +78,16 @@
       QWidget *parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-        return new ToolBar (oct_qobj, interp, go,
+        return new ToolBar (interp, go,
                             new QToolBar (parentWidget));
     }
 
   return nullptr;
 }
 
-ToolBar::ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+ToolBar::ToolBar (octave::interpreter& interp,
                   const graphics_object& go, QToolBar *bar)
-  : Object (oct_qobj, interp, go, bar), m_empty (nullptr), m_figure (nullptr)
+  : Object (interp, go, bar), m_empty (nullptr), m_figure (nullptr)
 {
   uitoolbar::properties& tp = properties<uitoolbar> ();
 
@@ -109,7 +108,7 @@
   bar->installEventFilter (this);
 }
 
-ToolBar::~ToolBar (void)
+ToolBar::~ToolBar ()
 { }
 
 void
@@ -169,13 +168,13 @@
 }
 
 void
-ToolBar::hideEmpty (void)
+ToolBar::hideEmpty ()
 {
   m_empty->setVisible (false);
 }
 
 void
-ToolBar::beingDeleted (void)
+ToolBar::beingDeleted ()
 {
   if (m_figure)
     {
--- a/libgui/graphics/ToolBar.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToolBar.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Figure;
@@ -43,24 +42,24 @@
   Q_OBJECT
 
 public:
-  ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ToolBar (octave::interpreter& interp,
            const graphics_object& go, QToolBar *bar);
-  ~ToolBar (void);
+  ~ToolBar ();
 
   static ToolBar *
-  create (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  create (octave::interpreter& interp,
           const graphics_object& go);
 
-  Container * innerContainer (void) { return nullptr; }
+  Container * innerContainer () { return nullptr; }
 
   bool eventFilter (QObject *watched, QEvent *event);
 
 protected:
   void update (int pId);
-  void beingDeleted (void);
+  void beingDeleted ();
 
 private slots:
-  void hideEmpty (void);
+  void hideEmpty ();
 
 private:
   QAction *m_empty;
--- a/libgui/graphics/ToolBarButton.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToolBarButton.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,16 +34,14 @@
 
 #include "ToolBarButton.h"
 #include "QtHandlesUtils.h"
-#include "octave-qobject.h"
 #include "gui-preferences-global.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 template <typename T>
-ToolBarButton<T>::ToolBarButton (octave::base_qobject& oct_qobj,
-                                 octave::interpreter& interp,
+ToolBarButton<T>::ToolBarButton (octave::interpreter& interp,
                                  const graphics_object& go, QAction *action)
-: Object (oct_qobj, interp, go, action), m_separator (nullptr)
+  : Object (interp, go, action), m_separator (nullptr)
 {
   typename T::properties& tp = properties<T> ();
 
@@ -81,7 +79,7 @@
 }
 
 template <typename T>
-ToolBarButton<T>::~ToolBarButton (void)
+ToolBarButton<T>::~ToolBarButton ()
 { }
 
 template <typename T>
--- a/libgui/graphics/ToolBarButton.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/ToolBarButton.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class interpreter;
 
 class Container;
@@ -42,11 +41,11 @@
 class ToolBarButton : public Object
 {
 public:
-  ToolBarButton (octave::base_qobject& oct_qobj, octave::interpreter& interp,
+  ToolBarButton (octave::interpreter& interp,
                  const graphics_object& go, QAction *action);
-  ~ToolBarButton (void);
+  ~ToolBarButton ();
 
-  Container * innerContainer (void) { return nullptr; }
+  Container * innerContainer () { return nullptr; }
 
 protected:
   void update (int pId);
--- a/libgui/graphics/annotation-dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/annotation-dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,19 +33,16 @@
 
 #include "gui-settings.h"
 #include "gui-preferences-gp.h"
-#include "octave-qobject.h"
+#include "gui-settings.h"
 
 #include "QtHandlesUtils.h"
 #include "annotation-dialog.h"
 #include "ui-annotation-dialog.h"
 
-using namespace octave;
-
-annotation_dialog::annotation_dialog (octave::base_qobject& oct_qobj,
-                                      QWidget *p, const octave_value_list& pr):
-  QDialog (p), m_octave_qobj (oct_qobj), ui (new Ui::annotation_dialog)
+annotation_dialog::annotation_dialog (QWidget *p, const octave_value_list& pr):
+  QDialog (p), m_ui (new Ui::annotation_dialog)
 {
-  props = pr;
+  m_props = pr;
 
   init ();
 }
@@ -53,36 +50,34 @@
 void
 annotation_dialog::init ()
 {
-  ui->setupUi (this);
+  m_ui->setupUi (this);
 
-  octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  octave::gui_settings *settings = rmgr.get_settings ();
+  octave::gui_settings settings;
 
   // restore last geometry
-  if (settings && settings->contains (gp_annotation_geometry.key))
-    restoreGeometry (settings->value (gp_annotation_geometry).toByteArray ());
+  if (settings.contains (gp_annotation_geometry.settings_key ()))
+    restoreGeometry (settings.byte_array_value (gp_annotation_geometry));
 
   // connect signals
-  connect (ui->button_box, &QDialogButtonBox::clicked,
+  connect (m_ui->button_box, &QDialogButtonBox::clicked,
            this, &annotation_dialog::button_clicked);
 
-  connect (ui->edit_string, &QLineEdit::textChanged,
+  connect (m_ui->edit_string, &QLineEdit::textChanged,
            this, &annotation_dialog::edit_string_changed);
 
-  connect (ui->btn_color, &QPushButton::clicked,
+  connect (m_ui->btn_color, &QPushButton::clicked,
            this, &annotation_dialog::prompt_for_color);
 
-  connect (ui->btn_background_color, &QPushButton::clicked,
+  connect (m_ui->btn_background_color, &QPushButton::clicked,
            this, &annotation_dialog::prompt_for_color);
 
-  connect (ui->btn_edge_color, &QPushButton::clicked,
+  connect (m_ui->btn_edge_color, &QPushButton::clicked,
            this, &annotation_dialog::prompt_for_color);
 
   // set gui element to default values
-  ui->cb_fit_box_to_text->setChecked (true);
-  ui->cb_horz_align->setCurrentIndex (ui->cb_horz_align->findText ("left"));
-  ui->cb_vert_align->setCurrentIndex (ui->cb_vert_align->findText ("middle"));
+  m_ui->cb_fit_box_to_text->setChecked (true);
+  m_ui->cb_horz_align->setCurrentIndex (m_ui->cb_horz_align->findText ("left"));
+  m_ui->cb_vert_align->setCurrentIndex (m_ui->cb_vert_align->findText ("middle"));
 
   // set gui elements to any values from input properties
   set_gui_props ();
@@ -90,7 +85,7 @@
 
 annotation_dialog::~annotation_dialog ()
 {
-  delete ui;
+  delete m_ui;
 }
 
 // internal slots
@@ -99,15 +94,12 @@
 annotation_dialog::button_clicked (QAbstractButton *button)
 {
   QDialogButtonBox::ButtonRole button_role
-    = ui->button_box->buttonRole (button);
+    = m_ui->button_box->buttonRole (button);
 
-  octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  octave::gui_settings *settings = rmgr.get_settings ();
+  octave::gui_settings settings;
 
   // save position
-  if (settings)
-    settings->setValue (gp_annotation_geometry.key, saveGeometry ());
+  settings.setValue (gp_annotation_geometry.settings_key (), saveGeometry ());
 
   if (button_role == QDialogButtonBox::ApplyRole
       || button_role == QDialogButtonBox::AcceptRole)
@@ -123,83 +115,83 @@
 octave_value_list
 annotation_dialog::get_properties () const
 {
-  return props;
+  return m_props;
 }
 
 void
 annotation_dialog::get_gui_props ()
 {
   // set props to the values of the gui
-  props = octave_value_list ();
+  m_props = octave_value_list ();
 
   Matrix position(1, 4);
-  position(0) = ui->sb_x->value ();
-  position(1) = ui->sb_y->value ();
-  position(2) = ui->sb_width->value ();
-  position(3) = ui->sb_height->value ();
-  props.append (ovl ("textbox", position));
+  position(0) = m_ui->sb_x->value ();
+  position(1) = m_ui->sb_y->value ();
+  position(2) = m_ui->sb_width->value ();
+  position(3) = m_ui->sb_height->value ();
+  m_props.append (ovl ("textbox", position));
 
-  props.append (ovl ("string", ui->edit_string->text ().toStdString ()));
-  props.append (ovl ("fitboxtotext",
-                     ui->cb_fit_box_to_text->isChecked () ? "on" : "off"));
+  m_props.append (ovl ("string", m_ui->edit_string->text ().toStdString ()));
+  m_props.append (ovl ("fitboxtotext",
+                     m_ui->cb_fit_box_to_text->isChecked () ? "on" : "off"));
 
   // FIXME: only "normalized" units is selectable, change the code below
   //        once more units are added in the UI.
   std::string tmpstr;
-  props.append (ovl ("units", "normalized"));
+  m_props.append (ovl ("units", "normalized"));
 
-  tmpstr = (ui->cb_horz_align->currentIndex () == 0 ? "left" :
-            (ui->cb_horz_align->currentIndex () == 1 ? "center" : "right"));
-  props.append (ovl ("horizontalalignment", tmpstr));
+  tmpstr = (m_ui->cb_horz_align->currentIndex () == 0 ? "left" :
+            (m_ui->cb_horz_align->currentIndex () == 1 ? "center" : "right"));
+  m_props.append (ovl ("horizontalalignment", tmpstr));
 
-  tmpstr = (ui->cb_vert_align->currentIndex () == 0 ? "top" :
-            (ui->cb_horz_align->currentIndex () == 1 ? "middle" : "bottom"));
-  props.append (ovl ("verticalalignment", tmpstr));
+  tmpstr = (m_ui->cb_vert_align->currentIndex () == 0 ? "top" :
+            (m_ui->cb_horz_align->currentIndex () == 1 ? "middle" : "bottom"));
+  m_props.append (ovl ("verticalalignment", tmpstr));
 
-  tmpstr = ui->cb_font_name->currentText ().toStdString ();
-  props.append (ovl ("fontname", tmpstr));
+  tmpstr = m_ui->cb_font_name->currentText ().toStdString ();
+  m_props.append (ovl ("fontname", tmpstr));
 
-  props.append (ovl ("fontsize", ui->sb_font_size->value ()));
-  props.append (ovl ("fontweight",
-                     ui->cb_font_bold->isChecked () ? "bold" : "normal"));
-  props.append (ovl ("fontangle",
-                     ui->cb_font_italic->isChecked () ? "italic" : "normal"));
-  props.append (ovl ("color", Utils::toRgb (ui->btn_color->palette ().
+  m_props.append (ovl ("fontsize", m_ui->sb_font_size->value ()));
+  m_props.append (ovl ("fontweight",
+                     m_ui->cb_font_bold->isChecked () ? "bold" : "normal"));
+  m_props.append (ovl ("fontangle",
+                     m_ui->cb_font_italic->isChecked () ? "italic" : "normal"));
+  m_props.append (ovl ("color", octave::Utils::toRgb (m_ui->btn_color->palette ().
                      color (QPalette::Button))));
 
   // FIXME: only "none" linestyle is selectable, change the code bellow
   //        once more linestyles are added in the UI.
-  props.append (ovl ("linestyle", "none"));
+  m_props.append (ovl ("linestyle", "none"));
 }
 
 void
 annotation_dialog::set_gui_props ()
 {
   // set the gui to the values from the props
-  octave_idx_type len = props.length ();
+  octave_idx_type len = m_props.length ();
 
   for (int i=0; i<len/2; i++)
     {
-      std::string name = props(i*2).string_value ();
+      std::string name = m_props(i*2).string_value ();
 
       if (name == "textbox")
         {
-          Matrix position = props(2*i +1).matrix_value ();
+          Matrix position = m_props(2*i +1).matrix_value ();
           int nels = position.numel ();
           if (nels >= 2)
             {
-              ui->sb_x->setValue (position(0));
-              ui->sb_y->setValue (position(1));
+              m_ui->sb_x->setValue (position(0));
+              m_ui->sb_y->setValue (position(1));
             }
           else
             {
-              ui->sb_x->setValue (0);
-              ui->sb_y->setValue (0);
+              m_ui->sb_x->setValue (0);
+              m_ui->sb_y->setValue (0);
             }
           if (nels >= 4)
             {
-              ui->sb_width->setValue (position(2));
-              ui->sb_height->setValue (position(3));
+              m_ui->sb_width->setValue (position(2));
+              m_ui->sb_height->setValue (position(3));
             }
           // FIXME: Should there be an else branch here?
           // In annotation.m "textbox" is forced to have a 4-elem vector.
@@ -207,65 +199,65 @@
       else if (name == "string")
         {
           // FIXME: handle if is array of strings ?
-          ui->edit_string->setText (props(2*i +1).string_value ().c_str ());
+          m_ui->edit_string->setText (m_props(2*i +1).string_value ().c_str ());
         }
       else if (name == "fitboxtotext")
         {
-          ui->cb_fit_box_to_text->setChecked (props(1*i +1).string_value () == "on");
+          m_ui->cb_fit_box_to_text->setChecked (m_props(1*i +1).string_value () == "on");
         }
       else if (name == "units")
         {
-          ui->cb_units->setCurrentIndex
-            (ui->cb_units->findText (props(1*i +1).string_value ().c_str ()));
+          m_ui->cb_units->setCurrentIndex
+            (m_ui->cb_units->findText (m_props(1*i +1).string_value ().c_str ()));
         }
       else if (name == "horizontalalignment")
         {
-          ui->cb_horz_align->setCurrentIndex
-            (ui->cb_horz_align->findText (props(1*i +1).string_value ().c_str ()));
+          m_ui->cb_horz_align->setCurrentIndex
+            (m_ui->cb_horz_align->findText (m_props(1*i +1).string_value ().c_str ()));
         }
       else if (name == "verticalalignment")
         {
-          ui->cb_vert_align->setCurrentIndex
-            (ui->cb_vert_align->findText (props(1*i +1).string_value ().c_str ()));
+          m_ui->cb_vert_align->setCurrentIndex
+            (m_ui->cb_vert_align->findText (m_props(1*i +1).string_value ().c_str ()));
         }
       else if (name == "fontname")
         {
-          ui->cb_vert_align->setCurrentIndex
-            (ui->cb_font_name->findText (props(1*i +1).string_value ().c_str ()));
+          m_ui->cb_vert_align->setCurrentIndex
+            (m_ui->cb_font_name->findText (m_props(1*i +1).string_value ().c_str ()));
         }
       else if (name == "fontsize")
         {
-          ui->sb_font_size->setValue (props(1*i +1).float_value ());
+          m_ui->sb_font_size->setValue (m_props(1*i +1).float_value ());
         }
       else if (name == "fontweight")
         {
-          ui->cb_font_bold->setChecked (props(1*i +1).string_value () == "bold");
+          m_ui->cb_font_bold->setChecked (m_props(1*i +1).string_value () == "bold");
         }
       else if (name == "fontangle")
         {
-          ui->cb_font_italic->setChecked (props(1*i +1).string_value () == "italic");
+          m_ui->cb_font_italic->setChecked (m_props(1*i +1).string_value () == "italic");
         }
       else if (name == "color")
         {
           QColor color;
-          if (props(1*i +1).is_matrix_type ())
-            color = Utils::fromRgb (props(2*i +1).matrix_value ());
+          if (m_props(1*i +1).is_matrix_type ())
+            color = octave::Utils::fromRgb (m_props(2*i +1).matrix_value ());
           else
-            color.setNamedColor (props(2*i +1).string_value ().c_str ());
+            color.setNamedColor (m_props(2*i +1).string_value ().c_str ());
 
           if (color.isValid ())
-            ui->btn_color->setPalette (QPalette (color));
+            m_ui->btn_color->setPalette (QPalette (color));
         }
 
     }
 
-  edit_string_changed (ui->edit_string->text ());
+  edit_string_changed (m_ui->edit_string->text ());
 }
 
 void
 annotation_dialog::edit_string_changed (const QString& str)
 {
-  ui->button_box->button (QDialogButtonBox::Ok)->setEnabled (str.length () > 0);
+  m_ui->button_box->button (QDialogButtonBox::Ok)->setEnabled (str.length () > 0);
 }
 
 void
--- a/libgui/graphics/annotation-dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/annotation-dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,20 +32,16 @@
 
 #include "ovl.h"
 
-OCTAVE_BEGIN_NAMESPACE(octave)
-class base_qobject;
-OCTAVE_END_NAMESPACE(octave)
-
-OCTAVE_BEGIN_NAMESPACE(Ui)
-class annotation_dialog;
-OCTAVE_END_NAMESPACE(Ui)
+namespace Ui
+{
+  class annotation_dialog;
+}
 
 class annotation_dialog : public QDialog
 {
   Q_OBJECT
 public:
-  annotation_dialog (octave::base_qobject& oct_qobj, QWidget *parent,
-                     const octave_value_list& pr);
+  annotation_dialog (QWidget *parent, const octave_value_list& pr);
   ~annotation_dialog ();
 
   octave_value_list get_properties () const;
@@ -62,9 +58,8 @@
   void get_gui_props ();
   void set_gui_props ();
 
-  octave::base_qobject& m_octave_qobj;
-  Ui::annotation_dialog *ui;
-  octave_value_list props;
+  Ui::annotation_dialog *m_ui;
+  octave_value_list m_props;
 };
 
 #endif
--- a/libgui/graphics/gl-select.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/gl-select.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 void
-opengl_selector::apply_pick_matrix (void)
+opengl_selector::apply_pick_matrix ()
 {
   GLdouble p_matrix[16];
 
@@ -47,12 +47,12 @@
 
   Matrix viewport = get_viewport_scaled ();
 
-  if (size > 0)
+  if (m_size > 0)
     {
-      m_glfcns.glTranslatef ((viewport(2) - 2 * (xp - viewport(0))) / size,
-                             (viewport(3) - 2 * (yp - viewport(1))) / size, 0);
+      m_glfcns.glTranslatef ((viewport(2) - 2 * (m_xp - viewport(0))) / m_size,
+                             (viewport(3) - 2 * (m_yp - viewport(1))) / m_size, 0);
 
-      m_glfcns.glScalef (viewport(2) / size, viewport(3) / size, 1.0);
+      m_glfcns.glScalef (viewport(2) / m_size, viewport(3) / m_size, 1.0);
     }
 
   m_glfcns.glMultMatrixd (p_matrix);
@@ -81,8 +81,8 @@
   m_glfcns.glEnable (GL_DEPTH_TEST);
   m_glfcns.glDepthFunc (GL_LEQUAL);
 
-  xp = x;
-  yp = y;
+  m_xp = x;
+  m_yp = y;
 
   GLuint select_buffer[BUFFER_SIZE];
 
@@ -90,7 +90,7 @@
   m_glfcns.glRenderMode (GL_SELECT);
   m_glfcns.glInitNames ();
 
-  object_map.clear ();
+  m_object_map.clear ();
 
   draw (ax);
 
@@ -117,7 +117,7 @@
 
               if ((flags & select_ignore_hittest) == 0)
                 {
-                  graphics_object go = object_map[name];
+                  graphics_object go = m_object_map[name];
 
                   if (! go.get_properties ().is_hittest ())
                     candidate = false;
@@ -136,12 +136,12 @@
         }
 
       if (current_name != 0xffffffff)
-        obj = object_map[current_name];
+        obj = m_object_map[current_name];
     }
   else if (hits < 0)
     warning ("opengl_selector::select: selection buffer overflow");
 
-  object_map.clear ();
+  m_object_map.clear ();
 
   return obj;
 }
@@ -149,9 +149,9 @@
 void
 opengl_selector::draw (const graphics_object& go, bool toplevel)
 {
-  GLuint name = object_map.size ();
+  GLuint name = m_object_map.size ();
 
-  object_map[name] = go;
+  m_object_map[name] = go;
   m_glfcns.glPushName (name);
   set_selecting (true);
   opengl_renderer::draw (go, toplevel);
--- a/libgui/graphics/gl-select.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/gl-select.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,10 +44,10 @@
 {
 public:
   opengl_selector (opengl_functions& glfcns)
-    : opengl_renderer (glfcns), size (5)
+    : opengl_renderer (glfcns), m_size (5)
   { }
 
-  virtual ~opengl_selector (void) = default;
+  virtual ~opengl_selector () = default;
 
   graphics_object select (const graphics_object& ax, int x, int y,
                           int flags = 0);
@@ -61,27 +61,27 @@
 
   virtual void setup_opengl_transformation (const axes::properties& props);
 
-  virtual void init_marker (const std::string& m, double size, float width);
+  virtual void init_marker (const std::string& m, double m_size, float width);
 
   virtual Matrix render_text (const std::string& txt,
                               double x, double y, double z,
                               int halign, int valign, double rotation = 0.0);
 
 private:
-  void apply_pick_matrix (void);
+  void apply_pick_matrix ();
 
   void fake_text (double x, double y, double z, const Matrix& bbox,
                   bool use_scale = true);
 
 private:
   // The mouse coordinate of the selection/picking point
-  int xp, yp;
+  int m_xp, m_yp;
 
   // The size (in pixels) of the picking window
-  int size;
+  int m_size;
 
   // The OpenGL name mapping
-  std::map<GLuint, graphics_object> object_map;
+  std::map<GLuint, graphics_object> m_object_map;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -1,5 +1,3 @@
-if AMCOND_BUILD_QT_GRAPHICS
-
 OCTAVE_GUI_GRAPHICS_MOC = \
   %reldir%/moc-ButtonControl.cc \
   %reldir%/moc-ButtonGroup.cc \
@@ -9,6 +7,7 @@
   %reldir%/moc-EditControl.cc \
   %reldir%/moc-Figure.cc \
   %reldir%/moc-FigureWindow.cc \
+  %reldir%/moc-GLCanvas.cc \
   %reldir%/moc-ListBoxControl.cc \
   %reldir%/moc-Menu.cc \
   %reldir%/moc-Object.cc \
@@ -128,7 +127,7 @@
   $(FONTCONFIG_CPPFLAGS) \
   $(HDF5_CPPFLAGS) \
   @OCTGUI_DLL_DEFS@ \
-  @QT_OPENGL_CPPFLAGS@ \
+  @QT_CPPFLAGS@ \
   -Ilibgui/graphics -I$(srcdir)/libgui/graphics \
   -Ilibgui/src -I$(srcdir)/libgui/src \
   -Iliboctave \
@@ -153,5 +152,3 @@
   $(libgraphics_MOC) \
   $(libgraphics_MOC_H) \
   $(libgraphics_UI_H)
-
-endif
--- a/libgui/graphics/qopengl-functions.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/qopengl-functions.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  qopengl_functions (void)
+  qopengl_functions ()
 #if defined (HAVE_QOPENGLFUNCTIONS_1_1)
     : m_glfcns ()
 #endif
@@ -52,9 +52,9 @@
 
   qopengl_functions& operator = (const qopengl_functions&) = default;
 
-  ~qopengl_functions (void) = default;
+  ~qopengl_functions () = default;
 
-  void init (void)
+  void init ()
   {
 #if defined (HAVE_QOPENGLFUNCTIONS_1_1)
     m_glfcns.initializeOpenGLFunctions ();
@@ -176,17 +176,17 @@
     m_glfcns.glEnable (cap);
   }
 
-  void glEndList (void)
+  void glEndList ()
   {
     m_glfcns.glEndList ();
   }
 
-  void glEnd (void)
+  void glEnd ()
   {
     m_glfcns.glEnd ();
   }
 
-  void glFinish (void)
+  void glFinish ()
   {
     m_glfcns.glFinish ();
   }
@@ -211,7 +211,7 @@
     m_glfcns.glGetDoublev (pname, data);
   }
 
-  GLenum glGetError (void)
+  GLenum glGetError ()
   {
     return m_glfcns.glGetError ();
   }
@@ -236,7 +236,7 @@
     m_glfcns.glHint (target, mode);
   }
 
-  void glInitNames (void)
+  void glInitNames ()
   {
     m_glfcns.glInitNames ();
   }
@@ -261,7 +261,7 @@
     m_glfcns.glLineWidth (width);
   }
 
-  void glLoadIdentity (void)
+  void glLoadIdentity ()
   {
     m_glfcns.glLoadIdentity ();
   }
@@ -327,17 +327,17 @@
     m_glfcns.glPolygonOffset (factor, units);
   }
 
-  void glPopAttrib (void)
+  void glPopAttrib ()
   {
     m_glfcns.glPopAttrib ();
   }
 
-  void glPopMatrix (void)
+  void glPopMatrix ()
   {
     m_glfcns.glPopMatrix ();
   }
 
-  void glPopName (void)
+  void glPopName ()
   {
     m_glfcns.glPopName ();
   }
@@ -347,7 +347,7 @@
     m_glfcns.glPushAttrib (mask);
   }
 
-  void glPushMatrix (void)
+  void glPushMatrix ()
   {
     m_glfcns.glPushMatrix ();
   }
--- a/libgui/graphics/qt-graphics-toolkit.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,8 +57,6 @@
 #include "ToolBar.h"
 #include "qt-graphics-toolkit.h"
 
-#include "octave-qobject.h"
-
 #include "event-manager.h"
 #include "graphics.h"
 #include "interpreter.h"
@@ -97,10 +95,8 @@
   return "";
 }
 
-qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp,
-                                          octave::base_qobject& oct_qobj)
-  : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp),
-    m_octave_qobj (oct_qobj)
+qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp)
+  : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp)
 {
   // Implemented with a signal/slot connection in order to properly
   // cross from the interpreter thread (where requests to create
@@ -411,47 +407,47 @@
   Object *obj = nullptr;
 
   if (go.isa ("figure"))
-    obj = Figure::create (m_octave_qobj, m_interpreter, go);
+    obj = Figure::create (m_interpreter, go);
   else if (go.isa ("uicontrol"))
     {
       uicontrol::properties& up =
         Utils::properties<uicontrol> (go);
 
       if (up.style_is ("pushbutton"))
-        obj = PushButtonControl::create (m_octave_qobj, m_interpreter, go);
+        obj = PushButtonControl::create (m_interpreter, go);
       else if (up.style_is ("edit"))
-        obj = EditControl::create (m_octave_qobj, m_interpreter, go);
+        obj = EditControl::create (m_interpreter, go);
       else if (up.style_is ("checkbox"))
-        obj = CheckBoxControl::create (m_octave_qobj, m_interpreter, go);
+        obj = CheckBoxControl::create (m_interpreter, go);
       else if (up.style_is ("radiobutton"))
-        obj = RadioButtonControl::create (m_octave_qobj, m_interpreter, go);
+        obj = RadioButtonControl::create (m_interpreter, go);
       else if (up.style_is ("togglebutton"))
-        obj = ToggleButtonControl::create (m_octave_qobj, m_interpreter, go);
+        obj = ToggleButtonControl::create (m_interpreter, go);
       else if (up.style_is ("text"))
-        obj = TextControl::create (m_octave_qobj, m_interpreter, go);
+        obj = TextControl::create (m_interpreter, go);
       else if (up.style_is ("popupmenu"))
-        obj = PopupMenuControl::create (m_octave_qobj, m_interpreter, go);
+        obj = PopupMenuControl::create (m_interpreter, go);
       else if (up.style_is ("slider"))
-        obj = SliderControl::create (m_octave_qobj, m_interpreter, go);
+        obj = SliderControl::create (m_interpreter, go);
       else if (up.style_is ("listbox"))
-        obj = ListBoxControl::create (m_octave_qobj, m_interpreter, go);
+        obj = ListBoxControl::create (m_interpreter, go);
     }
   else if (go.isa ("uibuttongroup"))
-    obj = ButtonGroup::create (m_octave_qobj, m_interpreter, go);
+    obj = ButtonGroup::create (m_interpreter, go);
   else if (go.isa ("uipanel"))
-    obj = Panel::create (m_octave_qobj, m_interpreter, go);
+    obj = Panel::create (m_interpreter, go);
   else if (go.isa ("uimenu"))
-    obj = Menu::create (m_octave_qobj, m_interpreter, go);
+    obj = Menu::create (m_interpreter, go);
   else if (go.isa ("uicontextmenu"))
-    obj = ContextMenu::create (m_octave_qobj, m_interpreter, go);
+    obj = ContextMenu::create (m_interpreter, go);
   else if (go.isa ("uitable"))
-    obj = Table::create (m_octave_qobj, m_interpreter, go);
+    obj = Table::create (m_interpreter, go);
   else if (go.isa ("uitoolbar"))
-    obj = ToolBar::create (m_octave_qobj, m_interpreter, go);
+    obj = ToolBar::create (m_interpreter, go);
   else if (go.isa ("uipushtool"))
-    obj = PushTool::create (m_octave_qobj, m_interpreter, go);
+    obj = PushTool::create (m_interpreter, go);
   else if (go.isa ("uitoggletool"))
-    obj = ToggleTool::create (m_octave_qobj, m_interpreter, go);
+    obj = ToggleTool::create (m_interpreter, go);
   else
     qWarning ("qt_graphics_toolkit::create_object: unsupported type '%s'",
               go.type ().c_str ());
--- a/libgui/graphics/qt-graphics-toolkit.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/graphics/qt-graphics-toolkit.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,6 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 class interpreter;
-class base_qobject;
 
 class Object;
 class ObjectProxy;
@@ -46,10 +45,9 @@
 
 public:
 
-  qt_graphics_toolkit (octave::interpreter& interp,
-                       octave::base_qobject& oct_qobj);
+  qt_graphics_toolkit (octave::interpreter& interp);
 
-  ~qt_graphics_toolkit (void) = default;
+  ~qt_graphics_toolkit () = default;
 
   // The interpreter may call graphics toolkit functions that we
   // implement here.  The Qt GUI that manages these actions runs in a
@@ -66,7 +64,7 @@
   // we should ensure that they are correctly handling the connection
   // between the interpreter and GUI threads.
 
-  bool is_valid (void) const { return true; }
+  bool is_valid () const { return true; }
 
   void redraw_figure (const graphics_object& h) const;
 
@@ -119,8 +117,6 @@
 private:
 
   octave::interpreter& m_interpreter;
-
-  octave::base_qobject& m_octave_qobj;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/languages/build_ts/octave-qt/qcolordialog.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qcolordialog.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -406,17 +406,6 @@
         if(curRow < numRows()-1)
             setCurrent(curRow + 1, curCol);
         break;
-#if 0
-    // bad idea that shouldn't have been implemented; very counterintuitive
-    case Qt::Key_Return:
-    case Qt::Key_Enter:
-        /*
-          ignore the key, so that the dialog get it, but still select
-          the current row/col
-        */
-        e->ignore();
-        // fallthrough intended
-#endif
     case Qt::Key_Space:
         setSelected(curRow, curCol);
         break;
--- a/libgui/languages/build_ts/octave-qt/qdialog.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qdialog.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -559,7 +559,7 @@
     QEventLoop eventLoop;
     d->eventLoop = &eventLoop;
     QPointer<QDialog> guard = this;
-    (void) eventLoop.exec(QEventLoop::DialogExec);
+    () eventLoop.exec(QEventLoop::DialogExec);
     if (guard.isNull())
         return QDialog::Rejected;
     d->eventLoop = 0;
--- a/libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -234,18 +234,6 @@
     info.displayType = m_iconProvider->type(fileInfo);
 #ifndef QT_NO_FILESYSTEMWATCHER
     // ### Not ready to listen all modifications
-    #if 0
-        // Enable the next two commented out lines to get updates when the file sizes change...
-        if (!fileInfo.exists() && !fileInfo.isSymLink()) {
-            info.size = -1;
-            //watcher->removePath(fileInfo.absoluteFilePath());
-        } else {
-            if (!fileInfo.absoluteFilePath().isEmpty() && fileInfo.exists() && fileInfo.isReadable()
-                && !watcher->files().contains(fileInfo.absoluteFilePath())) {
-                //watcher->addPath(fileInfo.absoluteFilePath());
-            }
-        }
-    #endif
 #endif
 
     if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) {
--- a/libgui/languages/build_ts/octave-qt/qfontdialog.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qfontdialog.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -463,7 +463,7 @@
          k->key() == Qt::Key_PageDown)) {
 
             int ci = d->sizeList->currentItem();
-            (void)QApplication::sendEvent(d->sizeList, k);
+            ()QApplication::sendEvent(d->sizeList, k);
 
             if (ci != d->sizeList->currentItem()
                     && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this))
--- a/libgui/languages/build_ts/octave-qt/qmessagebox.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qmessagebox.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -1717,12 +1717,7 @@
     // should perhaps be a style hint
 #ifdef Q_WS_MAC
     oldMsgBox = msgBox;
-#if 0
-    // ### doesn't work until close button is enabled in title bar
-    msgBox->d_func()->autoAddOkButton = false;
-#else
     msgBox->d_func()->buttonBox->setCenterButtons(true);
-#endif
     msgBox->show();
 #else
     msgBox->exec();
@@ -1807,12 +1802,7 @@
     // should perhaps be a style hint
 #ifdef Q_WS_MAC
     oldMsgBox = msgBox;
-#if 0
-    // ### doesn't work until close button is enabled in title bar
-    msgBox->d_func()->autoAddOkButton = false;
-#else
     msgBox->d_func()->buttonBox->setCenterButtons(true);
-#endif
     msgBox->show();
 #else
     msgBox->exec();
--- a/libgui/languages/build_ts/octave-qt/qprintdialog_win.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/languages/build_ts/octave-qt/qprintdialog_win.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -307,7 +307,7 @@
     if (!warnIfNotNative(d->printer))
         return;
 
-    (void)d->openWindowsPrintDialogModally();
+    ()d->openWindowsPrintDialogModally();
     return;
 }
 
--- a/libgui/liboctgui-build-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/liboctgui-build-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,6 +30,6 @@
 
 #include <string>
 
-extern OCTGUI_API std::string liboctgui_hg_id (void);
+extern OCTGUI_API std::string liboctgui_hg_id ();
 
 #endif
--- a/libgui/liboctgui-build-info.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/liboctgui-build-info.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 #include "liboctgui-build-info.h"
 
 std::string
-liboctgui_hg_id (void)
+liboctgui_hg_id ()
 {
   return "%OCTAVE_HG_ID%";
 }
--- a/libgui/qterminal/libqterminal/QTerminal.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/QTerminal.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -25,21 +25,24 @@
 #  include "config.h"
 #endif
 
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QColor>
 #include <QKeySequence>
-#include <QWidget>
-#include <QStringList>
-#include <QColor>
 #include <QList>
 #include <QMenu>
-#include <QClipboard>
-#include <QApplication>
-#include <QAction>
+#include <QRegularExpression>
+#include <QStringList>
+#include <QWidget>
 
 #include "gui-preferences-global.h"
 #include "gui-preferences-cs.h"
 #include "gui-preferences-sc.h"
-#include "octave-qobject.h"
-#include "resource-manager.h"
+#include "gui-settings.h"
+
+#include "builtin-defun-decls.h"
+#include "interpreter.h"
 
 #include "QTerminal.h"
 #if defined (Q_OS_WIN32)
@@ -49,21 +52,18 @@
 #endif
 
 QTerminal *
-QTerminal::create (octave::base_qobject& oct_qobj, QWidget *p)
+QTerminal::create (QWidget *p)
 {
 #if defined (Q_OS_WIN32)
-  QTerminal *terminal = new QWinTerminalImpl (oct_qobj, p);
+  QTerminal *terminal = new QWinTerminalImpl (p);
 #else
-  QTerminal *terminal = new QUnixTerminalImpl (oct_qobj, p);
+  QTerminal *terminal = new QUnixTerminalImpl (p);
 #endif
 
   // FIXME: this function should probably be called from or part of the
-  // QTerminal constructor, but I think that would mean some major
-  // surgery because then the constructor for QTerminal and the derived
-  // Unix- and Windows-specific versions would need access to the
-  // base_qobject object, or the design would have to change significantly.
+  // QTerminal constructor?
 
-  terminal->construct (oct_qobj);
+  terminal->construct ();
 
   return terminal;
 }
@@ -86,14 +86,13 @@
     // detecting links and error messages yet
     if (has_selected_text)
       {
-        QRegExp file ("(?:[ \\t]+)(\\S+) at line (\\d+) column (?:\\d+)");
-
-        int pos = file.indexIn (selected_text);
+        QRegularExpression file {"(?:[ \\t]+)(\\S+) at line (\\d+) column (?:\\d+)"};
+        QRegularExpressionMatch match = file.match (selected_text);
 
-        if (pos > -1)
+        if (match.hasMatch ())
           {
-            QString file_name = file.cap (1);
-            QString line = file.cap (2);
+            QString file_name = match.captured (1);
+            QString line = match.captured (2);
 
             _edit_action->setVisible (true);
             _edit_action->setText (tr ("Edit %1 at line %2")
@@ -108,13 +107,12 @@
 
     if (has_selected_text)
       {
-        QRegExp expr (".*\b*(\\w+)\b*.*");
-
-        int pos = expr.indexIn (selected_text);
+        QRegularExpression expr {".*\b*(\\w+)\b*.*"};
+        QRegularExpressionMatch match = expr.match (selected_text);
 
-        if (pos > -1)
+        if (match.hasMatch ())
           {
-            QString expr_found = expr.cap (1);
+            QString expr_found = match.captured (1);
 
             m_edit_selected_action->setVisible (true);
             m_edit_selected_action->setText (tr ("Edit %1").arg (expr_found));
@@ -154,7 +152,7 @@
 void
 QTerminal::run_selection ()
 {
-  QStringList commands = selectedText ().split (QRegExp ("[\r\n]"),
+  QStringList commands = selectedText ().split (QRegularExpression {"[\r\n]"},
 #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
                                                 Qt::SkipEmptyParts);
 #else
@@ -194,37 +192,43 @@
 // slot for showing documentation on selected epxression
 void QTerminal::doc_on_expression ()
 {
-  QString expr = m_doc_selected_action->data ().toString ();
-  m_octave_qobj.show_documentation_window (expr);
+  std::string expr = m_doc_selected_action->data ().toString ().toStdString ();
+
+  emit interpreter_event
+    ([=] (octave::interpreter& interp)
+     {
+       // INTERPRETER THREAD
+
+       octave::F__event_manager_show_documentation__ (interp, ovl (expr));
+     });
 }
 
 void
-QTerminal::notice_settings (const gui_settings *settings)
+QTerminal::notice_settings (void)
 {
-  if (! settings)
-    return;
+  octave::gui_settings settings;
 
   // Set terminal font:
   QFont term_font = QFont ();
   term_font.setStyleHint (QFont::TypeWriter);
-  QString default_font = settings->value (global_mono_font).toString ();
+  QString default_font = settings.string_value (global_mono_font);
   term_font.setFamily
-    (settings->value (cs_font.key, default_font).toString ());
+    (settings.value (cs_font.settings_key (), default_font).toString ());
   term_font.setPointSize
-    (settings->value (cs_font_size).toInt ());
+    (settings.int_value (cs_font_size));
   setTerminalFont (term_font);
 
   QFontMetrics metrics (term_font);
   setMinimumSize (metrics.maxWidth ()*16, metrics.height ()*3);
 
   QString cursor_type
-    = settings->value (cs_cursor).toString ();
+    = settings.string_value (cs_cursor);
 
   bool cursor_blinking;
-  if (settings->contains (global_cursor_blinking.key))
-    cursor_blinking = settings->value (global_cursor_blinking).toBool ();
+  if (settings.contains (global_cursor_blinking.settings_key ()))
+    cursor_blinking = settings.bool_value (global_cursor_blinking);
   else
-    cursor_blinking = settings->value (cs_cursor_blinking).toBool ();
+    cursor_blinking = settings.bool_value (cs_cursor_blinking);
 
   for (int ct = IBeamCursor; ct <= UnderlineCursor; ct++)
     {
@@ -236,47 +240,47 @@
     }
 
   bool cursorUseForegroundColor
-    = settings->value (cs_cursor_use_fgcol).toBool ();
+    = settings.bool_value (cs_cursor_use_fgcol);
 
-  int mode = settings->value (cs_color_mode).toInt ();
+  int mode = settings.int_value (cs_color_mode);
 
-  setForegroundColor (settings->color_value (cs_colors[0], mode));
+  setForegroundColor (settings.color_value (cs_colors[0], mode));
 
-  setBackgroundColor (settings->color_value (cs_colors[1], mode));
+  setBackgroundColor (settings.color_value (cs_colors[1], mode));
 
-  setSelectionColor (settings->color_value (cs_colors[2], mode));
+  setSelectionColor (settings.color_value (cs_colors[2], mode));
 
   setCursorColor (cursorUseForegroundColor,
-                  settings->color_value (cs_colors[3], mode));
+                  settings.color_value (cs_colors[3], mode));
 
-  setScrollBufferSize (settings->value (cs_hist_buffer).toInt ());
+  setScrollBufferSize (settings.int_value (cs_hist_buffer));
 
   // If the Copy shortcut is Ctrl+C, then the Copy action also emits
   // a signal for interrupting the current code executed by the worker.
   // If the Copy shortcut is not Ctrl+C, an extra interrupt action is
   // set up for emitting the interrupt signal.
 
-  QString sc = settings->sc_value (sc_main_edit_copy);
+  QString sc = settings.sc_value (sc_main_edit_copy);
 
   //  Dis- or enable extra interrupt action: We need an extra option when
   //  copy shortcut is not Ctrl-C or when global shortcuts (like copy) are
   //  disabled.
   bool extra_ir_action
       = (sc != QKeySequence (Qt::ControlModifier | Qt::Key_C).toString ())
-        || settings->value (sc_prevent_rl_conflicts).toBool ();
+        || settings.bool_value (sc_prevent_rl_conflicts);
 
   _interrupt_action->setEnabled (extra_ir_action);
   has_extra_interrupt (extra_ir_action);
 
   // check whether shortcut Ctrl-D is in use by the main-window
-  bool ctrld = settings->value (sc_main_ctrld).toBool ();
+  bool ctrld = settings.bool_value (sc_main_ctrld);
   _nop_action->setEnabled (! ctrld);
 }
 
 void
-QTerminal::construct (octave::base_qobject& oct_qobj)
+QTerminal::construct (void)
 {
-  octave::resource_manager& rmgr = oct_qobj.get_resource_manager ();
+  octave::gui_settings settings;
 
   // context menu
   setContextMenuPolicy (Qt::CustomContextMenu);
@@ -284,11 +288,11 @@
   _contextMenu = new QMenu (this);
 
   _copy_action
-    = _contextMenu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this,
+    = _contextMenu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this,
                                SLOT (copyClipboard ()));
 
   _paste_action
-    = _contextMenu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this,
+    = _contextMenu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this,
                                SLOT (pasteClipboard ()));
 
   _contextMenu->addSeparator ();
@@ -325,7 +329,7 @@
   addAction (_interrupt_action);
 
   _interrupt_action->setShortcut
-    (QKeySequence (Qt::ControlModifier + Qt::Key_C));
+    (QKeySequence (Qt::ControlModifier | Qt::Key_C));
   _interrupt_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
 
   bool ok = connect (_interrupt_action, SIGNAL (triggered ()),
@@ -335,6 +339,6 @@
   _nop_action = new QAction (this);
   addAction (_nop_action);
 
-  _nop_action->setShortcut (QKeySequence (Qt::ControlModifier + Qt::Key_D));
+  _nop_action->setShortcut (QKeySequence (Qt::ControlModifier | Qt::Key_D));
   _nop_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
 }
--- a/libgui/qterminal/libqterminal/QTerminal.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/QTerminal.h	Fri Jun 23 20:51:51 2023 +0200
@@ -24,23 +24,15 @@
 #ifndef QTERMINAL_H
 #define QTERMINAL_H
 
+#include "octave-config.h"
+
 #include <QColor>
 #include <QList>
 #include <QPoint>
 #include <QString>
 #include <QWidget>
 
-// For now, we need to use the following #include and using statement
-// for the signal/slot macros.  Could maybe change later when using
-// Qt5-style signal/slot connections.
-#include "gui-settings.h"
-
-using octave::gui_settings;
-
-namespace octave
-{
-  class base_qobject;
-}
+#include "qt-interpreter-events.h"
 
 class QMenu;
 class QAction;
@@ -51,8 +43,7 @@
 
 public:
 
-  static QTerminal *
-  create (octave::base_qobject& oct_qobj, QWidget *xparent);
+  static QTerminal * create (QWidget *xparent);
 
   virtual ~QTerminal (void) = default;
 
@@ -116,6 +107,9 @@
 
   void clear_command_window_request (void);
 
+  void interpreter_event (const octave::fcn_callback& fcn);
+  void interpreter_event (const octave::meth_callback& meth);
+
 public slots:
 
   virtual void copyClipboard (void) = 0;
@@ -126,7 +120,7 @@
 
   virtual void handleCustomContextMenuRequested (const QPoint& at);
 
-  void notice_settings (const gui_settings *settings);
+  void notice_settings (void);
 
   virtual void init_terminal_size (void) { }
 
@@ -146,15 +140,14 @@
 
 protected:
 
-  QTerminal (octave::base_qobject& oct_qobj, QWidget *xparent = nullptr)
-            : QWidget (xparent), m_octave_qobj (oct_qobj) { }
+  QTerminal (QWidget *xparent = nullptr)
+    : QWidget (xparent)
+  { }
 
-  void construct (octave::base_qobject& oct_qobj);
+  void construct ();
 
 private:
 
-  octave::base_qobject& m_octave_qobj;
-
   QMenu *_contextMenu;
   QAction * _copy_action;
   QAction * _paste_action;
--- a/libgui/qterminal/libqterminal/unix/Character.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Character.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,7 +26,7 @@
 #define CHARACTER_H
 
 // Qt
-#include <QtCore/QHash>
+#include <QHash>
 
 // Local
 #include "unix/CharacterColor.h"
--- a/libgui/qterminal/libqterminal/unix/Emulation.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Emulation.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -35,13 +35,11 @@
 // Qt
 #include <QApplication>
 #include <QClipboard>
-#include <QtCore/QHash>
+#include <QHash>
 #include <QKeyEvent>
-#include <QtCore/QRegExp>
-#include <QtCore/QTextStream>
-#include <QtCore/QThread>
-
-#include <QtCore/QTime>
+#include <QTextStream>
+#include <QThread>
+#include <QTime>
 
 // Konsole
 #include "unix/KeyboardTranslator.h"
--- a/libgui/qterminal/libqterminal/unix/Emulation.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Emulation.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,10 +30,9 @@
 
 // Qt
 #include <QKeyEvent>
-
-#include <QtCore/QTextCodec>
-#include <QtCore/QTextStream>
-#include <QtCore/QTimer>
+#include <QTextCodec>
+#include <QTextStream>
+#include <QTimer>
 
 class KeyboardTranslator;
 class HistoryType;
--- a/libgui/qterminal/libqterminal/unix/Filter.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Filter.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -24,14 +24,14 @@
 #include "unix/Filter.h"
 
 // Qt
-#include <QDesktopServices>
+#include <QtCore>
+
 #include <QAction>
 #include <QApplication>
 #include <QClipboard>
-#include <QtCore/QString>
-
-#include <QtCore/QSharedData>
-#include <QtCore>
+#include <QDesktopServices>
+#include <QSharedData>
+#include <QString>
 
 // Konsole
 #include "unix/TerminalCharacterDecoder.h"
@@ -349,11 +349,11 @@
     return _capturedTexts;
 }
 
-void RegExpFilter::setRegExp(const QRegExp& regExp)
+void RegExpFilter::setRegExp (const QRegularExpression& regExp)
 {
     _searchText = regExp;
 }
-QRegExp RegExpFilter::regExp() const
+QRegularExpression RegExpFilter::regExp () const
 {
     return _searchText;
 }
@@ -361,7 +361,7 @@
 {
     _buffer = QString();
 }*/
-void RegExpFilter::process()
+void RegExpFilter::process ()
 {
     int pos = 0;
     const QString* text = buffer();
@@ -371,37 +371,35 @@
     // ignore any regular expressions which match an empty string.
     // otherwise the while loop below will run indefinitely
     static const QString emptyString("");
-    if ( _searchText.exactMatch(emptyString) )
+    QRegularExpressionMatch match = _searchText.match (emptyString);
+    if ( match.hasMatch () )
         return;
 
-    while(pos >= 0)
+    match = _searchText.match (*text, pos);
+    while (match.hasMatch ())
     {
-        pos = _searchText.indexIn(*text,pos);
+        pos = match.capturedStart ();
+        int startLine = 0;
+        int endLine = 0;
+        int startColumn = 0;
+        int endColumn = 0;
 
-        if ( pos >= 0 )
-        {
-
-            int startLine = 0;
-            int endLine = 0;
-            int startColumn = 0;
-            int endColumn = 0;
-
+        //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength();
 
-            //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength();
+        getLineColumn (match.capturedStart (), startLine, startColumn);
+        getLineColumn (match.capturedEnd (), endLine, endColumn);
 
-            getLineColumn(pos,startLine,startColumn);
-            getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn);
+        RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
+                                       endLine,endColumn,_type);
+        spot->setCapturedTexts (match.capturedTexts ());
 
-            RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
-                                           endLine,endColumn,_type);
-            spot->setCapturedTexts(_searchText.capturedTexts());
+        addHotSpot( spot );
+        pos += match.capturedLength ();
 
-            addHotSpot( spot );
-            pos += _searchText.matchedLength();
+        // if matchedLength == 0, the program will get stuck in an infinite loop
+        Q_ASSERT( match.capturedLength () > 0 );
 
-            // if matchedLength == 0, the program will get stuck in an infinite loop
-            Q_ASSERT( _searchText.matchedLength() > 0 );
-        }
+        match = _searchText.match (*text, pos);
     }
 }
 
@@ -419,7 +417,7 @@
                                                endLine,endColumn,t);
 }
 
-void UrlFilter::process()
+void UrlFilter::process ()
 {
     int pos = 0;
     const QString* text = buffer();
@@ -429,43 +427,40 @@
     // ignore any regular expressions which match an empty string.
     // otherwise the while loop below will run indefinitely
     static const QString emptyString("");
-    if ( _searchText.exactMatch(emptyString) )
+    QRegularExpressionMatch match = _searchText.match (emptyString);
+    if ( match.hasMatch () )
         return;
 
-    while(pos >= 0)
+    match = _searchText.match (*text, pos);
+    while (match.hasMatch ())
     {
-        pos = _searchText.indexIn(*text,pos);
-
-        if ( pos >= 0 )
-        {
+        int startLine = 0;
+        int endLine = 0;
+        int startColumn = 0;
+        int endColumn = 0;
 
-            int startLine = 0;
-            int endLine = 0;
-            int startColumn = 0;
-            int endColumn = 0;
+        //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength();
 
-
-            //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength();
+        getLineColumn (match.capturedStart (), startLine, startColumn);
+        getLineColumn (match.capturedEnd (), endLine, endColumn);
 
-            getLineColumn(pos,startLine,startColumn);
-            getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn);
-
-            UrlFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
-                                           endLine,endColumn,_type);
-            spot->setCapturedTexts(_searchText.capturedTexts());
+        UrlFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
+                                              endLine,endColumn,_type);
+        spot->setCapturedTexts(match.capturedTexts ());
 
-            // Connect the signal of the urlobject to the slot of the filter;
-            // the filter is then signaling to the main window
-            connect (spot->get_urlObject (),
-                     SIGNAL (request_open_file_signal (const QString&, int)),
-                     this, SLOT (request_open_file (const QString&, int)));
+        // Connect the signal of the urlobject to the slot of the filter;
+        // the filter is then signaling to the main window
+        connect (spot->get_urlObject (),
+                 SIGNAL (request_open_file_signal (const QString&, int)),
+                 this, SLOT (request_open_file (const QString&, int)));
 
-            addHotSpot( spot );
-            pos += _searchText.matchedLength();
+        addHotSpot( spot );
+        pos += match.capturedLength();
 
-            // if matchedLength == 0, the program will get stuck in an infinite loop
-            Q_ASSERT( _searchText.matchedLength() > 0 );
-        }
+        // if matchedLength == 0, the program will get stuck in an infinite loop
+        Q_ASSERT( match.capturedLength () > 0 );
+
+        match = _searchText.match (*text, pos);
     }
 }
 
@@ -489,23 +484,27 @@
     else
         return QString();
 }
-UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
+UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType () const
 {
     QString url = capturedTexts().first();
 
-    if ( FullUrlRegExp.exactMatch(url) )
+    QRegularExpressionMatch match = FullUrlRegExp.match (url);
+    if ( match.hasMatch () )
         return StandardUrl;
-    else if ( EmailAddressRegExp.exactMatch(url) )
+    match = EmailAddressRegExp.match (url);
+    if ( match.hasMatch () )
         return Email;
-    else if ( ErrorLinkRegExp.exactMatch(url) )
+    match = ErrorLinkRegExp.match (url);
+    if ( match.hasMatch () )
         return ErrorLink;
-    else if ( ParseErrorLinkRegExp.exactMatch(url) )
+    match = ParseErrorLinkRegExp.match (url);
+    if ( match.hasMatch () )
         return ParseErrorLink;
-    else
-        return Unknown;
+
+    return Unknown;
 }
 
-void UrlFilter::HotSpot::activate(QObject* object)
+void UrlFilter::HotSpot::activate (QObject* object)
 {
     QString url = capturedTexts().first();
 
@@ -538,11 +537,11 @@
           }
         else if (kind == ErrorLink)
           {
-            int pos = ErrorLinkRegExp.indexIn (url);
-            if (pos > -1)
+            QRegularExpressionMatch match = ErrorLinkRegExp.match (url);
+            if (match.hasMatch ())
               {
-                QString file_name = ErrorLinkRegExp.cap (1);
-                QString line = ErrorLinkRegExp.cap (2);
+                QString file_name = match.captured (1);
+                QString line = match.captured (2);
                 // call the urlobject's method for opening a file; this
                 // method then signals to the filter
                 _urlObject->request_open_file (file_name, line.toInt ());
@@ -550,11 +549,11 @@
           }
         else if (kind == ParseErrorLink)
           {
-            int pos = ParseErrorLinkRegExp.indexIn (url);
-            if (pos > -1)
+            QRegularExpressionMatch match = ParseErrorLinkRegExp.match (url);
+            if (match.hasMatch ())
               {
-                QString line = ParseErrorLinkRegExp.cap (1);
-                QString file_name = ParseErrorLinkRegExp.cap (2);
+                QString line = match.captured (1);
+                QString file_name = match.captured (2);
                 // call the urlobject's method for opening a file; this
                 // method then signals to the filter
                 _urlObject->request_open_file (file_name, line.toInt ());
@@ -574,21 +573,27 @@
 //regexp matches:
 // full url:
 // protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot
-const QRegExp UrlFilter::FullUrlRegExp("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]");
+const QRegularExpression
+UrlFilter::FullUrlRegExp {"(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]"};
 // email address:
 // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
-const QRegExp UrlFilter::EmailAddressRegExp("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b");
+const QRegularExpression
+UrlFilter::EmailAddressRegExp {"\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b"};
 // matches full url or email address
-const QRegExp UrlFilter::CompleteUrlRegExp('('+FullUrlRegExp.pattern()+'|'+
-                                            EmailAddressRegExp.pattern()+')');
+const QRegularExpression
+UrlFilter::CompleteUrlRegExp {'(' + FullUrlRegExp.pattern() + '|' +
+                              EmailAddressRegExp.pattern() + ')'};
 // error link:
 //   normal error
-const QRegExp UrlFilter::ErrorLinkRegExp ("(\\S+) at line (\\d+) column (?:\\d+)");
+const QRegularExpression
+UrlFilter::ErrorLinkRegExp {"(\\S+) at line (\\d+) column (?:\\d+)"};
 //   parse error
-const QRegExp UrlFilter::ParseErrorLinkRegExp ("parse error near line (\\d+) of file (\\S+)");
+const QRegularExpression
+UrlFilter::ParseErrorLinkRegExp {"parse error near line (\\d+) of file (\\S+)"};
 //   complete regexp
-const QRegExp UrlFilter::CompleteErrorLinkRegExp ('('+ErrorLinkRegExp.pattern ()+'|'+
-                                                     ParseErrorLinkRegExp.pattern ()+')');
+const QRegularExpression
+UrlFilter::CompleteErrorLinkRegExp {'('+ErrorLinkRegExp.pattern ()+'|'+
+                                    ParseErrorLinkRegExp.pattern ()+')'};
 
 
 UrlFilter::UrlFilter (Type t)
@@ -607,7 +612,7 @@
 {
     _filter->activate(sender());
 }
-QList<QAction*> UrlFilter::HotSpot::actions()
+QList<QAction*> UrlFilter::HotSpot::actions ()
 {
     QList<QAction*> list;
 
@@ -633,11 +638,11 @@
     else if ( kind == ErrorLink )
     {
       QString url = capturedTexts().first();
-      int pos = ErrorLinkRegExp.indexIn (url);
-      if (pos >= 0)
+      QRegularExpressionMatch match = ErrorLinkRegExp.match (url);
+      if (match.hasMatch ())
         {
-          QString file_name = ErrorLinkRegExp.cap (1);
-          QString line = ErrorLinkRegExp.cap (2);
+          QString file_name = match.captured (1);
+          QString line = match.captured (2);
           openAction->setText(tr ("Edit %1 at line %2")
                               .arg (file_name).arg (line));
         }
@@ -645,11 +650,11 @@
     else if ( kind == ParseErrorLink )
     {
       QString url = capturedTexts().first();
-      int pos = ParseErrorLinkRegExp.indexIn (url);
-      if (pos >= 0)
+      QRegularExpressionMatch match = ParseErrorLinkRegExp.match (url);
+      if (match.hasMatch ())
         {
-          QString line = ParseErrorLinkRegExp.cap (1);
-          QString file_name = ParseErrorLinkRegExp.cap (2);
+          QString line = match.captured (1);
+          QString file_name = match.captured (2);
           openAction->setText(tr ("Edit %1 at line %2")
                               .arg (file_name).arg (line));
         }
--- a/libgui/qterminal/libqterminal/unix/Filter.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Filter.h	Fri Jun 23 20:51:51 2023 +0200
@@ -25,11 +25,11 @@
 
 // Qt
 #include <QAction>
-#include <QtCore/QList>
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
-#include <QtCore/QHash>
-#include <QtCore/QRegExp>
+#include <QHash>
+#include <QList>
+#include <QObject>
+#include <QRegularExpression>
+#include <QStringList>
 
 // Local
 #include "unix/Character.h"
@@ -230,9 +230,9 @@
      * Regular expressions which match the empty string are treated as not matching
      * anything.
      */
-    void setRegExp(const QRegExp& text);
+    void setRegExp(const QRegularExpression& text);
     /** Returns the regular expression which the filter searches for in blocks of text */
-    QRegExp regExp() const;
+    QRegularExpression regExp() const;
 
     /**
      * Reimplemented to search the filter's text buffer for text matching regExp()
@@ -256,7 +256,7 @@
                                     int endLine,int endColumn, Type);
     Type _type;
 
-    QRegExp _searchText;
+    QRegularExpression _searchText;
 };
 
 class FilterObject;
@@ -316,14 +316,14 @@
 
 private:
 
-    static const QRegExp FullUrlRegExp;
-    static const QRegExp EmailAddressRegExp;
-    static const QRegExp ErrorLinkRegExp;
-    static const QRegExp ParseErrorLinkRegExp;
-    static const QRegExp CompleteErrorLinkRegExp;
+    static const QRegularExpression FullUrlRegExp;
+    static const QRegularExpression EmailAddressRegExp;
+    static const QRegularExpression ErrorLinkRegExp;
+    static const QRegularExpression ParseErrorLinkRegExp;
+    static const QRegularExpression CompleteErrorLinkRegExp;
 
     // combined OR of FullUrlRegExp and EmailAddressRegExp
-    static const QRegExp CompleteUrlRegExp;
+    static const QRegularExpression CompleteUrlRegExp;
 };
 
 class FilterObject : public QObject
--- a/libgui/qterminal/libqterminal/unix/History.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/History.h	Fri Jun 23 20:51:51 2023 +0200
@@ -24,10 +24,11 @@
 #define HISTORY_H
 
 // Qt
-#include <QtCore/QBitRef>
-#include <QtCore/QHash>
 #include <QtCore>
 
+#include <QBitRef>
+#include <QHash>
+
 // Konsole
 #include "unix/BlockArray.h"
 #include "unix/Character.h"
--- a/libgui/qterminal/libqterminal/unix/KeyboardTranslator.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/KeyboardTranslator.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -29,12 +29,14 @@
 #include <stdio.h>
 
 // Qt
-#include <QtCore/QBuffer>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
 #include <QtCore>
 #include <QtGui>
 
+#include <QBuffer>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegularExpression>
+
 // FIXME: We should not have a special case for Mac here.  Instead, we
 // should be loading .keytab files at run time, and ideally, allowing
 // individual keys to be redefined from some preferences menu.
@@ -509,49 +511,52 @@
 {
     return false;
 }
-QList<KeyboardTranslatorReader::Token> KeyboardTranslatorReader::tokenize(const QString& line)
+QList<KeyboardTranslatorReader::Token>
+KeyboardTranslatorReader::tokenize (const QString& line)
 {
     QString text = line.simplified();
 
     // comment line: # comment
-    static QRegExp comment("\\#.*");
+    static QRegularExpression comment {"\\#.*"};
     // title line: keyboard "title"
-    static QRegExp title("keyboard\\s+\"(.*)\"");
+    static QRegularExpression title {"keyboard\\s+\"(.*)\""};
     // key line: key KeySequence : "output"
     // key line: key KeySequence : command
-    static QRegExp key("key\\s+([\\w\\+\\s\\-]+)\\s*:\\s*(\"(.*)\"|\\w+)");
+    static QRegularExpression key {"key\\s+([\\w\\+\\s\\-]+)\\s*:\\s*(\"(.*)\"|\\w+)"};
 
     QList<Token> list;
 
-    if ( text.isEmpty() || comment.exactMatch(text) )
+    if ( text.isEmpty() || comment.match (text).hasMatch () )
     {
         return list;
     }
 
-    if ( title.exactMatch(text) )
+    QRegularExpressionMatch match;
+    if ((match = title.match (text)).hasMatch ())
     {
         Token titleToken = { Token::TitleKeyword , QString() };
-        Token textToken = { Token::TitleText , title.capturedTexts()[1] };
+        Token textToken = { Token::TitleText , match.captured (1) };
 
         list << titleToken << textToken;
     }
-    else if  ( key.exactMatch(text) )
+    else if  ((match = key.match (text)).hasMatch ())
     {
         Token keyToken = { Token::KeyKeyword , QString() };
-        Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') };
+        Token sequenceToken = { Token::KeySequence,
+                                match.captured (1).remove (' ') };
 
         list << keyToken << sequenceToken;
 
-        if ( key.capturedTexts()[3].isEmpty() )
+        if ( match.captured (3).isEmpty () )
         {
             // capturedTexts()[2] is a command
-            Token commandToken = { Token::Command , key.capturedTexts()[2] };
+            Token commandToken = { Token::Command , match.captured (2) };
             list << commandToken;
         }
         else
         {
             // capturedTexts()[3] is the output string
-            Token outputToken = { Token::OutputText , key.capturedTexts()[3] };
+            Token outputToken = { Token::OutputText , match.captured (3) };
             list << outputToken;
         }
     }
@@ -671,7 +676,7 @@
     for ( int i = 0 ; i < result.count()-1 ; i++ )
     {
 
-        QByteRef ch = result[i];
+        char ch = result[i];
         if ( ch == '\\' )
         {
             char replacement[2] = {0,0};
--- a/libgui/qterminal/libqterminal/unix/KeyboardTranslator.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/KeyboardTranslator.h	Fri Jun 23 20:51:51 2023 +0200
@@ -25,13 +25,14 @@
 #define KEYBOARDTRANSLATOR_H
 
 // Qt
-#include <QtCore/QHash>
-#include <QtCore/QMultiHash>
-#include <QtCore/QList>
+#include <QtCore>
+
+#include <QHash>
 #include <QKeySequence>
-#include <QtCore/QMetaType>
-#include <QtCore/QVarLengthArray>
-#include <QtCore>
+#include <QList>
+#include <QMetaType>
+#include <QMultiHash>
+#include <QVarLengthArray>
 
 #if QT_VERSION >= 0x050100
 #  define K_GLOBAL_STATIC Q_GLOBAL_STATIC
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -24,9 +24,8 @@
 
 #include <termios.h>
 
-QUnixTerminalImpl::QUnixTerminalImpl(octave::base_qobject& oct_qobj,
-                                     QWidget *p)
-    : QTerminal(oct_qobj, p)
+QUnixTerminalImpl::QUnixTerminalImpl(QWidget *p)
+    : QTerminal(p)
 {
     initialize();
 }
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
     int fdstderr;
 
 public:
-    QUnixTerminalImpl(octave::base_qobject&, QWidget *parent);
+    QUnixTerminalImpl(QWidget *parent);
     virtual ~QUnixTerminalImpl();
 
     void setTerminalFont(const QFont &font);
--- a/libgui/qterminal/libqterminal/unix/Screen.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Screen.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -32,8 +32,8 @@
 #include <ctype.h>
 
 // Qt
-#include <QtCore/QTextStream>
-#include <QtCore/QDate>
+#include <QDate>
+#include <QTextStream>
 
 // Konsole
 #include "unix/konsole_wcwidth.h"
--- a/libgui/qterminal/libqterminal/unix/Screen.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Screen.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,9 +26,9 @@
 #define SCREEN_H
 
 // Qt
-#include <QtCore/QRect>
-#include <QtCore/QTextStream>
-#include <QtCore/QVarLengthArray>
+#include <QRect>
+#include <QTextStream>
+#include <QVarLengthArray>
 
 // Konsole
 #include "unix/Character.h"
--- a/libgui/qterminal/libqterminal/unix/ScreenWindow.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/ScreenWindow.h	Fri Jun 23 20:51:51 2023 +0200
@@ -23,9 +23,9 @@
 #define SCREENWINDOW_H
 
 // Qt
-#include <QtCore/QObject>
-#include <QtCore/QPoint>
-#include <QtCore/QRect>
+#include <QObject>
+#include <QPoint>
+#include <QRect>
 
 // Konsole
 #include "unix/Character.h"
--- a/libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -25,7 +25,7 @@
 #include "unix/TerminalCharacterDecoder.h"
 
 // Qt
-#include <QtCore/QTextStream>
+#include <QTextStream>
 
 PlainTextDecoder::PlainTextDecoder()
  : _output(nullptr)
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -31,13 +31,12 @@
 #include <stdlib.h>
 
 // Qt
+#include <QtCore>
+
 #include <QApplication>
-#include <QtCore/QByteRef>
-#include <QtCore/QDir>
-#include <QtCore/QFile>
-#include <QtCore/QRegExp>
-#include <QtCore/QStringList>
-#include <QtCore>
+#include <QDir>
+#include <QFile>
+#include <QStringList>
 
 #include "unix/TerminalView.h"
 #include "unix/Vt102Emulation.h"
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.h	Fri Jun 23 20:51:51 2023 +0200
@@ -27,8 +27,10 @@
 #define TERMINALMODEL_H
 
 // Qt
-#include <QtCore/QStringList>
 #include <QtCore>
+
+#include <QStringList>
+#include <QTextCodec>
 #include <QWidget>
 
 #include "unix/SelfListener.h"
--- a/libgui/qterminal/libqterminal/unix/TerminalView.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -33,23 +33,24 @@
 #include "unix/TerminalView.h"
 
 // Qt
+#include <QtCore>
+#include <QtGui>
+
 #include <QApplication>
 #include <QBoxLayout>
 #include <QClipboard>
+#include <QEvent>
+#include <QFile>
+#include <QGridLayout>
 #include <QKeyEvent>
-#include <QtCore/QEvent>
-#include <QtCore/QTime>
-#include <QtCore/QFile>
-#include <QGridLayout>
 #include <QLabel>
 #include <QLayout>
 #include <QPainter>
 #include <QPixmap>
 #include <QScrollBar>
 #include <QStyle>
+#include <QTime>
 #include <QToolTip>
-#include <QtCore>
-#include <QtGui>
 
 #include "unix/Filter.h"
 #include "unix/konsole_wcwidth.h"
@@ -331,7 +332,7 @@
   setAttribute(Qt::WA_OpaquePaintEvent);
 
   _gridLayout = new QGridLayout(this);
-  _gridLayout->setMargin(0);
+  _gridLayout->setContentsMargins (0, 0, 0, 0);
 
   setLayout( _gridLayout );
 }
@@ -570,26 +571,6 @@
 void TerminalView::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; }
 uint TerminalView::randomSeed() const { return _randomSeed; }
 
-#if 0
-/*!
-    Set XIM Position
-*/
-void TerminalDisplay::setCursorPos(const int curx, const int cury)
-{
-  QPoint tL  = contentsRect().topLeft();
-  int    tLx = tL.x();
-  int    tLy = tL.y();
-
-  int xpos, ypos;
-  ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent;
-  xpos = _leftMargin + tLx + _fontWidth*curx;
-  //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ???
-  // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
-  _cursorLine = cury;
-  _cursorCol = curx;
-}
-#endif
-
 // scrolls the image by 'lines', down if lines > 0 or up otherwise.
 //
 // the terminal emulation keeps track of the scrolling of the character
@@ -1647,13 +1628,6 @@
   extendSelection( ev->pos() );
 }
 
-#if 0
-void TerminalDisplay::setSelectionEnd()
-{
-  extendSelection( _configureRequestPoint );
-}
-#endif
-
 void TerminalView::extendSelection(const QPoint& position) {
   QPoint pos = position;
 
@@ -2043,13 +2017,8 @@
 
 void TerminalView::wheelEvent( QWheelEvent* ev )
 {
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
   if (ev->angleDelta().y() == 0)
     return;
-#else
-  if (ev->orientation() != Qt::Vertical)
-    return;
-#endif
 
   if ( _mouseMarks )
     _scrollBar->event(ev);
@@ -2064,11 +2033,8 @@
 #endif
       getCharacterPosition( pos , charLine , charColumn );
 
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
       int delta = ev->angleDelta().y();
-#else
-      int delta = ev->delta();
-#endif
+
       emit mouseSignal( delta > 0 ? 4 : 5,
                         charColumn + 1,
                         charLine + 1 +_scrollBar->value() -_scrollBar->maximum() ,
--- a/libgui/qterminal/libqterminal/unix/TerminalView.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,7 +26,7 @@
 
 // Qt
 #include <QColor>
-#include <QtCore/QPointer>
+#include <QPointer>
 #include <QWidget>
 
 // Konsole
--- a/libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -39,9 +39,8 @@
 #include <assert.h>
 
 // Qt
-#include <QtCore/QEvent>
+#include <QEvent>
 #include <QKeyEvent>
-#include <QtCore/QByteRef>
 
 // Konsole
 #include "unix/KeyboardTranslator.h"
@@ -359,7 +358,7 @@
     arg = 10*arg + (pbuf[i]-'0');
   if (pbuf[i] != ';') { ReportErrorToken(); return; }
   QChar *str = new QChar[ppos-i-2];
-  for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
+  for (int j = 0; j < ppos-i-2; j++) str[j] = QChar {pbuf[i+1+j]};
   QString unistr(str,ppos-i-2);
 
   // arg == 1 doesn't change the title. In XTerm it only changes the icon name
@@ -402,38 +401,6 @@
 
 void Vt102Emulation::tau( int token, int p, int q )
 {
-#if 0
-int N = (token>>0)&0xff;
-int A = (token>>8)&0xff;
-switch( N )
-{
-   case 0: printf("%c", (p < 128) ? p : '?');
-           break;
-   case 1: if (A == 'J') printf("\r");
-           else if (A == 'M') printf("\n");
-           else printf("CTL-%c ", (token>>8)&0xff);
-           break;
-   case 2: printf("ESC-%c ", (token>>8)&0xff);
-           break;
-   case 3: printf("ESC_CS-%c-%c ", (token>>8)&0xff, (token>>16)&0xff);
-           break;
-   case 4: printf("ESC_DE-%c ", (token>>8)&0xff);
-           break;
-   case 5: printf("CSI-PS-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
-           break;
-   case 6: printf("CSI-PN-%c [%d]", (token>>8)&0xff, p);
-           break;
-   case 7: printf("CSI-PR-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
-           break;
-   case 8: printf("VT52-%c", (token>>8)&0xff);
-           break;
-   case 9: printf("CSI-PG-%c", (token>>8)&0xff);
-           break;
-   case 10: printf("CSI-PE-%c", (token>>8)&0xff);
-           break;
-}
-#endif
-
   switch (token)
   {
 
--- a/libgui/qterminal/libqterminal/unix/Vt102Emulation.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/Vt102Emulation.h	Fri Jun 23 20:51:51 2023 +0200
@@ -29,9 +29,9 @@
 #include <stdio.h>
 
 // Qt
+#include <QHash>
 #include <QKeyEvent>
-#include <QtCore/QHash>
-#include <QtCore/QTimer>
+#include <QTimer>
 
 // Konsole
 #include "unix/Emulation.h"
--- a/libgui/qterminal/libqterminal/unix/konsole_wcwidth.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/konsole_wcwidth.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -131,81 +131,6 @@
       (ucs >= 0x20000 && ucs <= 0x2ffff) */));
 }
 
-#if 0
-/*
- * The following function is the same as konsole_wcwidth(), except that
- * spacing characters in the East Asian Ambiguous (A) category as
- * defined in Unicode Technical Report #11 have a column width of 2.
- * This experimental variant might be useful for users of CJK legacy
- * encodings who want to migrate to UCS. It is not otherwise
- * recommended for general use.
- */
-int konsole_wcwidth_cjk(quint16 ucs)
-{
-  /* sorted list of non-overlapping intervals of East Asian Ambiguous
-   * characters */
-  static const struct interval ambiguous[] = {
-    { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
-    { 0x00AA, 0x00AA }, { 0x00AD, 0x00AD }, { 0x00B0, 0x00B4 },
-    { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
-    { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
-    { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
-    { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
-    { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
-    { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
-    { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
-    { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
-    { 0x0148, 0x014A }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
-    { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
-    { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
-    { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
-    { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
-    { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, { 0x02CD, 0x02CD },
-    { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, { 0x02DD, 0x02DD },
-    { 0x0391, 0x03A1 }, { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 },
-    { 0x03C3, 0x03C9 }, { 0x0401, 0x0401 }, { 0x0410, 0x044F },
-    { 0x0451, 0x0451 }, { 0x2010, 0x2010 }, { 0x2013, 0x2016 },
-    { 0x2018, 0x2019 }, { 0x201C, 0x201D }, { 0x2020, 0x2021 },
-    { 0x2025, 0x2027 }, { 0x2030, 0x2030 }, { 0x2032, 0x2033 },
-    { 0x2035, 0x2035 }, { 0x203B, 0x203B }, { 0x2074, 0x2074 },
-    { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
-    { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
-    { 0x2113, 0x2113 }, { 0x2121, 0x2122 }, { 0x2126, 0x2126 },
-    { 0x212B, 0x212B }, { 0x2154, 0x2155 }, { 0x215B, 0x215B },
-    { 0x215E, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
-    { 0x2190, 0x2199 }, { 0x21D2, 0x21D2 }, { 0x21D4, 0x21D4 },
-    { 0x2200, 0x2200 }, { 0x2202, 0x2203 }, { 0x2207, 0x2208 },
-    { 0x220B, 0x220B }, { 0x220F, 0x220F }, { 0x2211, 0x2211 },
-    { 0x2215, 0x2215 }, { 0x221A, 0x221A }, { 0x221D, 0x2220 },
-    { 0x2223, 0x2223 }, { 0x2225, 0x2225 }, { 0x2227, 0x222C },
-    { 0x222E, 0x222E }, { 0x2234, 0x2237 }, { 0x223C, 0x223D },
-    { 0x2248, 0x2248 }, { 0x224C, 0x224C }, { 0x2252, 0x2252 },
-    { 0x2260, 0x2261 }, { 0x2264, 0x2267 }, { 0x226A, 0x226B },
-    { 0x226E, 0x226F }, { 0x2282, 0x2283 }, { 0x2286, 0x2287 },
-    { 0x2295, 0x2295 }, { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 },
-    { 0x22BF, 0x22BF }, { 0x2312, 0x2312 }, { 0x2460, 0x24BF },
-    { 0x24D0, 0x24E9 }, { 0x2500, 0x254B }, { 0x2550, 0x2574 },
-    { 0x2580, 0x258F }, { 0x2592, 0x2595 }, { 0x25A0, 0x25A1 },
-    { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 }, { 0x25B6, 0x25B7 },
-    { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 }, { 0x25C6, 0x25C8 },
-    { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 }, { 0x25E2, 0x25E5 },
-    { 0x25EF, 0x25EF }, { 0x2605, 0x2606 }, { 0x2609, 0x2609 },
-    { 0x260E, 0x260F }, { 0x261C, 0x261C }, { 0x261E, 0x261E },
-    { 0x2640, 0x2640 }, { 0x2642, 0x2642 }, { 0x2660, 0x2661 },
-    { 0x2663, 0x2665 }, { 0x2667, 0x266A }, { 0x266C, 0x266D },
-    { 0x266F, 0x266F }, { 0x300A, 0x300B }, { 0x301A, 0x301B },
-    { 0xE000, 0xF8FF }, { 0xFFFD, 0xFFFD }
-  };
-
-  /* binary search in table of non-spacing characters */
-  if (bisearch(ucs, ambiguous,
-	       sizeof(ambiguous) / sizeof(struct interval) - 1))
-    return 2;
-
-  return konsole_wcwidth(ucs);
-}
-#endif
-
 // single byte char: +1, multi byte char: +2
 int string_width( const QString &txt )
 {
--- a/libgui/qterminal/libqterminal/unix/konsole_wcwidth.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/konsole_wcwidth.h	Fri Jun 23 20:51:51 2023 +0200
@@ -11,12 +11,9 @@
 #define	_KONSOLE_WCWIDTH_H_
 
 // Qt
-#include <QtCore/QString>
+#include <QString>
 
 int konsole_wcwidth(quint16 ucs);
-#if 0
-int konsole_wcwidth_cjk(Q_UINT16 ucs);
-#endif
 
 int string_width( const QString &txt );
 
--- a/libgui/qterminal/libqterminal/unix/kpty_p.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/unix/kpty_p.h	Fri Jun 23 20:51:51 2023 +0200
@@ -25,7 +25,7 @@
 
 #include "unix/kpty.h"
 
-#include <QtCore/QByteArray>
+#include <QByteArray>
 
 struct KPtyPrivate {
     Q_DECLARE_PUBLIC(KPty)
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Fri Jun 23 20:51:51 2023 +0200
@@ -1437,9 +1437,8 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-QWinTerminalImpl::QWinTerminalImpl (octave::base_qobject& oct_qobj,
-                                    QWidget* parent)
-    : QTerminal (oct_qobj, parent), d (new QConsolePrivate (this)),
+QWinTerminalImpl::QWinTerminalImpl (QWidget* parent)
+    : QTerminal (parent), d (new QConsolePrivate (this)),
       allowTripleClick (false)
 {
     installEventFilter (this);
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,7 +49,7 @@
   friend class QConsoleView;
 
 public:
-  QWinTerminalImpl (octave::base_qobject&, QWidget* parent);
+  QWinTerminalImpl (QWidget* parent);
   ~QWinTerminalImpl (void);
 
   void setTerminalFont (const QFont& font);
--- a/libgui/src/color-picker.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/color-picker.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 }
 
 // Slot for button clicked: select a new color using QColorDialog
-void color_picker::select_color (void)
+void color_picker::select_color ()
 {
   QColor new_color = QColorDialog::getColor (m_color);
 
@@ -65,7 +65,7 @@
 }
 
 // Draw the button with the actual color (using a stylesheet)
-void color_picker::update_button (void)
+void color_picker::update_button ()
 {
   // Is this the right place to look for a "foreground" color that would
   // provide a reasonable border for the color swatches?
--- a/libgui/src/color-picker.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/color-picker.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,17 +42,17 @@
 
   color_picker (QColor color = QColor (0, 0, 0), QWidget *parent = nullptr);
 
-  QColor color (void) const { return m_color; }
+  QColor color () const { return m_color; }
 
   void set_color (QColor new_color);
 
 private slots:
 
-  void select_color (void);
+  void select_color ();
 
 private:
 
-  virtual void update_button (void);
+  virtual void update_button ();
 
   QColor m_color;
 };
--- a/libgui/src/command-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/command-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,16 +44,17 @@
 #include "event-manager.h"
 #include "gui-preferences-cs.h"
 #include "gui-preferences-global.h"
+#include "gui-settings.h"
 #include "gui-utils.h"
 #include "input.h"
 #include "interpreter.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-command_widget::command_widget (base_qobject& oct_qobj, QWidget *p)
-: QWidget (p), m_incomplete_parse (false),
-  m_prompt (QString ()),
-  m_console (new console (this, oct_qobj))
+command_widget::command_widget (QWidget *p)
+  : QWidget (p), m_incomplete_parse (false),
+    m_prompt (QString ()),
+    m_console (new console (this))
 {
   QPushButton *pause_button = new QPushButton (tr("Pause"), this);
   QPushButton *stop_button = new QPushButton (tr("Stop"), this);
@@ -83,9 +84,18 @@
   connect (stop_button, &QPushButton::clicked,
            this, &command_widget::interpreter_stop);
 
+  connect (this, &command_widget::update_prompt_signal,
+           this, &command_widget::update_prompt);
+
   connect (this, &command_widget::new_command_line_signal,
            m_console, &console::new_command_line);
 
+  connect (m_console, QOverload<const fcn_callback&>::of (&console::interpreter_event),
+           this, QOverload<const fcn_callback&>::of (&command_widget::interpreter_event));
+
+  connect (m_console, QOverload<const meth_callback&>::of (&console::interpreter_event),
+           this, QOverload<const meth_callback&>::of (&command_widget::interpreter_event));
+
   insert_interpreter_output ("\n\n    Welcome to Octave\n\n");
 
 }
@@ -100,22 +110,23 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
+     {
+       // INTERPRETER THREAD
 
-      // We can skip the entire callback function because it does not
-      // make any changes to the interpreter state.
+       // We can skip the entire callback function because it does not
+       // make any changes to the interpreter state.
+
+       if (this_cw.isNull ())
+         return;
 
-      if (this_cw.isNull ())
-        return;
+       std::string prompt = interp.PS1 ();
+       std::string decoded_prompt
+         = command_editor::decode_prompt_string (prompt);
 
-      event_manager& evmgr = interp.get_event_manager ();
-      input_system& input_sys = interp.get_input_system ();
-      std::string prompt = input_sys.PS1 ();
-      evmgr.update_prompt (command_editor::decode_prompt_string (prompt));
+       emit update_prompt_signal (QString::fromStdString (decoded_prompt));
 
-      emit new_command_line_signal ();
-    });
+       emit new_command_line_signal ();
+     });
 }
 
 void command_widget::update_prompt (const QString& prompt)
@@ -143,52 +154,54 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
+     {
+       // INTERPRETER THREAD
 
-      // If THIS_CW is no longer valid, we still want to parse and
-      // execute INPUT_LINE but we can't emit the signals associated
-      // with THIS_CW.
+       // If THIS_CW is no longer valid, we still want to parse and
+       // execute INPUT_LINE but we can't emit the signals associated
+       // with THIS_CW.
 
-      interp.parse_and_execute (input_line.toStdString (),
-                                m_incomplete_parse);
+       interp.parse_and_execute (input_line.toStdString (),
+                                 m_incomplete_parse);
 
-      if (this_cw.isNull ())
-        return;
+       if (this_cw.isNull ())
+         return;
 
-      event_manager& evmgr = interp.get_event_manager ();
-      input_system& input_sys = interp.get_input_system ();
+       std::string prompt
+         = m_incomplete_parse ? interp.PS2 () : interp.PS1 ();
 
-      std::string prompt
-        = m_incomplete_parse ? input_sys.PS2 () : input_sys.PS1 ();
+       std::string decoded_prompt
+         = command_editor::decode_prompt_string (prompt);
 
-      evmgr.update_prompt (command_editor::decode_prompt_string (prompt));
+       emit update_prompt_signal (QString::fromStdString (decoded_prompt));
 
-      emit new_command_line_signal ();
-    });
+       emit new_command_line_signal ();
+     });
 
 }
 
-void command_widget::notice_settings (const gui_settings *settings)
+void command_widget::notice_settings ()
 {
+  gui_settings settings;
+
   // Set terminal font:
   QFont term_font = QFont ();
   term_font.setStyleHint (QFont::TypeWriter);
-  QString default_font = settings->value (global_mono_font).toString ();
+  QString default_font = settings.string_value (global_mono_font);
   term_font.setFamily
-    (settings->value (cs_font.key, default_font).toString ());
+    (settings.value (cs_font.settings_key (), default_font).toString ());
   term_font.setPointSize
-    (settings->value (cs_font_size).toInt ());
+    (settings.int_value (cs_font_size));
 
   m_console->setFont (term_font);
 
   // Colors
-  int mode = settings->value (cs_color_mode).toInt ();
-  QColor fgc = settings->color_value (cs_colors[0], mode);
-  QColor bgc = settings->color_value (cs_colors[1], mode);
+  int mode = settings.int_value (cs_color_mode);
+  QColor fgc = settings.color_value (cs_colors[0], mode);
+  QColor bgc = settings.color_value (cs_colors[1], mode);
 
   m_console->setStyleSheet (QString ("color: %1; background-color:%2;")
-                            .arg (fgc.name ()).arg (bgc.name ()));
+                                   .arg (fgc.name ()).arg (bgc.name ()));
 }
 
 // The console itself using QScintilla.
@@ -196,7 +209,7 @@
 // "qpconsole" as proposed by user "DerManu" in the Qt-forum thread
 // https://forum.qt.io/topic/28765/command-terminal-using-qtextedit
 
-console::console (command_widget *p, base_qobject&)
+console::console (command_widget *p)
   : QsciScintilla (p),
     m_command_position (-1),
     m_cursor_position (0),
@@ -210,11 +223,11 @@
   connect (this, SIGNAL (cursorPositionChanged (int, int)),
            this, SLOT (cursor_position_changed (int, int)));
 
-  connect (this, SIGNAL (textChanged (void)),
-           this, SLOT (text_changed (void)));
+  connect (this, SIGNAL (textChanged ()),
+           this, SLOT (text_changed ()));
 
-  connect (this, SIGNAL (modificationAttempted (void)),
-           this, SLOT (move_cursor_to_end (void)));
+  connect (this, SIGNAL (modificationAttempted ()),
+           this, SLOT (move_cursor_to_end ()));
 }
 
 // Prepare a new command line with the current prompt
@@ -295,7 +308,7 @@
 
 // User attempted to type on read only mode: move cursor at end and allow
 // editing
-void console::move_cursor_to_end (void)
+void console::move_cursor_to_end ()
 {
   if ((! m_last_key_string.isEmpty ()) && (m_last_key_string.at (0).isPrint ()))
     {
@@ -306,7 +319,7 @@
 
 // Text has changed: is cursor still in "writable" area?
 // This signal seems to be emitted before cursor position changed.
-void console::text_changed (void)
+void console::text_changed ()
 {
   m_text_changed = true;
 }
--- a/libgui/src/command-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/command-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,14 +30,16 @@
 
 #include <Qsci/qsciscintilla.h>
 
-#include "octave-qobject.h"
-#include "gui-settings.h"
+// FIXME: We need the following header for the fcn_callback and
+// meth_callback typedefs.  Maybe it would be better to declare those in
+// a separate file because inclding "event-manager.h" pulls in a lot of
+// other unnecessary declarations.
+#include "event-manager.h"
 
 class QsciScintilla;
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class command_widget;
 
 class console : public QsciScintilla
@@ -46,15 +48,20 @@
 
 public:
 
-  console (command_widget *p, base_qobject& oct_qobj);
+  console (command_widget *p);
+
+signals:
+
+  void interpreter_event (const fcn_callback& fcn);
+  void interpreter_event (const meth_callback& meth);
 
 public slots:
 
   void cursor_position_changed (int line, int col);
 
-  void text_changed (void);
+  void text_changed ();
 
-  void move_cursor_to_end (void);
+  void move_cursor_to_end ();
 
   void new_command_line (const QString& command = QString ());
 
@@ -68,7 +75,7 @@
 
   void append_string (const QString& string);
 
-  void accept_command_line (void);
+  void accept_command_line ();
 
   int m_command_position;
   int m_cursor_position;
@@ -84,27 +91,28 @@
 
 public:
 
-  command_widget (base_qobject& oct_qobj, QWidget *p);
+  command_widget (QWidget *p);
 
   console * get_console ( ) { return m_console; };
 
   void init_command_prompt ();
 
-  QString prompt (void);
+  QString prompt ();
 
 signals:
 
-  void clear_line_edit (void);
+  void clear_line_edit ();
 
-  void interpreter_pause (void);
-  void interpreter_resume (void);
-  void interpreter_stop (void);
+  void interpreter_pause ();
+  void interpreter_resume ();
+  void interpreter_stop ();
+
+  void update_prompt_signal (const QString& prompt);
+  void new_command_line_signal (const QString& command = QString ());
 
   void interpreter_event (const fcn_callback& fcn);
   void interpreter_event (const meth_callback& meth);
 
-  void new_command_line_signal (const QString& command = QString ());
-
 public slots:
 
   void process_input_line (const QString& input_line);
@@ -113,7 +121,7 @@
 
   void insert_interpreter_output (const QString& msg);
 
-  void notice_settings (const gui_settings *settings);
+  void notice_settings ();
 
 private:
 
--- a/libgui/src/community-news.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/community-news.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,27 +35,25 @@
 #include "gui-utils.h"
 #include "gui-preferences-dw.h"
 #include "gui-preferences-nr.h"
+#include "gui-settings.h"
 #include "news-reader.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-community_news::community_news (base_qobject& oct_qobj, int serial)
-: QWidget (nullptr), m_browser (nullptr)
+community_news::community_news (int serial)
+  : QWidget (nullptr), m_browser (nullptr)
 {
-  construct (oct_qobj, "https://octave.org", "community-news.html", serial);
+  construct ("https://octave.org", "community-news.html", serial);
 }
 
-community_news::community_news (base_qobject& oct_qobj, QWidget *parent,
-                                const QString& base_url, const QString& page,
-                                int serial)
+community_news::community_news (QWidget *parent, const QString& base_url,
+                                const QString& page, int serial)
   : QWidget (parent), m_browser (nullptr)
 {
-  construct (oct_qobj, base_url, page, serial);
+  construct (base_url, page, serial);
 }
 
-void community_news::construct (base_qobject& oct_qobj,
-                                const QString& base_url, const QString& page,
+void community_news::construct (const QString& base_url, const QString& page,
                                 int serial)
 {
   m_browser = new QTextBrowser (this);
@@ -76,11 +74,10 @@
   resize (win_x/2, win_y/2);
   move ((win_x - width ())/2, (win_y - height ())/2);
 
-  resource_manager& rmgr = oct_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   QString icon;
-  QString icon_set = settings->value (dw_icon_set).toString ();
+  QString icon_set = settings.string_value (dw_icon_set);
   if (icon_set != "NONE")
     // No extra icon for Community news, take the one of the release notes
     icon = dw_icon_set_names[icon_set] + "ReleaseWidget.png";
@@ -92,15 +89,12 @@
   // FIXME: This is a news reader preference, so shouldn't it be used
   // in the news_reader object?
 
-  bool connect_to_web
-    = (settings
-       ? settings->value (nr_allow_connection).toBool ()
-       : true);
+  bool connect_to_web = settings.bool_value (nr_allow_connection);
 
   QThread *worker_thread = new QThread;
 
-  news_reader *reader = new news_reader (oct_qobj, base_url, page,
-                                         serial, connect_to_web);
+  news_reader *reader
+    = new news_reader (base_url, page, serial, connect_to_web);
 
   reader->moveToThread (worker_thread);
 
@@ -125,7 +119,7 @@
   m_browser->setHtml (news);
 }
 
-void community_news::display (void)
+void community_news::display ()
 {
   if (! isVisible ())
     show ();
--- a/libgui/src/community-news.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/community-news.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,33 +33,30 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class community_news : public QWidget
 {
   Q_OBJECT
 
 public:
 
-  community_news (base_qobject& oct_qobj, int serial);
+  community_news (int serial);
 
-  community_news (base_qobject& oct_qobj, QWidget *parent = nullptr,
+  community_news (QWidget *parent = nullptr,
                   const QString& base_url = "https://octave.org",
                   const QString& page = "community-news.html",
                   int serial = -1);
 
-  ~community_news (void) = default;
+  ~community_news () = default;
 
 public slots:
 
   void set_news (const QString& news);
 
-  void display (void);
+  void display ();
 
 private:
 
-  void construct (base_qobject& oct_qobj, const QString& base_url,
-                  const QString& page, int serial);
+  void construct (const QString& base_url, const QString& page, int serial);
 
   QTextBrowser *m_browser;
 };
--- a/libgui/src/dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,17 +39,18 @@
 #include <QLabel>
 #include <QMessageBox>
 #include <QPushButton>
+#include <QRegularExpression>
 #include <QVBoxLayout>
 
 #include "dialog.h"
-#include "octave-qobject.h"
 #include "gui-preferences-global.h"
+#include "gui-settings.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-QUIWidgetCreator::QUIWidgetCreator (base_qobject& oct_qobj)
-: QObject (), m_octave_qobj (oct_qobj), m_dialog_result (-1),
-  m_dialog_button (), m_string_list (), m_list_index (), m_path_name ()
+QUIWidgetCreator::QUIWidgetCreator ()
+  : QObject (), m_dialog_result (-1), m_dialog_button (),
+    m_string_list (), m_list_index (), m_path_name ()
 {
   connect (this, &QUIWidgetCreator::create_dialog,
            this, &QUIWidgetCreator::handle_create_dialog);
@@ -67,7 +68,7 @@
 QString QUIWidgetCreator::rm_amp (const QString& text)
 {
   QString text_wo_amp = text;
-  text_wo_amp.replace (QRegExp ("&(\\w)"), "\\1");
+  text_wo_amp.replace (QRegularExpression {"&(\\w)"}, "\\1");
   return text_wo_amp;
 }
 
@@ -180,8 +181,7 @@
                                              const QStringList& role)
 {
   MessageDialog *message_dialog
-    = new MessageDialog (m_octave_qobj, message, title, icon,
-                         button, defbutton, role);
+    = new MessageDialog (message, title, icon, button, defbutton, role);
 
   connect (message_dialog, &MessageDialog::buttonClicked,
            this, &QUIWidgetCreator::dialog_button_clicked);
@@ -232,7 +232,7 @@
                                                const QString& cancel_string)
 {
   ListDialog *list_dialog
-    = new ListDialog (m_octave_qobj, list, mode, wd, ht, initial,
+    = new ListDialog (list, mode, wd, ht, initial,
                       name, prompt, ok_string, cancel_string);
 
   connect (list_dialog, &ListDialog::finish_selection,
@@ -264,7 +264,7 @@
                                                   const QStringList& defaults)
 {
   InputDialog *input_dialog
-    = new InputDialog (m_octave_qobj, prompt, title, nr, nc, defaults);
+    = new InputDialog (prompt, title, nr, nc, defaults);
 
   connect (input_dialog, &InputDialog::finish_input,
            this, &QUIWidgetCreator::input_finished);
@@ -292,8 +292,7 @@
                                                  const QString& multimode)
 {
   FileDialog *file_dialog
-    = new FileDialog (m_octave_qobj, filters, title, filename,
-                      dirname, multimode);
+    = new FileDialog (filters, title, filename, dirname, multimode);
 
   connect (file_dialog, &FileDialog::finish_input,
            this, &QUIWidgetCreator::filedialog_finished);
@@ -316,7 +315,7 @@
   wake_all ();
 }
 
-MessageDialog::MessageDialog (base_qobject&, const QString& message,
+MessageDialog::MessageDialog (const QString& message,
                               const QString& title, const QString& qsicon,
                               const QStringList& qsbutton,
                               const QString& defbutton,
@@ -388,7 +387,7 @@
     }
 }
 
-ListDialog::ListDialog (base_qobject&, const QStringList& list,
+ListDialog::ListDialog (const QStringList& list,
                         const QString& mode, int wd, int ht,
                         const QList<int>& initial, const QString& title,
                         const QStringList& prompt,
@@ -406,13 +405,12 @@
   else
     view->setSelectionMode (QAbstractItemView::NoSelection);
 
-  selector = view->selectionModel ();
-  int i = 0;
-  for (auto it = initial.begin (); it != initial.end (); it++)
+  m_selector = view->selectionModel ();
+  for (int i = 0; i < initial.count(); i++)
     {
-      QModelIndex idx = m_model->index (initial.value (i++) - 1, 0,
+      QModelIndex idx = m_model->index (initial.value (i) - 1, 0,
                                         QModelIndex ());
-      selector->select (idx, QItemSelectionModel::Select);
+      m_selector->select (idx, QItemSelectionModel::Select);
     }
 
   bool fixed_layout = false;
@@ -427,26 +425,17 @@
   QVBoxLayout *listLayout = new QVBoxLayout;
   if (! prompt.isEmpty ())
     {
-      // For now, assume html-like Rich Text.  May be incompatible
-      // with something down the road, but just testing capability.
+      // Note: Assume html-like Rich Text.
+      // Check for future incompatibilities if any.
       QString prompt_string;
-      for (int j = 0; j < prompt.length (); j++)
+      prompt_string.append (prompt.at (0));
+      for (int j = 1; j < prompt.length (); j++)
         {
-          if (j > 0)
-            // FIXME: Why define and then immediately test value?
-#define RICH_TEXT 1
-#if RICH_TEXT
-            prompt_string.append ("<br>");
-#else
-          prompt_string.append ("\n");
-#endif
+          prompt_string.append ("<br>");
           prompt_string.append (prompt.at (j));
         }
       QLabel *plabel = new QLabel (prompt_string);
-#if RICH_TEXT
       plabel->setTextFormat (Qt::RichText);
-#endif
-#undef RICH_TEXT
       listLayout->addWidget (plabel);
     }
   listLayout->addWidget (view);
@@ -486,12 +475,12 @@
            this, &ListDialog::item_double_clicked);
 }
 
-void ListDialog::buttonOk_clicked (void)
+void ListDialog::buttonOk_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
 
-  QModelIndexList selected_index = selector->selectedIndexes ();
+  QModelIndexList selected_index = m_selector->selectedIndexes ();
   QIntList selected_int;
 
   for (int i = 0; i < selected_index.size (); i++)
@@ -502,7 +491,7 @@
   done (QDialog::Accepted);
 }
 
-void ListDialog::buttonCancel_clicked (void)
+void ListDialog::buttonCancel_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -514,7 +503,7 @@
   done (QDialog::Rejected);
 }
 
-void ListDialog::reject (void)
+void ListDialog::reject ()
 {
   buttonCancel_clicked ();
 }
@@ -524,7 +513,7 @@
   buttonOk_clicked ();
 }
 
-InputDialog::InputDialog (base_qobject&, const QStringList& prompt,
+InputDialog::InputDialog (const QStringList& prompt,
                           const QString& title, const QFloatList& nr,
                           const QFloatList& nc, const QStringList& defaults)
   : QDialog ()
@@ -557,7 +546,7 @@
               line_edit->setFixedWidth (intval);
             }
         }
-      input_line << line_edit;
+      m_input_line << line_edit;
 #if LINE_EDIT_FOLLOWS_PROMPT
       promptInputLayout->addWidget (label, i + 1, 0);
       promptInputLayout->addWidget (line_edit, i + 1, 1);
@@ -591,19 +580,19 @@
            this, &InputDialog::buttonCancel_clicked);
 }
 
-void InputDialog::buttonOk_clicked (void)
+void InputDialog::buttonOk_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
 
   QStringList string_result;
-  for (int i = 0; i < input_line.size (); i++)
-    string_result << input_line.at (i)->text ();
+  for (int i = 0; i < m_input_line.size (); i++)
+    string_result << m_input_line.at (i)->text ();
   emit finish_input (string_result, 1);
   done (QDialog::Accepted);
 }
 
-void InputDialog::buttonCancel_clicked (void)
+void InputDialog::buttonCancel_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -613,13 +602,12 @@
   done (QDialog::Rejected);
 }
 
-void InputDialog::reject (void)
+void InputDialog::reject ()
 {
   buttonCancel_clicked ();
 }
 
-FileDialog::FileDialog (base_qobject& oct_qobj,
-                        const QStringList& name_filters,
+FileDialog::FileDialog (const QStringList& name_filters,
                         const QString& title, const QString& filename,
                         const QString& dirname, const QString& multimode)
   : QFileDialog ()
@@ -631,9 +619,10 @@
   setDirectory (dirname);
 
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-  resource_manager& rmgr = oct_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     setOption(QFileDialog::DontUseNativeDialog);
 
   if (multimode == "on")         // uigetfile multiselect=on
@@ -669,13 +658,13 @@
   connect (this, &FileDialog::rejected, this, &FileDialog::rejectSelection);
 }
 
-void FileDialog::rejectSelection (void)
+void FileDialog::rejectSelection ()
 {
   QStringList empty;
   emit finish_input (empty, "", 0);
 }
 
-void FileDialog::acceptSelection (void)
+void FileDialog::acceptSelection ()
 {
   QStringList string_result;
   QString path;
--- a/libgui/src/dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,17 +44,15 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class QUIWidgetCreator : public QObject
 {
   Q_OBJECT
 
 public:
 
-  QUIWidgetCreator (base_qobject& oct_qobj);
+  QUIWidgetCreator ();
 
-  ~QUIWidgetCreator (void) = default;
+  ~QUIWidgetCreator () = default;
 
 public:
 
@@ -64,9 +62,9 @@
                           const QString& icon, const QStringList& button,
                           const QString& defbutton, const QStringList& role);
 
-  int get_dialog_result (void) { return m_dialog_result; }
+  int get_dialog_result () { return m_dialog_result; }
 
-  QString get_dialog_button (void) { return m_dialog_button; }
+  QString get_dialog_button () { return m_dialog_button; }
 
   QPair<QIntList, int> list_dialog (const QStringList& list,
                                     const QString& mode,
@@ -77,24 +75,24 @@
                                     const QString& ok_string,
                                     const QString& cancel_string);
 
-  QIntList get_list_index (void) const { return m_list_index; }
+  QIntList get_list_index () const { return m_list_index; }
 
   QStringList input_dialog (const QStringList& prompt, const QString& title,
                             const QFloatList& nr, const QFloatList& nc,
                             const QStringList& defaults);
 
-  QStringList get_string_list (void) const { return m_string_list; }
+  QStringList get_string_list () const { return m_string_list; }
 
   QStringList file_dialog (const QStringList& filters, const QString& title,
                            const QString& filename, const QString& dirname,
                            const QString& multimode);
 
-  QString get_dialog_path (void) const { return m_path_name; }
+  QString get_dialog_path () const { return m_path_name; }
 
-  void lock (void) { m_mutex.lock (); }
-  void wait (void) { m_waitcondition.wait (&m_mutex); }
-  void unlock (void) { m_mutex.unlock (); }
-  void wake_all (void) { m_waitcondition.wakeAll (); }
+  void lock () { m_mutex.lock (); }
+  void wait () { m_waitcondition.wait (&m_mutex); }
+  void unlock () { m_mutex.unlock (); }
+  void wake_all () { m_waitcondition.wakeAll (); }
 
 signals:
 
@@ -148,8 +146,6 @@
 
 private:
 
-  base_qobject& m_octave_qobj;
-
   int m_dialog_result;
   QString m_dialog_button;
 
@@ -176,12 +172,12 @@
 
 public:
 
-  MessageDialog (base_qobject& oct_qobj, const QString& message,
+  MessageDialog (const QString& message,
                  const QString& title, const QString& icon,
                  const QStringList& button, const QString& defbutton,
                  const QStringList& role);
 
-  ~MessageDialog (void) = default;
+  ~MessageDialog () = default;
 
 private:
 
@@ -197,17 +193,15 @@
 {
   Q_OBJECT
 
-  QItemSelectionModel *selector;
-
 public:
 
-  ListDialog (base_qobject& oct_qobj, const QStringList& list,
+  ListDialog (const QStringList& list,
               const QString& mode, int width, int height,
               const QList<int>& initial, const QString& name,
               const QStringList& prompt, const QString& ok_string,
               const QString& cancel_string);
 
-  ~ListDialog (void) = default;
+  ~ListDialog () = default;
 
 signals:
 
@@ -215,32 +209,31 @@
 
 public slots:
 
-  void buttonOk_clicked (void);
+  void buttonOk_clicked ();
 
-  void buttonCancel_clicked (void);
+  void buttonCancel_clicked ();
 
-  void reject (void);
+  void reject ();
 
   void item_double_clicked (const QModelIndex&);
 
 private:
 
   QAbstractItemModel *m_model;
+  QItemSelectionModel *m_selector;
 };
 
 class InputDialog : public QDialog
 {
   Q_OBJECT
 
-  QList<QLineEdit *> input_line;
-
 public:
 
-  InputDialog (base_qobject& oct_qobj, const QStringList& prompt,
+  InputDialog (const QStringList& prompt,
                const QString& title, const QFloatList& nr,
                const QFloatList& nc, const QStringList& defaults);
 
-  ~InputDialog (void) = default;
+  ~InputDialog () = default;
 
 signals:
 
@@ -248,11 +241,15 @@
 
 public slots:
 
-  void buttonOk_clicked (void);
+  void buttonOk_clicked ();
+
+  void buttonCancel_clicked ();
 
-  void buttonCancel_clicked (void);
+  void reject ();
 
-  void reject (void);
+private:
+
+  QList<QLineEdit *> m_input_line;
 };
 
 class FileDialog : public QFileDialog
@@ -261,11 +258,11 @@
 
 public:
 
-  FileDialog (base_qobject& oct_qobj, const QStringList& filters,
+  FileDialog (const QStringList& filters,
               const QString& title, const QString& filename,
               const QString& dirname, const QString& multimode);
 
-  ~FileDialog (void) = default;
+  ~FileDialog () = default;
 
 signals:
 
@@ -273,9 +270,9 @@
 
 private slots:
 
-  void acceptSelection (void);
+  void acceptSelection ();
 
-  void rejectSelection (void);
+  void rejectSelection ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/documentation-bookmarks.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation-bookmarks.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -28,20 +28,22 @@
 #endif
 
 #include <QCompleter>
+#include <QDir>
+#include <QFileInfo>
+#include <QLabel>
+#include <QLineEdit>
 #include <QMenu>
-#include <QShortcut>
+#include <QMessageBox>
 #include <QVBoxLayout>
 #include <QWidget>
 
 #include "documentation.h"
 #include "documentation-bookmarks.h"
 
-#include "gui-settings.h"
 #include "gui-preferences-global.h"
 #include "gui-preferences-dc.h"
 #include "gui-preferences-sc.h"
-#include "octave-qtutils.h"
-#include "shortcut-manager.h"
+#include "gui-settings.h"
 
 #include "defaults.h"
 #include "file-ops.h"
@@ -49,17 +51,14 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-documentation_bookmarks::documentation_bookmarks (
-                                                  documentation *doc, documentation_browser *browser,
-                                                  base_qobject& oct_qobj, QWidget *p)
-: QWidget (p),
-  m_doc (doc), m_browser (browser), m_octave_qobj (oct_qobj),
-  m_ctx_menu_item (nullptr)
+documentation_bookmarks::documentation_bookmarks (documentation *doc,
+                                                  documentation_browser *browser,
+                                                  QWidget *p)
+  : QWidget (p), m_doc (doc), m_browser (browser), m_ctx_menu_item (nullptr)
 {
   setObjectName ("documentation_tab_bookmarks");
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   // Setup the tree view with the bookmarks
   m_tree = new QTreeWidget (p);
@@ -82,14 +81,14 @@
            this, &documentation_bookmarks::handle_double_click);
 
   // Define the icons for the tree view
-  icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirClosedIcon),
+  m_icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirClosedIcon),
                          QIcon::Normal, QIcon::Off);
-  icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirOpenIcon),
+  m_icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirOpenIcon),
                          QIcon::Normal, QIcon::On);
-  icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon));
+  m_icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon));
 
   // Setup and read the bookmarkfile
-  QFileInfo f (settings->fileName ());
+  QFileInfo f (settings.fileName ());
   QString f_path = f.absolutePath ();
   f.setFile (QDir (f_path), dc_bookmark_file);
   m_xbel_file.setFileName (f.absoluteFilePath ());
@@ -121,7 +120,7 @@
   m_filter->setSizePolicy (size_pol);
   m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
 
-  m_filter->addItems (settings->value (dc_bookmark_filter_mru).toStringList ());
+  m_filter->addItems (settings.string_list_value (dc_bookmark_filter_mru));
 
   connect (m_filter, &QComboBox::editTextChanged,
            this, &documentation_bookmarks::filter_bookmarks);
@@ -129,7 +128,7 @@
            this, &documentation_bookmarks::update_filter_history);
 
   m_filter_checkbox = new QCheckBox (m_filter_widget);
-  bool filter_state = settings->value (dc_bookmark_filter_active).toBool ();
+  bool filter_state = settings.bool_value (dc_bookmark_filter_active);
   m_filter_checkbox->setChecked (filter_state);
   filter_activate (filter_state);
 
@@ -141,10 +140,10 @@
   h_box_bm->addWidget (filter_label);
   h_box_bm->addWidget (m_filter_checkbox);
   h_box_bm->addWidget (m_filter);
-  h_box_bm->setMargin (2);
+  h_box_bm->setContentsMargins (2, 2, 2, 2);
   m_filter_widget->setLayout (h_box_bm);
 
-  m_filter_shown = settings->value (dc_bookmark_filter_shown).toBool ();
+  m_filter_shown = settings.bool_value (dc_bookmark_filter_shown);
   m_filter_widget->setVisible (m_filter_shown);
 
   // Resulting Layout of this widget
@@ -155,7 +154,7 @@
 }
 
 // Slot for adding the current page as a bookmark
-void documentation_bookmarks::add_bookmark (void)
+void documentation_bookmarks::add_bookmark ()
 {
   QUrl url = m_browser->historyUrl (0);
 
@@ -189,9 +188,9 @@
   new_item->setData (0, tag_role, QVariant (bookmark_tag));
   new_item->setData (0, url_role, QVariant (url));
   new_item->setFlags ((new_item->flags () & (~Qt::ItemIsDropEnabled))
-                      | Qt::ItemIsEditable
-                      | Qt::ItemIsDragEnabled);
-  new_item->setIcon (0, icon_bookmark);
+                                          | Qt::ItemIsEditable
+                                          | Qt::ItemIsDragEnabled);
+  new_item->setIcon (0, m_icon_bookmark);
 
   // Insert as top level or child item
   // TODO: Open dialog allowing to select a target folder if this
@@ -227,15 +226,15 @@
 
 // Function for actually adding a folder to the tree
 QTreeWidgetItem* documentation_bookmarks::add_folder (const QString& folder,
-                                                      QTreeWidgetItem *item, bool expanded)
+                                          QTreeWidgetItem *item, bool expanded)
 {
   QTreeWidgetItem *new_folder = new QTreeWidgetItem (QStringList (folder));
   new_folder->setData (0, tag_role, QVariant (folder_tag));
   new_folder->setFlags (new_folder->flags() | Qt::ItemIsEditable
-                        | Qt::ItemIsDragEnabled
-                        | Qt::ItemIsDropEnabled);
+                                            | Qt::ItemIsDragEnabled
+                                            | Qt::ItemIsDropEnabled);
   new_folder->setChildIndicatorPolicy (QTreeWidgetItem::DontShowIndicatorWhenChildless);
-  new_folder->setIcon (0, icon_folder);
+  new_folder->setIcon (0, m_icon_folder);
   new_folder->setExpanded (expanded);
 
   // Insert as top level or child item
@@ -283,7 +282,7 @@
   filter_bookmarks (pattern);
 }
 
-void documentation_bookmarks::update_filter_history (void)
+void documentation_bookmarks::update_filter_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -322,11 +321,11 @@
 
   if (m_ctx_menu_item)
     {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+      gui_settings settings;
 
       menu.addAction (tr ("&Open"), this, &documentation_bookmarks::open);
       menu.addAction (tr ("&Rename"), this, &documentation_bookmarks::edit);
-      menu.addAction (rmgr.icon ("window-close"), tr ("Remo&ve"),
+      menu.addAction (settings.icon ("window-close"), tr ("Remo&ve"),
                       this, &documentation_bookmarks::remove);
       menu.addSeparator ();
     }
@@ -366,12 +365,9 @@
 {
   QList<QTreeWidgetItem *> items = m_tree->selectedItems ();
 
-  for (auto it = items.begin () ; it != items.end (); it++)
-    {
-      if (*it)
-        m_tree->takeTopLevelItem (
-                                  m_tree->indexOfTopLevelItem (*it));
-    }
+  for (const auto& it : items)
+    if (it)
+      m_tree->takeTopLevelItem (m_tree->indexOfTopLevelItem (it));
 }
 
 void documentation_bookmarks::show_filter (bool)
@@ -380,32 +376,34 @@
   m_filter_widget->setVisible (m_filter_shown);
 }
 
-void documentation_bookmarks::save_settings (gui_settings *settings)
+void documentation_bookmarks::save_settings ()
 {
   // Write the bookmarks to the xbel-file
   write_bookmarks ();
 
   // Store settings
-  settings->setValue (dc_bookmark_filter_active.key, m_filter_checkbox->isChecked ());
-  settings->setValue (dc_bookmark_filter_shown.key, m_filter_shown);
+  gui_settings settings;
+
+  settings.setValue (dc_bookmark_filter_active.settings_key (), m_filter_checkbox->isChecked ());
+  settings.setValue (dc_bookmark_filter_shown.settings_key (), m_filter_shown);
 
   QStringList mru;
   for (int i = 0; i < m_filter->count (); i++)
     mru.append (m_filter->itemText (i));
-  settings->setValue (dc_bookmark_filter_mru.key, mru);
+  settings.setValue (dc_bookmark_filter_mru.settings_key (), mru);
 
-  settings->sync ();
+  settings.sync ();
 }
 
-void documentation_bookmarks::write_bookmarks (void)
+void documentation_bookmarks::write_bookmarks ()
 {
   if (! m_xbel_file.open (QFile::WriteOnly | QFile::Text))
     {
       QMessageBox::warning (this, tr("Octave: Saving Documentation Bookmarks"),
                             tr("Unable to write file %1:\n%2.\n\n"
                                "Documentation bookmarks are not saved!\n")
-                            .arg (m_xbel_file.fileName ())
-                            .arg (m_xbel_file.errorString()));
+                              .arg (m_xbel_file.fileName ())
+                              .arg (m_xbel_file.errorString()));
       return;
     }
 
@@ -450,7 +448,7 @@
     }
 }
 
-QString documentation_bookmarks::read_bookmarks (void)
+QString documentation_bookmarks::read_bookmarks ()
 {
   QString error_message;
 
@@ -458,8 +456,8 @@
   if (! m_xbel_file.open (QFile::ReadOnly | QFile::Text))
     {
       error_message = tr ("Unable to read file %1:\n%2.")
-        .arg (m_xbel_file.fileName ())
-        .arg (m_xbel_file.errorString());
+                          .arg (m_xbel_file.fileName ())
+                          .arg (m_xbel_file.errorString());
       return error_message;
     }
 
@@ -469,7 +467,7 @@
     {
       error_message = tr ("No start element found in %1.\n"
                           "Invalid bookmark file?")
-        .arg (m_xbel_file.fileName ());
+                          .arg (m_xbel_file.fileName ());
       return error_message;
     }
 
@@ -479,7 +477,7 @@
       error_message = tr ("The file\n"
                           "%1\n"
                           "is not a valid XBEL file version 1.0.")
-        .arg (m_xbel_file.fileName ());
+                          .arg (m_xbel_file.fileName ());
       return error_message;
     }
 
--- a/libgui/src/documentation-bookmarks.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation-bookmarks.h	Fri Jun 23 20:51:51 2023 +0200
@@ -28,15 +28,14 @@
 
 #include <QCheckBox>
 #include <QComboBox>
+#include <QFile>
 #include <QTreeWidget>
 #include <QXmlStreamWriter>
 
 #include "documentation.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class documentation;
 
 class documentation_bookmarks : public QWidget
@@ -45,23 +44,23 @@
 
 public:
 
-  documentation_bookmarks (
-                           documentation *doc, documentation_browser *browser,
-                           base_qobject& oct_qobj, QWidget *p = nullptr);
+  documentation_bookmarks (documentation *doc,
+                           documentation_browser *browser,
+                           QWidget *p = nullptr);
 
-  ~documentation_bookmarks (void) = default;
+  ~documentation_bookmarks () = default;
 
 public slots:
 
-  void add_bookmark (void);
+  void add_bookmark ();
   void add_folder (bool);
-  void save_settings (gui_settings *settings);
+  void save_settings ();
 
 private slots:
 
   void filter_bookmarks (const QString& pattern);
   void filter_activate (bool state);
-  void update_filter_history (void);
+  void update_filter_history ();
   void handle_double_click (QTreeWidgetItem *item, int col = 0);
   void ctx_menu (const QPoint& xpos);
   void open (bool);
@@ -72,15 +71,15 @@
 private:
 
   enum item_role
-    {
-      url_role = Qt::UserRole,
-      tag_role = Qt::UserRole + 1
-    };
+  {
+    url_role = Qt::UserRole,
+    tag_role = Qt::UserRole + 1
+  };
   enum item_tag
-    {
-      bookmark_tag,
-      folder_tag
-    };
+  {
+    bookmark_tag,
+    folder_tag
+  };
 
   void add_bookmark (const QString& title, const QString& url,
                      QTreeWidgetItem *item = nullptr);
@@ -89,28 +88,27 @@
                                bool expanded = true);
 
   /*!
-    Writing to and reading bookmarks from an xbel-file as
-    proposed in the qt example
-    [QXmlStream Bookmarks Example](https://doc.qt.io/qt-5/qtxml-streambookmarks-example.html)
+      Writing to and reading bookmarks from an xbel-file as
+      proposed in the qt example
+      [QXmlStream Bookmarks Example](https://doc.qt.io/qt-5/qtxml-streambookmarks-example.html)
   */
-  void write_bookmarks (void);
+  void write_bookmarks ();
   void write_tree_item (QXmlStreamWriter *xml_writer,
                         const QTreeWidgetItem *item);
-  QString read_bookmarks (void);
+  QString read_bookmarks ();
   void read_next_item (QXmlStreamReader *xml_writer, item_tag tag,
                        QTreeWidgetItem *item = nullptr);
 
   documentation *m_doc;
   documentation_browser *m_browser;
-  base_qobject& m_octave_qobj;
 
   QComboBox *m_filter;
   QTreeWidget *m_tree;
 
   QTreeWidgetItem *m_ctx_menu_item;
 
-  QIcon icon_folder;
-  QIcon icon_bookmark;
+  QIcon m_icon_folder;
+  QIcon m_icon_bookmark;
 
   QWidget *m_filter_widget;
   QCheckBox *m_filter_checkbox;
--- a/libgui/src/documentation-dock-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation-dock-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,10 +33,9 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-documentation_dock_widget::documentation_dock_widget (QWidget *p,
-                                                      base_qobject& oct_qobj)
-: octave_dock_widget ("DocumentationDockWidget", p, oct_qobj),
-  m_docs (new documentation (this, oct_qobj))
+documentation_dock_widget::documentation_dock_widget (QWidget *p)
+  : octave_dock_widget ("DocumentationDockWidget", p),
+    m_docs (new documentation (this))
 {
   set_title (tr ("Documentation"));
   setStatusTip (tr ("See the documentation for help."));
@@ -47,28 +46,28 @@
     make_window ();
 }
 
-void documentation_dock_widget::notice_settings (const gui_settings *settings)
+void documentation_dock_widget::notice_settings ()
 {
-  m_docs->notice_settings (settings);
+  m_docs->notice_settings ();
 }
 
-void documentation_dock_widget::save_settings (void)
+void documentation_dock_widget::save_settings ()
 {
   m_docs->save_settings ();
   octave_dock_widget::save_settings ();
 }
 
-void documentation_dock_widget::copyClipboard (void)
+void documentation_dock_widget::copyClipboard ()
 {
   m_docs->copyClipboard ();
 }
 
-void documentation_dock_widget::pasteClipboard (void)
+void documentation_dock_widget::pasteClipboard ()
 {
   m_docs->pasteClipboard ();
 }
 
-void documentation_dock_widget::selectAll (void)
+void documentation_dock_widget::selectAll ()
 {
   m_docs->selectAll ();
 }
--- a/libgui/src/documentation-dock-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation-dock-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,26 +31,24 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class documentation_dock_widget : public octave_dock_widget
 {
   Q_OBJECT
 
 public:
 
-  documentation_dock_widget (QWidget *parent, base_qobject& oct_qobj);
+  documentation_dock_widget (QWidget *parent);
 
-  ~documentation_dock_widget (void) = default;
+  ~documentation_dock_widget () = default;
 
 public slots:
 
-  void notice_settings (const gui_settings *settings);
-  void save_settings (void);
+  void notice_settings ();
+  void save_settings ();
 
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
 
   void showDoc (const QString& name);
   void registerDoc (const QString& name);
--- a/libgui/src/documentation.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,17 +47,19 @@
 #include <QLabel>
 #include <QLineEdit>
 #include <QMessageBox>
+#include <QRegularExpression>
 #include <QTabWidget>
 #include <QTimer>
+#include <QWheelEvent>
 #include <QVBoxLayout>
+#include <QWheelEvent>
 
 #include "documentation.h"
 #include "documentation-bookmarks.h"
 #include "gui-preferences-global.h"
 #include "gui-preferences-dc.h"
 #include "gui-preferences-sc.h"
-#include "octave-qobject.h"
-#include "shortcut-manager.h"
+#include "gui-settings.h"
 
 #include "defaults.h"
 #include "file-ops.h"
@@ -67,19 +69,19 @@
 
 // The documentation splitter, which is the main widget
 // of the doc dock widget
-documentation::documentation (QWidget *p, base_qobject& oct_qobj)
-: QSplitter (Qt::Horizontal, p),
-  m_octave_qobj (oct_qobj), m_doc_widget (this),
-  m_tool_bar (new QToolBar (this)),
-  m_query_string (QString ()),
-  m_indexed (false),
-  m_current_ref_name (QString ()),
-  m_prev_pages_menu (new QMenu (this)),
-  m_next_pages_menu (new QMenu (this)),
-  m_prev_pages_count (0),
-  m_next_pages_count (0),
-  m_findnext_shortcut (new QShortcut (this)),
-  m_findprev_shortcut (new QShortcut (this))
+documentation::documentation (QWidget *p)
+  : QSplitter (Qt::Horizontal, p),
+    m_doc_widget (this),
+    m_tool_bar (new QToolBar (this)),
+    m_query_string (QString ()),
+    m_indexed (false),
+    m_current_ref_name (QString ()),
+    m_prev_pages_menu (new QMenu (this)),
+    m_next_pages_menu (new QMenu (this)),
+    m_prev_pages_count (0),
+    m_next_pages_count (0),
+    m_findnext_shortcut (new QShortcut (this)),
+    m_findprev_shortcut (new QShortcut (this))
 {
   // Get original collection
   QString collection = getenv ("OCTAVE_QTHELP_COLLECTION");
@@ -156,14 +158,16 @@
   QToolButton *forward_button = new QToolButton (find_footer);
   forward_button->setText (tr ("Search forward"));
   forward_button->setToolTip (tr ("Search forward"));
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  forward_button->setIcon (rmgr.icon ("go-down"));
+
+  gui_settings settings;
+
+  forward_button->setIcon (settings.icon ("go-down"));
   connect (forward_button, &QToolButton::pressed,
            this, [=] () { find (); });
   QToolButton *backward_button = new QToolButton (find_footer);
   backward_button->setText (tr ("Search backward"));
   backward_button->setToolTip (tr ("Search backward"));
-  backward_button->setIcon (rmgr.icon ("go-up"));
+  backward_button->setIcon (settings.icon ("go-up"));
   connect (backward_button, &QToolButton::pressed,
            this, &documentation::find_backward);
   QHBoxLayout *h_box_find_footer = new QHBoxLayout (find_footer);
@@ -171,7 +175,7 @@
   h_box_find_footer->addWidget (m_find_line_edit);
   h_box_find_footer->addWidget (forward_button);
   h_box_find_footer->addWidget (backward_button);
-  h_box_find_footer->setMargin (2);
+  h_box_find_footer->setContentsMargins (2, 2, 2, 2);
   find_footer->setLayout (h_box_find_footer);
 
   QVBoxLayout *v_box_browser_find = new QVBoxLayout (browser_find);
@@ -180,7 +184,7 @@
   v_box_browser_find->addWidget (find_footer);
   browser_find->setLayout (v_box_browser_find);
 
-  notice_settings (rmgr.get_settings ());
+  notice_settings ();
 
   m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
   connect (m_findnext_shortcut, &QShortcut::activated,
@@ -232,7 +236,7 @@
       QHBoxLayout *h_box_index = new QHBoxLayout (filter_all);
       h_box_index->addWidget (filter_label);
       h_box_index->addWidget (m_filter);
-      h_box_index->setMargin (2);
+      h_box_index->setContentsMargins (2, 2, 2, 2);
       filter_all->setLayout (h_box_index);
 
       QWidget *index_all = new QWidget (navi);
@@ -262,8 +266,7 @@
                this, &documentation::filter_update_history);
 
       // Bookmarks (own class)
-      m_bookmarks
-        = new documentation_bookmarks (this, m_doc_browser, m_octave_qobj, navi);
+      m_bookmarks = new documentation_bookmarks (this, m_doc_browser, navi);
       navi->addTab (m_bookmarks, tr ("Bookmarks"));
 
       connect (m_action_bookmark, &QAction::triggered,
@@ -300,7 +303,7 @@
     }
 }
 
-documentation::~documentation (void)
+documentation::~documentation ()
 {
   // Cleanup temporary file and directory
   QFile file (m_collection);
@@ -345,17 +348,18 @@
   return a;
 }
 
-void documentation::construct_tool_bar (void)
+void documentation::construct_tool_bar ()
 {
   // Home, Previous, Next
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
+
   m_action_go_home
-    = add_action (rmgr.icon ("go-home"), tr ("Go home"), SLOT (home (void)),
+    = add_action (settings.icon ("go-home"), tr ("Go home"), SLOT (home ()),
                   m_doc_browser, m_tool_bar);
 
   m_action_go_prev
-    = add_action (rmgr.icon ("go-previous"), tr ("Go back"),
-                  SLOT (backward (void)), m_doc_browser, m_tool_bar);
+    = add_action (settings.icon ("go-previous"), tr ("Go back"),
+                  SLOT (backward ()), m_doc_browser, m_tool_bar);
   m_action_go_prev->setEnabled (false);
 
   // popdown menu with prev pages files
@@ -369,8 +373,8 @@
   m_tool_bar->addWidget (popdown_button_prev_pages);
 
   m_action_go_next
-    = add_action (rmgr.icon ("go-next"), tr ("Go forward"),
-                  SLOT (forward (void)), m_doc_browser, m_tool_bar);
+    = add_action (settings.icon ("go-next"), tr ("Go forward"),
+                  SLOT (forward ()), m_doc_browser, m_tool_bar);
   m_action_go_next->setEnabled (false);
 
   // popdown menu with prev pages files
@@ -412,29 +416,29 @@
   // Find
   m_tool_bar->addSeparator ();
   m_action_find
-    = add_action (rmgr.icon ("edit-find"), tr ("Find"),
-                  SLOT (activate_find (void)), this, m_tool_bar);
+    = add_action (settings.icon ("edit-find"), tr ("Find"),
+                  SLOT (activate_find ()), this, m_tool_bar);
 
   // Zoom
   m_tool_bar->addSeparator ();
   m_action_zoom_in
-    = add_action (rmgr.icon ("view-zoom-in"), tr ("Zoom in"),
-                  SLOT (zoom_in (void)), m_doc_browser, m_tool_bar);
+    = add_action (settings.icon ("view-zoom-in"), tr ("Zoom in"),
+                  SLOT (zoom_in ()), m_doc_browser, m_tool_bar);
   m_action_zoom_out
-    = add_action (rmgr.icon ("view-zoom-out"), tr ("Zoom out"),
-                  SLOT (zoom_out (void)), m_doc_browser, m_tool_bar);
+    = add_action (settings.icon ("view-zoom-out"), tr ("Zoom out"),
+                  SLOT (zoom_out ()), m_doc_browser, m_tool_bar);
   m_action_zoom_original
-    = add_action (rmgr.icon ("view-zoom-original"), tr ("Zoom original"),
-                  SLOT (zoom_original (void)), m_doc_browser, m_tool_bar);
+    = add_action (settings.icon ("view-zoom-original"), tr ("Zoom original"),
+                  SLOT (zoom_original ()), m_doc_browser, m_tool_bar);
 
   // Bookmarks (connect slots later)
   m_tool_bar->addSeparator ();
   m_action_bookmark
-    = add_action (rmgr.icon ("bookmark-new"), tr ("Bookmark current page"),
-                  nullptr, nullptr, m_tool_bar);
+    = add_action (settings.icon ("bookmark-new"),
+                  tr ("Bookmark current page"), nullptr, nullptr, m_tool_bar);
 }
 
-void documentation::global_search (void)
+void documentation::global_search ()
 {
   if (! m_help_engine)
     return;
@@ -458,20 +462,21 @@
     return;
 
   // Get quoted search strings first, then take first string as fall back
-  QRegExp rx ("\"([^\"]*)\"");
-  if (rx.indexIn (query_string, 0) != -1)
-    m_internal_search = rx.cap (1);
+  QRegularExpression rx {"\"([^\"]*)\""};
+  QRegularExpressionMatch match = rx.match (query_string);
+  if (match.hasMatch ())
+    m_internal_search = match.captured (1);
   else
 #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
     m_internal_search = query_string.split (" ", Qt::SkipEmptyParts).first ();
 #else
-  m_internal_search = query_string.split (" ", QString::SkipEmptyParts).first ();
+    m_internal_search = query_string.split (" ", QString::SkipEmptyParts).first ();
 #endif
 
   m_help_engine->searchEngine ()->search (queries);
 }
 
-void documentation::global_search_started (void)
+void documentation::global_search_started ()
 {
   qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
 }
@@ -504,21 +509,21 @@
 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
                 url = res.front ().url ();
 #else
-              url = res.front ().first;
+                url = res.front ().first;
 #endif
               else
                 {
                   // Remove the quotes we added
                   QString search_string = m_internal_search;
 
-                  for (auto r = res.begin (); r != res.end (); r++)
+                  for (const auto& r : res)
                     {
 #if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
-                      QString title = r->title ().toLower ();
-                      QUrl tmpurl = r->url ();
+                      QString title = r.title ().toLower ();
+                      QUrl tmpurl = r.url ();
 #else
-                      QString title = r->second.toLower ();
-                      QUrl tmpurl = r->first;
+                      QString title = r.second.toLower ();
+                      QUrl tmpurl = r.first;
 #endif
                       if (title.contains (search_string.toLower ()))
                         {
@@ -603,15 +608,17 @@
   m_doc_browser->moveCursor (QTextCursor::Start);
 }
 
-void documentation::notice_settings (const gui_settings *settings)
+void documentation::notice_settings ()
 {
+  gui_settings settings;
+
   // If m_help_engine is not defined, the objects accessed by this method
   // are not valid.  Thus, just return in this case.
   if (! m_help_engine)
     return;
 
   // Icon size in the toolbar.
-  int size_idx = settings->value (global_icon_size).toInt ();
+  int size_idx = settings.int_value (global_icon_size);
   size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
   QStyle *st = style ();
@@ -619,33 +626,30 @@
   m_tool_bar->setIconSize (QSize (icon_size, icon_size));
 
   // Shortcuts
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-
-  scmgr.set_shortcut (m_action_find, sc_edit_edit_find_replace);
-  scmgr.shortcut (m_findnext_shortcut, sc_edit_edit_find_next);
-  scmgr.shortcut (m_findprev_shortcut, sc_edit_edit_find_previous);
-  scmgr.set_shortcut (m_action_zoom_in, sc_edit_view_zoom_in);
-  scmgr.set_shortcut (m_action_zoom_out, sc_edit_view_zoom_out);
-  scmgr.set_shortcut (m_action_zoom_original, sc_edit_view_zoom_normal);
-  scmgr.set_shortcut (m_action_go_home, sc_doc_go_home);
-  scmgr.set_shortcut (m_action_go_prev, sc_doc_go_back);
-  scmgr.set_shortcut (m_action_go_next, sc_doc_go_next);
-  scmgr.set_shortcut (m_action_bookmark, sc_doc_bookmark);
+  settings.set_shortcut (m_action_find, sc_edit_edit_find_replace);
+  settings.shortcut (m_findnext_shortcut, sc_edit_edit_find_next);
+  settings.shortcut (m_findprev_shortcut, sc_edit_edit_find_previous);
+  settings.set_shortcut (m_action_zoom_in, sc_edit_view_zoom_in);
+  settings.set_shortcut (m_action_zoom_out, sc_edit_view_zoom_out);
+  settings.set_shortcut (m_action_zoom_original, sc_edit_view_zoom_normal);
+  settings.set_shortcut (m_action_go_home, sc_doc_go_home);
+  settings.set_shortcut (m_action_go_prev, sc_doc_go_back);
+  settings.set_shortcut (m_action_go_next, sc_doc_go_next);
+  settings.set_shortcut (m_action_bookmark, sc_doc_bookmark);
 
   // Settings for the browser
-  m_doc_browser->notice_settings (settings);
+  m_doc_browser->notice_settings ();
 }
 
-void documentation::save_settings (void)
+void documentation::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  m_doc_browser->save_settings (settings);
-  m_bookmarks->save_settings (settings);
+  m_doc_browser->save_settings ();
+  m_bookmarks->save_settings ();
 }
 
-void documentation::copyClipboard (void)
+void documentation::copyClipboard ()
 {
   if (m_doc_browser->hasFocus ())
     {
@@ -653,11 +657,11 @@
     }
 }
 
-void documentation::pasteClipboard (void) { }
+void documentation::pasteClipboard () { }
 
-void documentation::selectAll (void) { }
+void documentation::selectAll () { }
 
-void documentation::load_index (void)
+void documentation::load_index ()
 {
   m_indexed = true;
 
@@ -737,7 +741,7 @@
     }
 }
 
-void documentation::activate_find (void)
+void documentation::activate_find ()
 {
   if (m_find_line_edit->parentWidget ()->isVisible ())
     {
@@ -764,7 +768,7 @@
   m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
 }
 
-void documentation::filter_update_history (void)
+void documentation::filter_update_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -776,7 +780,7 @@
   m_filter->setCurrentIndex (0);
 }
 
-void documentation::find_backward (void)
+void documentation::find_backward ()
 {
   find (true);
 }
@@ -824,7 +828,7 @@
     }
 }
 
-void documentation::record_anchor_position (void)
+void documentation::record_anchor_position ()
 {
   if (! m_help_engine)
     return;
@@ -832,7 +836,7 @@
   m_search_anchor_position = m_doc_browser->textCursor ().position ();
 }
 
-void documentation::handle_cursor_position_change (void)
+void documentation::handle_cursor_position_change ()
 {
   if (! m_help_engine)
     return;
@@ -885,7 +889,7 @@
     }
 }
 
-void documentation::update_history_menus (void)
+void documentation::update_history_menus ()
 {
   if (m_prev_pages_count != m_doc_browser->backwardHistoryCount ())
     {
@@ -952,7 +956,7 @@
   QString retval = title;
   QString u = url.toString ();
 
-  retval.remove (QRegExp ("\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*"));
+  retval.remove (QRegularExpression {"\\s*\\(*GNU Octave \\(version [^\\)]*\\)[: \\)]*"});
 
   // Since the title only contains the section name and not the
   // specific anchor, extract the latter from the url and append
@@ -962,19 +966,22 @@
       // Get the anchor from the url
       QString anchor = u.split ('#').last ();
       // Remove internal string parts
-      anchor.remove (QRegExp ("^index-"));
-      anchor.remove (QRegExp ("^SEC_"));
-      anchor.remove (QRegExp ("^XREF"));
+      anchor.remove (QRegularExpression {"^index-"});
+      anchor.remove (QRegularExpression {"^SEC_"});
+      anchor.remove (QRegularExpression {"^XREF"});
       anchor.remove ("Concept-Index_cp_letter-");
       anchor.replace ("-", " ");
 
       // replace encoded special chars by their unencoded versions
-      QRegExp rx = QRegExp ("_00([0-7][0-9a-f])");
+      QRegularExpression rx {"_00([0-7][0-9a-f])"};
+      QRegularExpressionMatch match = rx.match (anchor, 0);
       int pos = 0;
-      while ((pos = rx.indexIn(anchor, pos)) != -1)
+      while (match.hasMatch ())
         {
-          anchor.replace ("_00"+rx.cap (1), QChar (rx.cap (1).toInt (nullptr, 16)));
-          pos += rx.matchedLength();
+          anchor.replace ("_00" + match.captured (1),
+                          QChar (match.captured (1).toInt (nullptr, 16)));
+          pos += match.capturedLength ();
+          match = rx.match (anchor, pos);
         }
 
       if (retval != anchor)
@@ -998,7 +1005,7 @@
   // Make sure we have access to one of the monospace fonts listed in
   // octave.css for rendering formated code blocks
   QStringList fonts = {"Fantasque Sans Mono", "FreeMono", "Courier New",
-    "Cousine", "Courier"};
+                       "Cousine", "Courier"};
 
   bool load_default_font = true;
 
@@ -1019,7 +1026,7 @@
                                 + sys::file_ops::dir_sep_str ());
 
       QStringList default_fonts = {"FreeMono", "FreeMonoBold",
-        "FreeMonoBoldOblique", "FreeMonoOblique"};
+                                   "FreeMonoBoldOblique", "FreeMonoOblique"};
 
       for (int i = 0; i < default_fonts.size (); ++i)
         {
@@ -1039,12 +1046,14 @@
     QDesktopServices::openUrl (url);
 }
 
-void documentation_browser::notice_settings (const gui_settings *settings)
+void documentation_browser::notice_settings ()
 {
+  gui_settings settings;
+
   // Zoom level only at startup, not when other settings have changed
   if (m_zoom_level > max_zoom_level)
     {
-      m_zoom_level = settings->value (dc_browser_zoom_level).toInt ();
+      m_zoom_level = settings.int_value (dc_browser_zoom_level);
       zoomIn (m_zoom_level);
     }
 }
@@ -1057,14 +1066,16 @@
     return QTextBrowser::loadResource(type, url);
 }
 
-void documentation_browser::save_settings (gui_settings *settings)
+void documentation_browser::save_settings ()
 {
-  settings->setValue (dc_browser_zoom_level.key, m_zoom_level);
+  gui_settings settings;
 
-  settings->sync ();
+  settings.setValue (dc_browser_zoom_level.settings_key (), m_zoom_level);
+
+  settings.sync ();
 }
 
-void documentation_browser::zoom_in (void)
+void documentation_browser::zoom_in ()
 {
   if (m_zoom_level < max_zoom_level)
     {
@@ -1073,7 +1084,7 @@
     }
 }
 
-void documentation_browser::zoom_out (void)
+void documentation_browser::zoom_out ()
 {
   if (m_zoom_level > min_zoom_level)
     {
@@ -1082,7 +1093,7 @@
     }
 }
 
-void documentation_browser::zoom_original (void)
+void documentation_browser::zoom_original ()
 {
   zoomIn (- m_zoom_level);
   m_zoom_level = 0;
@@ -1092,14 +1103,10 @@
 {
   if (we->modifiers () == Qt::ControlModifier)
     {
-#if defined (HAVE_QWHEELEVENT_ANGLEDELTA)
       if (we->angleDelta().y () > 0)
-#else
-        if (we->delta() > 0)
-#endif
-          zoom_in ();
-        else
-          zoom_out ();
+        zoom_in ();
+      else
+        zoom_out ();
 
       we->accept ();
     }
--- a/libgui/src/documentation.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/documentation.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,11 +37,8 @@
 #include <QWidget>
 #include <QtHelp/QHelpEngine>
 
-#include "gui-settings.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class documentation;
 class documentation_bookmarks;
 
@@ -54,7 +51,7 @@
 public:
 
   documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr);
-  ~documentation_browser (void) = default;
+  ~documentation_browser () = default;
 
   virtual QVariant loadResource (int type, const QUrl& url);
 
@@ -62,14 +59,14 @@
 
   void handle_index_clicked (const QUrl& url,
                              const QString& keyword = QString ());
-  void notice_settings (const gui_settings *settings);
-  void save_settings (gui_settings *settings);
+  void notice_settings ();
+  void save_settings ();
 
   //! Zooming in and out while taking care of the zoom level
   //!@{
-  void zoom_in (void);
-  void zoom_out (void);
-  void zoom_original (void);
+  void zoom_in ();
+  void zoom_out ();
+  void zoom_original ();
   //!@}
 
 protected:
@@ -87,10 +84,10 @@
   //! zoom_in and zoom_out without actually zooming but
   //! with changing the stored zoom level
   enum
-    {
-      min_zoom_level = -5,
-      max_zoom_level = 10
-    };
+  {
+    min_zoom_level = -5,
+    max_zoom_level = 10
+  };
 };
 
 //! The documentation main class derived from QSplitter
@@ -101,17 +98,17 @@
 
 public:
 
-  documentation (QWidget *parent, base_qobject& oct_qobj);
-  ~documentation (void);
+  documentation (QWidget *parent);
+  ~documentation ();
 
   /*!
-    Generate a string with page name @p title and current anchor
-    from @p url for using in prev/next or bookmarks menu:
+      Generate a string with page name @p title and current anchor
+      from @p url for using in prev/next or bookmarks menu:
 
-    @param title current title of the page as QString
-    @param url   current url  as QUrl
+        @param title current title of the page as QString
+        @param url   current url  as QUrl
 
-    @return QString "title: anchor"
+        @return QString "title: anchor"
   */
   QString title_and_anchor (const QString& title, const QUrl& url);
 
@@ -121,39 +118,39 @@
 
 public slots:
 
-  void notice_settings (const gui_settings *settings);
-  void save_settings (void);
+  void notice_settings ();
+  void save_settings ();
 
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
 
-  void load_index (void);
+  void load_index ();
   void load_ref (const QString& name = QString ());
   void registerDoc (const QString& name);
   void unregisterDoc (const QString& name);
 
 private slots:
 
-  void activate_find (void);
-  void global_search (void);
-  void global_search_started (void);
+  void activate_find ();
+  void global_search ();
+  void global_search_started ();
   void global_search_finished (int hits);
   void filter_update (const QString& expression);
-  void filter_update_history (void);
+  void filter_update_history ();
   void find (bool backward = false);
-  void find_backward (void);
+  void find_backward ();
   void find_forward_from_anchor (const QString& text);
-  void record_anchor_position (void);
-  void handle_cursor_position_change (void);
+  void record_anchor_position ();
+  void handle_cursor_position_change ();
   void handle_search_result_clicked (const QUrl& url);
 
-  void update_history_menus (void);
+  void update_history_menus ();
   void open_hist_url (QAction *a);
 
 private:
 
-  void construct_tool_bar (void);
+  void construct_tool_bar ();
   QAction * add_action (const QIcon& icon, const QString& text,
                         const char *member, QWidget *receiver = nullptr,
                         QToolBar *tool_bar = nullptr);
@@ -162,8 +159,6 @@
   //! Select all occurrences of a string in the doc browser
   void select_all_occurrences (const QString& text);
 
-  base_qobject& m_octave_qobj;
-
   QHelpEngine *m_help_engine;
   QString m_internal_search;
   documentation_browser *m_doc_browser;
--- a/libgui/src/dw-main-window.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/dw-main-window.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,31 +33,31 @@
 #endif
 
 #include <QDockWidget>
+#include <QEvent>
 #include <QMenu>
 
 #include "dw-main-window.h"
-#include "octave-qobject.h"
-#include "shortcut-manager.h"
 #include "gui-preferences-sc.h"
+#include "gui-settings.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-dw_main_window::dw_main_window (base_qobject& oct_qobj, QWidget *p)
-: QMainWindow (p), m_octave_qobj (oct_qobj)
+dw_main_window::dw_main_window (QWidget *p)
+  : QMainWindow (p)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   // Adding the actions for closing the dock widgets
   m_close_action
-    = add_action (nullptr, rmgr.icon ("window-close", false),
+    = add_action (nullptr, settings.icon ("window-close", false),
                   tr ("&Close"), SLOT (request_close ()), this);
 
   m_close_all_action
-    = add_action (nullptr, rmgr.icon ("window-close", false),
+    = add_action (nullptr, settings.icon ("window-close", false),
                   tr ("Close &All"), SLOT (request_close_all ()), this);
 
   m_close_others_action
-    = add_action (nullptr, rmgr.icon ("window-close", false),
+    = add_action (nullptr, settings.icon ("window-close", false),
                   tr ("Close &Other"), SLOT (request_close_other ()), this);
 
   m_switch_left_action
@@ -75,7 +75,7 @@
   m_actions_list << m_switch_left_action;
   m_actions_list << m_switch_right_action;
 
-  notice_settings (rmgr.get_settings ());
+  notice_settings ();
 }
 
 // Re-implementing the popup menu of the main window
@@ -127,16 +127,16 @@
 }
 
 // Update the settings
-void dw_main_window::notice_settings (const gui_settings *)
+void dw_main_window::notice_settings ()
 {
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
+  gui_settings settings;
 
-  scmgr.set_shortcut (m_close_action, sc_edit_file_close);
-  scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all);
-  scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other);
+  settings.set_shortcut (m_close_action, sc_edit_file_close);
+  settings.set_shortcut (m_close_all_action, sc_edit_file_close_all);
+  settings.set_shortcut (m_close_others_action, sc_edit_file_close_other);
 
-  scmgr.set_shortcut (m_switch_left_action, sc_edit_tabs_switch_left_tab);
-  scmgr.set_shortcut (m_switch_right_action, sc_edit_tabs_switch_right_tab);
+  settings.set_shortcut (m_switch_left_action, sc_edit_tabs_switch_left_tab);
+  settings.set_shortcut (m_switch_right_action, sc_edit_tabs_switch_right_tab);
 }
 
 // Slots for handling actions
--- a/libgui/src/dw-main-window.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/dw-main-window.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,33 +26,27 @@
 #if ! defined (octave_dw_main_window_h)
 #define octave_dw_main_window_h 1
 
+#include "octave-config.h"
+
 #include <QMainWindow>
 
-#include "gui-settings.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class dw_main_window : public QMainWindow
 {
   Q_OBJECT
 
 public:
 
-  dw_main_window (base_qobject& oct_qboj, QWidget *parent = nullptr);
-
-  ~dw_main_window (void) = default;
+  dw_main_window (QWidget *parent = nullptr);
 
-  // No copying!
+  ~dw_main_window () = default;
 
-  dw_main_window (const dw_main_window&) = delete;
-
-  dw_main_window& operator = (const dw_main_window&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (dw_main_window)
 
 public slots:
 
-  void notice_settings (const gui_settings *);
+  void notice_settings ();
 
 protected slots:
 
@@ -76,8 +70,6 @@
   QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,
                         const char *member, QWidget *receiver);
 
-  base_qobject& m_octave_qobj;
-
   QList<QDockWidget *> m_dw_list;
 
   QAction *m_close_action;
--- a/libgui/src/external-editor-interface.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/external-editor-interface.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -29,17 +29,16 @@
 
 #include <QMessageBox>
 #include <QProcess>
+#include <QRegularExpression>
 
 #include "external-editor-interface.h"
 #include "gui-settings.h"
 #include "gui-preferences-global.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-external_editor_interface::external_editor_interface (QWidget *p,
-                                                      base_qobject& oct_qobj)
-: QWidget (p), m_octave_qobj (oct_qobj)
+external_editor_interface::external_editor_interface (QWidget *p)
+  : QWidget (p)
 { }
 
 // Calling the external editor
@@ -57,7 +56,7 @@
   editor.replace ("%f", file);
   editor.replace ("%l", QString::number (line));
 
-  QStringList arguments = editor.split (QRegExp("\\s+"));
+  QStringList arguments = editor.split (QRegularExpression {"\\s+"});
   editor = arguments.takeFirst ();
 
   // start the process and check for success
@@ -100,12 +99,12 @@
 }
 
 // Get and verify the settings of the external editor program
-QString external_editor_interface::external_editor (void)
+QString external_editor_interface::external_editor ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  QString editor = settings->value (global_custom_editor.key,
-                                    global_custom_editor.def).toString ();
+  gui_settings settings;
+
+  QString editor = settings.value (global_custom_editor.settings_key (),
+                                   global_custom_editor.def ()).toString ();
 
   // check the settings (avoid an empty string)
   if (editor.trimmed ().isEmpty ())
--- a/libgui/src/external-editor-interface.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/external-editor-interface.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,17 +31,15 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class external_editor_interface : public QWidget
 {
   Q_OBJECT
 
 public:
 
-  external_editor_interface (QWidget *main_win, base_qobject& oct_qobj);
+  external_editor_interface (QWidget *main_win);
 
-  ~external_editor_interface (void) = default;
+  ~external_editor_interface () = default;
 
 signals:
 
@@ -63,9 +61,7 @@
 
 private:
 
-  QString external_editor (void);
-
-  base_qobject& m_octave_qobj;
+  QString external_editor ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/files-dock-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/files-dock-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,8 +49,7 @@
 #include "files-dock-widget.h"
 #include "gui-preferences-fb.h"
 #include "gui-preferences-global.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
+#include "gui-settings.h"
 #include "qt-interpreter-events.h"
 
 #include "oct-env.h"
@@ -63,7 +62,7 @@
 
   FileTreeViewer (QWidget *p) : QTreeView (p) { }
 
-  ~FileTreeViewer (void) = default;
+  ~FileTreeViewer () = default;
 
   void mousePressEvent (QMouseEvent *e)
   {
@@ -130,9 +129,9 @@
   {
     const QString message =
 
-      files_dock_widget::tr ("Could not rename file \"%1\" to \"%2\".")
-      .arg (old_name)
-      .arg (new_name);
+        files_dock_widget::tr ("Could not rename file \"%1\" to \"%2\".")
+            .arg (old_name)
+            .arg (new_name);
     QMessageBox::information (static_cast<QWidget *> (parent ()),
                               QFileSystemModel::tr ("Invalid filename"),
                               message, QMessageBox::Ok);
@@ -145,7 +144,7 @@
 {
 public:
   RenameItemDelegate (QObject *parent = nullptr)
-    : QStyledItemDelegate{ parent }
+      : QStyledItemDelegate{ parent }
   {
   }
 
@@ -178,8 +177,8 @@
   }
 };
 
-files_dock_widget::files_dock_widget (QWidget *p, base_qobject& oct_qobj)
-  : octave_dock_widget ("FilesDockWidget", p, oct_qobj)
+files_dock_widget::files_dock_widget (QWidget *p)
+  : octave_dock_widget ("FilesDockWidget", p)
 {
   set_title (tr ("File Browser"));
   setToolTip (tr ("Browse your files"));
@@ -194,18 +193,18 @@
   m_columns_shown.append (tr ("Alternating row colors"));
 
   m_columns_shown_keys = QStringList ();
-  m_columns_shown_keys.append (fb_show_size.key);
-  m_columns_shown_keys.append (fb_show_type.key);
-  m_columns_shown_keys.append (fb_show_date.key);
-  m_columns_shown_keys.append (fb_show_hidden.key);
-  m_columns_shown_keys.append (fb_show_altcol.key);
+  m_columns_shown_keys.append (fb_show_size.settings_key ());
+  m_columns_shown_keys.append (fb_show_type.settings_key ());
+  m_columns_shown_keys.append (fb_show_date.settings_key ());
+  m_columns_shown_keys.append (fb_show_hidden.settings_key ());
+  m_columns_shown_keys.append (fb_show_altcol.settings_key ());
 
   m_columns_shown_defs = QList <QVariant> ();
-  m_columns_shown_defs.append (fb_show_size.def);
-  m_columns_shown_defs.append (fb_show_type.def);
-  m_columns_shown_defs.append (fb_show_date.def);
-  m_columns_shown_defs.append (fb_show_hidden.def);
-  m_columns_shown_defs.append (fb_show_altcol.def);
+  m_columns_shown_defs.append (fb_show_size.def ());
+  m_columns_shown_defs.append (fb_show_type.def ());
+  m_columns_shown_defs.append (fb_show_date.def ());
+  m_columns_shown_defs.append (fb_show_hidden.def ());
+  m_columns_shown_defs.append (fb_show_altcol.def ());
 
   QWidget *container = new QWidget (this);
 
@@ -225,20 +224,21 @@
   QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
   m_current_directory->setSizePolicy (sizePol);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   QAction *directory_up_action
-    = new QAction (rmgr.icon ("folder-up", false, "go-up"), "", m_navigation_tool_bar);
+    = new QAction (settings.icon ("folder-up", false, "go-up"), "",
+                   m_navigation_tool_bar);
   directory_up_action->setToolTip (tr ("One directory up"));
 
   m_sync_browser_directory_action
-    = new QAction (rmgr.icon ("go-first"), tr ("Show Octave directory"),
+    = new QAction (settings.icon ("go-first"), tr ("Show Octave directory"),
                    m_navigation_tool_bar);
   m_sync_browser_directory_action->setToolTip (tr ("Go to current Octave directory"));
   m_sync_browser_directory_action->setEnabled (false);
 
   m_sync_octave_directory_action
-    = new QAction (rmgr.icon ("go-last"), tr ("Set Octave directory"),
+    = new QAction (settings.icon ("go-last"), tr ("Set Octave directory"),
                    m_navigation_tool_bar);
   m_sync_octave_directory_action->setToolTip (tr ("Set Octave directory to current browser directory"));
   m_sync_octave_directory_action->setEnabled (false);
@@ -246,30 +246,31 @@
   QToolButton *popdown_button = new QToolButton ();
   popdown_button->setToolTip (tr ("Actions on current directory"));
   QMenu *popdown_menu = new QMenu ();
-  popdown_menu->addAction (rmgr.icon ("user-home"),
+  popdown_menu->addAction (settings.icon ("user-home"),
                            tr ("Show Home Directory"), this,
                            SLOT (popdownmenu_home (bool)));
   popdown_menu->addAction (m_sync_browser_directory_action);
   popdown_menu->addAction (m_sync_octave_directory_action);
   popdown_button->setMenu (popdown_menu);
   popdown_button->setPopupMode (QToolButton::InstantPopup);
-  popdown_button->setDefaultAction (
-                                    new QAction (rmgr.icon ("folder-settings", false, "applications-system"),
-                                                 "", m_navigation_tool_bar));
+  popdown_button->setDefaultAction
+    (new QAction (settings.icon ("folder-settings", false,
+                                 "applications-system"),
+                  "", m_navigation_tool_bar));
 
   popdown_menu->addSeparator ();
-  popdown_menu->addAction (rmgr.icon ("folder"),
+  popdown_menu->addAction (settings.icon ("folder"),
                            tr ("Set Browser Directory..."),
                            this, &files_dock_widget::popdownmenu_search_dir);
   popdown_menu->addSeparator ();
-  popdown_menu->addAction (rmgr.icon ("edit-find"),
+  popdown_menu->addAction (settings.icon ("edit-find"),
                            tr ("Find Files..."),
                            this, &files_dock_widget::popdownmenu_findfiles);
   popdown_menu->addSeparator ();
-  popdown_menu->addAction (rmgr.icon ("document-new"),
+  popdown_menu->addAction (settings.icon ("document-new"),
                            tr ("New File..."),
                            this, &files_dock_widget::popdownmenu_newfile);
-  popdown_menu->addAction (rmgr.icon ("folder-new"),
+  popdown_menu->addAction (settings.icon ("folder-new"),
                            tr ("New Directory..."),
                            this, &files_dock_widget::popdownmenu_newdir);
 
@@ -284,24 +285,21 @@
   connect (m_sync_browser_directory_action, &QAction::triggered,
            this, &files_dock_widget::do_sync_browser_directory);
 
-  gui_settings *settings = rmgr.get_settings ();
-  // FIXME: what should happen if settings is 0?
-
   // Create the QFileSystemModel starting in the desired directory
   QDir startup_dir;  // take current dir
 
-  if (settings->value (fb_restore_last_dir).toBool ())
+  if (settings.bool_value (fb_restore_last_dir))
     {
       // restore last dir from previous session
       QStringList last_dirs
-        = settings->value (fb_mru_list.key).toStringList ();
+        = settings.value (fb_mru_list.settings_key ()).toStringList ();
       if (last_dirs.length () > 0)
         startup_dir = QDir (last_dirs.at (0));  // last dir in previous session
     }
-  else if (! settings->value (fb_startup_dir).toString ().isEmpty ())
+  else if (! settings.string_value (fb_startup_dir).isEmpty ())
     {
       // do not restore but there is a startup dir configured
-      startup_dir = QDir (settings->value (fb_startup_dir.key).toString ());
+      startup_dir = QDir (settings.value (fb_startup_dir.settings_key ()).toString ());
     }
 
   if (! startup_dir.exists ())
@@ -312,8 +310,8 @@
 
   m_file_system_model = new file_system_model (this);
   m_file_system_model->setResolveSymlinks (false);
-  m_file_system_model->setFilter (
-                                  QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries);
+  m_file_system_model->setFilter
+    (QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries);
   QModelIndex rootPathIndex
     = m_file_system_model->setRootPath (startup_dir.absolutePath ());
 
@@ -348,14 +346,14 @@
   // get sort column and order as well as column state (order and width)
 
   m_file_tree_view->sortByColumn
-    (settings->value (fb_sort_column).toInt (),
-     static_cast<Qt::SortOrder> (settings->value (fb_sort_order).toUInt ()));
-  // FIXME: use value<Qt::SortOrder> instead of static cast after
-  //        dropping support of Qt 5.4
+    (settings.int_value (fb_sort_column),
+     static_cast<Qt::SortOrder> (settings.uint_value (fb_sort_order)));
+     // FIXME: use value<Qt::SortOrder> instead of static cast after
+     //        dropping support of Qt 5.4
 
-  if (settings->contains (fb_column_state.key))
+  if (settings.contains (fb_column_state.settings_key ()))
     m_file_tree_view->header ()->restoreState
-      (settings->value (fb_column_state.key).toByteArray ());
+      (settings.value (fb_column_state.settings_key ()).toByteArray ());
 
   // Set header properties for sorting
   m_file_tree_view->header ()->setSectionsClickable (true);
@@ -363,7 +361,7 @@
   m_file_tree_view->header ()->setSortIndicatorShown (true);
 
   QStringList mru_dirs =
-    settings->value (fb_mru_list.key).toStringList ();
+    settings.value (fb_mru_list.settings_key ()).toStringList ();
   m_current_directory->addItems (mru_dirs);
 
   m_current_directory->setEditText
@@ -387,7 +385,7 @@
   vbox_layout->setSpacing (0);
   vbox_layout->addWidget (m_navigation_tool_bar);
   vbox_layout->addWidget (m_file_tree_view);
-  vbox_layout->setMargin (1);
+  vbox_layout->setContentsMargins (1, 1, 1, 1);
 
   container->setLayout (vbox_layout);
 
@@ -427,29 +425,25 @@
     make_window ();
 }
 
-void files_dock_widget::save_settings (void)
+void files_dock_widget::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (! settings)
-    return;
+  gui_settings settings;
 
   int sort_column = m_file_tree_view->header ()->sortIndicatorSection ();
   Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder ();
-  settings->setValue (fb_sort_column.key, sort_column);
-  settings->setValue (fb_sort_order.key, sort_order);
-  settings->setValue (fb_column_state.key,
-                      m_file_tree_view->header ()->saveState ());
+  settings.setValue (fb_sort_column.settings_key (), sort_column);
+  settings.setValue (fb_sort_order.settings_key (), sort_order);
+  settings.setValue (fb_column_state.settings_key (),
+                     m_file_tree_view->header ()->saveState ());
 
   QStringList dirs;
   for (int i=0; i< m_current_directory->count (); i++)
     {
       dirs.append (m_current_directory->itemText (i));
     }
-  settings->setValue (fb_mru_list.key, dirs);
+  settings.setValue (fb_mru_list.settings_key (), dirs);
 
-  settings->sync ();
+  settings.sync ();
 
   octave_dock_widget::save_settings ();
 
@@ -469,12 +463,12 @@
   display_directory (dir);
 }
 
-void files_dock_widget::accept_directory_line_edit (void)
+void files_dock_widget::accept_directory_line_edit ()
 {
   display_directory (m_current_directory->currentText ());
 }
 
-void files_dock_widget::change_directory_up (void)
+void files_dock_widget::change_directory_up ()
 {
   QDir dir
     = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
@@ -483,7 +477,7 @@
   display_directory (dir.absolutePath ());
 }
 
-void files_dock_widget::do_sync_octave_directory (void)
+void files_dock_widget::do_sync_octave_directory ()
 {
   QDir dir
     = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
@@ -491,7 +485,7 @@
   emit displayed_directory_changed (dir.absolutePath ());
 }
 
-void files_dock_widget::do_sync_browser_directory (void)
+void files_dock_widget::do_sync_browser_directory ()
 {
   display_directory (m_octave_dir, false); // false: no sync of octave dir
 }
@@ -533,9 +527,10 @@
           QString abs_fname = fileInfo.absoluteFilePath ();
 
           QString suffix = fileInfo.suffix ().toLower ();
-          resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-          gui_settings *settings = rmgr.get_settings ();
-          QString ext = settings->value (fb_txt_file_ext).toString ();
+
+          gui_settings settings;
+
+          QString ext = settings.string_value (fb_txt_file_ext);
 #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
           QStringList extensions = ext.split (";", Qt::SkipEmptyParts);
 #else
@@ -564,13 +559,12 @@
 
 void files_dock_widget::toggle_header (int col)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   QString key = m_columns_shown_keys.at (col);
-  bool shown = settings->value (key, false).toBool ();
-  settings->setValue (key, ! shown);
-  settings->sync ();
+  bool shown = settings.value (key, false).toBool ();
+  settings.setValue (key, ! shown);
+  settings.sync ();
 
   switch (col)
     {
@@ -583,7 +577,7 @@
     case 3:
     case 4:
       // other actions depending on new settings
-      notice_settings (settings);
+      notice_settings ();
       break;
     }
 }
@@ -596,8 +590,7 @@
     delete m_sig_mapper;
   m_sig_mapper = new QSignalMapper (this);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   for (int i = 0; i < m_columns_shown.size (); i++)
     {
@@ -606,8 +599,8 @@
       m_sig_mapper->setMapping (action, i);
       action->setCheckable (true);
       action->setChecked
-        (settings->value (m_columns_shown_keys.at (i),
-                          m_columns_shown_defs.at (i)).toBool ());
+        (settings.value (m_columns_shown_keys.at (i),
+                         m_columns_shown_defs.at (i)).toBool ());
     }
 
   // FIXME: We could use
@@ -654,10 +647,10 @@
                               | QItemSelectionModel::Rows);
         }
 
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+      gui_settings settings;
 
       // construct the context menu depending on item
-      menu.addAction (rmgr.icon ("document-open"), tr ("Open"),
+      menu.addAction (settings.icon ("document-open"), tr ("Open"),
                       this, &files_dock_widget::contextmenu_open);
 
       if (info.isDir ())
@@ -674,7 +667,7 @@
                       this, &files_dock_widget::contextmenu_copy_selection);
 
       if (info.isFile () && info.suffix () == "m")
-        menu.addAction (rmgr.icon ("media-playback-start"), tr ("Run"),
+        menu.addAction (settings.icon ("media-playback-start"), tr ("Run"),
                         this, &files_dock_widget::contextmenu_run);
 
       if (info.isFile ())
@@ -684,7 +677,7 @@
       if (info.isDir ())
         {
           menu.addSeparator ();
-          menu.addAction (rmgr.icon ("go-first"), tr ("Set Current Directory"),
+          menu.addAction (settings.icon ("go-first"), tr ("Set Current Directory"),
                           this, &files_dock_widget::contextmenu_setcurrentdir);
 
           QMenu *add_path_menu = menu.addMenu (tr ("Add to Path"));
@@ -703,21 +696,21 @@
 
           menu.addSeparator ();
 
-          menu.addAction (rmgr.icon ("edit-find"), tr ("Find Files..."),
+          menu.addAction (settings.icon ("edit-find"), tr ("Find Files..."),
                           this, &files_dock_widget::contextmenu_findfiles);
         }
 
       menu.addSeparator ();
       menu.addAction (m_rename_action);
-      menu.addAction (rmgr.icon ("edit-delete"), tr ("Delete..."),
+      menu.addAction (settings.icon ("edit-delete"), tr ("Delete..."),
                       this, &files_dock_widget::contextmenu_delete);
 
       if (info.isDir ())
         {
           menu.addSeparator ();
-          menu.addAction (rmgr.icon ("document-new"), tr ("New File..."),
+          menu.addAction (settings.icon ("document-new"), tr ("New File..."),
                           this, &files_dock_widget::contextmenu_newfile);
-          menu.addAction (rmgr.icon ("folder-new"), tr ("New Directory..."),
+          menu.addAction (settings.icon ("folder-new"), tr ("New Directory..."),
                           this, &files_dock_widget::contextmenu_newdir);
         }
 
@@ -733,9 +726,9 @@
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& it : rows)
     {
-      QFileInfo file = m_file_system_model->fileInfo (*it);
+      QFileInfo file = m_file_system_model->fileInfo (it);
       if (file.exists ())
         display_directory (file.absoluteFilePath ());
     }
@@ -747,9 +740,9 @@
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& it : rows)
     {
-      QFileInfo file = m_file_system_model->fileInfo (*it);
+      QFileInfo file = m_file_system_model->fileInfo (it);
       if (file.exists ())
         emit open_file (file.absoluteFilePath ());
     }
@@ -760,8 +753,8 @@
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for (auto it = rows.begin (); it != rows.end (); it++)
-    open_item_in_app (*it);
+  for (const auto& it : rows)
+    open_item_in_app (it);
 }
 
 void files_dock_widget::contextmenu_copy_selection (bool)
@@ -771,10 +764,9 @@
 
   QStringList selection;
 
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& it : rows)
     {
-      QFileInfo info = m_file_system_model->fileInfo (*it);
-
+      QFileInfo info = m_file_system_model->fileInfo (it);
       selection << info.fileName ();
     }
 
@@ -853,10 +845,10 @@
       else
         {
           dlg_answer = QMessageBox::question (this,
-                                              tr ("Delete file/directory"),
-                                              tr ("Are you sure you want to delete\n")
-                                              + info.filePath (),
-                                              QMessageBox::Yes | QMessageBox::No);
+                         tr ("Delete file/directory"),
+                         tr ("Are you sure you want to delete\n")
+                         + info.filePath (),
+                         QMessageBox::Yes | QMessageBox::No);
         }
 
       if (dlg_answer == QMessageBox::Yes)
@@ -865,9 +857,9 @@
             {
               // see if directory is empty
               QDir path (info.absoluteFilePath ());
-              QList<QFileInfo> fileLst = path.entryInfoList (
-                                                             QDir::Hidden | QDir::AllEntries |
-                                                             QDir::NoDotAndDotDot | QDir::System);
+              QList<QFileInfo> fileLst
+                = path.entryInfoList (QDir::Hidden | QDir::AllEntries
+                                      | QDir::NoDotAndDotDot | QDir::System);
 
               if (fileLst.count () != 0)
                 QMessageBox::warning (this, tr ("Delete file/directory"),
@@ -906,11 +898,9 @@
 
   QList<QFileInfo> infos;
 
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& idx : rows)
     {
-      QModelIndex index = *it;
-
-      QFileInfo info = m_file_system_model->fileInfo (index);
+      QFileInfo info = m_file_system_model->fileInfo (idx);
 
       if (info.exists () &&
           ((dir & info.isDir ()) || (! dir && info.isFile ())))
@@ -1006,11 +996,13 @@
     }
 }
 
-void files_dock_widget::notice_settings (const gui_settings *settings)
+void files_dock_widget::notice_settings ()
 {
+  gui_settings settings;
+
   // QSettings pointer is checked before emitting.
 
-  int size_idx = settings->value (global_icon_size).toInt ();
+  int size_idx = settings.int_value (global_icon_size);
   size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
   QStyle *st = style ();
@@ -1020,22 +1012,22 @@
   // filenames are always shown, other columns can be hidden by settings
   for (int i = 0; i < 3; i++)
     m_file_tree_view->setColumnHidden (i + 1,
-                                       ! settings->value (m_columns_shown_keys.at (i),false).toBool ());
+                                       ! settings.value (m_columns_shown_keys.at (i),false).toBool ());
 
   QDir::Filters current_filter = m_file_system_model->filter ();
-  if (settings->value (m_columns_shown_keys.at (3), false).toBool ())
+  if (settings.value (m_columns_shown_keys.at (3), false).toBool ())
     m_file_system_model->setFilter (current_filter | QDir::Hidden);
   else
     m_file_system_model->setFilter (current_filter & (~QDir::Hidden));
 
   m_file_tree_view->setAlternatingRowColors
-    (settings->value (m_columns_shown_keys.at (4),true).toBool ());
+    (settings.value (m_columns_shown_keys.at (4),true).toBool ());
   m_file_tree_view->setModel (m_file_system_model);
 
   // enable the buttons to sync octave/browser dir
   // only if this is not done by default
   m_sync_octave_dir
-    = settings->value (fb_sync_octdir).toBool ();
+    = settings.bool_value (fb_sync_octdir);
   m_sync_octave_directory_action->setEnabled (! m_sync_octave_dir);
   m_sync_browser_directory_action->setEnabled (! m_sync_octave_dir);
 
@@ -1063,15 +1055,16 @@
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly;
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts |= QFileDialog::DontUseNativeDialog;
 
   QString dir = QFileDialog::getExistingDirectory (this,
-                                                   tr ("Set directory of file browser"),
-                                                   m_file_system_model->rootPath (),
-                                                   QFileDialog::Option (opts));
+                   tr ("Set directory of file browser"),
+                   m_file_system_model->rootPath (),
+                   QFileDialog::Option (opts));
   set_current_directory (dir);
 }
 
--- a/libgui/src/files-dock-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/files-dock-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,8 +46,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 //!  Dock widget to display files in the current directory.
 
 class files_dock_widget : public octave_dock_widget
@@ -56,9 +54,9 @@
 
 public:
 
-  files_dock_widget (QWidget *parent, base_qobject& oct_qobj);
+  files_dock_widget (QWidget *parent);
 
-  ~files_dock_widget (void) = default;
+  ~files_dock_widget () = default;
 
 signals:
 
@@ -107,15 +105,15 @@
 
   //! Slot for handling the up-directory button in the toolbar.
 
-  void change_directory_up (void);
+  void change_directory_up ();
 
   //! Slot for handling the sync octave directory button in the toolbar.
 
-  void do_sync_octave_directory (void);
+  void do_sync_octave_directory ();
 
   //! Slot for handling the sync browser directory button in the toolbar.
 
-  void do_sync_browser_directory (void);
+  void do_sync_browser_directory ();
 
   //! Sets the current directory being displayed.
 
@@ -123,7 +121,7 @@
 
   //! Accepts user input a the line edit for the current directory.
 
-  void accept_directory_line_edit (void);
+  void accept_directory_line_edit ();
 
   //! Set the internal variable that holds the actual octave variable.
 
@@ -131,9 +129,9 @@
 
   //! Tells the widget to react on changed settings.
 
-  void notice_settings (const gui_settings *settings);
+  void notice_settings ();
 
-  void save_settings (void);
+  void save_settings ();
 
 private slots:
 
--- a/libgui/src/find-files-dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/find-files-dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,17 +49,17 @@
 #include "find-files-model.h"
 #include "gui-preferences-global.h"
 #include "gui-preferences-ff.h"
-#include "octave-qobject.h"
+#include "gui-settings.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-find_files_dialog::find_files_dialog (QWidget *p, base_qobject& oct_qobj)
-: QDialog (p), m_octave_qobj (oct_qobj)
+find_files_dialog::find_files_dialog (QWidget *p)
+  : QDialog (p)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   setWindowTitle (tr ("Find Files"));
-  setWindowIcon (rmgr.icon ("edit-find"));
+  setWindowIcon (settings.icon ("edit-find"));
 
   m_dir_iterator = nullptr;
 
@@ -67,20 +67,18 @@
   connect (m_timer, &QTimer::timeout,
            this, &find_files_dialog::look_for_files);
 
-  gui_settings *settings = rmgr.get_settings ();
-
   QLabel *file_name_label = new QLabel (tr ("Named:"));
   m_file_name_edit = new QLineEdit;
   m_file_name_edit->setToolTip (tr ("Enter the filename search expression"));
 
-  m_file_name_edit->setText (settings->value (ff_file_name).toString ());
+  m_file_name_edit->setText (settings.string_value (ff_file_name));
   file_name_label->setBuddy (m_file_name_edit);
 
   QLabel *start_dir_label = new QLabel (tr ("Start in:"));
 
   m_start_dir_edit = new QLineEdit;
-  m_start_dir_edit->setText (settings->value (ff_start_dir.key,
-                                              QDir::currentPath ()).toString ());
+  m_start_dir_edit->setText (settings.value (ff_start_dir.settings_key (),
+                                             QDir::currentPath ()).toString ());
   m_start_dir_edit->setToolTip (tr ("Enter the start directory"));
   start_dir_label->setBuddy (m_start_dir_edit);
 
@@ -90,27 +88,27 @@
            this, &find_files_dialog::browse_folders);
 
   m_recurse_dirs_check = new QCheckBox (tr ("Search subdirectories"));
-  m_recurse_dirs_check->setChecked (settings->value (ff_recurse_dirs).toBool ());
+  m_recurse_dirs_check->setChecked (settings.bool_value (ff_recurse_dirs));
   m_recurse_dirs_check->setToolTip (tr ("Search recursively through directories for matching files"));
 
   m_include_dirs_check = new QCheckBox (tr ("Include directory names"));
-  m_include_dirs_check->setChecked (settings->value (ff_include_dirs).toBool ());
+  m_include_dirs_check->setChecked (settings.bool_value (ff_include_dirs));
   m_include_dirs_check->setToolTip (tr ("Include matching directories in search results"));
 
   m_name_case_check = new QCheckBox (tr ("Name case insensitive"));
-  m_name_case_check->setChecked (settings->value (ff_name_case).toBool ());
+  m_name_case_check->setChecked (settings.bool_value (ff_name_case));
   m_name_case_check->setToolTip (tr ("Set matching name is case insensitive"));
 
   m_contains_text_check = new QCheckBox (tr ("Contains text:"));
   m_contains_text_check->setToolTip (tr ("Enter the file content search expression"));
-  m_contains_text_check->setChecked (settings->value (ff_check_text).toBool ());
+  m_contains_text_check->setChecked (settings.bool_value (ff_check_text));
 
   m_contains_text_edit = new QLineEdit ();
   m_contains_text_edit->setToolTip (tr ("Text to match"));
-  m_contains_text_edit->setText (settings->value (ff_contains_text).toString ());
+  m_contains_text_edit->setText (settings.string_value (ff_contains_text));
 
   m_content_case_check = new QCheckBox (tr ("Text case insensitive"));
-  m_content_case_check->setChecked (settings->value (ff_content_case).toBool ());
+  m_content_case_check->setChecked (settings.bool_value (ff_content_case));
   m_content_case_check->setToolTip (tr ("Set text content is case insensitive"));
 
   find_files_model *model = new find_files_model (this);
@@ -124,15 +122,15 @@
   m_file_list->setAlternatingRowColors (true);
   m_file_list->setToolTip (tr ("Search results"));
   m_file_list->setSortingEnabled (true);
-  m_file_list->horizontalHeader ()->restoreState (settings->value (ff_column_state.key).toByteArray ());
+  m_file_list->horizontalHeader ()->restoreState (settings.value (ff_column_state.settings_key ()).toByteArray ());
   m_file_list->horizontalHeader ()->setSortIndicatorShown (true);
   m_file_list->horizontalHeader ()->setSectionsClickable (true);
   m_file_list->horizontalHeader ()->setStretchLastSection (true);
-  m_file_list->sortByColumn (settings->value (ff_sort_files_by_column).toInt (),
+  m_file_list->sortByColumn (settings.int_value (ff_sort_files_by_column),
                              static_cast<Qt::SortOrder>
-                             (settings->value (ff_sort_files_by_order).toUInt ()));
-  // FIXME: use value<Qt::SortOrder> instead of static cast after
-  //        dropping support of Qt 5.4
+                             (settings.uint_value (ff_sort_files_by_order)));
+              // FIXME: use value<Qt::SortOrder> instead of static cast after
+              //        dropping support of Qt 5.4
 
   connect (m_file_list, &QTableView::doubleClicked,
            this, &find_files_dialog::item_double_clicked);
@@ -202,39 +200,35 @@
            this, &find_files_dialog::handle_done);
 }
 
-find_files_dialog::~find_files_dialog (void)
+find_files_dialog::~find_files_dialog ()
 {
   delete m_dir_iterator;
 }
 
-void find_files_dialog::save_settings (void)
+void find_files_dialog::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (! settings)
-    return;
+  gui_settings settings;
 
   int sort_column = m_file_list->horizontalHeader ()->sortIndicatorSection ();
   Qt::SortOrder sort_order
     = m_file_list->horizontalHeader ()->sortIndicatorOrder ();
-  settings->setValue (ff_sort_files_by_column.key, sort_column);
-  settings->setValue (ff_sort_files_by_order.key, sort_order);
-  settings->setValue (ff_column_state.key, m_file_list->horizontalHeader ()->saveState ());
+  settings.setValue (ff_sort_files_by_column.settings_key (), sort_column);
+  settings.setValue (ff_sort_files_by_order.settings_key (), sort_order);
+  settings.setValue (ff_column_state.settings_key (), m_file_list->horizontalHeader ()->saveState ());
 
-  settings->setValue (ff_file_name.key, m_file_name_edit->text ());
+  settings.setValue (ff_file_name.settings_key (), m_file_name_edit->text ());
 
-  settings->setValue (ff_start_dir.key, m_start_dir_edit->text ());
+  settings.setValue (ff_start_dir.settings_key (), m_start_dir_edit->text ());
 
-  settings->setValue (ff_recurse_dirs.key, m_recurse_dirs_check->text ());
-  settings->setValue (ff_include_dirs.key, m_include_dirs_check->text ());
-  settings->setValue (ff_name_case.key, m_name_case_check->text ());
+  settings.setValue (ff_recurse_dirs.settings_key (), m_recurse_dirs_check->text ());
+  settings.setValue (ff_include_dirs.settings_key (), m_include_dirs_check->text ());
+  settings.setValue (ff_name_case.settings_key (), m_name_case_check->text ());
 
-  settings->setValue (ff_contains_text.key, m_contains_text_edit->text ());
-  settings->setValue (ff_check_text.key, m_contains_text_check->isChecked ());
-  settings->setValue (ff_content_case.key, m_content_case_check->isChecked ());
+  settings.setValue (ff_contains_text.settings_key (), m_contains_text_edit->text ());
+  settings.setValue (ff_check_text.settings_key (), m_contains_text_check->isChecked ());
+  settings.setValue (ff_content_case.settings_key (), m_content_case_check->isChecked ());
 
-  settings->sync ();
+  settings.sync ();
 }
 
 void find_files_dialog::set_search_dir (const QString& dir)
@@ -243,7 +237,7 @@
   m_start_dir_edit->setText (dir);
 }
 
-void find_files_dialog::start_find (void)
+void find_files_dialog::start_find ()
 {
   stop_find ();
 
@@ -285,7 +279,7 @@
   m_timer->start (0);
 }
 
-void find_files_dialog::stop_find (void)
+void find_files_dialog::stop_find ()
 {
   m_timer->stop ();
 
@@ -308,13 +302,15 @@
   m_status_bar->showMessage (res_str);
 }
 
-void find_files_dialog::browse_folders (void)
+void find_files_dialog::browse_folders ()
 {
   int opts = 0;  // No options by default.
+
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts = QFileDialog::DontUseNativeDialog;
 
   QString dir =
@@ -347,7 +343,7 @@
     }
 }
 
-void find_files_dialog::look_for_files (void)
+void find_files_dialog::look_for_files ()
 {
   if (m_dir_iterator && m_dir_iterator->hasNext ())
     {
@@ -395,8 +391,8 @@
               QString match_str = m_contains_text_edit->text ();
 
               Qt::CaseSensitivity cs = m_content_case_check->isChecked ()
-                ? Qt::CaseInsensitive
-                : Qt::CaseSensitive;
+                                       ? Qt::CaseInsensitive
+                                       : Qt::CaseSensitive;
 
               do
                 {
--- a/libgui/src/find-files-dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/find-files-dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,19 +39,17 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class find_files_dialog : public QDialog
 {
   Q_OBJECT
 
 public:
 
-  find_files_dialog (QWidget *parent, base_qobject& oct_qobj);
+  find_files_dialog (QWidget *parent);
 
-  virtual ~find_files_dialog (void);
+  virtual ~find_files_dialog ();
 
-  void save_settings (void);
+  void save_settings ();
 
 signals:
 
@@ -64,10 +62,10 @@
 
 private slots:
 
-  void start_find (void);
-  void stop_find (void);
-  void browse_folders (void);
-  void look_for_files (void);
+  void start_find ();
+  void stop_find ();
+  void browse_folders ();
+  void look_for_files ();
   void item_double_clicked (const QModelIndex&);
   void handle_done (int);
 
@@ -75,8 +73,6 @@
 
   bool is_match (const QFileInfo& info);
 
-  base_qobject& m_octave_qobj;
-
   QLineEdit *m_start_dir_edit;
   QLineEdit *m_file_name_edit;
   QPushButton *m_stop_button;
--- a/libgui/src/find-files-model.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/find-files-model.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -95,7 +95,7 @@
   m_sortorder = 0;
 }
 
-void find_files_model::clear (void)
+void find_files_model::clear ()
 {
   beginResetModel ();
 
@@ -111,6 +111,9 @@
   QList<QFileInfo>::Iterator it;
   find_file_less_than less_than (m_sortorder);
 
+  // FIXME: This loop is trying to insert info in a sorted QList.
+  // Is there a library function or data structure
+  // that can do this without a loop?
   for (it = m_files.begin (); it != m_files.end (); it++)
     {
       if (less_than (info, *it))
--- a/libgui/src/find-files-model.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/find-files-model.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,9 +41,9 @@
 
   find_files_model (QObject *p = nullptr);
 
-  ~find_files_model (void) = default;
+  ~find_files_model () = default;
 
-  void clear (void);
+  void clear ();
 
   void addFile (const QFileInfo& info);
 
--- a/libgui/src/graphics-init.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/graphics-init.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,6 @@
 #include <QThread>
 
 #include "graphics-init.h"
-#include "octave-qobject.h"
 #include "qt-graphics-toolkit.h"
 #include "QtHandlesUtils.h"
 
@@ -42,10 +41,8 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-void graphics_init (interpreter& interp, base_qobject& oct_qobj)
+void graphics_init (interpreter& interp)
 {
-#if defined (HAVE_QT_GRAPHICS)
-
   gh_manager& gh_mgr = interp.get_gh_manager ();
 
   autolock guard (gh_mgr.graphics_lock ());
@@ -54,7 +51,7 @@
 
   gh_mgr.enable_event_processing (true);
 
-  qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp, oct_qobj);
+  qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp);
 
   if (QThread::currentThread ()
       != QApplication::instance ()->thread ())
@@ -67,13 +64,6 @@
   gtk_mgr.register_toolkit ("qt");
 
   gtk_mgr.load_toolkit (tk);
-
-#else
-
-  octave_unused_parameter (interp);
-  octave_unused_parameter (oct_qobj);
-
-#endif
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/graphics-init.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/graphics-init.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,9 +33,8 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 class interpreter;
-class base_qobject;
 
-extern void graphics_init (interpreter& interp, base_qobject& oct_qobj);
+extern void graphics_init (interpreter& interp);
 
 OCTAVE_END_NAMESPACE(octave)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 <QPalette>
+
+#include "gui-preferences-cs.h"
+#include "gui-settings.h"
+
+// Console preferences
+
+gui_pref
+cs_font ("terminal/fontName", QVariant ());
+
+gui_pref
+cs_font_size ("terminal/fontSize", QVariant (10));
+
+gui_pref
+cs_cursor ("terminal/cursorType", QVariant ("ibeam"));
+
+gui_pref
+cs_cursor_blinking ("terminal/cursorBlinking", QVariant (true));
+
+gui_pref
+cs_cursor_use_fgcol ("terminal/cursorUseForegroundColor", QVariant (true));
+
+gui_pref
+cs_hist_buffer ("terminal/history_buffer", QVariant (1000));
+
+gui_pref
+cs_color_mode ("terminal/color_mode", QVariant (0));
+
+gui_pref cs_colors[2*cs_colors_count] =
+{
+  {"terminal/color_f" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},
+  {"terminal/color_b" + settings_color_modes_ext[0], QVariant (QPalette::Base)},
+  {"terminal/color_s" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
+  {"terminal/color_c" + settings_color_modes_ext[0], QVariant (QPalette::QPalette::WindowText)},
+  {"terminal/color_f" + settings_color_modes_ext[1], QVariant ()}, // Default colors for 2nd mode empty,
+  {"terminal/color_b" + settings_color_modes_ext[1], QVariant ()}, // since they are determined at runtime
+  {"terminal/color_s" + settings_color_modes_ext[1], QVariant ()}, // by inverting the lightness of the
+  {"terminal/color_c" + settings_color_modes_ext[1], QVariant ()}  // default colors in light mode
+};
+
+gui_pref
+cs_focus_cmd ("terminal/focus_after_command", QVariant (false));
+
+gui_pref
+cs_dbg_location ("terminal/print_debug_location", QVariant (false));
--- a/libgui/src/gui-preferences-cs.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-cs.h	Fri Jun 23 20:51:51 2023 +0200
@@ -27,15 +27,12 @@
 #define octave_gui_preferences_cs_h 1
 
 #include "gui-preferences.h"
-#include "gui-settings.h"
 
 // Console preferences
 
-const gui_pref
-cs_font ("terminal/fontName", QVariant ());
+extern gui_pref cs_font;
 
-const gui_pref
-cs_font_size ("terminal/fontSize", QVariant (10));
+extern gui_pref cs_font_size;
 
 const std::vector<std::string> cs_cursor_types =
 {
@@ -44,33 +41,20 @@
   "underline"
 };
 
-const gui_pref
-cs_cursor ("terminal/cursorType", QVariant ("ibeam"));
+extern gui_pref cs_cursor;
 
-const gui_pref
-cs_cursor_blinking ("terminal/cursorBlinking", QVariant (true));
+extern gui_pref cs_cursor_blinking;
 
-const gui_pref
-cs_cursor_use_fgcol ("terminal/cursorUseForegroundColor", QVariant (true));
+extern gui_pref cs_cursor_use_fgcol;
 
-const gui_pref
-cs_hist_buffer ("terminal/history_buffer", QVariant (1000));
+extern gui_pref cs_hist_buffer;
 
-const gui_pref
-cs_color_mode ("terminal/color_mode", QVariant (0));
+extern gui_pref cs_color_mode;
 
 const unsigned int cs_colors_count = 4;
-const gui_pref cs_colors[2*cs_colors_count] =
-{
-  {"terminal/color_f" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},
-  {"terminal/color_b" + settings_color_modes_ext[0], QVariant (QPalette::Base)},
-  {"terminal/color_s" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
-  {"terminal/color_c" + settings_color_modes_ext[0], QVariant (QPalette::QPalette::WindowText)},
-  {"terminal/color_f" + settings_color_modes_ext[1], QVariant ()}, // Default colors for 2nd mode empty,
-  {"terminal/color_b" + settings_color_modes_ext[1], QVariant ()}, // since they are determined at runtime
-  {"terminal/color_s" + settings_color_modes_ext[1], QVariant ()}, // by inverting the lightness of the
-  {"terminal/color_c" + settings_color_modes_ext[1], QVariant ()}  // default colors in light mode
-};
+
+extern gui_pref cs_colors[];
+
 const QStringList
 cs_color_names = {
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "foreground"),
@@ -79,10 +63,8 @@
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "cursor")
 };
 
-const gui_pref
-cs_focus_cmd ("terminal/focus_after_command", QVariant (false));
+extern gui_pref cs_focus_cmd;
 
-const gui_pref
-cs_dbg_location ("terminal/print_debug_location", QVariant (false));
+extern gui_pref cs_dbg_location;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-dc.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-dc.h"
+
+// documentation properties
+
+gui_pref
+dc_bookmark_filter_active ("documentation_widget/filter_active", QVariant (false));
+
+gui_pref
+dc_bookmark_filter_shown ("documentation_widget/filter_shown", QVariant (true));
+
+gui_pref
+dc_bookmark_filter_mru ("documentation_widget/bookmark_filter_mru", QVariant ());
+
+// Zoom level
+gui_pref
+dc_browser_zoom_level ("documentation_widget/browser_zoom_level", QVariant (0));
--- a/libgui/src/gui-preferences-dc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-dc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,14 +32,12 @@
 
 const QString
 dc_bookmark_file ("octave-doc-bookmarks.xbel");
-const gui_pref
-dc_bookmark_filter_active ("documentation_widget/filter_active", QVariant (false));
+
+extern gui_pref dc_bookmark_filter_active;
 
-const gui_pref
-dc_bookmark_filter_shown ("documentation_widget/filter_shown", QVariant (true));
+extern gui_pref dc_bookmark_filter_shown;
 
-const gui_pref
-dc_bookmark_filter_mru ("documentation_widget/bookmark_filter_mru", QVariant ());
+extern gui_pref dc_bookmark_filter_mru;
 
 // Constants for the xbel file format
 const QLatin1String dc_xbel_doctype ("<!DOCTYPE xbel>");
@@ -55,7 +53,6 @@
 const QLatin1String dc_xbel_name_format ("xbel");
 
 // Zoom level
-const gui_pref
-dc_browser_zoom_level ("documentation_widget/browser_zoom_level", QVariant (0));
+extern gui_pref dc_browser_zoom_level;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-dw.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 <QColor>
+#include <QRect>
+
+#include "gui-preferences-dw.h"
+
+gui_pref
+dw_focus_follows_mouse ("DockWidgets/focus_follows_mouse", QVariant (false));
+
+gui_pref
+dw_title_custom_style ("DockWidgets/widget_title_custom_style",
+                       QVariant (true));
+
+gui_pref dw_title_3d ("DockWidgets/widget_title_3d", QVariant (20));
+
+gui_pref dw_title_fg_color ("DockWidgets/title_fg_color",
+                            QVariant (QColor (0, 0, 0)));
+
+gui_pref dw_title_fg_color_active ("DockWidgets/title_fg_color_active",
+                                   QVariant (QColor (255, 255, 255)));
+
+gui_pref dw_title_bg_color ("DockWidgets/title_bg_color",
+                            QVariant (QColor (192, 192, 192)));
+
+gui_pref dw_title_bg_color_active ("DockWidgets/title_bg_color_active",
+                                   QVariant (QColor (128, 128, 128)));
+
+gui_pref dw_icon_set ("DockWidgets/widget_icon_set", QVariant ("NONE"));
+
+// The following keys have to be used with .arg (objectName ())
+gui_pref dw_float_geometry ("DockWidgets/%1_floating_geometry",
+                            QVariant (QRect (50, 50, 480, 640)));
+
+gui_pref dw_dock_geometry ("DockWidgets/%1",
+                           QVariant (QRect (10, 10, 240, 320)));
+
+gui_pref dw_is_visible ("DockWidgets/%1Visible", QVariant (true));
+
+gui_pref dw_is_floating ("DockWidgets/%1Floating", QVariant (false));
+
+gui_pref dw_is_minimized ("DockWidgets/%1_minimized", QVariant (false));
--- a/libgui/src/gui-preferences-dw.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-dw.h	Fri Jun 23 20:51:51 2023 +0200
@@ -28,28 +28,21 @@
 
 #include "gui-preferences.h"
 
-const gui_pref
-dw_focus_follows_mouse ("DockWidgets/focus_follows_mouse", QVariant (false));
+extern gui_pref dw_focus_follows_mouse;
+
+extern gui_pref dw_title_custom_style;
 
-const gui_pref
-dw_title_custom_style ("DockWidgets/widget_title_custom_style",
-                       QVariant (true));
+extern gui_pref dw_title_3d;
 
-const gui_pref dw_title_3d ("DockWidgets/widget_title_3d", QVariant (20));
+extern gui_pref dw_title_fg_color;
 
-const gui_pref dw_title_fg_color ("DockWidgets/title_fg_color",
-                                  QVariant (QColor (0, 0, 0)));
+extern gui_pref dw_title_fg_color_active;
 
-const gui_pref dw_title_fg_color_active ("DockWidgets/title_fg_color_active",
-                                         QVariant (QColor (255, 255, 255)));
+extern gui_pref dw_title_bg_color;
 
-const gui_pref dw_title_bg_color ("DockWidgets/title_bg_color",
-                                  QVariant (QColor (192, 192, 192)));
+extern gui_pref dw_title_bg_color_active;
 
-const gui_pref dw_title_bg_color_active ("DockWidgets/title_bg_color_active",
-                                         QVariant (QColor (128, 128, 128)));
-
-const gui_pref dw_icon_set ("DockWidgets/widget_icon_set", QVariant ("NONE"));
+extern gui_pref dw_icon_set;
 
 const QHash <QString, QString> dw_icon_set_names
   = {
@@ -61,16 +54,14 @@
     };
 
 // The following keys have to be used with .arg (objectName ())
-const gui_pref dw_float_geometry ("DockWidgets/%1_floating_geometry",
-                                  QVariant (QRect (50, 50, 480, 640)));
+extern gui_pref dw_float_geometry;
 
-const gui_pref dw_dock_geometry ("DockWidgets/%1",
-                                 QVariant (QRect (10, 10, 240, 320)));
+extern gui_pref dw_dock_geometry;
 
-const gui_pref dw_is_visible ("DockWidgets/%1Visible", QVariant (true));
+extern gui_pref dw_is_visible;
 
-const gui_pref dw_is_floating ("DockWidgets/%1Floating", QVariant (false));
+extern gui_pref dw_is_floating;
 
-const gui_pref dw_is_minimized ("DockWidgets/%1_minimized", QVariant (false));
+extern gui_pref dw_is_minimized;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-ed.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,255 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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
+
+#if defined (HAVE_QSCINTILLA)
+#include <Qsci/qsciscintilla.h>
+#endif
+
+#include "gui-preferences-ed.h"
+#include "gui-settings.h"
+#include "localcharset-wrapper.h"
+
+// Editor preferences
+
+// Lexer
+
+gui_pref
+ed_color_mode ("editor/color_mode", QVariant (0));
+
+// Code completion
+
+gui_pref
+ed_code_completion_octave_builtins ("editor/codeCompletion_octave_builtins",
+                                    QVariant (true));
+
+gui_pref
+ed_code_completion_octave_functions ("editor/codeCompletion_octave_functions",
+                                     QVariant (true));
+
+gui_pref
+ed_code_completion_keywords ("editor/codeCompletion_keywords", QVariant (true));
+
+gui_pref
+ed_code_completion_document ("editor/codeCompletion_document", QVariant (true));
+
+gui_pref
+ed_code_completion_replace ("editor/codeCompletion_replace", QVariant (false));
+
+gui_pref
+ed_code_completion_case ("editor/codeCompletion_case", QVariant (true));
+
+gui_pref
+ed_code_completion ("editor/codeCompletion", QVariant (true));
+
+gui_pref
+ed_code_completion_threshold ("editor/codeCompletion_threshold", QVariant (3));
+
+// Code formatting
+
+gui_pref
+ed_code_folding ("editor/code_folding", QVariant (true));
+
+gui_pref
+ed_auto_indent ("editor/auto_indent", QVariant (true));
+
+gui_pref
+ed_tab_indents_line ("editor/tab_indents_line", QVariant (false));
+
+gui_pref
+ed_backspace_unindents_line ("editor/backspace_unindents_line",
+                             QVariant (false));
+
+gui_pref
+ed_show_indent_guides ("editor/show_indent_guides", QVariant (false));
+
+gui_pref
+ed_indent_uses_tabs ("editor/indent_uses_tabs", QVariant (false));
+
+gui_pref
+ed_indent_width ("editor/indent_width", QVariant (2));
+
+gui_pref
+ed_tab_width ("editor/tab_width", QVariant (2));
+
+gui_pref
+ed_auto_endif ("editor/auto_endif", QVariant (1));
+
+// Long line handling
+
+gui_pref
+ed_long_line_column ("editor/long_line_column", QVariant (80));
+
+gui_pref
+ed_long_line_marker ("editor/long_line_marker", QVariant (true));
+
+gui_pref
+ed_long_line_marker_line ("editor/long_line_marker_line", QVariant (true));
+
+gui_pref
+ed_long_line_marker_background ("editor/long_line_marker_background",
+                                QVariant (false));
+
+gui_pref
+ed_wrap_lines ("editor/wrap_lines", QVariant (false));
+
+gui_pref
+ed_break_lines ("editor/break_lines", QVariant (false));
+
+gui_pref
+ed_break_lines_comments ("editor/break_lines_comments", QVariant (false));
+
+// Other
+
+gui_pref
+ed_highlight_all_occurrences ("editor/highlight_all_occurrences",
+                              QVariant (true));
+
+gui_pref
+ed_show_Line_numbers ("editor/showLineNumbers", QVariant (true));
+
+gui_pref
+ed_line_numbers_size ("editor/line_numbers_size", QVariant ( 0));
+
+gui_pref
+ed_show_edit_status_bar ("editor/show_edit_status_bar", QVariant (true));
+
+gui_pref
+ed_highlight_current_line ("editor/highlightCurrentLine", QVariant (true));
+
+gui_pref
+ed_highlight_current_line_color ("editor/highlightCurrentLineColor",
+                                 QVariant (settings_color_no_change));
+
+gui_pref
+ed_show_white_space ("editor/show_white_space", QVariant (false));
+
+gui_pref
+ed_show_white_space_indent ("editor/show_white_space_indent", QVariant (false));
+
+gui_pref
+ed_show_line_numbers ("editor/showLineNumbers", QVariant (true));
+
+gui_pref
+ed_show_eol_chars ("editor/show_eol_chars", QVariant (false));
+
+gui_pref
+ed_show_toolbar ("editor/show_toolbar", QVariant (true));
+
+gui_pref
+ed_show_hscroll_bar ("editor/show_hscroll_bar", QVariant (true));
+
+// Octave comment strings
+
+gui_pref
+ed_comment_str_old ("editor/octave_comment_string", QVariant (0));
+
+gui_pref
+ed_comment_str ("editor/oct_comment_str", QVariant (0));
+
+gui_pref
+ed_uncomment_str ("editor/oct_uncomment_str", QVariant (1 + 2 + 4 + 8));
+
+// Session data
+
+gui_pref
+ed_restore_session ("editor/restoreSession", QVariant (true));
+
+gui_pref
+ed_session_names ("editor/savedSessionTabs", QVariant (QStringList ()));
+
+gui_pref
+ed_session_enc ("editor/saved_session_encodings", QVariant (QStringList ()));
+
+gui_pref
+ed_session_ind ("editor/saved_session_tab_index", QVariant (QStringList ()));
+
+gui_pref
+ed_session_lines ("editor/saved_session_lines", QVariant (QStringList ()));
+
+gui_pref
+ed_session_bookmarks ("editor/saved_session_bookmarks", QVariant (QStringList ()));
+
+// Tabs
+
+gui_pref
+ed_tab_position ("editor/tab_position", QVariant (QTabWidget::North));
+
+gui_pref
+ed_tabs_rotated ("editor/tabs_rotated", QVariant (false));
+
+gui_pref
+ed_tabs_max_width ("editor/tabs_max_width", QVariant (0));
+
+// File handling
+
+gui_pref
+ed_force_newline ("editor/force_newline", QVariant (true));
+
+gui_pref
+ed_rm_trailing_spaces ("editor/rm_trailing_spaces", QVariant (true));
+
+gui_pref
+ed_default_eol_mode ("editor/default_eol_mode", QVariant (os_eol_mode));
+
+gui_pref
+ed_show_dbg_file ("editor/show_dbg_file", QVariant (true));
+
+gui_pref
+ed_default_enc ("editor/default_encoding", QVariant ("UTF-8"));
+
+gui_pref
+ed_create_new_file ("editor/create_new_file", QVariant (false));
+
+gui_pref
+ed_hiding_closes_files ("editor/hiding_closes_files", QVariant (false));
+
+gui_pref
+ed_always_reload_changed_files ("editor/always_reload_changed_files",
+                                QVariant (false));
+
+gui_pref
+ed_mru_file_list ("editor/mru_file_list", QVariant ());
+
+gui_pref
+ed_mru_file_encodings ("editor/mru_file_encodings", QVariant ());
+
+// The find dialog
+
+// Dialog position, the default will be calculated from the editor's geometry
+gui_pref
+ed_fdlg_pos ("editor/fdgl_pos", QVariant (QPoint (0, 0)));
+
+gui_pref
+ed_fdlg_opts ("editor/fdgl_opts", QVariant (FIND_DLG_WRAP));
+
+gui_pref
+ed_fdlg_search ("editor/fdgl_search", QVariant ());
+
+gui_pref
+ed_fdlg_replace ("editor/fdgl_replace", QVariant ());
--- a/libgui/src/gui-preferences-ed.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-ed.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,150 +31,103 @@
 #endif
 
 #include "gui-settings.h"
-#include "localcharset-wrapper.h"
 
 // Editor preferences
 
 // Lexer
 
-const gui_pref
-ed_color_mode ("editor/color_mode", QVariant (0));
+extern gui_pref ed_color_mode;
 
 const int ed_max_lexer_styles = 64;
 const int ed_max_style_number = 128;
 
 // Code completion
 
-const gui_pref
-ed_code_completion_octave_builtins ("editor/codeCompletion_octave_builtins",
-                                    QVariant (true));
+extern gui_pref ed_code_completion_octave_builtins;
+
+extern gui_pref ed_code_completion_octave_functions;
 
-const gui_pref
-ed_code_completion_octave_functions ("editor/codeCompletion_octave_functions",
-                                     QVariant (true));
+extern gui_pref ed_code_completion_keywords;
 
-const gui_pref
-ed_code_completion_keywords ("editor/codeCompletion_keywords", QVariant (true));
+extern gui_pref ed_code_completion_document;
 
-const gui_pref
-ed_code_completion_document ("editor/codeCompletion_document", QVariant (true));
+extern gui_pref ed_code_completion_replace;
 
-const gui_pref
-ed_code_completion_replace ("editor/codeCompletion_replace", QVariant (false));
+extern gui_pref ed_code_completion_case;
 
-const gui_pref
-ed_code_completion_case ("editor/codeCompletion_case", QVariant (true));
+extern gui_pref ed_code_completion;
 
-const gui_pref
-ed_code_completion ("editor/codeCompletion", QVariant (true));
-
-const gui_pref
-ed_code_completion_threshold ("editor/codeCompletion_threshold", QVariant (3));
+extern gui_pref ed_code_completion_threshold;
 
 // Code formatting
 
-const gui_pref
-ed_code_folding ("editor/code_folding", QVariant (true));
+extern gui_pref ed_code_folding;
 
-const gui_pref
-ed_auto_indent ("editor/auto_indent", QVariant (true));
+extern gui_pref ed_auto_indent;
 
-const gui_pref
-ed_tab_indents_line ("editor/tab_indents_line", QVariant (false));
+extern gui_pref ed_tab_indents_line;
 
-const gui_pref
-ed_backspace_unindents_line ("editor/backspace_unindents_line",
-                             QVariant (false));
+extern gui_pref ed_backspace_unindents_line;
 
-const gui_pref
-ed_show_indent_guides ("editor/show_indent_guides", QVariant (false));
+extern gui_pref ed_show_indent_guides;
 
-const gui_pref
-ed_indent_uses_tabs ("editor/indent_uses_tabs", QVariant (false));
+extern gui_pref ed_indent_uses_tabs;
 
-const gui_pref
-ed_indent_width ("editor/indent_width", QVariant (2));
+extern gui_pref ed_indent_width;
 
-const gui_pref
-ed_tab_width ("editor/tab_width", QVariant (2));
+extern gui_pref ed_tab_width;
 
-const gui_pref
-ed_auto_endif ("editor/auto_endif", QVariant (1));
+extern gui_pref ed_auto_endif;
 
 // Long line handling
 
-const gui_pref
-ed_long_line_column ("editor/long_line_column", QVariant (80));
+extern gui_pref ed_long_line_column;
 
-const gui_pref
-ed_long_line_marker ("editor/long_line_marker", QVariant (true));
+extern gui_pref ed_long_line_marker;
 
-const gui_pref
-ed_long_line_marker_line ("editor/long_line_marker_line", QVariant (true));
+extern gui_pref ed_long_line_marker_line;
 
-const gui_pref
-ed_long_line_marker_background ("editor/long_line_marker_background",
-                                QVariant (false));
+extern gui_pref ed_long_line_marker_background;
+
+extern gui_pref ed_wrap_lines;
 
-const gui_pref
-ed_wrap_lines ("editor/wrap_lines", QVariant (false));
+extern gui_pref ed_break_lines;
 
-const gui_pref
-ed_break_lines ("editor/break_lines", QVariant (false));
-
-const gui_pref
-ed_break_lines_comments ("editor/break_lines_comments", QVariant (false));
+extern gui_pref ed_break_lines_comments;
 
 // Other
 
-const gui_pref
-ed_highlight_all_occurrences ("editor/highlight_all_occurrences",
-                              QVariant (true));
+extern gui_pref ed_highlight_all_occurrences;
 
-const gui_pref
-ed_show_Line_numbers ("editor/showLineNumbers", QVariant (true));
+extern gui_pref ed_show_Line_numbers;
+
+extern gui_pref ed_line_numbers_size;
 
-const gui_pref
-ed_line_numbers_size ("editor/line_numbers_size", QVariant ( 0));
+extern gui_pref ed_show_edit_status_bar;
 
-const gui_pref
-ed_show_edit_status_bar ("editor/show_edit_status_bar", QVariant (true));
+extern gui_pref ed_highlight_current_line;
 
-const gui_pref
-ed_highlight_current_line ("editor/highlightCurrentLine", QVariant (true));
+extern gui_pref ed_highlight_current_line_color;
 
-const gui_pref
-ed_highlight_current_line_color ("editor/highlightCurrentLineColor",
-                                 QVariant (settings_color_no_change));
+extern gui_pref ed_show_white_space;
 
-const gui_pref
-ed_show_white_space ("editor/show_white_space", QVariant (false));
+extern gui_pref ed_show_white_space_indent;
 
-const gui_pref
-ed_show_white_space_indent ("editor/show_white_space_indent", QVariant (false));
+extern gui_pref ed_show_line_numbers;
 
-const gui_pref
-ed_show_line_numbers ("editor/showLineNumbers", QVariant (true));
-
-const gui_pref
-ed_show_eol_chars ("editor/show_eol_chars", QVariant (false));
+extern gui_pref ed_show_eol_chars;
 
-const gui_pref
-ed_show_toolbar ("editor/show_toolbar", QVariant (true));
+extern gui_pref ed_show_toolbar;
 
-const gui_pref
-ed_show_hscroll_bar ("editor/show_hscroll_bar", QVariant (true));
+extern gui_pref ed_show_hscroll_bar;
 
 // Octave comment strings
 
-const gui_pref
-ed_comment_str_old ("editor/octave_comment_string", QVariant (0));
+extern gui_pref ed_comment_str_old;
 
-const gui_pref
-ed_comment_str ("editor/oct_comment_str", QVariant (0));
+extern gui_pref ed_comment_str;
 
-const gui_pref
-ed_uncomment_str ("editor/oct_uncomment_str", QVariant (1 + 2 + 4 + 8));
+extern gui_pref ed_uncomment_str;
 
 const QString
 ed_last_comment_str ("editor/oct_last_comment_str");
@@ -192,23 +145,17 @@
 
 // Session data
 
-const gui_pref
-ed_restore_session ("editor/restoreSession", QVariant (true));
+extern gui_pref ed_restore_session;
 
-const gui_pref
-ed_session_names ("editor/savedSessionTabs", QVariant (QStringList ()));
+extern gui_pref ed_session_names;
 
-const gui_pref
-ed_session_enc ("editor/saved_session_encodings", QVariant (QStringList ()));
+extern gui_pref ed_session_enc;
 
-const gui_pref
-ed_session_ind ("editor/saved_session_tab_index", QVariant (QStringList ()));
+extern gui_pref ed_session_ind;
 
-const gui_pref
-ed_session_lines ("editor/saved_session_lines", QVariant (QStringList ()));
+extern gui_pref ed_session_lines;
 
-const gui_pref
-ed_session_bookmarks ("editor/saved_session_bookmarks", QVariant (QStringList ()));
+extern gui_pref ed_session_bookmarks;
 
 // Tabs
 const QStringList
@@ -219,22 +166,17 @@
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Right")
 };
 
-const gui_pref
-ed_tab_position ("editor/tab_position", QVariant (QTabWidget::North));
+extern gui_pref ed_tab_position;
 
-const gui_pref
-ed_tabs_rotated ("editor/tabs_rotated", QVariant (false));
+extern gui_pref ed_tabs_rotated;
 
-const gui_pref
-ed_tabs_max_width ("editor/tabs_max_width", QVariant (0));
+extern gui_pref ed_tabs_max_width;
 
 // File handling
 
-const gui_pref
-ed_force_newline ("editor/force_newline", QVariant (true));
+extern gui_pref ed_force_newline;
 
-const gui_pref
-ed_rm_trailing_spaces ("editor/rm_trailing_spaces", QVariant (true));
+extern gui_pref ed_rm_trailing_spaces;
 
 #if defined (HAVE_QSCINTILLA)
 #if defined (Q_OS_WIN32)
@@ -246,30 +188,21 @@
 const int os_eol_mode = 2;
 #endif
 
-const gui_pref
-ed_default_eol_mode ("editor/default_eol_mode", QVariant (os_eol_mode));
+extern gui_pref ed_default_eol_mode;
 
-const gui_pref
-ed_show_dbg_file ("editor/show_dbg_file", QVariant (true));
+extern gui_pref ed_show_dbg_file;
 
-const gui_pref
-ed_default_enc ("editor/default_encoding", QVariant ("UTF-8"));
+extern gui_pref ed_default_enc;
 
-const gui_pref
-ed_create_new_file ("editor/create_new_file", QVariant (false));
+extern gui_pref ed_create_new_file;
 
-const gui_pref
-ed_hiding_closes_files ("editor/hiding_closes_files", QVariant (false));
+extern gui_pref ed_hiding_closes_files;
+
+extern gui_pref ed_always_reload_changed_files;
 
-const gui_pref
-ed_always_reload_changed_files ("editor/always_reload_changed_files",
-                                QVariant (false));
+extern gui_pref ed_mru_file_list;
 
-const gui_pref
-ed_mru_file_list ("editor/mru_file_list", QVariant ());
-
-const gui_pref
-ed_mru_file_encodings ("editor/mru_file_encodings", QVariant ());
+extern gui_pref ed_mru_file_encodings;
 
 // The find dialog
 
@@ -286,15 +219,12 @@
 };
 
 // Dialog position, the default will be calculated from the editor's geometry
-const gui_pref
-ed_fdlg_pos ("editor/fdgl_pos", QVariant (QPoint (0, 0)));
+extern gui_pref ed_fdlg_pos;
+
+extern gui_pref ed_fdlg_opts;
 
-const gui_pref
-ed_fdlg_opts ("editor/fdgl_opts", QVariant (FIND_DLG_WRAP));
+extern gui_pref ed_fdlg_search;
 
-const gui_pref
-ed_fdlg_search ("editor/fdgl_search", QVariant ());
-const gui_pref
-ed_fdlg_replace ("editor/fdgl_replace", QVariant ());
+extern gui_pref ed_fdlg_replace;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-fb.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-fb.h"
+
+// Files dock widget
+
+gui_pref
+fb_column_state ("filesdockwidget/column_state", QVariant ());
+
+gui_pref
+fb_mru_list ("filesdockwidget/mru_dir_list", QVariant (QStringList ()));
+
+gui_pref
+fb_show_size ("filesdockwidget/showFileSize", QVariant (false));
+
+gui_pref
+fb_show_type ("filesdockwidget/showFileType", QVariant (false));
+
+gui_pref
+fb_show_date ("filesdockwidget/showLastModified", QVariant (false));
+
+gui_pref
+fb_show_hidden ("filesdockwidget/showHiddenFiles", QVariant (false));
+
+gui_pref
+fb_show_altcol ("filesdockwidget/useAlternatingRowColors", QVariant (true));
+
+gui_pref
+fb_sort_column ("filesdockwidget/sort_files_by_column", QVariant (0));
+
+gui_pref
+fb_sort_order ("filesdockwidget/sort_files_by_order",
+               QVariant (Qt::AscendingOrder));
+
+gui_pref
+fb_sync_octdir ("filesdockwidget/sync_octave_directory", QVariant (true));
+
+gui_pref
+fb_restore_last_dir ("filesdockwidget/restore_last_dir", QVariant (false));
+
+gui_pref
+fb_startup_dir ("filesdockwidget/startup_dir", QVariant (QString ()));
+
+gui_pref
+fb_txt_file_ext ("filesdockwidget/txt_file_extensions",
+                 QVariant ("m;c;cc;cpp;h;txt"));
+
--- a/libgui/src/gui-preferences-fb.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-fb.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,45 +30,30 @@
 
 // Files dock widget
 
-const gui_pref
-fb_column_state ("filesdockwidget/column_state", QVariant ());
+extern gui_pref fb_column_state;
 
-const gui_pref
-fb_mru_list ("filesdockwidget/mru_dir_list", QVariant (QStringList ()));
+extern gui_pref fb_mru_list;
 
-const gui_pref
-fb_show_size ("filesdockwidget/showFileSize", QVariant (false));
+extern gui_pref fb_show_size;
 
-const gui_pref
-fb_show_type ("filesdockwidget/showFileType", QVariant (false));
+extern gui_pref fb_show_type;
 
-const gui_pref
-fb_show_date ("filesdockwidget/showLastModified", QVariant (false));
+extern gui_pref fb_show_date;
 
-const gui_pref
-fb_show_hidden ("filesdockwidget/showHiddenFiles", QVariant (false));
+extern gui_pref fb_show_hidden;
 
-const gui_pref
-fb_show_altcol ("filesdockwidget/useAlternatingRowColors", QVariant (true));
+extern gui_pref fb_show_altcol;
 
-const gui_pref
-fb_sort_column ("filesdockwidget/sort_files_by_column", QVariant (0));
+extern gui_pref fb_sort_column;
 
-const gui_pref
-fb_sort_order ("filesdockwidget/sort_files_by_order",
-               QVariant (Qt::AscendingOrder));
+extern gui_pref fb_sort_order;
 
-const gui_pref
-fb_sync_octdir ("filesdockwidget/sync_octave_directory", QVariant (true));
+extern gui_pref fb_sync_octdir;
 
-const gui_pref
-fb_restore_last_dir ("filesdockwidget/restore_last_dir", QVariant (false));
+extern gui_pref fb_restore_last_dir;
 
-const gui_pref
-fb_startup_dir ("filesdockwidget/startup_dir", QVariant (QString ()));
+extern gui_pref fb_startup_dir;
 
-const gui_pref
-fb_txt_file_ext ("filesdockwidget/txt_file_extensions",
-                 QVariant ("m;c;cc;cpp;h;txt"));
+extern gui_pref fb_txt_file_ext;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-ff.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,66 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-ff.h"
+
+// Find files dialog preferences
+
+gui_pref
+ff_file_name ("findfiles/file_name", QVariant ("*"));
+
+gui_pref
+ff_start_dir ("findfiles/start_dir", QVariant (""));
+
+gui_pref
+ff_recurse_dirs ("findfiles/recurse_dirs", QVariant (false));
+
+gui_pref
+ff_include_dirs ("findfiles/include_dirs", QVariant (false));
+
+gui_pref
+ff_name_case ("findfiles/name_case", QVariant (false));
+
+gui_pref
+ff_check_text ("findfiles/check_text", QVariant (false));
+
+gui_pref
+ff_contains_text ("findfiles/contains_text", QVariant (""));
+
+gui_pref
+ff_content_case ("findfiles/content_case", QVariant (false));
+
+gui_pref
+ff_column_state ("findfiles/column_state", QVariant ());
+
+gui_pref
+ff_sort_files_by_column ("findfiles/sort_files_by_column", QVariant (0));
+
+gui_pref
+ff_sort_files_by_order ("findfiles/sort_files_by_order",
+                        QVariant (Qt::AscendingOrder));
--- a/libgui/src/gui-preferences-ff.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-ff.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,39 +30,27 @@
 
 // Find files dialog preferences
 
-const gui_pref
-ff_file_name ("findfiles/file_name", QVariant ("*"));
+extern gui_pref ff_file_name;
 
-const gui_pref
-ff_start_dir ("findfiles/start_dir", QVariant (""));
+extern gui_pref ff_start_dir;
 
-const gui_pref
-ff_recurse_dirs ("findfiles/recurse_dirs", QVariant (false));
+extern gui_pref ff_recurse_dirs;
 
-const gui_pref
-ff_include_dirs ("findfiles/include_dirs", QVariant (false));
+extern gui_pref ff_include_dirs;
 
-const gui_pref
-ff_name_case ("findfiles/name_case", QVariant (false));
+extern gui_pref ff_name_case;
 
-const gui_pref
-ff_check_text ("findfiles/check_text", QVariant (false));
+extern gui_pref ff_check_text;
 
-const gui_pref
-ff_contains_text ("findfiles/contains_text", QVariant (""));
+extern gui_pref ff_contains_text;
 
-const gui_pref
-ff_content_case ("findfiles/content_case", QVariant (false));
+extern gui_pref ff_content_case;
 
-const gui_pref
-ff_column_state ("findfiles/column_state", QVariant ());
+extern gui_pref ff_column_state;
 
-const gui_pref
-ff_sort_files_by_column ("findfiles/sort_files_by_column", QVariant (0));
+extern gui_pref ff_sort_files_by_column;
 
-const gui_pref
-ff_sort_files_by_order ("findfiles/sort_files_by_order",
-                        QVariant (Qt::AscendingOrder));
+extern gui_pref ff_sort_files_by_order;
 
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-global.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,119 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-global.h"
+
+// Global preferences
+
+gui_pref
+global_skip_welcome_wizard ("global_skip_welcome_wizard", false);
+
+gui_pref
+global_mono_font ("monospace_font", global_font_family);
+
+// Style
+
+gui_pref
+global_style ("style", QVariant ("default"));
+
+// Icon size (in preferences: values -1, 0, 1)
+
+gui_pref
+global_icon_size ("toolbar_icon_size", QVariant (0));
+
+gui_pref
+global_icon_theme ("use_system_icon_theme", QVariant (true));
+
+gui_pref
+global_icon_theme_index ("icon_theme", QVariant (ICON_THEME_SYSTEM));
+
+gui_pref
+global_icon_fallbacks ("icon_fallbacks", QVariant (QStringList ()));
+
+gui_pref
+global_status_bar ("show_status_bar", QVariant (true));
+
+#if defined (Q_OS_MAC)
+// prevent native file dialogs on MAC by setting the default "false" and
+// setting the flag for ignoring the pref to "true" (3rd argument)
+gui_pref
+global_use_native_dialogs ("use_native_file_dialogs", QVariant (false), true);
+#elif defined (Q_OS_WIN32)
+gui_pref
+global_use_native_dialogs ("use_native_file_dialogs", QVariant (false));
+#else
+gui_pref
+global_use_native_dialogs ("use_native_file_dialogs", QVariant (true));
+#endif
+
+gui_pref
+global_cursor_blinking ("cursor_blinking", QVariant (true));
+
+gui_pref
+global_language ("language", QVariant ("SYSTEM"));
+
+gui_pref
+global_ov_startup_dir ("octave_startup_dir", QVariant (QString ()));
+
+gui_pref
+global_restore_ov_dir ("restore_octave_dir", QVariant (false));
+
+gui_pref
+global_use_custom_editor ("useCustomFileEditor", QVariant (false));
+
+#if defined (Q_OS_WIN32)
+gui_pref
+global_custom_editor ("customFileEditor", QVariant ("notepad++ -n%l %f"));
+#else
+gui_pref
+global_custom_editor ("customFileEditor", QVariant ("emacs +%l %f"));
+#endif
+
+gui_pref
+global_prompt_to_exit ("prompt_to_exit", QVariant (false));
+
+// Proxy
+
+gui_pref
+global_proxy_host ("proxyHostName", QVariant (QString ()));
+
+gui_pref
+global_use_proxy ("useProxyServer", QVariant (false));
+
+gui_pref
+global_proxy_type ("proxyType", QVariant (QString ()));
+
+gui_pref
+global_proxy_port ("proxyPort", QVariant (80));
+
+gui_pref
+global_proxy_user ("proxyUserName", QVariant (QString ()));
+
+gui_pref
+global_proxy_pass ("proxyPassword", QVariant (QString ()));
--- a/libgui/src/gui-preferences-global.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-global.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,6 +26,8 @@
 #if ! defined (octave_gui_preferences_global_h)
 #define octave_gui_preferences_global_h 1
 
+#include <QStyle>
+
 #include "gui-preferences.h"
 
 // Constants
@@ -34,6 +36,8 @@
 
 // Global preferences
 
+extern gui_pref global_skip_welcome_wizard;
+
 // Get the default monospaced font
 #if defined (Q_OS_WIN)
 const QString global_font_family = "Courier";
@@ -43,13 +47,11 @@
 const QString global_font_family = "Monospace";
 #endif
 
-const gui_pref
-global_mono_font ("monospace_font", global_font_family);
+extern gui_pref global_mono_font;
 
 // Style
 
-const gui_pref
-global_style ("style", QVariant ("default"));
+extern gui_pref global_style;
 
 const QString
 global_toolbar_style ("QToolBar {"
@@ -78,11 +80,9 @@
   QStyle::PM_LargeIconSize
 };
 
-const gui_pref
-global_icon_size ("toolbar_icon_size", QVariant (0));
+extern gui_pref global_icon_size;
 
-const gui_pref
-global_icon_theme ("use_system_icon_theme", QVariant (true));
+extern gui_pref global_icon_theme;
 
 enum
 {
@@ -100,8 +100,8 @@
   ":/icons/cursors/"
 };
 
-const gui_pref
-global_icon_theme_index ("icon_theme", QVariant (ICON_THEME_SYSTEM));
+extern gui_pref global_icon_theme_index;
+
 const QStringList
 global_all_icon_themes = {
   "",
@@ -117,9 +117,9 @@
   "Tango"
 };
 
-const gui_pref
-global_status_bar ("show_status_bar", QVariant (true));
+extern gui_pref global_icon_fallbacks;
 
+extern gui_pref global_status_bar;
 
 enum
 {
@@ -133,55 +133,44 @@
 #if defined (Q_OS_MAC)
 // prevent native file dialogs on MAC by setting the default "false" and
 // setting the flag for ignoring the pref to "true" (3rd argument)
-const gui_pref
-global_use_native_dialogs ("use_native_file_dialogs", QVariant (false), true);
+extern gui_pref global_use_native_dialogs;
 #elif defined (Q_OS_WIN32)
-const gui_pref
-global_use_native_dialogs ("use_native_file_dialogs", QVariant (false));
+extern gui_pref global_use_native_dialogs;
 #else
-const gui_pref
-global_use_native_dialogs ("use_native_file_dialogs", QVariant (true));
+extern gui_pref global_use_native_dialogs;
 #endif
 
-const gui_pref
-global_cursor_blinking ("cursor_blinking", QVariant (true));
+extern gui_pref global_cursor_blinking;
 
-const gui_pref
-global_language ("language", QVariant ("SYSTEM"));
+extern gui_pref global_language;
 
-const gui_pref
-global_ov_startup_dir ("octave_startup_dir", QVariant (QString ()));
-const gui_pref
-global_restore_ov_dir ("restore_octave_dir", QVariant (false));
+extern gui_pref global_ov_startup_dir;
 
-const gui_pref
-global_use_custom_editor ("useCustomFileEditor", QVariant (false));
+extern gui_pref global_restore_ov_dir;
+
+extern gui_pref global_use_custom_editor;
 
 #if defined (Q_OS_WIN32)
-const gui_pref
-global_custom_editor ("customFileEditor", QVariant ("notepad++ -n%l %f"));
+extern gui_pref global_custom_editor;
 #else
-const gui_pref
-global_custom_editor ("customFileEditor", QVariant ("emacs +%l %f"));
+extern gui_pref global_custom_editor;
 #endif
 
-const gui_pref
-global_prompt_to_exit ("prompt_to_exit", QVariant (false));
+extern gui_pref global_prompt_to_exit;
 
 // Proxy
 
-const gui_pref
-global_proxy_host ("proxyHostName", QVariant (QString ()));
-const gui_pref
-global_use_proxy ("useProxyServer", QVariant (false));
-const gui_pref
-global_proxy_type ("proxyType", QVariant (QString ()));
-const gui_pref
-global_proxy_port ("proxyPort", QVariant (80));
-const gui_pref
-global_proxy_user ("proxyUserName", QVariant (QString ()));
-const gui_pref
-global_proxy_pass ("proxyPassword", QVariant (QString ()));
+extern gui_pref global_proxy_host;
+
+extern gui_pref global_use_proxy;
+
+extern gui_pref global_proxy_type;
+
+extern gui_pref global_proxy_port;
+
+extern gui_pref global_proxy_user;
+
+extern gui_pref global_proxy_pass;
 
 const QStringList
 global_proxy_all_types = {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-gp.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-gp.h"
+
+// Graphics utilities
+
+gui_pref
+gp_annotation_geometry ("annotation/geometry", QVariant ());
--- a/libgui/src/gui-preferences-gp.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-gp.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 
 // Graphics utilities
 
-const gui_pref
-gp_annotation_geometry ("annotation/geometry", QVariant ());
+extern gui_pref gp_annotation_geometry;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-hw.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-hw.h"
+
+// News Reader properties
+
+gui_pref
+hw_filter_active ("history_dock_widget/filter_active", QVariant (false));
+
+gui_pref
+hw_filter_shown ("history_dock_widget/filter_shown", QVariant (true));
+
+gui_pref
+hw_mru_list ("history_dock_widget/mru_list", QVariant ());
--- a/libgui/src/gui-preferences-hw.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-hw.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,13 +30,10 @@
 
 // News Reader properties
 
-const gui_pref
-hw_filter_active ("history_dock_widget/filter_active", QVariant (false));
+extern gui_pref hw_filter_active;
 
-const gui_pref
-hw_filter_shown ("history_dock_widget/filter_shown", QVariant (true));
+extern gui_pref hw_filter_shown;
 
-const gui_pref
-hw_mru_list ("history_dock_widget/mru_list", QVariant ());
+extern gui_pref hw_mru_list;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-mw.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,43 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2018-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-mw.h"
+
+// Main window preferences
+
+// Geometry wihtout default since default layout is built programmatically
+gui_pref
+mw_geometry ("MainWindow/geometry", QVariant (QByteArray ()));
+
+// State wihtout default since default layout is built programmatically
+gui_pref
+mw_state ("MainWindow/windowState", QVariant (QByteArray ()));
+
+gui_pref
+mw_dir_list ("MainWindow/current_directory_list", QVariant (QStringList ()));
--- a/libgui/src/gui-preferences-mw.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-mw.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,14 +31,11 @@
 // Main window preferences
 
 // Geometry wihtout default since default layout is built programmatically
-const gui_pref
-mw_geometry ("MainWindow/geometry", QVariant (QByteArray ()));
+extern gui_pref mw_geometry;
 
 // State wihtout default since default layout is built programmatically
-const gui_pref
-mw_state ("MainWindow/windowState", QVariant (QByteArray ()));
+extern gui_pref mw_state;
 
-const gui_pref
-mw_dir_list ("MainWindow/current_directory_list", QVariant (QStringList ()));
+extern gui_pref mw_dir_list;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-nr.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-nr.h"
+#include <QDateTime>
+
+// News Reader properties
+
+gui_pref
+nr_last_time ("news/last_time_checked", QVariant (QDateTime ()));
+
+gui_pref
+nr_last_news ("news/last_news_item", QVariant (0));
+
+gui_pref
+nr_allow_connection ("news/allow_web_connection", QVariant (false));
--- a/libgui/src/gui-preferences-nr.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-nr.h	Fri Jun 23 20:51:51 2023 +0200
@@ -27,17 +27,13 @@
 #define octave_gui_preferences_nr_h 1
 
 #include "gui-preferences.h"
-#include <QDateTime>
 
 // News Reader properties
 
-const gui_pref
-nr_last_time ("news/last_time_checked", QVariant (QDateTime ()));
+extern gui_pref nr_last_time;
 
-const gui_pref
-nr_last_news ("news/last_news_item", QVariant (0));
+extern gui_pref nr_last_news;
 
-const gui_pref
-nr_allow_connection ("news/allow_web_connection", QVariant (false));
+extern gui_pref nr_allow_connection;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-pd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-pd.h"
+
+// Path Dialog properties
+
+gui_pref
+pd_geometry ("path_dlg_geometry", QVariant (QByteArray ()));
--- a/libgui/src/gui-preferences-pd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-pd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 
 // Path Dialog properties
 
-const gui_pref
-pd_geometry ("path_dlg_geometry", QVariant (QByteArray ()));
+extern gui_pref pd_geometry;
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-sc.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,228 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 <QCoreApplication>
+#include <QSet>
+
+#include "gui-preferences-sc.h"
+
+// Note: Trying to shorten the uses of
+//
+//   QCoreApplication::translate (CONTEXT, STRING)
+//
+// by defining a macro won't work because lupdate won't know to look for
+// the macro.
+
+sc_pref sc_dock_widget_dock (QCoreApplication::translate ("shortcuts", "Undock/Dock Widget"), sc_dock_widget + ":dock", CTRL_ALT | Qt::Key_D);
+sc_pref sc_dock_widget_close (QCoreApplication::translate ("shortcuts", "Close Widget"), sc_dock_widget + ":close", CTRL_ALT | Qt::Key_C);
+
+// Main window menu
+
+// file
+sc_pref sc_main_file_new_file (QCoreApplication::translate ("shortcuts", "New File"), sc_main_file + ":new_file", QKeySequence::New);
+sc_pref sc_main_file_new_function (QCoreApplication::translate ("shortcuts", "New Function"), sc_main_file + ":new_function", CTRL_SHIFT | Qt::Key_N);
+sc_pref sc_main_file_new_figure (QCoreApplication::translate ("shortcuts", "New Figure"), sc_main_file + ":new_figure", QKeySequence::UnknownKey);
+sc_pref sc_main_file_open_file (QCoreApplication::translate ("shortcuts", "Open File"), sc_main_file + ":open_file", QKeySequence::Open);
+sc_pref sc_main_file_load_workspace (QCoreApplication::translate ("shortcuts", "Load Workspace"), sc_main_file + ":load_workspace", QKeySequence::UnknownKey);
+sc_pref sc_main_file_save_workspace (QCoreApplication::translate ("shortcuts", "Save Workspace As"), sc_main_file + ":save_workspace", QKeySequence::UnknownKey);
+sc_pref sc_main_file_exit (QCoreApplication::translate ("shortcuts", "Exit Octave"), sc_main_file + ":exit", QKeySequence::Quit);
+
+// edit
+sc_pref sc_main_edit_copy (QCoreApplication::translate ("shortcuts", "Copy"), sc_main_edit + ":copy", QKeySequence::Copy);
+sc_pref sc_main_edit_paste (QCoreApplication::translate ("shortcuts", "Paste"), sc_main_edit + ":paste", QKeySequence::Paste);
+sc_pref sc_main_edit_undo (QCoreApplication::translate ("shortcuts", "Undo"), sc_main_edit + ":undo", QKeySequence::Undo);
+sc_pref sc_main_edit_select_all (QCoreApplication::translate ("shortcuts", "Select All"), sc_main_edit + ":select_all", QKeySequence::SelectAll);
+sc_pref sc_main_edit_clear_clipboard (QCoreApplication::translate ("shortcuts", "Clear Clipboard"), sc_main_edit + ":clear_clipboard", QKeySequence::UnknownKey);
+sc_pref sc_main_edit_find_in_files (QCoreApplication::translate ("shortcuts", "Find in Files"), sc_main_edit + ":find_in_files", CTRL_SHIFT | Qt::Key_F);
+sc_pref sc_main_edit_clear_command_window (QCoreApplication::translate ("shortcuts", "Clear Command Window"), sc_main_edit + ":clear_command_window", QKeySequence::UnknownKey);
+sc_pref sc_main_edit_clear_history (QCoreApplication::translate ("shortcuts", "Clear Command History"), sc_main_edit + ":clear_history", QKeySequence::UnknownKey);
+sc_pref sc_main_edit_clear_workspace (QCoreApplication::translate ("shortcuts", "Clear Workspace"), sc_main_edit + ":clear_workspace", QKeySequence::UnknownKey);
+sc_pref sc_main_edit_set_path (QCoreApplication::translate ("shortcuts", "Set Path"), sc_main_edit + ":set_path", QKeySequence::UnknownKey);
+sc_pref sc_main_edit_preferences (QCoreApplication::translate ("shortcuts", "Preferences"), sc_main_edit + ":preferences", QKeySequence::UnknownKey);
+
+// debug
+sc_pref sc_main_debug_step_over (QCoreApplication::translate ("shortcuts", "Step"), sc_main_debug + ":step_over", PRE | Qt::Key_F10);
+sc_pref sc_main_debug_step_into (QCoreApplication::translate ("shortcuts", "Step Into"), sc_main_debug + ":step_into", PRE | Qt::Key_F11);
+sc_pref sc_main_debug_step_out (QCoreApplication::translate ("shortcuts", "Step Out"), sc_main_debug + ":step_out", PRE | Qt::ShiftModifier | Qt::Key_F11);
+sc_pref sc_main_debug_continue (QCoreApplication::translate ("shortcuts", "Continue"), sc_main_debug + ":continue", PRE | Qt::Key_F5);
+sc_pref sc_main_debug_quit (QCoreApplication::translate ("shortcuts", "Quit Debug Mode"), sc_main_debug + ":quit", PRE | Qt::ShiftModifier | Qt::Key_F5);
+
+// tools
+sc_pref sc_main_tools_start_profiler (QCoreApplication::translate ("shortcuts", "Start/Stop Profiler Session"), sc_main_tools + ":start_profiler", CTRL_SHIFT | Qt::Key_P);
+sc_pref sc_main_tools_resume_profiler (QCoreApplication::translate ("shortcuts", "Resume Profiler Session"), sc_main_tools + ":resume_profiler", QKeySequence::UnknownKey);
+sc_pref sc_main_tools_show_profiler (QCoreApplication::translate ("shortcuts", "Show Profile Data"), sc_main_tools + ":show_profiler", Qt::AltModifier | Qt::ShiftModifier | Qt::Key_P);
+
+
+// window
+sc_pref sc_main_window_show_command (QCoreApplication::translate ("shortcuts", "Show Command Window"), sc_main_window + ":show_command", PRE | CTRL_SHIFT | Qt::Key_0);
+sc_pref sc_main_window_show_history (QCoreApplication::translate ("shortcuts", "Show Command History"), sc_main_window + ":show_history", PRE | CTRL_SHIFT | Qt::Key_1);
+sc_pref sc_main_window_show_file_browser (QCoreApplication::translate ("shortcuts", "Show File Browser"), sc_main_window + ":show_file_browser", PRE | CTRL_SHIFT | Qt::Key_2);
+sc_pref sc_main_window_show_workspace (QCoreApplication::translate ("shortcuts", "Show Workspace"), sc_main_window + ":show_workspace", PRE | CTRL_SHIFT | Qt::Key_3);
+sc_pref sc_main_window_show_editor (QCoreApplication::translate ("shortcuts", "Show Editor"), sc_main_window + ":show_editor", PRE | CTRL_SHIFT | Qt::Key_4);
+sc_pref sc_main_window_show_doc (QCoreApplication::translate ("shortcuts", "Show Documentation"), sc_main_window + ":show_doc", PRE | CTRL_SHIFT | Qt::Key_5);
+sc_pref sc_main_window_show_variable_editor (QCoreApplication::translate ("shortcuts", "Show Variable Editor"), sc_main_window + ":show_variable_editor", PRE | CTRL_SHIFT | Qt::Key_6);
+sc_pref sc_main_window_command (QCoreApplication::translate ("shortcuts", "Command Window"), sc_main_window + ":command", PRE | CTRL | Qt::Key_0);
+sc_pref sc_main_window_history (QCoreApplication::translate ("shortcuts", "Command History"), sc_main_window + ":history", PRE | CTRL | Qt::Key_1);
+sc_pref sc_main_window_file_browser (QCoreApplication::translate ("shortcuts", "File Browser"), sc_main_window + ":file_browser", PRE | CTRL | Qt::Key_2);
+sc_pref sc_main_window_workspace (QCoreApplication::translate ("shortcuts", "Workspace"), sc_main_window + ":workspace", PRE | CTRL | Qt::Key_3);
+sc_pref sc_main_window_editor (QCoreApplication::translate ("shortcuts", "Editor"), sc_main_window + ":editor", PRE | CTRL | Qt::Key_4);
+sc_pref sc_main_window_doc (QCoreApplication::translate ("shortcuts", "Documentation"), sc_main_window + ":doc", PRE | CTRL | Qt::Key_5);
+sc_pref sc_main_window_variable_editor (QCoreApplication::translate ("shortcuts", "Variable Editor"), sc_main_window + ":variable_editor", PRE | CTRL | Qt::Key_6);
+sc_pref sc_main_window_previous_dock (QCoreApplication::translate ("shortcuts", "Previous Widget"), sc_main_window + ":previous_widget", PRE | CTRL_ALT | Qt::Key_P);
+sc_pref sc_main_window_reset (QCoreApplication::translate ("shortcuts", "Reset Default Window Layout"), sc_main_window + ":reset", QKeySequence::UnknownKey);
+
+// help
+sc_pref sc_main_help_ondisk_doc (QCoreApplication::translate ("shortcuts", "Show On-disk Documentation"), sc_main_help + ":ondisk_doc", QKeySequence::UnknownKey);
+sc_pref sc_main_help_online_doc (QCoreApplication::translate ("shortcuts", "Show Online Documentation"), sc_main_help + ":online_doc", QKeySequence::UnknownKey);
+sc_pref sc_main_help_report_bug (QCoreApplication::translate ("shortcuts", "Report Bug"), sc_main_help + ":report_bug", QKeySequence::UnknownKey);
+sc_pref sc_main_help_packages (QCoreApplication::translate ("shortcuts", "Octave Packages"), sc_main_help + ":packages", QKeySequence::UnknownKey);
+sc_pref sc_main_help_contribute (QCoreApplication::translate ("shortcuts", "Contribute to Octave"), sc_main_help + ":contribute", QKeySequence::UnknownKey);
+sc_pref sc_main_help_developer (QCoreApplication::translate ("shortcuts", "Octave Developer Resources"), sc_main_help + ":developer", QKeySequence::UnknownKey);
+sc_pref sc_main_help_about (QCoreApplication::translate ("shortcuts", "About Octave"), sc_main_help + ":about", QKeySequence::UnknownKey);
+
+// news
+sc_pref sc_main_news_release_notes (QCoreApplication::translate ("shortcuts", "Release Notes"), sc_main_news + ":release_notes", QKeySequence::UnknownKey);
+sc_pref sc_main_news_community_news (QCoreApplication::translate ("shortcuts", "Community News"), sc_main_news + ":community_news", QKeySequence::UnknownKey);
+
+// Tab handling
+// The following shortcuts are moved into a separate tab.  The key names
+// are not change for preserving compatibility with older versions
+sc_pref sc_edit_file_close (QCoreApplication::translate ("shortcuts", "Close Tab"), sc_edit_file_cl, QKeySequence::Close);
+sc_pref sc_edit_file_close_all (QCoreApplication::translate ("shortcuts", "Close All Tabs"), sc_edit_file_cl + "_all", QKeySequence::UnknownKey);
+sc_pref sc_edit_file_close_other (QCoreApplication::translate ("shortcuts", "Close Other Tabs"), sc_edit_file_cl + "_other", QKeySequence::UnknownKey);
+sc_pref sc_edit_tabs_switch_left_tab (QCoreApplication::translate ("shortcuts", "Switch to Left Tab"), sc_edit_tabs + ":switch_left_tab", CTRL | Qt::Key_PageUp);
+sc_pref sc_edit_tabs_switch_right_tab (QCoreApplication::translate ("shortcuts", "Switch to Right Tab"), sc_edit_tabs + ":switch_right_tab", CTRL | Qt::Key_PageDown);
+sc_pref sc_edit_tabs_move_tab_left (QCoreApplication::translate ("shortcuts", "Move Tab Left"), sc_edit_tabs + ":move_tab_left", Qt::AltModifier | Qt::Key_PageUp);
+sc_pref sc_edit_tabs_move_tab_right (QCoreApplication::translate ("shortcuts", "Move Tab Right"), sc_edit_tabs + ":move_tab_right", Qt::AltModifier | Qt::Key_PageDown);
+
+// Zooming
+sc_pref sc_edit_view_zoom_in (QCoreApplication::translate ("shortcuts", "Zoom In"), sc_edit_view_zoom + "_in", QKeySequence::ZoomIn);
+sc_pref sc_edit_view_zoom_out (QCoreApplication::translate ("shortcuts", "Zoom Out"), sc_edit_view_zoom + "_out", QKeySequence::ZoomOut);
+#if defined (Q_OS_MAC)
+sc_pref sc_edit_view_zoom_normal (QCoreApplication::translate ("shortcuts", "Zoom Normal"), sc_edit_view_zoom + "_normal", CTRL | Qt::Key_Underscore);
+#else
+sc_pref sc_edit_view_zoom_normal (QCoreApplication::translate ("shortcuts", "Zoom Normal"), sc_edit_view_zoom + "_normal", CTRL | Qt::Key_Period);
+#endif
+
+// Actions of the editor
+
+// file
+sc_pref sc_edit_file_edit_function (QCoreApplication::translate ("shortcuts", "Edit Function"), sc_edit_file + ":edit_function", CTRL | Qt::Key_E);
+sc_pref sc_edit_file_save (QCoreApplication::translate ("shortcuts", "Save File"), sc_edit_file + ":save", QKeySequence::Save);
+sc_pref sc_edit_file_save_as (QCoreApplication::translate ("shortcuts", "Save File As"), sc_edit_file + ":save_as", QKeySequence::SaveAs);
+sc_pref sc_edit_file_print (QCoreApplication::translate ("shortcuts", "Print"), sc_edit_file + ":print", QKeySequence::Print);
+
+// edit
+sc_pref sc_edit_edit_redo (QCoreApplication::translate ("shortcuts", "Redo"), sc_edit_edit + ":redo", QKeySequence::Redo);
+sc_pref sc_edit_edit_cut (QCoreApplication::translate ("shortcuts", "Cut"), sc_edit_edit + ":cut", QKeySequence::Cut);
+sc_pref sc_edit_edit_find_replace (QCoreApplication::translate ("shortcuts", "Find and Replace"), sc_edit_edit_find + "_replace", QKeySequence::Find);
+sc_pref sc_edit_edit_find_next (QCoreApplication::translate ("shortcuts", "Find Next"), sc_edit_edit_find + "_next", QKeySequence::FindNext);
+sc_pref sc_edit_edit_find_previous (QCoreApplication::translate ("shortcuts", "Find Previous"), sc_edit_edit_find + "_previous", QKeySequence::FindPrevious);
+sc_pref sc_edit_edit_delete_start_word (QCoreApplication::translate ("shortcuts", "Delete to Start of Word"), sc_edit_edit + ":delete_start_word", QKeySequence::DeleteStartOfWord);
+sc_pref sc_edit_edit_delete_end_word (QCoreApplication::translate ("shortcuts", "Delete to End of Word"), sc_edit_edit + ":delete_end_word", QKeySequence::DeleteEndOfWord);
+sc_pref sc_edit_edit_delete_start_line (QCoreApplication::translate ("shortcuts", "Delete to Start of Line"), sc_edit_edit + ":delete_start_line", CTRL_SHIFT | Qt::Key_Backspace);
+sc_pref sc_edit_edit_delete_end_line (QCoreApplication::translate ("shortcuts", "Delete to End of Line"), sc_edit_edit + ":delete_end_line", CTRL_SHIFT | Qt::Key_Delete);
+sc_pref sc_edit_edit_delete_line (QCoreApplication::translate ("shortcuts", "Delete Line"), sc_edit_edit + ":delete_line", CTRL_SHIFT | Qt::Key_L);
+sc_pref sc_edit_edit_copy_line (QCoreApplication::translate ("shortcuts", "Copy Line"), sc_edit_edit + ":copy_line", CTRL_SHIFT | Qt::Key_C);
+sc_pref sc_edit_edit_cut_line (QCoreApplication::translate ("shortcuts", "Cut Line"), sc_edit_edit + ":cut_line", CTRL_SHIFT | Qt::Key_X);
+sc_pref sc_edit_edit_duplicate_selection (QCoreApplication::translate ("shortcuts", "Duplicate Selection/Line"), sc_edit_edit + ":duplicate_selection", CTRL | Qt::Key_D);
+sc_pref sc_edit_edit_transpose_line (QCoreApplication::translate ("shortcuts", "Transpose Line"), sc_edit_edit + ":transpose_line", CTRL | Qt::Key_T);
+sc_pref sc_edit_edit_completion_list (QCoreApplication::translate ("shortcuts", "Show Completion List"), sc_edit_edit + ":completion_list", CTRL | Qt::Key_Space);
+
+sc_pref sc_edit_edit_comment_selection (QCoreApplication::translate ("shortcuts", "Comment Selection"), sc_edit_edit + ":comment_selection", CTRL | Qt::Key_R);
+sc_pref sc_edit_edit_uncomment_selection (QCoreApplication::translate ("shortcuts", "Uncomment Selection"), sc_edit_edit + ":uncomment_selection", CTRL_SHIFT | Qt::Key_R);
+sc_pref sc_edit_edit_comment_var_selection (QCoreApplication::translate ("shortcuts", "Comment Selection (Choosing String)"), sc_edit_edit + ":comment_var_selection", CTRL_ALT | Qt::Key_R);
+sc_pref sc_edit_edit_upper_case (QCoreApplication::translate ("shortcuts", "Uppercase Selection"), sc_edit_edit + ":upper_case", CTRL | Qt::Key_U);
+sc_pref sc_edit_edit_lower_case (QCoreApplication::translate ("shortcuts", "Lowercase Selection"), sc_edit_edit + ":lower_case", CTRL_ALT | Qt::Key_U);
+
+#if defined (Q_OS_MAC)
+sc_pref sc_edit_edit_indent_selection (QCoreApplication::translate ("shortcuts", "Indent Selection Rigidly"), sc_edit_edit + ":indent_selection", PRE | Qt::Key_Tab);
+sc_pref sc_edit_edit_unindent_selection (QCoreApplication::translate ("shortcuts", "Unindent Selection Rigidly"), sc_edit_edit + ":unindent_selection", PRE | Qt::ShiftModifier | Qt::Key_Tab);
+#else
+sc_pref sc_edit_edit_indent_selection (QCoreApplication::translate ("shortcuts", "Indent Selection Rigidly"), sc_edit_edit + ":indent_selection", CTRL | Qt::Key_Tab);
+sc_pref sc_edit_edit_unindent_selection (QCoreApplication::translate ("shortcuts", "Unindent Selection Rigidly"), sc_edit_edit + ":unindent_selection", CTRL_SHIFT | Qt::Key_Tab);
+#endif
+sc_pref sc_edit_edit_smart_indent_line_or_selection (QCoreApplication::translate ("shortcuts", "Indent Code"), sc_edit_edit + ":smart_indent_line_or_selection", QKeySequence::UnknownKey);
+
+sc_pref sc_edit_edit_conv_eol_winows (QCoreApplication::translate ("shortcuts", "Convert Line Endings to Windows"), sc_edit_edit + ":conv_eol_winows", QKeySequence::UnknownKey);
+sc_pref sc_edit_edit_conv_eol_unix (QCoreApplication::translate ("shortcuts", "Convert Line Endings to Unix"), sc_edit_edit + ":conv_eol_unix", QKeySequence::UnknownKey);
+sc_pref sc_edit_edit_conv_eol_mac (QCoreApplication::translate ("shortcuts", "Convert Line Endings to Mac"), sc_edit_edit + ":conv_eol_mac", QKeySequence::UnknownKey);
+
+sc_pref sc_edit_edit_goto_line (QCoreApplication::translate ("shortcuts", "Goto Line"), sc_edit_edit + ":goto_line", CTRL | Qt::Key_L);
+sc_pref sc_edit_edit_move_to_brace (QCoreApplication::translate ("shortcuts", "Move to Matching Brace"), sc_edit_edit + ":move_to_brace", CTRL | Qt::Key_M);
+sc_pref sc_edit_edit_select_to_brace (QCoreApplication::translate ("shortcuts", "Select to Matching Brace"), sc_edit_edit + ":select_to_brace", CTRL_SHIFT | Qt::Key_M);
+sc_pref sc_edit_edit_toggle_bookmark (QCoreApplication::translate ("shortcuts", "Toggle Bookmark"), sc_edit_edit + ":toggle_bookmark", PRE | Qt::Key_F7);
+sc_pref sc_edit_edit_next_bookmark (QCoreApplication::translate ("shortcuts", "Next Bookmark"), sc_edit_edit + ":next_bookmark", PRE | Qt::Key_F2);
+sc_pref sc_edit_edit_previous_bookmark (QCoreApplication::translate ("shortcuts", "Previous Bookmark"), sc_edit_edit + ":previous_bookmark", PRE | Qt::ShiftModifier | Qt::Key_F2);
+sc_pref sc_edit_edit_remove_bookmark (QCoreApplication::translate ("shortcuts", "Remove All Bookmark"), sc_edit_edit + ":remove_bookmark", QKeySequence::UnknownKey);
+
+sc_pref sc_edit_edit_preferences (QCoreApplication::translate ("shortcuts", "Preferences"), sc_edit_edit + ":preferences", QKeySequence::UnknownKey);
+sc_pref sc_edit_edit_styles_preferences (QCoreApplication::translate ("shortcuts", "Styles Preferences"), sc_edit_edit + ":styles_preferences", QKeySequence::UnknownKey);
+
+// view
+sc_pref sc_edit_view_show_line_numbers (QCoreApplication::translate ("shortcuts", "Show Line Numbers"), sc_edit_view + ":show_line_numbers", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_white_spaces (QCoreApplication::translate ("shortcuts", "Show Whitespace Characters"), sc_edit_view + ":show_white_spaces", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_eol_chars (QCoreApplication::translate ("shortcuts", "Show Line Endings"), sc_edit_view + ":show_eol_chars", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_ind_guides (QCoreApplication::translate ("shortcuts", "Show Indentation Guides"), sc_edit_view + ":show_ind_guides", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_long_line (QCoreApplication::translate ("shortcuts", "Show Long Line Marker"), sc_edit_view + ":show_long_line", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_toolbar (QCoreApplication::translate ("shortcuts", "Show Toolbar"), sc_edit_view + ":show_toolbar", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_statusbar (QCoreApplication::translate ("shortcuts", "Show Statusbar"), sc_edit_view + ":show_statusbar", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_show_hscrollbar (QCoreApplication::translate ("shortcuts", "Show Horizontal Scrollbar"), sc_edit_view + ":show_hscrollbar", QKeySequence::UnknownKey);
+sc_pref sc_edit_view_sort_tabs (QCoreApplication::translate ("shortcuts", "Sort Tabs Alphabetically"), sc_edit_view + ":sort_tabs", QKeySequence::UnknownKey);
+
+// debug
+sc_pref sc_edit_debug_toggle_breakpoint (QCoreApplication::translate ("shortcuts", "Toggle Breakpoint"), sc_edit_debug + ":toggle_breakpoint", QKeySequence::UnknownKey);
+sc_pref sc_edit_debug_next_breakpoint (QCoreApplication::translate ("shortcuts", "Next Breakpoint"), sc_edit_debug + ":next_breakpoint", QKeySequence::UnknownKey);
+sc_pref sc_edit_debug_previous_breakpoint (QCoreApplication::translate ("shortcuts", "Previous Breakpoint"), sc_edit_debug + ":previous_breakpoint", QKeySequence::UnknownKey);
+sc_pref sc_edit_debug_remove_breakpoints (QCoreApplication::translate ("shortcuts", "Remove All Breakpoints"), sc_edit_debug + ":remove_breakpoints", QKeySequence::UnknownKey);
+
+// run
+sc_pref sc_edit_run_run_file (QCoreApplication::translate ("shortcuts", "Run File"), sc_edit_run + ":run_file", PRE | Qt::Key_F5);
+sc_pref sc_edit_run_run_selection (QCoreApplication::translate ("shortcuts", "Run Selection"), sc_edit_run + ":run_selection", PRE | Qt::Key_F9);
+
+// help
+sc_pref sc_edit_help_help_keyword (QCoreApplication::translate ("shortcuts", "Help on Keyword"), sc_edit_help + ":help_keyword", QKeySequence::HelpContents);
+sc_pref sc_edit_help_doc_keyword (QCoreApplication::translate ("shortcuts", "Document on Keyword"), sc_edit_help + ":doc_keyword", Qt::SHIFT | Qt::Key_F1);
+
+
+// Documentation browser
+sc_pref sc_doc_go_home (QCoreApplication::translate ("shortcuts", "Go to Homepage"), sc_doc + ":go_home", Qt::AltModifier | Qt::Key_Home);
+sc_pref sc_doc_go_back (QCoreApplication::translate ("shortcuts", "Go Back one Page"), sc_doc + ":go_back", QKeySequence::Back);
+sc_pref sc_doc_go_next (QCoreApplication::translate ("shortcuts", "Go Forward one Page"), sc_doc + ":go_next", QKeySequence::Forward);
+sc_pref sc_doc_bookmark (QCoreApplication::translate ("shortcuts", "Bookmark this Page"), sc_doc + ":bookmark", CTRL | Qt::Key_D);
+
+QString get_shortcut_section (const QString& key)
+{
+  QString section;
+
+  if (key.contains (':'))
+    section = key.section (':', 0, 0, QString::SectionSkipEmpty);
+
+  return section;
+}
--- a/libgui/src/gui-preferences-sc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-sc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,207 +55,209 @@
 const Qt::KeyboardModifiers CTRL_SHIFT = CTRL | Qt::ShiftModifier;
 const Qt::KeyboardModifiers CTRL_ALT = CTRL | Qt::AltModifier;
 
+const QString sc_group ("shortcuts");
+
 // Shortcuts not related to specific Menus
 
 // Dock widgets
 const QString sc_dock_widget ("dock_widget");
-const sc_pref sc_dock_widget_dock (sc_dock_widget + ":dock", CTRL_ALT + Qt::Key_D);
-const sc_pref sc_dock_widget_close (sc_dock_widget + ":close", CTRL_ALT + Qt::Key_C);
+extern sc_pref sc_dock_widget_dock;
+extern sc_pref sc_dock_widget_close;
 
 // Main window menu
 
 // file
 const QString sc_main_file ("main_file");
-const sc_pref sc_main_file_new_file (sc_main_file + ":new_file", QKeySequence::New);
-const sc_pref sc_main_file_new_function (sc_main_file + ":new_function", CTRL_SHIFT + Qt::Key_N);
-const sc_pref sc_main_file_new_figure (sc_main_file + ":new_figure", QKeySequence::UnknownKey);
-const sc_pref sc_main_file_open_file (sc_main_file + ":open_file", QKeySequence::Open);
-const sc_pref sc_main_file_load_workspace (sc_main_file + ":load_workspace", QKeySequence::UnknownKey);
-const sc_pref sc_main_file_save_workspace (sc_main_file + ":save_workspace", QKeySequence::UnknownKey);
-const sc_pref sc_main_file_exit (sc_main_file + ":exit", QKeySequence::Quit);
+extern sc_pref sc_main_file_new_file;
+extern sc_pref sc_main_file_new_function;
+extern sc_pref sc_main_file_new_figure;
+extern sc_pref sc_main_file_open_file;
+extern sc_pref sc_main_file_load_workspace;
+extern sc_pref sc_main_file_save_workspace;
+extern sc_pref sc_main_file_exit;
 
 // edit
 const QString sc_main_edit ("main_edit");
-const sc_pref sc_main_edit_copy (sc_main_edit + ":copy", QKeySequence::Copy);
-const sc_pref sc_main_edit_paste (sc_main_edit + ":paste", QKeySequence::Paste);
-const sc_pref sc_main_edit_undo (sc_main_edit + ":undo", QKeySequence::Undo);
-const sc_pref sc_main_edit_select_all (sc_main_edit + ":select_all", QKeySequence::SelectAll);
-const sc_pref sc_main_edit_clear_clipboard (sc_main_edit + ":clear_clipboard", QKeySequence::UnknownKey);
-const sc_pref sc_main_edit_find_in_files (sc_main_edit + ":find_in_files", CTRL_SHIFT + Qt::Key_F);
-const sc_pref sc_main_edit_clear_command_window (sc_main_edit + ":clear_command_window", QKeySequence::UnknownKey);
-const sc_pref sc_main_edit_clear_history (sc_main_edit + ":clear_history", QKeySequence::UnknownKey);
-const sc_pref sc_main_edit_clear_workspace (sc_main_edit + ":clear_workspace", QKeySequence::UnknownKey);
-const sc_pref sc_main_edit_set_path (sc_main_edit + ":set_path", QKeySequence::UnknownKey);
-const sc_pref sc_main_edit_preferences (sc_main_edit + ":preferences", QKeySequence::UnknownKey);
+extern sc_pref sc_main_edit_copy;
+extern sc_pref sc_main_edit_paste;
+extern sc_pref sc_main_edit_undo;
+extern sc_pref sc_main_edit_select_all;
+extern sc_pref sc_main_edit_clear_clipboard;
+extern sc_pref sc_main_edit_find_in_files;
+extern sc_pref sc_main_edit_clear_command_window;
+extern sc_pref sc_main_edit_clear_history;
+extern sc_pref sc_main_edit_clear_workspace;
+extern sc_pref sc_main_edit_set_path;
+extern sc_pref sc_main_edit_preferences;
 
 // debug
 const QString sc_main_debug ("main_debug");
-const sc_pref sc_main_debug_step_over (sc_main_debug + ":step_over", PRE + Qt::Key_F10);
-const sc_pref sc_main_debug_step_into (sc_main_debug + ":step_into", PRE + Qt::Key_F11);
-const sc_pref sc_main_debug_step_out (sc_main_debug + ":step_out", PRE + Qt::ShiftModifier + Qt::Key_F11);
-const sc_pref sc_main_debug_continue (sc_main_debug + ":continue", PRE + Qt::Key_F5);
-const sc_pref sc_main_debug_quit (sc_main_debug + ":quit", PRE + Qt::ShiftModifier + Qt::Key_F5);
+extern sc_pref sc_main_debug_step_over;
+extern sc_pref sc_main_debug_step_into;
+extern sc_pref sc_main_debug_step_out;
+extern sc_pref sc_main_debug_continue;
+extern sc_pref sc_main_debug_quit;
 
 // tools
 const QString sc_main_tools ("main_tools");
-const sc_pref sc_main_tools_start_profiler (sc_main_tools + ":start_profiler", CTRL_SHIFT + Qt::Key_P);
-const sc_pref sc_main_tools_resume_profiler (sc_main_tools + ":resume_profiler", QKeySequence::UnknownKey);
-const sc_pref sc_main_tools_show_profiler (sc_main_tools + ":show_profiler", Qt::AltModifier + Qt::ShiftModifier + Qt::Key_P);
+extern sc_pref sc_main_tools_start_profiler;
+extern sc_pref sc_main_tools_resume_profiler;
+extern sc_pref sc_main_tools_show_profiler;
 
 
 // window
 const QString sc_main_window ("main_window");
-const sc_pref sc_main_window_show_command (sc_main_window + ":show_command", PRE + CTRL_SHIFT + Qt::Key_0);
-const sc_pref sc_main_window_show_history (sc_main_window + ":show_history", PRE + CTRL_SHIFT + Qt::Key_1);
-const sc_pref sc_main_window_show_file_browser (sc_main_window + ":show_file_browser", PRE + CTRL_SHIFT + Qt::Key_2);
-const sc_pref sc_main_window_show_workspace (sc_main_window + ":show_workspace", PRE + CTRL_SHIFT + Qt::Key_3);
-const sc_pref sc_main_window_show_editor (sc_main_window + ":show_editor", PRE + CTRL_SHIFT + Qt::Key_4);
-const sc_pref sc_main_window_show_doc (sc_main_window + ":show_doc", PRE + CTRL_SHIFT + Qt::Key_5);
-const sc_pref sc_main_window_show_variable_editor (sc_main_window + ":show_variable_editor", PRE + CTRL_SHIFT + Qt::Key_6);
-const sc_pref sc_main_window_command (sc_main_window + ":command", PRE + CTRL + Qt::Key_0);
-const sc_pref sc_main_window_history (sc_main_window + ":history", PRE + CTRL + Qt::Key_1);
-const sc_pref sc_main_window_file_browser (sc_main_window + ":file_browser", PRE + CTRL + Qt::Key_2);
-const sc_pref sc_main_window_workspace (sc_main_window + ":workspace", PRE + CTRL + Qt::Key_3);
-const sc_pref sc_main_window_editor (sc_main_window + ":editor", PRE + CTRL + Qt::Key_4);
-const sc_pref sc_main_window_doc (sc_main_window + ":doc", PRE + CTRL + Qt::Key_5);
-const sc_pref sc_main_window_variable_editor (sc_main_window + ":variable_editor", PRE + CTRL + Qt::Key_6);
-const sc_pref sc_main_window_previous_dock (sc_main_window + ":previous_widget", PRE + CTRL_ALT + Qt::Key_P);
-const sc_pref sc_main_window_reset (sc_main_window + ":reset", QKeySequence::UnknownKey);
+extern sc_pref sc_main_window_show_command;
+extern sc_pref sc_main_window_show_history;
+extern sc_pref sc_main_window_show_file_browser;
+extern sc_pref sc_main_window_show_workspace;
+extern sc_pref sc_main_window_show_editor;
+extern sc_pref sc_main_window_show_doc;
+extern sc_pref sc_main_window_show_variable_editor;
+extern sc_pref sc_main_window_command;
+extern sc_pref sc_main_window_history;
+extern sc_pref sc_main_window_file_browser;
+extern sc_pref sc_main_window_workspace;
+extern sc_pref sc_main_window_editor;
+extern sc_pref sc_main_window_doc;
+extern sc_pref sc_main_window_variable_editor;
+extern sc_pref sc_main_window_previous_dock;
+extern sc_pref sc_main_window_reset;
 
 // help
 const QString sc_main_help ("main_help");
-const sc_pref sc_main_help_ondisk_doc (sc_main_help + ":ondisk_doc", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_online_doc (sc_main_help + ":online_doc", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_report_bug (sc_main_help + ":report_bug", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_packages (sc_main_help + ":packages", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_contribute (sc_main_help + ":contribute", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_developer (sc_main_help + ":developer", QKeySequence::UnknownKey);
-const sc_pref sc_main_help_about (sc_main_help + ":about", QKeySequence::UnknownKey);
+extern sc_pref sc_main_help_ondisk_doc;
+extern sc_pref sc_main_help_online_doc;
+extern sc_pref sc_main_help_report_bug;
+extern sc_pref sc_main_help_packages;
+extern sc_pref sc_main_help_contribute;
+extern sc_pref sc_main_help_developer;
+extern sc_pref sc_main_help_about;
 
 // news
 const QString sc_main_news ("main_news");
-const sc_pref sc_main_news_release_notes (sc_main_news + ":release_notes", QKeySequence::UnknownKey);
-const sc_pref sc_main_news_community_news (sc_main_news + ":community_news", QKeySequence::UnknownKey);
+extern sc_pref sc_main_news_release_notes;
+extern sc_pref sc_main_news_community_news;
 
 // Tab handling
 // The following shortcuts are moved into a separate tab.  The key names
 // are not change for preserving compatibility with older versions
 const QString sc_edit_file ("editor_file");
 const QString sc_edit_file_cl (sc_edit_file + ":close");
-const sc_pref sc_edit_file_close (sc_edit_file_cl, QKeySequence::Close);
-const sc_pref sc_edit_file_close_all (sc_edit_file_cl + "_all", QKeySequence::UnknownKey);
-const sc_pref sc_edit_file_close_other (sc_edit_file_cl + "_other", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_file_close;
+extern sc_pref sc_edit_file_close_all;
+extern sc_pref sc_edit_file_close_other;
 const QString sc_edit_tabs ("editor_tabs");
-const sc_pref sc_edit_tabs_switch_left_tab (sc_edit_tabs + ":switch_left_tab", CTRL + Qt::Key_PageUp);
-const sc_pref sc_edit_tabs_switch_right_tab (sc_edit_tabs + ":switch_right_tab", CTRL + Qt::Key_PageDown);
-const sc_pref sc_edit_tabs_move_tab_left (sc_edit_tabs + ":move_tab_left", Qt::AltModifier + Qt::Key_PageUp);
-const sc_pref sc_edit_tabs_move_tab_right (sc_edit_tabs + ":move_tab_right", Qt::AltModifier + Qt::Key_PageDown);
+extern sc_pref sc_edit_tabs_switch_left_tab;
+extern sc_pref sc_edit_tabs_switch_right_tab;
+extern sc_pref sc_edit_tabs_move_tab_left;
+extern sc_pref sc_edit_tabs_move_tab_right;
 
 // Zooming
 const QString sc_edit_zoom ("editor_zoom"); // only a group name in the pref dialog
 const QString sc_edit_view ("editor_view");
 const QString sc_edit_view_zoom (sc_edit_view + ":zoom");
-const sc_pref sc_edit_view_zoom_in (sc_edit_view_zoom + "_in", QKeySequence::ZoomIn);
-const sc_pref sc_edit_view_zoom_out (sc_edit_view_zoom + "_out", QKeySequence::ZoomOut);
+extern sc_pref sc_edit_view_zoom_in;
+extern sc_pref sc_edit_view_zoom_out;
 #if defined (Q_OS_MAC)
-const sc_pref sc_edit_view_zoom_normal (sc_edit_view_zoom + "_normal", CTRL + Qt::Key_Underscore);
+extern sc_pref sc_edit_view_zoom_normal;
 #else
-const sc_pref sc_edit_view_zoom_normal (sc_edit_view_zoom + "_normal", CTRL + Qt::Key_Period);
+extern sc_pref sc_edit_view_zoom_normal;
 #endif
 
 // Actions of the editor
 
 // file
-const sc_pref sc_edit_file_edit_function (sc_edit_file + ":edit_function", CTRL + Qt::Key_E);
-const sc_pref sc_edit_file_save (sc_edit_file + ":save", QKeySequence::Save);
-const sc_pref sc_edit_file_save_as (sc_edit_file + ":save_as", QKeySequence::SaveAs);
-const sc_pref sc_edit_file_print (sc_edit_file + ":print", QKeySequence::Print);
+extern sc_pref sc_edit_file_edit_function;
+extern sc_pref sc_edit_file_save;
+extern sc_pref sc_edit_file_save_as;
+extern sc_pref sc_edit_file_print;
 
 // edit
 const QString sc_edit_find ("editor_find"); // only a group name in the pref dialog
 const QString sc_edit_edit ("editor_edit");
 const QString sc_edit_edit_find (sc_edit_edit + ":find");
-const sc_pref sc_edit_edit_redo (sc_edit_edit + ":redo", QKeySequence::Redo);
-const sc_pref sc_edit_edit_cut (sc_edit_edit + ":cut", QKeySequence::Cut);
-const sc_pref sc_edit_edit_find_replace (sc_edit_edit_find + "_replace", QKeySequence::Find);
-const sc_pref sc_edit_edit_find_next (sc_edit_edit_find + "_next", QKeySequence::FindNext);
-const sc_pref sc_edit_edit_find_previous (sc_edit_edit_find + "_previous", QKeySequence::FindPrevious);
-const sc_pref sc_edit_edit_delete_start_word (sc_edit_edit + ":delete_start_word", QKeySequence::DeleteStartOfWord);
-const sc_pref sc_edit_edit_delete_end_word (sc_edit_edit + ":delete_end_word", QKeySequence::DeleteEndOfWord);
-const sc_pref sc_edit_edit_delete_start_line (sc_edit_edit + ":delete_start_line", CTRL_SHIFT + Qt::Key_Backspace);
-const sc_pref sc_edit_edit_delete_end_line (sc_edit_edit + ":delete_end_line", CTRL_SHIFT + Qt::Key_Delete);
-const sc_pref sc_edit_edit_delete_line (sc_edit_edit + ":delete_line", CTRL_SHIFT + Qt::Key_L);
-const sc_pref sc_edit_edit_copy_line (sc_edit_edit + ":copy_line", CTRL_SHIFT + Qt::Key_C);
-const sc_pref sc_edit_edit_cut_line (sc_edit_edit + ":cut_line", CTRL_SHIFT + Qt::Key_X);
-const sc_pref sc_edit_edit_duplicate_selection (sc_edit_edit + ":duplicate_selection", CTRL + Qt::Key_D);
-const sc_pref sc_edit_edit_transpose_line (sc_edit_edit + ":transpose_line", CTRL + Qt::Key_T);
-const sc_pref sc_edit_edit_completion_list (sc_edit_edit + ":completion_list", CTRL + Qt::Key_Space);
+extern sc_pref sc_edit_edit_redo;
+extern sc_pref sc_edit_edit_cut;
+extern sc_pref sc_edit_edit_find_replace;
+extern sc_pref sc_edit_edit_find_next;
+extern sc_pref sc_edit_edit_find_previous;
+extern sc_pref sc_edit_edit_delete_start_word;
+extern sc_pref sc_edit_edit_delete_end_word;
+extern sc_pref sc_edit_edit_delete_start_line;
+extern sc_pref sc_edit_edit_delete_end_line;
+extern sc_pref sc_edit_edit_delete_line;
+extern sc_pref sc_edit_edit_copy_line;
+extern sc_pref sc_edit_edit_cut_line;
+extern sc_pref sc_edit_edit_duplicate_selection;
+extern sc_pref sc_edit_edit_transpose_line;
+extern sc_pref sc_edit_edit_completion_list;
 
-const sc_pref sc_edit_edit_comment_selection (sc_edit_edit + ":comment_selection", CTRL + Qt::Key_R);
-const sc_pref sc_edit_edit_uncomment_selection (sc_edit_edit + ":uncomment_selection", CTRL_SHIFT + Qt::Key_R);
-const sc_pref sc_edit_edit_comment_var_selection (sc_edit_edit + ":comment_var_selection", CTRL_ALT + Qt::Key_R);
-const sc_pref sc_edit_edit_upper_case (sc_edit_edit + ":upper_case", CTRL + Qt::Key_U);
-const sc_pref sc_edit_edit_lower_case (sc_edit_edit + ":lower_case", CTRL_ALT + Qt::Key_U);
+extern sc_pref sc_edit_edit_comment_selection;
+extern sc_pref sc_edit_edit_uncomment_selection;
+extern sc_pref sc_edit_edit_comment_var_selection;
+extern sc_pref sc_edit_edit_upper_case;
+extern sc_pref sc_edit_edit_lower_case;
 
 #if defined (Q_OS_MAC)
-const sc_pref sc_edit_edit_indent_selection (sc_edit_edit + ":indent_selection", PRE + Qt::Key_Tab);
-const sc_pref sc_edit_edit_unindent_selection (sc_edit_edit + ":unindent_selection", PRE + Qt::ShiftModifier + Qt::Key_Tab);
+extern sc_pref sc_edit_edit_indent_selection;
+extern sc_pref sc_edit_edit_unindent_selection;
 #else
-const sc_pref sc_edit_edit_indent_selection (sc_edit_edit + ":indent_selection", CTRL + Qt::Key_Tab);
-const sc_pref sc_edit_edit_unindent_selection (sc_edit_edit + ":unindent_selection", CTRL_SHIFT + Qt::Key_Tab);
+extern sc_pref sc_edit_edit_indent_selection;
+extern sc_pref sc_edit_edit_unindent_selection;
 #endif
-const sc_pref sc_edit_edit_smart_indent_line_or_selection (sc_edit_edit + ":smart_indent_line_or_selection", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_edit_smart_indent_line_or_selection;
 
-const sc_pref sc_edit_edit_conv_eol_winows (sc_edit_edit + ":conv_eol_winows", QKeySequence::UnknownKey);
-const sc_pref sc_edit_edit_conv_eol_unix (sc_edit_edit + ":conv_eol_unix", QKeySequence::UnknownKey);
-const sc_pref sc_edit_edit_conv_eol_mac (sc_edit_edit + ":conv_eol_mac", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_edit_conv_eol_winows;
+extern sc_pref sc_edit_edit_conv_eol_unix;
+extern sc_pref sc_edit_edit_conv_eol_mac;
 
-const sc_pref sc_edit_edit_goto_line (sc_edit_edit + ":goto_line", CTRL + Qt::Key_L);
-const sc_pref sc_edit_edit_move_to_brace (sc_edit_edit + ":move_to_brace", CTRL + Qt::Key_M);
-const sc_pref sc_edit_edit_select_to_brace (sc_edit_edit + ":select_to_brace", CTRL_SHIFT + Qt::Key_M);
-const sc_pref sc_edit_edit_toggle_bookmark (sc_edit_edit + ":toggle_bookmark", PRE + Qt::Key_F7);
-const sc_pref sc_edit_edit_next_bookmark (sc_edit_edit + ":next_bookmark", PRE + Qt::Key_F2);
-const sc_pref sc_edit_edit_previous_bookmark (sc_edit_edit + ":previous_bookmark", PRE + Qt::SHIFT + Qt::Key_F2);
-const sc_pref sc_edit_edit_remove_bookmark (sc_edit_edit + ":remove_bookmark", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_edit_goto_line;
+extern sc_pref sc_edit_edit_move_to_brace;
+extern sc_pref sc_edit_edit_select_to_brace;
+extern sc_pref sc_edit_edit_toggle_bookmark;
+extern sc_pref sc_edit_edit_next_bookmark;
+extern sc_pref sc_edit_edit_previous_bookmark;
+extern sc_pref sc_edit_edit_remove_bookmark;
 
-const sc_pref sc_edit_edit_preferences (sc_edit_edit + ":preferences", QKeySequence::UnknownKey);
-const sc_pref sc_edit_edit_styles_preferences (sc_edit_edit + ":styles_preferences", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_edit_preferences;
+extern sc_pref sc_edit_edit_styles_preferences;
 
 // view
-const sc_pref sc_edit_view_show_line_numbers (sc_edit_view + ":show_line_numbers", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_white_spaces (sc_edit_view + ":show_white_spaces", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_eol_chars (sc_edit_view + ":show_eol_chars", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_ind_guides (sc_edit_view + ":show_ind_guides", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_long_line (sc_edit_view + ":show_long_line", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_toolbar (sc_edit_view + ":show_toolbar", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_statusbar (sc_edit_view + ":show_statusbar", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_show_hscrollbar (sc_edit_view + ":show_hscrollbar", QKeySequence::UnknownKey);
-const sc_pref sc_edit_view_sort_tabs (sc_edit_view + ":sort_tabs", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_view_show_line_numbers;
+extern sc_pref sc_edit_view_show_white_spaces;
+extern sc_pref sc_edit_view_show_eol_chars;
+extern sc_pref sc_edit_view_show_ind_guides;
+extern sc_pref sc_edit_view_show_long_line;
+extern sc_pref sc_edit_view_show_toolbar;
+extern sc_pref sc_edit_view_show_statusbar;
+extern sc_pref sc_edit_view_show_hscrollbar;
+extern sc_pref sc_edit_view_sort_tabs;
 
 // debug
 const QString sc_edit_debug ("editor_debug");
-const sc_pref sc_edit_debug_toggle_breakpoint (sc_edit_debug + ":toggle_breakpoint", QKeySequence::UnknownKey);
-const sc_pref sc_edit_debug_next_breakpoint (sc_edit_debug + ":next_breakpoint", QKeySequence::UnknownKey);
-const sc_pref sc_edit_debug_previous_breakpoint (sc_edit_debug + ":previous_breakpoint", QKeySequence::UnknownKey);
-const sc_pref sc_edit_debug_remove_breakpoints (sc_edit_debug + ":remove_breakpoints", QKeySequence::UnknownKey);
+extern sc_pref sc_edit_debug_toggle_breakpoint;
+extern sc_pref sc_edit_debug_next_breakpoint;
+extern sc_pref sc_edit_debug_previous_breakpoint;
+extern sc_pref sc_edit_debug_remove_breakpoints;
 
 // run
 const QString sc_edit_run ("editor_run");
-const sc_pref sc_edit_run_run_file (sc_edit_run + ":run_file", PRE + Qt::Key_F5);
-const sc_pref sc_edit_run_run_selection (sc_edit_run + ":run_selection", PRE + Qt::Key_F9);
+extern sc_pref sc_edit_run_run_file;
+extern sc_pref sc_edit_run_run_selection;
 
 // help
 const QString sc_edit_help ("editor_help");
-const sc_pref sc_edit_help_help_keyword (sc_edit_help + ":help_keyword", QKeySequence::HelpContents);
-const sc_pref sc_edit_help_doc_keyword (sc_edit_help + ":doc_keyword", Qt::SHIFT + Qt::Key_F1);
+extern sc_pref sc_edit_help_help_keyword;
+extern sc_pref sc_edit_help_doc_keyword;
 
 
 // Documentation browser
 const QString sc_doc ("doc_browser");
-const sc_pref sc_doc_go_home (sc_doc + ":go_home", Qt::AltModifier + Qt::Key_Home);
-const sc_pref sc_doc_go_back (sc_doc + ":go_back", QKeySequence::Back);
-const sc_pref sc_doc_go_next (sc_doc + ":go_next", QKeySequence::Forward);
-const sc_pref sc_doc_bookmark (sc_doc + ":bookmark", CTRL + Qt::Key_D);
+extern sc_pref sc_doc_go_home;
+extern sc_pref sc_doc_go_back;
+extern sc_pref sc_doc_go_next;
+extern sc_pref sc_doc_bookmark;
 
 
 // Other normal, shortcut related options
@@ -268,4 +270,6 @@
 const gui_pref
 sc_prevent_rl_conflicts_menu ("shortcuts/prevent_readline_conflicts_menu", QVariant (false));
 
+extern QString get_shortcut_section (const QString& key);
+
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-sd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-sd.h"
+
+// Settings dialog
+
+gui_pref
+sd_geometry ("settings/geometry", QVariant ());
+
+gui_pref
+sd_last_tab ("settings/last_tab", QVariant (0));
+
+gui_pref
+sd_last_editor_styles_tab ("settings/last_editor_styles_tab", QVariant (0));
--- a/libgui/src/gui-preferences-sd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-sd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,37 +30,39 @@
 
 // Settings dialog
 
-const gui_pref
-sd_geometry ("settings/geometry", QVariant ());
+extern gui_pref sd_geometry;
 
-const gui_pref
-sd_last_tab ("settings/last_tab", QVariant (0));
+extern gui_pref sd_last_tab;
 
-const gui_pref
-sd_last_editor_styles_tab ("settings/last_editor_styles_tab", QVariant (0));
+extern gui_pref sd_last_editor_styles_tab;
 
 // Textstrings for second color schemes
-const QString settings_color_modes = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "Second color mode (light/dark)");
-const QString settings_color_modes_tooltip = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "Switches to another set of colors.\n"
-    "Useful for defining a dark/light mode.\n"
-    "Discards non-applied current changes!");
-const QString settings_reload_colors = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "&Reload default colors");
-const QString settings_reload_colors_tooltip = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "Reloads the default colors,\n"
-    "depending on currently selected mode.");
-const QString settings_reload_styles = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "&Reload default styles");
-const QString settings_reload_styles_tooltip = QT_TRANSLATE_NOOP (
-    "octave::settings_dialog",
-    "Reloads the default values of the styles,\n"
-    "depending on currently selected mode.");
+const QString settings_color_modes
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "Second color mode (light/dark)");
+
+const QString settings_color_modes_tooltip
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "Switches to another set of colors.\n"
+                       "Useful for defining a dark/light mode.\n"
+                       "Discards non-applied current changes!");
+
+const QString settings_reload_colors
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "&Reload default colors");
+
+const QString settings_reload_colors_tooltip
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "Reloads the default colors,\n"
+                       "depending on currently selected mode.");
+
+const QString settings_reload_styles
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "&Reload default styles");
+
+const QString settings_reload_styles_tooltip
+  = QT_TRANSLATE_NOOP ("octave::settings_dialog",
+                       "Reloads the default values of the styles,\n"
+                       "depending on currently selected mode.");
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-ve.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-ve.h"
+
+#include <QApplication>
+
+// Variable Editor preferences
+
+gui_pref
+ve_use_terminal_font ("variable_editor/use_terminal_font", QVariant (true));
+
+gui_pref
+ve_font_name ("variable_editor/font_name", QVariant ());
+
+gui_pref
+ve_font_size ("variable_editor/font_size", QVariant (10));
+
+gui_pref
+ve_column_width ("variable_editor/column_width", QVariant (100));
+
+gui_pref
+ve_row_height ("variable_editor/row_height", QVariant (10));
+
+gui_pref
+ve_alternate_rows ("variable_editor/alternate_rows", QVariant (false));
+
+gui_pref
+ve_color_mode ("variable_editor/color_mode", QVariant (0));
+
+gui_pref ve_colors[2*ve_colors_count] =
+{
+  {"variable_editor/color_f" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},
+  {"variable_editor/color_b" + settings_color_modes_ext[0], QVariant (QPalette::Base)},
+  {"variable_editor/color_s" + settings_color_modes_ext[0], QVariant (QPalette::HighlightedText)},
+  {"variable_editor/color_h" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
+  {"variable_editor/color_a" + settings_color_modes_ext[0], QVariant (QPalette::AlternateBase)},
+  {"variable_editor/color_f" + settings_color_modes_ext[1], QVariant ()},
+  {"variable_editor/color_b" + settings_color_modes_ext[1], QVariant ()},
+  {"variable_editor/color_s" + settings_color_modes_ext[1], QVariant ()},
+  {"variable_editor/color_h" + settings_color_modes_ext[1], QVariant ()},
+  {"variable_editor/color_a" + settings_color_modes_ext[1], QVariant ()}
+};
--- a/libgui/src/gui-preferences-ve.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-ve.h	Fri Jun 23 20:51:51 2023 +0200
@@ -27,48 +27,29 @@
 #define octave_gui_preferences_ve_h 1
 
 #include "gui-preferences.h"
-
-#include <QApplication>
+#include "gui-settings.h"
 
 // Variable Editor preferences
 
-const gui_pref
-ve_use_terminal_font ("variable_editor/use_terminal_font", QVariant (true));
+extern gui_pref ve_use_terminal_font;
 
-const gui_pref
-ve_font_name ("variable_editor/font_name", QVariant ());
+extern gui_pref ve_font_name;
 
-const gui_pref
-ve_font_size ("variable_editor/font_size", QVariant (10));
+extern gui_pref ve_font_size;
 
-const gui_pref
-ve_column_width ("variable_editor/column_width", QVariant (100));
+extern gui_pref ve_column_width;
 
-const gui_pref
-ve_row_height ("variable_editor/row_height", QVariant (10));
+extern gui_pref ve_row_height;
 
-const gui_pref
-ve_alternate_rows ("variable_editor/alternate_rows", QVariant (false));
+extern gui_pref ve_alternate_rows;
 
-const gui_pref
-ve_color_mode ("variable_editor/color_mode", QVariant (0));
+extern gui_pref ve_color_mode;
 
 const QString ve_color_chars ("fbsha");
 
 const int ve_colors_count = 5;
-const gui_pref ve_colors[2*ve_colors_count] =
-{
-  {"variable_editor/color_f" + settings_color_modes_ext[0], QVariant (QPalette::WindowText)},
-  {"variable_editor/color_b" + settings_color_modes_ext[0], QVariant (QPalette::Base)},
-  {"variable_editor/color_s" + settings_color_modes_ext[0], QVariant (QPalette::HighlightedText)},
-  {"variable_editor/color_h" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
-  {"variable_editor/color_a" + settings_color_modes_ext[0], QVariant (QPalette::AlternateBase)},
-  {"variable_editor/color_f" + settings_color_modes_ext[1], QVariant ()},
-  {"variable_editor/color_b" + settings_color_modes_ext[1], QVariant ()},
-  {"variable_editor/color_s" + settings_color_modes_ext[1], QVariant ()},
-  {"variable_editor/color_h" + settings_color_modes_ext[1], QVariant ()},
-  {"variable_editor/color_a" + settings_color_modes_ext[1], QVariant ()}
-};
+
+extern gui_pref ve_colors[];
 
 const QStringList ve_color_names = {
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Foreground"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences-ws.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-ws.h"
+#include "gui-settings.h"
+
+// Workspace view
+
+gui_pref
+ws_enable_colors ("workspaceview/enable_colors", QVariant (false));
+
+gui_pref
+ws_hide_tool_tips ("workspaceview/hide_tools_tips", QVariant (false));
+
+gui_pref
+ws_filter_active ("workspaceview/filter_active", QVariant (false));
+
+gui_pref
+ws_filter_shown ("workspaceview/filter_shown", QVariant (true));
+
+gui_pref
+ws_column_state ("workspaceview/column_state", QVariant ());
+
+gui_pref
+ws_sort_column ("workspaceview/sort_by_column", QVariant (0));
+
+gui_pref
+ws_sort_order ("workspaceview/sort_order", QVariant (Qt::AscendingOrder));
+
+gui_pref
+ws_mru_list ("workspaceview/mru_list", QVariant ());
+
+gui_pref
+ws_max_filter_history ("workspaceview/max_filter_history", QVariant (10));
+
+gui_pref
+ws_color_mode ("workspaceview/color_mode", QVariant (0));
+
+gui_pref ws_colors[2*ws_colors_count] =
+{
+  {"workspaceview/color_a" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
+  {"workspaceview/color_g" + settings_color_modes_ext[0], QVariant (QPalette::Midlight)},
+  {"workspaceview/color_p" + settings_color_modes_ext[0], QVariant (QPalette::Dark)},
+  {"workspaceview/color_a" + settings_color_modes_ext[1], QVariant ()},
+  {"workspaceview/color_g" + settings_color_modes_ext[1], QVariant ()},
+  {"workspaceview/color_p" + settings_color_modes_ext[1], QVariant ()}
+};
--- a/libgui/src/gui-preferences-ws.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences-ws.h	Fri Jun 23 20:51:51 2023 +0200
@@ -27,33 +27,24 @@
 #define octave_gui_preferences_ws_h 1
 
 #include "gui-preferences.h"
-#include "gui-settings.h"
 
 // Workspace view
 
-const gui_pref
-ws_enable_colors ("workspaceview/enable_colors", QVariant (false));
+extern gui_pref ws_enable_colors;
 
-const gui_pref
-ws_hide_tool_tips ("workspaceview/hide_tools_tips", QVariant (false));
+extern gui_pref ws_hide_tool_tips;
 
-const gui_pref
-ws_filter_active ("workspaceview/filter_active", QVariant (false));
+extern gui_pref ws_filter_active;
 
-const gui_pref
-ws_filter_shown ("workspaceview/filter_shown", QVariant (true));
+extern gui_pref ws_filter_shown;
 
-const gui_pref
-ws_column_state ("workspaceview/column_state", QVariant ());
+extern gui_pref ws_column_state;
 
-const gui_pref
-ws_sort_column ("workspaceview/sort_by_column", QVariant (0));
+extern gui_pref ws_sort_column;
 
-const gui_pref
-ws_sort_order ("workspaceview/sort_order", QVariant (Qt::AscendingOrder));
+extern gui_pref ws_sort_order;
 
-const gui_pref
-ws_mru_list ("workspaceview/mru_list", QVariant ());
+extern gui_pref ws_mru_list;
 
 const QStringList ws_columns_shown = {
   QT_TRANSLATE_NOOP ("octave::workspace_view", "Class"),
@@ -69,22 +60,13 @@
   "workspaceview/show_attribute"
 };
 
-const gui_pref
-ws_max_filter_history ("workspaceview/max_filter_history", QVariant (10));
+extern gui_pref ws_max_filter_history;
 
-const gui_pref
-ws_color_mode ("workspaceview/color_mode", QVariant (0));
+extern gui_pref ws_color_mode;
 
 const int ws_colors_count = 3;
-const gui_pref ws_colors[2*ws_colors_count] =
-{
-  {"workspaceview/color_a" + settings_color_modes_ext[0], QVariant (QPalette::Highlight)},
-  {"workspaceview/color_g" + settings_color_modes_ext[0], QVariant (QPalette::Midlight)},
-  {"workspaceview/color_p" + settings_color_modes_ext[0], QVariant (QPalette::Dark)},
-  {"workspaceview/color_a" + settings_color_modes_ext[1], QVariant ()},
-  {"workspaceview/color_g" + settings_color_modes_ext[1], QVariant ()},
-  {"workspaceview/color_p" + settings_color_modes_ext[1], QVariant ()}
-};
+
+extern gui_pref ws_colors[];
 
 const QString ws_class_chars ("agp");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,173 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2017-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "gui-preferences-sc.h"
+#include "gui-preferences.h"
+
+gui_pref::gui_pref (const QString& settings_key, const QVariant& def,
+                    bool ignore)
+  : m_settings_key (settings_key), m_def (def), m_ignore (ignore)
+{
+  all_gui_preferences::insert (settings_key, *this);
+}
+
+all_gui_preferences *all_gui_preferences::s_instance = nullptr;
+
+void all_gui_preferences::insert (const QString& settings_key,
+                                  const gui_pref& pref)
+{
+  ensure_instance ();
+
+  s_instance->do_insert (settings_key, pref);
+}
+
+const gui_pref all_gui_preferences::value (const QString& settings_key)
+{
+  ensure_instance ();
+
+  return s_instance->do_value (settings_key);
+}
+
+QStringList all_gui_preferences::keys ()
+{
+  ensure_instance ();
+
+  return s_instance->do_keys ();
+}
+
+void all_gui_preferences::do_insert (const QString& settings_key,
+                                     const gui_pref& pref)
+{
+  m_hash.insert (settings_key, pref);
+}
+
+const gui_pref
+all_gui_preferences::do_value (const QString& settings_key) const
+{
+  return m_hash.value (settings_key);
+}
+
+QStringList all_gui_preferences::do_keys () const
+{
+  return m_hash.keys ();
+}
+
+void all_gui_preferences::ensure_instance ()
+{
+  if (! s_instance)
+    s_instance = new all_gui_preferences ();
+}
+
+sc_pref::sc_pref (const QString& description, const QString& settings_key,
+                  Qt::Key def)
+  : m_description (description), m_settings_key (settings_key), m_def (def),
+    m_def_std (QKeySequence::UnknownKey)
+{
+  all_shortcut_preferences::insert (settings_key, *this);
+}
+
+sc_pref::sc_pref (const QString& description, const QString& settings_key,
+                  unsigned int def)
+  : m_description (description), m_settings_key (settings_key), m_def (def),
+    m_def_std (QKeySequence::UnknownKey)
+{
+  all_shortcut_preferences::insert (settings_key, *this);
+}
+
+sc_pref::sc_pref (const QString& description, const QString& settings_key,
+                  QKeySequence::StandardKey def_std)
+  : m_description (description), m_settings_key (settings_key), m_def (0),
+    m_def_std (def_std)
+{
+  all_shortcut_preferences::insert (settings_key, *this);
+}
+
+QKeySequence sc_pref::def_value () const
+{
+  QKeySequence key_seq = QKeySequence ();
+
+  if (m_def)
+    key_seq = QKeySequence (m_def);
+  else if (m_def_std != QKeySequence::UnknownKey)
+    key_seq = QKeySequence (m_def_std);
+
+  return key_seq;
+}
+
+QString sc_pref::def_text () const
+{
+  return def_value ().toString ();
+}
+
+all_shortcut_preferences *all_shortcut_preferences::s_instance = nullptr;
+
+void all_shortcut_preferences::insert (const QString& settings_key,
+                                       const sc_pref& scpref)
+{
+  ensure_instance ();
+
+  s_instance->do_insert (settings_key, scpref);
+}
+
+const sc_pref all_shortcut_preferences::value (const QString& settings_key)
+{
+  ensure_instance ();
+
+  return s_instance->do_value (settings_key);
+}
+
+QStringList all_shortcut_preferences::keys ()
+{
+  ensure_instance ();
+
+  return s_instance->do_keys ();
+}
+
+void all_shortcut_preferences::do_insert (const QString& settings_key,
+                                          const sc_pref& scpref)
+{
+  m_hash.insert (settings_key, scpref);
+}
+
+const sc_pref
+all_shortcut_preferences::do_value (const QString& settings_key) const
+{
+  return m_hash.value (settings_key);
+}
+
+QStringList all_shortcut_preferences::do_keys () const
+{
+  return m_hash.keys ();
+}
+
+void all_shortcut_preferences::ensure_instance ()
+{
+  if (! s_instance)
+    s_instance = new all_shortcut_preferences ();
+}
--- a/libgui/src/gui-preferences.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-preferences.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,66 +26,187 @@
 #if ! defined (octave_gui_preferences_h)
 #define octave_gui_preferences_h 1
 
+#include "octave-config.h"
+
 #include <QStringList>
 #include <QStyle>
 #include <QTabWidget>
-#include <QTextCodec>
 #include <QVariant>
 
+// FIXME: Would it be possible/make sense to merge gui_pref and sc_pref
+// into a single class or to at least have them derived from a common
+// base class so we could have one global hash table that contains all
+// of them?
+
 // Structure for the definition of pairs: key and default value
 
-struct gui_pref
+class gui_pref
 {
-  gui_pref (const QString& key_arg, const QVariant& def_arg,
-            const bool ignore_arg = false)
-    : key (key_arg), def (def_arg), ignore (ignore_arg)
-  { }
+public:
+
+  // Default constructed gui_pref objects are invalid, but we need this
+  // to create QHash objects that contain gui_pref objects.  No invalid
+  // gui_pref objects should acutally be used.
+
+  gui_pref () = default;
+
+  gui_pref (const QString& settings_key, const QVariant& def,
+            bool ignore = false);
+
+  gui_pref (const gui_pref&) = default;
+
+  gui_pref& operator = (const gui_pref&) = default;
 
-  // No copying!
+  ~gui_pref () = default;
+
+  QString settings_key () const { return m_settings_key; }
+  QVariant def () const { return m_def; }
+  bool ignore () const { return m_ignore; }
+
+private:
+
+  // The settings key name.
+  QString m_settings_key;
+
+  // The default value.
+  QVariant m_def;
+
+  // TRUE means always take the default.
+  bool m_ignore;
+};
 
-  gui_pref (const gui_pref&) = delete;
+// FIXME: Is there a better/more modern way to manage this data than to
+// have this style of singleton class?
+
+// Allow lookup of gui_pref objects when we don't know the name at
+// compile time.
 
-  gui_pref& operator = (const gui_pref&) = delete;
+class all_gui_preferences
+{
+public:
+
+  all_gui_preferences () = default;
+
+  OCTAVE_DISABLE_COPY_MOVE (all_gui_preferences)
+
+  ~all_gui_preferences () = default;
+
+  static void insert (const QString& settings_key, const gui_pref& pref);
 
-  ~gui_pref (void) = default;
+  static const gui_pref value (const QString& settings_key);
+
+  static QStringList keys ();
+
+private:
+
+  // Map from shortcut identifier (settings key) to gui_pref object.
+  QHash <QString, gui_pref> m_hash;
 
-  const QString key;   // the key name
-  const QVariant def;  // the default value
-  const bool ignore;   // when true, ignore, i.e. always take default
+  void do_insert (const QString& settings_key, const gui_pref& pref);
+
+  const gui_pref do_value (const QString& settings_key) const;
+
+  QStringList do_keys () const;
+
+  static void ensure_instance ();
+
+  // Map from shortcut identifier (settings key) to sc_pref object.
+  static all_gui_preferences *s_instance;
 };
 
 // The version for shortcuts, where the default value is stored as a
 // combination of Qt:Keys (resutling in an unsigend int, when added)
 // or as one of the predefined standard key sequences.
 
-const QString sc_group ("shortcuts/");  // group name is handled separately
-
-struct sc_pref
+class sc_pref
 {
-  sc_pref (const QString& key_arg, Qt::Key def_arg)
-    : key (key_arg), def (static_cast<unsigned int> (def_arg)),
-      def_std (QKeySequence::UnknownKey)
-  { }
+public:
+
+  // Default constructed sc_pref objects are invalid, but we need this
+  // to create QHash objects that contain sc_pref objects.  No invalid
+  // sc_pref objects should acutally be used.
+
+  sc_pref () = default;
+
+  sc_pref (const QString& description, const QString& settings_key,
+           Qt::Key def);
+
+  sc_pref (const QString& description_arg, const QString& settings_key,
+           unsigned int def);
+
+  sc_pref (const QString& description_arg, const QString& settings_key,
+           QKeySequence::StandardKey def_std);
+
+  sc_pref (const sc_pref&) = default;
+
+  sc_pref& operator = (const sc_pref&) = default;
 
-  sc_pref (const QString& key_arg, unsigned int def_arg)
-    : key (key_arg), def (def_arg), def_std (QKeySequence::UnknownKey)
-  { }
+  ~sc_pref () = default;
+
+  QString description () const { return m_description; }
+
+  QString settings_key () const { return m_settings_key; }
+
+  unsigned int def () const { return m_def; }
+
+  QKeySequence::StandardKey def_std () const { return m_def_std; }
+
+  QKeySequence def_value () const;
+
+  QString def_text () const;
+
+private:
+
+  // Description of the shortcut.
+  QString m_description;
+
+  // The settings key name.
+  QString m_settings_key;
 
-  sc_pref (const QString& key_arg, QKeySequence::StandardKey def_std_arg)
-    : key (key_arg), def (0), def_std (def_std_arg)
-  { }
+  // The default as key.
+  unsigned int m_def;
+
+  // The default as standard key.
+  QKeySequence::StandardKey m_def_std;
+};
+
+// FIXME: Is there a better/more modern way to manage this data than to
+// have this style of singleton class?
 
-  // No copying!
+// Allow lookup of sc_pref objects when we don't know the name at
+// compile time.
 
-  sc_pref (const sc_pref&) = delete;
+class all_shortcut_preferences
+{
+public:
+
+  all_shortcut_preferences () = default;
+
+  OCTAVE_DISABLE_COPY_MOVE (all_shortcut_preferences)
 
-  sc_pref& operator = (const sc_pref&) = delete;
+  ~all_shortcut_preferences () = default;
+
+  static void insert (const QString& settings_key, const sc_pref& scpref);
 
-  ~sc_pref (void) = default;
+  static const sc_pref value (const QString& settings_key);
+
+  static QStringList keys ();
+
+private:
 
-  const QString key;                        // the key name
-  const unsigned int def;                   // the default as key
-  const QKeySequence::StandardKey def_std;  // the default as standard key
+  // Map from shortcut identifier (settings key) to sc_pref object.
+  QHash <QString, sc_pref> m_hash;
+
+  void do_insert (const QString& settings_key, const sc_pref& scpref);
+
+  const sc_pref do_value (const QString& settings_key) const;
+
+  QStringList do_keys () const;
+
+  static void ensure_instance ();
+
+  // Map from shortcut identifier (settings key) to sc_pref object.
+  static all_shortcut_preferences *s_instance;
 };
 
 #endif
--- a/libgui/src/gui-settings.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-settings.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,13 +27,97 @@
 #  include "config.h"
 #endif
 
+#include <algorithm>
+#include <array>
+#include <string>
+
+#include <cmath>
+
+#include <QAction>
 #include <QApplication>
+#include <QByteArray>
+#include <QComboBox>
+#include <QDateTime>
+#include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+#include <QFontDatabase>
+#include <QIcon>
+#include <QLibraryInfo>
+#include <QMessageBox>
+#include <QNetworkProxy>
 #include <QSettings>
+#include <QShortcut>
+#include <QString>
+#include <QStringList>
+#include <QTranslator>
 
+#include "gui-preferences-cs.h"
+#include "gui-preferences-ed.h"
+#include "gui-preferences-sc.h"
+#include "gui-preferences-global.h"
 #include "gui-settings.h"
 
+#include "localcharset-wrapper.h"
+#include "oct-env.h"
+#include "oct-string.h"
+
+#include "defaults.h"
+
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+QString gui_settings::file_name () const
+{
+  return fileName ();
+}
+
+QString gui_settings::directory_name () const
+{
+  QFileInfo sfile (fileName ());
+
+  return sfile.absolutePath ();
+}
+
+bool gui_settings::bool_value (const gui_pref& pref) const
+{
+  return value (pref).toBool ();
+}
+
+QByteArray gui_settings::byte_array_value (const gui_pref& pref) const
+{
+  return value (pref).toByteArray ();
+}
+
+QColor gui_settings::color_value (const gui_pref& pref) const
+{
+  return value (pref).value<QColor> ();
+}
+
+QDateTime gui_settings::date_time_value (const gui_pref& pref) const
+{
+  return value (pref).toDateTime ();
+}
+
+int gui_settings::int_value (const gui_pref& pref) const
+{
+  return value (pref).toInt ();
+}
+
+QString gui_settings::string_value (const gui_pref& pref) const
+{
+  return value (pref).toString ();
+}
+
+QStringList gui_settings::string_list_value (const gui_pref& pref) const
+{
+  return value (pref).toStringList ();
+}
+
+uint gui_settings::uint_value (const gui_pref& pref) const
+{
+  return value (pref).toUInt ();
+}
+
 QColor gui_settings::get_color_value (const QVariant& def, int mode) const
 {
   QColor default_color;
@@ -47,15 +131,19 @@
       // The default colors are given as color roles for
       // the application's palette
       default_color = QApplication::palette ().color
-        (static_cast<QPalette::ColorRole> (def.toInt ()));
-      // FIXME: use value<QPalette::ColorRole> instead of static cast after
-      //        dropping support of Qt 5.4
+                      (static_cast<QPalette::ColorRole> (def.toInt ()));
+                // FIXME: use value<QPalette::ColorRole> instead of static cast after
+                //        dropping support of Qt 5.4
     }
 
   if ((mode == 1) && (default_color != settings_color_no_change))
     {
       // In second mode, determine the default color from the first mode
+#if HAVE_QCOLOR_FLOAT_TYPE
+      float h, s, l, a;
+#else
       qreal h, s, l, a;
+#endif
       default_color.getHslF (&h, &s, &l, &a);
       qreal l_new = 1.0-l*0.85;
       if (l < 0.3)
@@ -68,9 +156,9 @@
 
 QColor gui_settings::color_value (const gui_pref& pref, int mode) const
 {
-  QColor default_color = get_color_value (pref.def, mode);
+  QColor default_color = get_color_value (pref.def (), mode);
 
-  return value (pref.key + settings_color_modes_ext[mode],
+  return value (pref.settings_key () + settings_color_modes_ext[mode],
                 QVariant (default_color)).value<QColor> ();
 }
 
@@ -81,31 +169,606 @@
   if (m > 1)
     m = 1;
 
-  setValue (pref.key + settings_color_modes_ext[m], QVariant (color));
+  setValue (pref.settings_key () + settings_color_modes_ext[m],
+            QVariant (color));
 }
 
-QString gui_settings::sc_value (const sc_pref& pref) const
+QString gui_settings::sc_value (const sc_pref& scpref) const
 {
-  QKeySequence key_seq = sc_def_value (pref);
+  QKeySequence key_seq = sc_def_value (scpref);
 
   // Get the value from the settings where the key sequences are stored
   // as strings
-  return value (sc_group + pref.key, key_seq.toString ()).toString ();
+  return value (sc_group + "/" + scpref.settings_key (),
+                key_seq.toString ()).toString ();
+}
+
+QKeySequence gui_settings::sc_def_value (const sc_pref& scpref) const
+{
+  return scpref.def_value ();
+}
+
+void gui_settings::set_shortcut (QAction *action, const sc_pref& scpref,
+                                 bool enable)
+{
+  if (! enable)
+    {
+      // Disable => remove existing shortcut from the action
+      action->setShortcut (QKeySequence ());
+      return;
+    }
+
+  QString shortcut = sc_value (scpref);
+
+  if (! shortcut.isEmpty ())
+    action->setShortcut (QKeySequence (shortcut));
+  else
+    qDebug () << "Key: " << scpref.settings_key ()
+              << " not found in settings";
+}
+
+void gui_settings::shortcut (QShortcut *sc, const sc_pref& scpref)
+{
+  QString shortcut = sc_value (scpref);
+
+  if (! shortcut.isEmpty ())
+    sc->setKey (QKeySequence (shortcut));
+  else
+    qDebug () << "Key: " << scpref.settings_key ()
+              << " not found in settings";
+}
+
+void gui_settings::config_icon_theme ()
+{
+  int theme_index;
+
+  if (contains (global_icon_theme_index.settings_key ()))
+    theme_index = int_value (global_icon_theme_index);
+  else
+    {
+      // New pref does not exist.  Use old if required.  Add new and
+      // remove deprecated key.
+
+      if (bool_value (global_icon_theme))
+        theme_index = ICON_THEME_SYSTEM;
+      else
+        theme_index = ICON_THEME_OCTAVE;
+
+      setValue (global_icon_theme_index.settings_key (), theme_index);
+      remove (global_icon_theme.settings_key ());
+    }
+
+  QIcon::setThemeName (global_all_icon_themes.at (theme_index));
+
+  QStringList icon_fallbacks;
+
+  // Set the required fallback search paths.
+
+  switch (theme_index)
+    {
+    case ICON_THEME_SYSTEM:
+      icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);
+      icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);
+      break;
+    case ICON_THEME_TANGO:
+      icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);
+      break;
+    case ICON_THEME_OCTAVE:
+      icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);
+      break;
+    }
+
+  icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS);
+
+  setValue (global_icon_fallbacks.settings_key (), icon_fallbacks);
+}
+
+QIcon gui_settings::icon (const QString& icon_name, bool octave_only,
+                          const QString& icon_alt_name)
+{
+  if (octave_only)
+    return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png");
+
+  if (QIcon::hasThemeIcon (icon_name))
+    return QIcon (QIcon::fromTheme (icon_name));
+  else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name))
+    return QIcon (QIcon::fromTheme (icon_alt_name));
+
+  QStringList icon_fallbacks
+    = value (global_icon_fallbacks.settings_key ()).toStringList ();
+
+  for (int i = 0; i < icon_fallbacks.length (); i++ )
+    {
+      QString icon_file (icon_fallbacks.at (i) + icon_name + ".png");
+      if (QFile (icon_file).exists ())
+        return QIcon (icon_file);
+    }
+
+    //QIcon::setThemeName (current_theme);
+    return QIcon ();
+}
+
+QString gui_settings::get_default_font_family ()
+{
+  // Get all available fixed width fonts from the Qt font database.
+
+  QFontDatabase font_database;
+  QStringList fonts;
+
+  for (QString font : font_database.families ())
+    {
+      if (font_database.isFixedPitch (font))
+        fonts << font;
+    }
+
+  QString default_family;
+
+#if defined (Q_OS_MAC)
+  // Use hard coded default on macOS, since selection of fixed width
+  // default font is unreliable (see bug #59128).
+  // Test for macOS default fixed width font
+  if (fonts.contains (global_mono_font.def ().toString ()))
+    default_family = global_mono_font.def ().toString ();
+#endif
+
+  // If default font is still empty (on all other platforms or
+  // if macOS default font is not available): use QFontDatabase
+  if (default_family.isEmpty ())
+    {
+      // Get the system's default monospaced font
+      QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont);
+      default_family = fixed_font.defaultFamily ();
+
+      // Since this might be unreliable, test all available fixed width fonts
+      if (! fonts.contains (default_family))
+        {
+          // Font returned by QFontDatabase is not in fixed fonts list.
+          // Fallback: take first from this list
+          default_family = fonts[0];
+        }
+    }
+
+  // Test env variable which has preference
+  std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT");
+  if (! env_default_family.empty ())
+    default_family = QString::fromStdString (env_default_family);
+
+  return default_family;
+}
+
+QStringList gui_settings::get_default_font ()
+{
+  QString default_family = get_default_font_family ();
+
+  // determine the fefault font size of the system
+  // FIXME: QApplication::font () does not return the monospace font,
+  //        but the size should be probably near to the monospace font
+  QFont font = QApplication::font ();
+
+  int font_size = font.pointSize ();
+  if (font_size == -1)
+    font_size = static_cast <int> (std::floor(font.pointSizeF ()));
+
+  // check for valid font size, otherwise take default 10
+  QString default_font_size = "10";
+  if (font_size > 0)
+    default_font_size = QString::number (font_size);
+
+  std::string env_default_font_size
+    = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE");
+
+  if (! env_default_font_size.empty ())
+    default_font_size = QString::fromStdString (env_default_font_size);
+
+  QStringList result;
+  result << default_family;
+  result << default_font_size;
+  return result;
+}
+
+QString gui_settings::get_gui_translation_dir ()
+{
+  // get environment variable for the locale dir (e.g. from run-octave)
+  std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR");
+  if (dldir.empty ())
+    dldir = config::oct_locale_dir ();  // env-var empty, load the default location
+  return QString::fromStdString (dldir);
+}
+
+void gui_settings::config_translators (QTranslator *qt_tr,
+                                       QTranslator *qsci_tr,
+                                       QTranslator *gui_tr)
+{
+  bool loaded;
+
+  QString qt_trans_dir
+    = QLibraryInfo::location (QLibraryInfo::TranslationsPath);
+
+  QString language = "SYSTEM";  // take system language per default
+
+  // FIXME: can we somehow ensure that the settings object will always
+  // be initialize and valid?
+
+  // get the locale from the settings if already available
+  language = string_value (global_language);
+
+  // load the translations depending on the settings
+  if (language == "SYSTEM")
+    {
+      // get the system locale and pass it to the translators for loading
+      // the suitable translation files
+      QLocale sys_locale = QLocale::system ();
+
+      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);
+
+      loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir);
+      if (! loaded)  // try lower case
+        qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir);
+
+      gui_tr->load (language, get_gui_translation_dir ());
+    }
+
+}
+
+#if defined (HAVE_QSCINTILLA)
+int gui_settings::get_valid_lexer_styles (QsciLexer *lexer, int *styles)
+{
+  int max_style = 0;
+  int actual_style = 0;
+  while (actual_style < ed_max_style_number && max_style < ed_max_lexer_styles)
+    {
+      if ((lexer->description (actual_style)) != "")  // valid style
+        styles[max_style++] = actual_style;
+      actual_style++;
+    }
+  return max_style;
+}
+#endif
+
+/*!
+ * Copys the attributes bold, italic and underline from QFont
+ * @p attr to the font @p base and returns the result without
+ * changing @p base,
+ * @param attr QFont with the desired attributes
+ * @param base QFont with desired family and size
+ */
+static QFont copy_font_attributes (const QFont& attr, const QFont& base)
+{
+  QFont dest (base);
+
+  dest.setBold (attr.bold ());
+  dest.setItalic (attr.italic ());
+  dest.setUnderline (attr.underline ());
+
+  return dest;
 }
 
-QKeySequence gui_settings::sc_def_value (const sc_pref& pref) const
+#if defined (HAVE_QSCINTILLA)
+void gui_settings::read_lexer_settings (QsciLexer *lexer, int mode, int def)
+{
+  // Test whether the settings for lexer is already contained in the
+  // given gui settings file. If yes, load them, if not copy them from the
+  // default settings file.
+  // This is useful when a new language support is implemented and the
+  // existing settings file is used (which is of course the common case).
+  int m = mode;
+  if (m > 1)
+    m = 1;
+
+  QString group ("Scintilla" + settings_color_modes_ext[m]);
+
+  beginGroup (group);
+  beginGroup (lexer->language ());
+
+  QStringList lexer_keys = allKeys ();
+
+  endGroup ();
+  endGroup ();
+
+  if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0)
+    {
+      // We have to reload the default values or no Lexer keys found:
+      // If mode == 0, take all settings except font from default lexer
+      // If Mode == 1, take all settings except font from default lexer
+      //               and convert the color by inverting the lightness
+
+      // Get the default font
+      QStringList def_font = get_default_font ();
+      QFont df (def_font[0], def_font[1].toInt ());
+      QFont dfa = copy_font_attributes (lexer->defaultFont (), df);
+      lexer->setDefaultFont (dfa);
+
+      QColor c, p;
+
+      int styles[ed_max_lexer_styles];  // array for saving valid styles
+      int max_style = get_valid_lexer_styles (lexer, styles);
+
+      for (int i = 0; i < max_style; i++)
+        {
+          c = get_color_value (QVariant (lexer->color (styles[i])), m);
+          lexer->setColor (c, styles[i]);
+          p = get_color_value (QVariant (lexer->paper (styles[i])), m);
+          lexer->setPaper (p, styles[i]);
+          dfa = copy_font_attributes (lexer->font (styles[i]), df);
+          lexer->setFont (dfa, styles[i]);
+        }
+      // Set defaults last for not changing the defaults of the styles
+      lexer->setDefaultColor (lexer->color (styles[0]));
+      lexer->setDefaultPaper (lexer->paper (styles[0]));
+
+      // Write settings if not just reload the default values
+      if (def != settings_reload_default_colors_flag)
+        {
+          const std::string group_str = group.toStdString ();
+          lexer->writeSettings (*this, group_str.c_str ());
+          sync ();
+        }
+    }
+  else
+    {
+      // Found lexer keys, read the settings
+      const std::string group_str = group.toStdString ();
+      lexer->readSettings (*this, group_str.c_str ());
+    }
+}
+#endif
+
+bool gui_settings::update_settings_key (const QString& old_key,
+                                        const QString& new_key)
 {
-  QKeySequence key_seq = QKeySequence ();
+  if (contains (old_key))
+    {
+      QVariant preference = value (old_key);
+      setValue (new_key, preference);
+      remove (old_key);
+      return true;
+    }
+
+  return false;
+}
+
+void gui_settings::update_network_settings ()
+{
+  QNetworkProxy proxy;
+
+  // Assume no proxy and empty proxy data
+  QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy;
+  QString scheme;
+  QString host;
+  int port = 0;
+  QString user;
+  QString pass;
+  QUrl proxy_url = QUrl ();
+
+  if (bool_value (global_use_proxy))
+    {
+      // Use a proxy, collect all required information
+      QString proxy_type_string = string_value (global_proxy_type);
+
+      // The proxy type for the Qt proxy settings
+      if (proxy_type_string == "Socks5Proxy")
+        proxy_type = QNetworkProxy::Socks5Proxy;
+      else if (proxy_type_string == "HttpProxy")
+        proxy_type = QNetworkProxy::HttpProxy;
+
+      // The proxy data from the settings
+      if (proxy_type_string == "HttpProxy"
+          || proxy_type_string == "Socks5Proxy")
+        {
+          host = string_value (global_proxy_host);
+          port = int_value (global_proxy_port);
+          user = string_value (global_proxy_user);
+          pass = string_value (global_proxy_pass);
+          if (proxy_type_string == "HttpProxy")
+            scheme = "http";
+          else if (proxy_type_string == "Socks5Proxy")
+            scheme = "socks5";
+
+          QUrl env_var_url = QUrl ();
+          proxy_url.setScheme (scheme);
+          proxy_url.setHost (host);
+          proxy_url.setPort (port);
+          if (! user.isEmpty ())
+            proxy_url.setUserName (user);
+          if (! pass.isEmpty ())
+            proxy_url.setPassword (pass);
+        }
+
+      // The proxy data from environment variables
+      if (proxy_type_string == global_proxy_all_types.at (2))
+        {
+          const std::array<std::string, 6> env_vars =
+          {
+            "ALL_PROXY", "all_proxy",
+            "HTTP_PROXY", "http_proxy",
+            "HTTPS_PROXY", "https_proxy"
+          };
+
+          unsigned int count = 0;
+          while (! proxy_url.isValid () && count < env_vars.size ())
+            {
+              proxy_url = QUrl (QString::fromStdString
+                                  (sys::env::getenv (env_vars[count])));
+              count++;
+            }
+
+          if (proxy_url.isValid ())
+            {
+              // Found an entry, get the data from the string
+              scheme = proxy_url.scheme ();
+
+              if (scheme.contains ("socks", Qt::CaseInsensitive))
+                proxy_type = QNetworkProxy::Socks5Proxy;
+              else
+                proxy_type = QNetworkProxy::HttpProxy;
 
-  // Check, which of the elements for the default value in the sc_pref
-  // structure has a valid value and take this as default.  If both
-  // elements are not valid, leave the key sequence empty
-  if (pref.def)
-    key_seq = QKeySequence (pref.def);
-  else if (pref.def_std != QKeySequence::UnknownKey)
-    key_seq = QKeySequence (pref.def_std);
+              host = proxy_url.host ();
+              port = proxy_url.port ();
+              user = proxy_url.userName ();
+              pass = proxy_url.password ();
+            }
+        }
+    }
+
+  // Set proxy for Qt framework
+  proxy.setType (proxy_type);
+  proxy.setHostName (host);
+  proxy.setPort (port);
+  proxy.setUser (user);
+  proxy.setPassword (pass);
+
+  QNetworkProxy::setApplicationProxy (proxy);
+
+  // Set proxy for curl library if not based on environment variables
+  std::string proxy_url_str = proxy_url.toString().toStdString ();
+  sys::env::putenv ("http_proxy", proxy_url_str);
+  sys::env::putenv ("HTTP_PROXY", proxy_url_str);
+  sys::env::putenv ("https_proxy", proxy_url_str);
+  sys::env::putenv ("HTTPS_PROXY", proxy_url_str);
+}
+
+// initialize a given combo box with available text encodings
+void gui_settings::combo_encoding (QComboBox *combo, const QString& current)
+{
+  std::vector<std::string> encoding_list {string::get_encoding_list ()};
+
+  // prepend SYSTEM
+  std::string locale_charset {octave_locale_charset_wrapper ()};
+  std::transform (locale_charset.begin (), locale_charset.end (),
+                  locale_charset.begin (), ::toupper);
+  locale_charset = "SYSTEM (" + locale_charset + ")";
+  encoding_list.insert (encoding_list.begin (), locale_charset);
+
+  // get the value from the settings file if no current encoding is given
+  QString enc {current};
+
+  // Check for valid codec for the default.  If this fails, "SYSTEM" (i.e.
+  // locale_charset) will be chosen.
+  // FIXME: The default is "SYSTEM" on all platforms.  So can this fallback
+  // logic be removed completely?
+  bool default_exists = false;
+  bool show_system = false;
+  if (ed_default_enc.def ().toString ().startsWith ("SYSTEM"))
+    show_system = true;
+  else if (std::find (encoding_list.begin (), encoding_list.end (),
+                      ed_default_enc.def ().toString ().toStdString ())
+           != encoding_list.end ())
+    default_exists = true;
+
+  QString default_enc = QString::fromStdString (locale_charset);
+
+  if (enc.isEmpty ())
+    {
+      enc = string_value (ed_default_enc);
+
+      if (enc.isEmpty ())  // still empty?
+        {
+          if (default_exists)
+            enc = ed_default_enc.def ().toString ();
+          else
+            enc = default_enc;
+        }
+    }
+
+  // fill the combo box
+  for (const auto& c : encoding_list)
+    combo->addItem (QString::fromStdString (c));
+
+  // prepend current encoding if not in list
+  if (combo->findText (enc, Qt::MatchExactly) < 0)
+    combo->insertItem (0, enc);
 
-  return key_seq;
+  // prepend the default item
+  combo->insertSeparator (0);
+  if (show_system || ! default_exists)
+    combo->insertItem (0, default_enc);
+  else
+    combo->insertItem (0, ed_default_enc.def ().toString ());
+
+  // select the current encoding
+  combo->setCurrentIndex (combo->findText (enc, Qt::MatchExactly));
+
+  combo->setMaxVisibleItems (12);
+}
+
+void gui_settings::reload ()
+{
+  // Declare some empty options, which may be set at first startup for
+  // writing them into the newly created settings file
+  QString custom_editor;
+  QStringList def_font;
+
+  // Check whether the settings file does not yet exist
+  if (! QFile::exists (file_name ()))
+    {
+      // Get the default font (for terminal)
+      def_font = get_default_font ();
+
+      // Get a custom editor defined as env variable
+      std::string env_default_editor
+        = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR");
+
+      if (! env_default_editor.empty ())
+        custom_editor = QString::fromStdString (env_default_editor);
+    }
+
+  check ();
+
+  // Write some settings that were dynamically determined at first startup
+
+  // Custom editor
+  if (! custom_editor.isEmpty ())
+    setValue (global_custom_editor.settings_key (), custom_editor);
+
+  // Default monospace font for the terminal
+  if (def_font.count () > 1)
+    {
+      setValue (cs_font.settings_key (), def_font[0]);
+      setValue (cs_font_size.settings_key (), def_font[1].toInt ());
+    }
+
+  // Write the default monospace font into the settings for later use by
+  // console and editor as fallbacks of their font preferences.
+  setValue (global_mono_font.settings_key (), get_default_font_family ());
+}
+
+void gui_settings::check ()
+{
+  if (status () == QSettings::NoError)
+    {
+      // Test usability (force file to be really created)
+      setValue ("dummy", 0);
+      sync ();
+    }
+
+  if (! (QFile::exists (file_name ())
+         && isWritable ()
+         && status () == QSettings::NoError))
+    {
+      QString msg
+        = QString (QT_TR_NOOP ("Error %1 creating the settings file\n%2\n"
+                               "Make sure you have read and write permissions to\n%3\n\n"
+                               "Octave GUI must be closed now."));
+
+      QMessageBox::critical (nullptr,
+                             QString (QT_TR_NOOP ("Octave Critical Error")),
+                             msg.arg (status ())
+                                .arg (file_name ())
+                                .arg (directory_name ()));
+
+      exit (1);
+    }
+  else
+    remove ("dummy");  // Remove test entry
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/gui-settings.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-settings.h	Fri Jun 23 20:51:51 2023 +0200
@@ -28,7 +28,19 @@
 
 #include "octave-config.h"
 
+#include <QColor>
 #include <QSettings>
+#include <QString>
+#if defined (HAVE_QSCINTILLA)
+#  include <Qsci/qscilexer.h>
+#endif
+
+class QByteArray;
+class QComboBox;
+class QDateTime;
+class QIcon;
+class QShortcut;
+class QTranslator;
 
 #include "gui-preferences.h"
 
@@ -40,6 +52,13 @@
 
 public:
 
+  // Location, name, and format of settings file determined by
+  // settings in qt_application class construtor.
+
+  gui_settings (QObject *parent = nullptr)
+    : QSettings (parent)
+  { }
+
   gui_settings (const QString& file_name, QSettings::Format format,
                 QObject *parent = nullptr)
     : QSettings (file_name, format, parent)
@@ -52,43 +71,68 @@
     : QSettings (format, scope, organization, application, parent)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (gui_settings)
 
-  gui_settings (const gui_settings&) = delete;
+  ~gui_settings () = default;
 
-  gui_settings& operator = (const gui_settings&) = delete;
+  QString file_name () const;
 
-  ~gui_settings (void) = default;
+  QString directory_name () const;
 
   using QSettings::value;
 
   QVariant value (const gui_pref& pref) const
   {
-    if (pref.ignore)
-      return pref.def;  // ignore the current pref and always use default
+    if (pref.ignore ())
+      return pref.def ();  // ignore the current pref and always use default
+
+    return value (pref.settings_key (), pref.def ());
+  }
+
+  // Convenience functions to (slightly) reduce clutter by allowing us
+  // to write
+  //
+  //   settings.bool_value (gui_pref_name)
+  //
+  // instead of
+  //
+  //   settings.value (gui_pref_name).toBool ()
 
-    return value (pref.key, pref.def);
-  }
+  bool bool_value (const gui_pref& pref) const;
+
+  QByteArray byte_array_value (const gui_pref& pref) const;
+
+  QColor color_value (const gui_pref& pref) const;
+
+  QDateTime date_time_value (const gui_pref& pref) const;
+
+  int int_value (const gui_pref& pref) const;
+
+  QString string_value (const gui_pref& pref) const;
+
+  QStringList string_list_value (const gui_pref& pref) const;
+
+  uint uint_value (const gui_pref& pref) const;
 
   /*!
     Reading a color from the given QVaraitn @p def taking different
     color modes into account. The default value for a second color mode
     @p mode=1 is deterimined from the standard default value @p mode=0
     by inverting the lightness
-    \f{eqnarray*}{
-    H_1 &=& H_0\\
-    S_1 &=& S_0\\
-    L_1 &=& 1.0 - 0.85 L_0    L_0 > 0.3
-    L_1 &=& 1.0 - 0.70 L_0    L_0 < 0.3
-    \f}
+      \f{eqnarray*}{
+         H_1 &=& H_0\\
+         S_1 &=& S_0\\
+         L_1 &=& 1.0 - 0.85 L_0    L_0 > 0.3
+         L_1 &=& 1.0 - 0.70 L_0    L_0 < 0.3
+      \f}
 
     @param def  Color default value given by a QVariant of QColor
-    or QPalette::ColorRole
+                or QPalette::ColorRole
     @param mode Color mode (currently 0 or 1, default is 0)
 
     @return Color as QColor
   */
-  QColor get_color_value (const QVariant& def, int mode = 0) const;
+  QColor get_color_value (const QVariant& def, int mode) const;
 
   /*!
     Reading a color from the gui_settings taking possible color modes
@@ -97,12 +141,12 @@
     the lightness (see get_color_value())
 
     @param pref gui preference (key string, default value); the default
-    value can be given by QColor or QPalette::ColorRole
+                value can be given by QColor or QPalette::ColorRole
     @param mode Color mode (currently 0 or 1, default is 0)
 
     @return Color as QColor
   */
-  QColor color_value (const gui_pref& pref, int mode = 0) const;
+  QColor color_value (const gui_pref& pref, int mode) const;
 
   /*!
     Writing a color to the gui_settings taking possible color modes
@@ -115,12 +159,57 @@
 
   */
   void set_color_value (const gui_pref& pref, const QColor& color,
-                        int mode = 0);
+                        int mode);
 
   QString sc_value (const sc_pref& pref) const;
 
   QKeySequence sc_def_value (const sc_pref& pref) const;
 
+  void set_shortcut (QAction *action, const sc_pref& scpref,
+                     bool enable = true);
+
+  void shortcut (QShortcut *sc, const sc_pref& scpref);
+
+  // config_icon_theme, icon, get_default_font_family,
+  // get_default_font, and possibly reload and check could be global
+  // functions instead of member functions.  But at least for the icon
+  // function, defining it as a member function means that we can
+  // create a single gui_settings object and access multiple icon
+  // objects rather than having to create a separate settings object
+  // each time that an icon is needed.  OTOH, creating the base
+  // QSettings object is supposed to be fast, so that may not matter.
+  // Hmm.
+
+  void config_icon_theme ();
+
+  QIcon icon (const QString& icon_name, bool octave_only = false,
+              const QString& icon_alt_name = QString ());
+
+  QString get_default_font_family ();
+
+  QStringList get_default_font ();
+
+  QString get_gui_translation_dir ();
+
+  void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr,
+                           QTranslator *gui_tr);
+
+#if defined (HAVE_QSCINTILLA)
+  int get_valid_lexer_styles (QsciLexer *lexer, int *styles);
+  void read_lexer_settings (QsciLexer *lexer, int mode = 0, int def = 0);
+#endif
+
+  bool update_settings_key (const QString& new_key, const QString& old_key);
+
+  void update_network_settings ();
+
+  void combo_encoding (QComboBox *combo, const QString& current = QString ());
+
+  void reload ();
+
+private:
+
+  void check ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
@@ -134,3 +223,4 @@
 const int settings_reload_default_colors_flag = -1;
 
 #endif
+
--- a/libgui/src/gui-utils.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/gui-utils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,11 @@
 interpolate_color (const QColor& col1, const QColor& col2,
                    double fs, double fv)
 {
+#if HAVE_QCOLOR_FLOAT_TYPE
+  float h1, s1, v1, h2, s2, v2;
+#else
   qreal h1, s1, v1, h2, s2, v2;
+#endif
 
   col1.getHsvF (&h1, &s1, &v1);
   col2.getHsvF (&h2, &s2, &v2);
@@ -117,8 +121,9 @@
 
   // And compute again the intersection with the screen if this resizing
   // led to corners outside the screen
-  actual_geometry = actual_screen_geom.intersected (
-                                                    QRect (QPoint (isx1,isy1), QPoint (isx2,isy2)));
+  actual_geometry
+    = actual_screen_geom.intersected (QRect (QPoint (isx1, isy1),
+                                             QPoint (isx2, isy2)));
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/history-dock-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/history-dock-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,8 +38,8 @@
 #include "gui-preferences-cs.h"
 #include "gui-preferences-global.h"
 #include "gui-preferences-hw.h"
+#include "gui-settings.h"
 #include "history-dock-widget.h"
-#include "octave-qobject.h"
 
 #include "cmd-hist.h"
 
@@ -47,8 +47,8 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-history_dock_widget::history_dock_widget (QWidget *p, base_qobject& oct_qobj)
-: octave_dock_widget ("HistoryDockWidget", p, oct_qobj)
+history_dock_widget::history_dock_widget (QWidget *p)
+  : octave_dock_widget ("HistoryDockWidget", p)
 {
   setStatusTip (tr ("Browse and search the command history."));
 
@@ -80,33 +80,29 @@
     m_history_list_view->scrollToBottom ();
 }
 
-void history_dock_widget::clear_history (void)
+void history_dock_widget::clear_history ()
 {
   m_history_model->setStringList (QStringList ());
 }
 
-void history_dock_widget::save_settings (void)
+void history_dock_widget::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  if (! settings)
-    return;
-
-  settings->setValue (hw_filter_active.key, m_filter_checkbox->isChecked ());
-  settings->setValue (hw_filter_shown.key, m_filter_shown);
+  settings.setValue (hw_filter_active.settings_key (), m_filter_checkbox->isChecked ());
+  settings.setValue (hw_filter_shown.settings_key (), m_filter_shown);
 
   QStringList mru;
   for (int i = 0; i < m_filter->count (); i++)
     mru.append (m_filter->itemText (i));
-  settings->setValue (hw_mru_list.key, mru);
+  settings.setValue (hw_mru_list.settings_key (), mru);
 
-  settings->sync ();
+  settings.sync ();
 
   octave_dock_widget::save_settings ();
 }
 
-void history_dock_widget::update_filter_history (void)
+void history_dock_widget::update_filter_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -153,13 +149,13 @@
 
   if (index.isValid () && index.column () == 0)
     {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+      gui_settings settings;
 
-      menu.addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this,
+      menu.addAction (settings.icon ("edit-copy"), tr ("Copy"), this,
                       &history_dock_widget::handle_contextmenu_copy);
       menu.addAction (tr ("Evaluate"), this,
                       &history_dock_widget::handle_contextmenu_evaluate);
-      menu.addAction (rmgr.icon ("document-new"), tr ("Create script"), this,
+      menu.addAction (settings.icon ("document-new"), tr ("Create script"), this,
                       &history_dock_widget::handle_contextmenu_create_script);
     }
   if (m_filter_shown)
@@ -183,13 +179,13 @@
   QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
   QModelIndexList rows = selectionModel->selectedRows ();
   bool prev_valid_row = false;
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& it : rows)
     {
-      if ((*it).isValid ())
+      if (it.isValid ())
         {
           if (prev_valid_row)
             text += '\n';
-          text += (*it).data ().toString ();
+          text += it.data ().toString ();
           prev_valid_row = true;
         }
     }
@@ -200,11 +196,9 @@
 {
   QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
   QModelIndexList rows = selectionModel->selectedRows ();
-  for (auto it = rows.begin () ; it != rows.end (); it++)
-    {
-      if ((*it).isValid ())
-        emit command_double_clicked ((*it).data ().toString ());
-    }
+  for (const auto& it : rows)
+    if (it.isValid ())
+      emit command_double_clicked (it.data ().toString ());
 }
 
 void history_dock_widget::handle_contextmenu_create_script (bool)
@@ -214,13 +208,13 @@
   QModelIndexList rows = selectionModel->selectedRows ();
 
   bool prev_valid_row = false;
-  for (auto it = rows.begin (); it != rows.end (); it++)
+  for (const auto& it : rows)
     {
-      if ((*it).isValid ())
+      if (it.isValid ())
         {
           if (prev_valid_row)
             text += '\n';
-          text += (*it).data ().toString ();
+          text += it.data ().toString ();
           prev_valid_row = true;
         }
     }
@@ -229,7 +223,7 @@
     emit command_create_script (text);
 }
 
-void history_dock_widget::handle_contextmenu_filter (void)
+void history_dock_widget::handle_contextmenu_filter ()
 {
   m_filter_shown = ! m_filter_shown;
   m_filter_widget->setVisible (m_filter_shown);
@@ -237,7 +231,7 @@
   set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()) ;
 }
 
-void history_dock_widget::copyClipboard (void)
+void history_dock_widget::copyClipboard ()
 {
   if (m_history_list_view->hasFocus ())
     handle_contextmenu_copy (true);
@@ -249,7 +243,7 @@
     }
 }
 
-void history_dock_widget::pasteClipboard (void)
+void history_dock_widget::pasteClipboard ()
 {
   if (m_filter->lineEdit ()->hasFocus ())
     {
@@ -260,7 +254,7 @@
     }
 }
 
-void history_dock_widget::selectAll (void)
+void history_dock_widget::selectAll ()
 {
   if (m_filter->lineEdit ()->hasFocus ())
     m_filter->lineEdit ()->selectAll ();
@@ -280,7 +274,7 @@
     }
 }
 
-void history_dock_widget::construct (void)
+void history_dock_widget::construct ()
 {
   m_history_model = new QStringListModel ();
   m_sort_filter_proxy_model.setSourceModel (m_history_model);
@@ -318,29 +312,27 @@
   filter_layout->addWidget (filter_label);
   filter_layout->addWidget (m_filter_checkbox);
   filter_layout->addWidget (m_filter);
-  filter_layout->setMargin(0);
+  filter_layout->setContentsMargins (0, 0, 0, 0);
   m_filter_widget->setLayout (filter_layout);
 
   QVBoxLayout *hist_layout = new QVBoxLayout ();
   hist_layout->addWidget (m_filter_widget);
   hist_layout->addWidget (m_history_list_view);
 
-  hist_layout->setMargin (2);
+  hist_layout->setContentsMargins (2, 2, 2, 2);
   hist_layout->setSpacing (0);
   widget ()->setLayout (hist_layout);
 
   // Init state of the filter
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
 
-  m_filter_shown
-    = settings->value (hw_filter_shown).toBool ();
+  gui_settings settings;
+
+  m_filter_shown = settings.bool_value (hw_filter_shown);
   m_filter_widget->setVisible (m_filter_shown);
 
-  m_filter->addItems (settings->value (hw_mru_list).toStringList ());
+  m_filter->addItems (settings.string_list_value (hw_mru_list));
 
-  bool filter_state
-    = settings->value (hw_filter_active).toBool ();
+  bool filter_state = settings.bool_value (hw_filter_active);
   m_filter_checkbox->setChecked (filter_state);
   filter_activate (filter_state);
 
@@ -359,15 +351,17 @@
   m_history_list_view->setTextElideMode (Qt::ElideRight);
 }
 
-void history_dock_widget::notice_settings (const gui_settings *settings)
+void history_dock_widget::notice_settings ()
 {
+  gui_settings settings;
+
   QFont font = QFont ();
 
   font.setStyleHint (QFont::TypeWriter);
-  QString default_font = settings->value (global_mono_font).toString ();
+  QString default_font = settings.string_value (global_mono_font);
 
-  font.setFamily (settings->value (cs_font.key, default_font).toString ());
-  font.setPointSize (settings->value (cs_font_size).toInt ());
+  font.setFamily (settings.value (cs_font.settings_key (), default_font).toString ());
+  font.setPointSize (settings.int_value (cs_font_size));
 
   m_history_list_view->setFont (font);
 }
--- a/libgui/src/history-dock-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/history-dock-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,17 +37,15 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class history_dock_widget : public octave_dock_widget
 {
   Q_OBJECT
 
 public:
 
-  history_dock_widget (QWidget *parent, base_qobject& oct_qobj);
+  history_dock_widget (QWidget *parent);
 
-  ~history_dock_widget (void) = default;
+  ~history_dock_widget () = default;
 
 signals:
 
@@ -65,13 +63,13 @@
 
   void set_history (const QStringList& hist);
   void append_history (const QString& hist_entry);
-  void clear_history (void);
-  void save_settings (void);
-  void notice_settings (const gui_settings *);
+  void clear_history ();
+  void save_settings ();
+  void notice_settings ();
 
 private slots:
 
-  void update_filter_history (void);
+  void update_filter_history ();
   void filter_activate (bool enable);
 
   void ctxMenu (const QPoint& pos);
@@ -79,17 +77,17 @@
   void handle_contextmenu_copy (bool flag);
   void handle_contextmenu_evaluate (bool flag);
   void handle_contextmenu_create_script (bool flag);
-  void handle_contextmenu_filter (void);
+  void handle_contextmenu_filter ();
 
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
 
   virtual void handle_visibility (bool visible);
 
 private:
 
-  void construct (void);
+  void construct ();
   void set_filter_focus (bool focus);
 
   QListView *m_history_list_view;
--- a/libgui/src/interpreter-qobject.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/interpreter-qobject.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,10 +39,10 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 interpreter_qobject::interpreter_qobject (base_qobject& oct_qobj)
-: QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr)
+  : QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr)
 { }
 
-void interpreter_qobject::execute (void)
+void interpreter_qobject::execute ()
 {
   // The Octave application context owns the interpreter.
 
@@ -67,10 +67,8 @@
       if (app_context.start_gui_p ()
           && ! m_octave_qobj.experimental_terminal_widget ())
         {
-          input_system& input_sys = interp.get_input_system ();
-
-          input_sys.PS1 (">> ");
-          input_sys.PS2 ("");
+          interp.PS1 (">> ");
+          interp.PS2 ("");
         }
 
       if (interp.initialized ())
@@ -82,7 +80,7 @@
 
           emit ready ();
 
-          graphics_init (interp, m_octave_qobj);
+          graphics_init (interp);
 
           // Start executing commands in the command window.
 
@@ -130,7 +128,7 @@
   evmgr.post_event (meth);
 }
 
-void interpreter_qobject::interrupt (void)
+void interpreter_qobject::interrupt ()
 {
   if (! m_interpreter)
     return;
@@ -141,7 +139,7 @@
   m_interpreter->interrupt ();
 }
 
-void interpreter_qobject::pause (void)
+void interpreter_qobject::pause ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -158,7 +156,7 @@
     }
 }
 
-void interpreter_qobject::stop (void)
+void interpreter_qobject::stop ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -175,7 +173,7 @@
     }
 }
 
-void interpreter_qobject::resume (void)
+void interpreter_qobject::resume ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -195,7 +193,7 @@
     }
 }
 
-qt_interpreter_events *interpreter_qobject::qt_link (void)
+qt_interpreter_events *interpreter_qobject::qt_link ()
 {
   return m_octave_qobj.qt_link ();
 }
--- a/libgui/src/interpreter-qobject.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/interpreter-qobject.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,25 +44,25 @@
 
   interpreter_qobject (base_qobject& oct_qobj);
 
-  ~interpreter_qobject (void) = default;
+  ~interpreter_qobject () = default;
 
-  qt_interpreter_events * qt_link (void);
+  qt_interpreter_events * qt_link ();
 
   void interpreter_event (const fcn_callback& fcn);
 
   void interpreter_event (const meth_callback& meth);
 
-  void interrupt (void);
+  void interrupt ();
 
   // Note: PAUSE, STOP, and RESUME are currently only used by the new
   // experimental terminal widget.
-  void pause (void);
-  void stop (void);
-  void resume (void);
+  void pause ();
+  void stop ();
+  void resume ();
 
 signals:
 
-  void ready (void);
+  void ready ();
 
   void shutdown_finished (int);
 
@@ -88,7 +88,7 @@
 
   //! Initialize and execute the octave interpreter.
 
-  void execute (void);
+  void execute ();
 
 private:
 
--- a/libgui/src/led-indicator.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/led-indicator.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -67,11 +67,10 @@
 {
   QColor col_light = interpolate_color (col, QColor (Qt::white), 0.25, 0.9);
 
-  const QString style = QString (
-                                 "border-radius: %1; background-color: "
-                                 "qlineargradient(spread:pad, x1:0.2, y1:0.2, x2:1, y2:1, stop:0 "
-                                 "%2, stop:1 %3);"
-                                 ).arg (width ()/2).arg (col_light.name ()).arg (col.name ());
+  const QString style
+    = QString ("border-radius: %1; background-color: "
+               "qlineargradient(spread:pad, x1:0.2, y1:0.2, x2:1, y2:1, stop:0 "
+               "%2, stop:1 %3);").arg (width ()/2).arg (col_light.name ()).arg (col.name ());
 
   return style;
 }
--- a/libgui/src/m-editor/file-editor-interface.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/file-editor-interface.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,33 +30,30 @@
 #include <QMenuBar>
 #include <QToolBar>
 
-#include "gui-settings.h"
 #include "octave-dock-widget.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class file_editor_interface : public octave_dock_widget
 {
   Q_OBJECT
 
 public:
 
-  file_editor_interface (QWidget *p, base_qobject& oct_qobj)
-    : octave_dock_widget ("FileEditor", p, oct_qobj)
+  file_editor_interface (QWidget *p)
+    : octave_dock_widget ("FileEditor", p)
   { }
 
-  virtual ~file_editor_interface (void) = default;
+  virtual ~file_editor_interface () = default;
 
-  virtual QMenu * get_mru_menu (void) = 0;
-  virtual QMenu * debug_menu (void) = 0;
-  virtual QToolBar * toolbar (void) = 0;
-  virtual QMenuBar * menubar (void) = 0;
+  virtual QMenu * get_mru_menu () = 0;
+  virtual QMenu * debug_menu () = 0;
+  virtual QToolBar * toolbar () = 0;
+  virtual QMenuBar * menubar () = 0;
 
   virtual void insert_global_actions (QList<QAction *>) = 0;
-  virtual void handle_enter_debug_mode (void) = 0;
-  virtual void handle_exit_debug_mode (void) = 0;
+  virtual void handle_enter_debug_mode () = 0;
+  virtual void handle_exit_debug_mode () = 0;
 
   virtual void
   handle_insert_debugger_pointer_request (const QString& file, int line) = 0;
@@ -70,11 +67,11 @@
 
   virtual void handle_edit_file_request (const QString& file) = 0;
 
-  virtual bool check_closing (void) = 0;
+  virtual bool check_closing () = 0;
 
   virtual void empty_script (bool, bool) = 0;
 
-  virtual void restore_session (gui_settings *) = 0;
+  virtual void restore_session () = 0;
 
   virtual void enable_menu_shortcuts (bool enable) = 0;
 
--- a/libgui/src/m-editor/file-editor-tab.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/file-editor-tab.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,13 +44,15 @@
 #include <QMessageBox>
 #include <QPrintDialog>
 #include <QPushButton>
+#include <QRegularExpression>
 #include <QScrollBar>
 #include <QSaveFile>
+#include <QStandardPaths>
 #include <QStyle>
 #include <QTextBlock>
-#include <QTextCodec>
 #include <QTextStream>
 #include <QVBoxLayout>
+
 #if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)
 #  define HAVE_LEXER_OCTAVE 1
 #  include <Qsci/qscilexeroctave.h>
@@ -71,14 +73,14 @@
 #include "gui-preferences-cs.h"
 #include "gui-preferences-ed.h"
 #include "gui-preferences-global.h"
+#include "gui-settings.h"
 #include "gui-utils.h"
 #include "marker.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
 #include "octave-txt-lexer.h"
 
 #include "cmd-edit.h"
 #include "file-ops.h"
+#include "iconv-wrappers.h"
 #include "localcharset-wrapper.h"
 #include "uniconv-wrappers.h"
 
@@ -104,9 +106,7 @@
 
 // Make parent null for the file editor tab so that warning WindowModal
 // messages don't affect grandparents.
-file_editor_tab::file_editor_tab (base_qobject& oct_qobj,
-                                  const QString& directory_arg)
-: m_octave_qobj (oct_qobj)
+file_editor_tab::file_editor_tab (const QString& directory_arg)
 {
   m_lexer_apis = nullptr;
   m_is_octave_file = true;
@@ -118,7 +118,7 @@
   m_file_name = "";
   m_file_system_watcher.setObjectName ("_qt_autotest_force_engine_poller");
 
-  m_edit_area = new octave_qscintilla (this, m_octave_qobj);
+  m_edit_area = new octave_qscintilla (this);
   m_line = 0;
   m_col  = 0;
 
@@ -199,7 +199,7 @@
                                          marker::unsure_debugger_position);
 
   connect (m_edit_area, SIGNAL (marginClicked (int, int,
-                                               Qt::KeyboardModifiers)),
+                                Qt::KeyboardModifiers)),
            this, SLOT (handle_margin_clicked (int, int,
                                               Qt::KeyboardModifiers)));
 
@@ -225,7 +225,7 @@
   QVBoxLayout *edit_area_layout = new QVBoxLayout ();
   edit_area_layout->addWidget (m_edit_area);
   edit_area_layout->addWidget (m_status_bar);
-  edit_area_layout->setMargin (0);
+  edit_area_layout->setContentsMargins (0, 0, 0, 0);
   edit_area_layout->setSpacing (0);
   setLayout (edit_area_layout);
 
@@ -266,19 +266,18 @@
   connect (this, &file_editor_tab::do_save_file_signal,
            this, &file_editor_tab::do_save_file);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (settings)
-    notice_settings (settings, true);
+  notice_settings (true);
+
+  gui_settings settings;
 
   // encoding, not updated with the settings
-  m_encoding = settings->value (ed_default_enc.key, "UTF-8").toString ();
+  m_encoding = settings.value (ed_default_enc.settings_key (), "UTF-8").toString ();
   m_enc_indicator->setText (m_encoding);
   // no changes in encoding yet
   m_new_encoding = m_encoding;
 }
 
-file_editor_tab::~file_editor_tab (void)
+file_editor_tab::~file_editor_tab ()
 {
   // Tell all connected markers to self-destruct.
   emit remove_all_breakpoints_signal ();
@@ -330,38 +329,42 @@
 
 void file_editor_tab::handle_context_menu_edit (const QString& word_at_cursor)
 {
-  // Search for a subfunction in actual file (this is done first because
-  // Octave finds this function before others with the same name in the
-  // search path.
-  QRegExp rxfun1 ("^[\t ]*function[^=]+=[\t ]*"
-                  + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$");
-  QRegExp rxfun2 ("^[\t ]*function[\t ]+"
-                  + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$");
-  QRegExp rxfun3 ("^[\t ]*function[\t ]+"
-                  + word_at_cursor + "[\t ]*$");
-  QRegExp rxfun4 ("^[\t ]*function[^=]+=[\t ]*"
-                  + word_at_cursor + "[\t ]*$");
-
-  int pos_fct = -1;
+  // Search for a function with that name in the current file
+  // This is done first because local functions and subfunctions have priority
+  // over other functions with the same name in the load path.
+  QRegularExpression rxfun1 {"^[\t ]*function[^=]+=[\t ]*"
+                             + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"};
+  QRegularExpression rxfun2 {"^[\t ]*function[\t ]+"
+                             + word_at_cursor + "[\t ]*\\([^\\)]*\\)[\t ]*$"};
+  QRegularExpression rxfun3 {"^[\t ]*function[\t ]+"
+                             + word_at_cursor + "[\t ]*$"};
+  QRegularExpression rxfun4 {"^[\t ]*function[^=]+=[\t ]*"
+                             + word_at_cursor + "[\t ]*$"};
+
+  QRegularExpressionMatch match;
   QStringList lines = m_edit_area->text ().split ("\n");
 
   int line;
   for (line = 0; line < lines.count (); line++)
     {
-      if ((pos_fct = rxfun1.indexIn (lines.at (line))) != -1)
+      match = rxfun1.match (lines.at (line));
+      if (match.hasMatch ())
         break;
-      if ((pos_fct = rxfun2.indexIn (lines.at (line))) != -1)
+      match = rxfun2.match (lines.at (line));
+      if (match.hasMatch ())
         break;
-      if ((pos_fct = rxfun3.indexIn (lines.at (line))) != -1)
+      match = rxfun3.match (lines.at (line));
+      if (match.hasMatch ())
         break;
-      if ((pos_fct = rxfun4.indexIn (lines.at (line))) != -1)
+      match = rxfun4.match (lines.at (line));
+      if (match.hasMatch ())
         break;
     }
 
-  if (pos_fct > -1)
+  if (match.hasMatch ())
     {
       // reg expr. found: it is an internal function
-      m_edit_area->setCursorPosition (line, pos_fct);
+      m_edit_area->setCursorPosition (line, match.capturedStart ());
       m_edit_area->SendScintilla (2232, line);     // SCI_ENSUREVISIBLE
       // SCI_VISIBLEFROMDOCLINE
       int vis_line = m_edit_area->SendScintilla (2220, line);
@@ -440,67 +443,67 @@
 
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          // We are intentionally skipping any side effects that may
-          // occur in the evaluation of NEW_COND if THIS_FETAB is no
-          // longer valid.
-
-          if (this_fetab.isNull ())
-            return;
-
-          error_system& es = interp.get_error_system ();
-
-          unwind_protect frame;
-
-          // Prevent an error in the evaluation here from sending us
-          // into the debugger.
-
-          es.interpreter_try (frame);
-
-          bool eval_error = false;
-          std::string msg;
-
-          try
-            {
-              tree_evaluator& tw = interp.get_evaluator ();
-              bp_table& bptab = tw.get_bp_table ();
-
-              bptab.condition_valid (new_cond.toStdString ());
-
-              // The condition seems OK, so set the conditional
-              // breakpoint.
-
-              emit request_add_breakpoint (line, new_cond);
-            }
-          catch (const execution_exception& ee)
-            {
-              interp.recover_from_exception ();
-
-              msg = ee.message ();
-              eval_error = true;
-            }
-          catch (const interrupt_exception&)
-            {
-              interp.recover_from_exception ();
-
-              msg = "evaluation interrupted";
-              eval_error = true;
-            }
-
-          if (eval_error)
-            {
-              // Try again with a prompt that indicates the last
-              // attempt was an error.
-
-              QString new_prompt = (tr ("ERROR: ")
-                                    + QString::fromStdString (msg)
-                                    + "\n\ndbstop if");
-
-              emit dbstop_if (new_prompt, line, "");
-            }
-        });
+         {
+           // INTERPRETER THREAD
+
+           // We are intentionally skipping any side effects that may
+           // occur in the evaluation of NEW_COND if THIS_FETAB is no
+           // longer valid.
+
+           if (this_fetab.isNull ())
+             return;
+
+           error_system& es = interp.get_error_system ();
+
+           unwind_protect frame;
+
+           // Prevent an error in the evaluation here from sending us
+           // into the debugger.
+
+           es.interpreter_try (frame);
+
+           bool eval_error = false;
+           std::string msg;
+
+           try
+             {
+               tree_evaluator& tw = interp.get_evaluator ();
+               bp_table& bptab = tw.get_bp_table ();
+
+               bptab.condition_valid (new_cond.toStdString ());
+
+               // The condition seems OK, so set the conditional
+               // breakpoint.
+
+               emit request_add_breakpoint (line, new_cond);
+             }
+           catch (const execution_exception& ee)
+             {
+               interp.recover_from_exception ();
+
+               msg = ee.message ();
+               eval_error = true;
+             }
+           catch (const interrupt_exception&)
+             {
+               interp.recover_from_exception ();
+
+               msg = "evaluation interrupted";
+               eval_error = true;
+             }
+
+           if (eval_error)
+             {
+               // Try again with a prompt that indicates the last
+               // attempt was an error.
+
+               QString new_prompt = (tr ("ERROR: ")
+                                     + QString::fromStdString (msg)
+                                     + "\n\ndbstop if");
+
+               emit dbstop_if (new_prompt, line, "");
+             }
+         });
     }
 }
 
@@ -562,7 +565,7 @@
 // not match what Octave core is interpreting in the
 // file on disk.  This function gives the user the option
 // to save before creating the breakpoint.
-bool file_editor_tab::unchanged_or_saved (void)
+bool file_editor_tab::unchanged_or_saved ()
 {
   bool retval = true;
   if (m_edit_area->isModified () || ! valid_file_name ())
@@ -611,7 +614,7 @@
     }
 }
 
-void file_editor_tab::update_lexer (void)
+void file_editor_tab::update_lexer ()
 {
   // Create a new lexer
   QsciLexer *lexer = nullptr;
@@ -726,8 +729,7 @@
 {
   QsciLexer *lexer = m_edit_area->lexer ();
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   if (m_lexer_apis)
     {
@@ -756,9 +758,9 @@
 
       // get settings which infos are used for octave
       bool octave_builtins
-        = settings->value (ed_code_completion_octave_builtins).toBool ();
+        = settings.bool_value (ed_code_completion_octave_builtins);
       bool octave_functions
-        = settings->value (ed_code_completion_octave_functions).toBool ();
+        = settings.bool_value (ed_code_completion_octave_functions);
 
       QCoreApplication::setApplicationName (tmp_app_name);  // Restore name
 
@@ -832,59 +834,59 @@
             {
               // The interpreter_event callback function below emits a
               // signal.  Because we don't control when that happens,
-              // use a guarded pointer so that the callback can abort if
-              // this object is no longer valid.
+              // use a guarded pointer so that the callback can abort
+              // if this object is no longer valid.
 
               QPointer<file_editor_tab> this_fetab (this);
 
               emit interpreter_event
                 ([=] (interpreter& interp)
-                {
-                  // INTERPRETER THREAD
-
-                  // We can skip the entire callback function because it
-                  // does not make any changes to the interpreter
-                  // state.
-
-                  if (this_fetab.isNull ())
-                    return;
-
-                  QStringList api_entries;
-
-                  octave_value_list tmp = Fiskeyword ();
-                  const Cell ctmp = tmp(0).cell_value ();
-                  for (octave_idx_type i = 0; i < ctmp.numel (); i++)
-                    {
-                      std::string kw = ctmp(i).string_value ();
-                      api_entries.append (QString::fromStdString (kw));
-                    }
-
-                  if (octave_builtins)
-                    {
-                      symbol_table& symtab = interp.get_symbol_table ();
-
-                      string_vector bfl = symtab.built_in_function_names ();
-
-                      for (octave_idx_type i = 0; i < bfl.numel (); i++)
-                        api_entries.append (QString::fromStdString (bfl[i]));
-                    }
-
-                  if (octave_functions)
-                    {
-                      load_path& lp = interp.get_load_path ();
-
-                      string_vector ffl = lp.fcn_names ();
-                      string_vector afl = interp.autoloaded_functions ();
-
-                      for (octave_idx_type i = 0; i < ffl.numel (); i++)
-                        api_entries.append (QString::fromStdString (ffl[i]));
-
-                      for (octave_idx_type i = 0; i < afl.numel (); i++)
-                        api_entries.append (QString::fromStdString (afl[i]));
-                    }
-
-                  emit request_add_octave_apis (api_entries);
-                });
+                 {
+                   // INTERPRETER THREAD
+
+                   // We can skip the entire callback function because
+                   // it does not make any changes to the interpreter
+                   // state.
+
+                   if (this_fetab.isNull ())
+                     return;
+
+                   QStringList api_entries;
+
+                   octave_value_list tmp = Fiskeyword ();
+                   const Cell ctmp = tmp(0).cell_value ();
+                   for (octave_idx_type i = 0; i < ctmp.numel (); i++)
+                     {
+                       std::string kw = ctmp(i).string_value ();
+                       api_entries.append (QString::fromStdString (kw));
+                     }
+
+                   if (octave_builtins)
+                     {
+                       symbol_table& symtab = interp.get_symbol_table ();
+
+                       string_vector bfl = symtab.built_in_function_names ();
+
+                       for (octave_idx_type i = 0; i < bfl.numel (); i++)
+                         api_entries.append (QString::fromStdString (bfl[i]));
+                     }
+
+                   if (octave_functions)
+                     {
+                       load_path& lp = interp.get_load_path ();
+
+                       string_vector ffl = lp.fcn_names ();
+                       string_vector afl = interp.autoloaded_functions ();
+
+                       for (octave_idx_type i = 0; i < ffl.numel (); i++)
+                         api_entries.append (QString::fromStdString (ffl[i]));
+
+                       for (octave_idx_type i = 0; i < afl.numel (); i++)
+                         api_entries.append (QString::fromStdString (afl[i]));
+                     }
+
+                   emit request_add_octave_apis (api_entries);
+                 });
             }
           else
             {
@@ -895,7 +897,7 @@
                   QString keyword = QString (lexer->keywords (i));
 
                   QStringList keyword_list
-                    = keyword.split (QRegExp (R"(\s+)"));
+                    = keyword.split (QRegularExpression {R"(\s+)"});
 
                   for (int j = 0; j < keyword_list.size (); j++)
                     m_lexer_apis->add (keyword_list.at (j));
@@ -909,8 +911,8 @@
   if (update_apis_only)
     return;   // We are done here
 
-  int mode = settings->value (ed_color_mode).toInt ();
-  rmgr.read_lexer_settings (lexer, settings, mode);
+  int mode = settings.int_value (ed_color_mode);
+  settings.read_lexer_settings (lexer, mode);
 
   m_edit_area->setCaretForegroundColor (lexer->color (0));
   m_edit_area->setIndentationGuidesForegroundColor (lexer->color (0));
@@ -934,11 +936,11 @@
   m_edit_area->setFoldMarginColors (bgm, fgm);
 
   QColor current_line_bg
-    = settings->color_value (ed_highlight_current_line_color, mode);
+    = settings.color_value (ed_highlight_current_line_color, mode);
   if (current_line_bg == settings_color_no_change)
-    bgm = interpolate_color (bg, fg, 0.5, 0.1);  // It is the "auto" color
-  else
-    bgm = current_line_bg;  // Specific color given
+     bgm = interpolate_color (bg, fg, 0.5, 0.1);  // It is the "auto" color
+   else
+     bgm = current_line_bg;  // Specific color given
 
   m_edit_area->setCaretLineBackgroundColor (bgm);
 
@@ -949,7 +951,7 @@
 
   // fix line number width with respect to the font size of the lexer and
   // set the line numbers font depending on the lexer's font
-  if (settings->value (ed_show_line_numbers).toBool ())
+  if (settings.bool_value (ed_show_line_numbers))
     {
       // Line numbers width
       auto_margin_width ();
@@ -958,7 +960,7 @@
       QFont line_numbers_font = lexer->defaultFont ();
       int font_size = line_numbers_font.pointSize ();
       font_size = font_size
-        + settings->value (ed_line_numbers_size).toInt ();
+                  + settings.int_value (ed_line_numbers_size);
       if (font_size < 4)
         font_size = 4;
       line_numbers_font.setPointSize (font_size);
@@ -978,7 +980,7 @@
   emit api_entries_added ();
 }
 
-void file_editor_tab::handle_api_entries_added (void)
+void file_editor_tab::handle_api_entries_added ()
 {
   // disconnect slot for saving prepared info if already connected
   disconnect (m_lexer_apis, &QsciAPIs::apiPreparationFinished,
@@ -995,7 +997,7 @@
   m_lexer_apis->prepare ();  // prepare apis info
 }
 
-void file_editor_tab::save_apis_info (void)
+void file_editor_tab::save_apis_info ()
 {
   m_lexer_apis->savePrepared (m_prep_apis_file);
 }
@@ -1161,7 +1163,7 @@
   // Wrap.  Should use the last line of the file, not 1<<15
   if (prevline == -1)
     prevline = m_edit_area->markerFindPrevious (m_edit_area->lines (),
-                                                (1 << marker::bookmark));
+                                               (1 << marker::bookmark));
 
   m_edit_area->setCursorPosition (prevline, 0);
 }
@@ -1208,14 +1210,14 @@
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      tree_evaluator& tw = interp.get_evaluator ();
-      bp_table& bptab = tw.get_bp_table ();
-
-      bptab.remove_breakpoint_from_file (m_file_name.toStdString (), line);
-    });
+     {
+       // INTERPRETER THREAD
+
+       tree_evaluator& tw = interp.get_evaluator ();
+       bp_table& bptab = tw.get_bp_table ();
+
+       bptab.remove_breakpoint_from_file (m_file_name.toStdString (), line);
+     });
 }
 
 void file_editor_tab::toggle_breakpoint (const QWidget *ID)
@@ -1286,15 +1288,15 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      tree_evaluator& tw = interp.get_evaluator ();
-      bp_table& bptab = tw.get_bp_table ();
-
-      bptab.remove_all_breakpoints_from_file (m_file_name.toStdString (),
-                                              true);
-    });
+     {
+       // INTERPRETER THREAD
+
+       tree_evaluator& tw = interp.get_evaluator ();
+       bp_table& bptab = tw.get_bp_table ();
+
+       bptab.remove_all_breakpoints_from_file (m_file_name.toStdString (),
+                                               true);
+     });
 }
 
 void file_editor_tab::scintilla_command (const QWidget *ID,
@@ -1395,27 +1397,28 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      // If THIS_FETAB is no longer valid, we still want to set the
-      // breakpoint in the interpreter but we can't emit the signal
-      // associated with THIS_FETAB.
-
-      // FIXME: note duplication with the code in
-      // handle_context_menu_break_condition.
-
-      tree_evaluator& tw = interp.get_evaluator ();
-      bp_table& bptab = tw.get_bp_table ();
-
-      int lineno = bptab.add_breakpoint_in_file (m_file_name.toStdString (),
-                                                 line, cond.toStdString ());
-      if (this_fetab.isNull ())
-        return;
-
-      if (lineno)
-        emit maybe_remove_next (lineno);
-    });
+     {
+       // INTERPRETER THREAD
+
+       // If THIS_FETAB is no longer valid, we still want to set the
+       // breakpoint in the interpreter but we can't emit the signal
+       // associated with THIS_FETAB.
+
+       // FIXME: note duplication with the code in
+       // handle_context_menu_break_condition.
+
+       tree_evaluator& tw = interp.get_evaluator ();
+       bp_table& bptab = tw.get_bp_table ();
+
+       int lineno = bptab.add_breakpoint_in_file (m_file_name.toStdString (),
+                                                  line, cond.toStdString ());
+
+       if (this_fetab.isNull ())
+         return;
+
+       if (lineno)
+         emit maybe_remove_next (lineno);
+     });
 }
 
 void file_editor_tab::handle_remove_next (int remove_line)
@@ -1533,7 +1536,7 @@
   m_edit_area->endUndoAction ();
 }
 
-void file_editor_tab::do_smart_indent_line_or_selected_text (void)
+void file_editor_tab::do_smart_indent_line_or_selected_text ()
 {
   m_edit_area->beginUndoAction ();
 
@@ -1562,7 +1565,7 @@
 
 void file_editor_tab::do_comment_selected_text (bool comment, bool input_str)
 {
-  QRegExp rxc;
+  QRegularExpression rxc;
   QString ws = "^(?:[ \\t]*)";
   QStringList comment_str = m_edit_area->comment_string (comment);
   QString used_comment_str = comment_str.at (0);
@@ -1572,20 +1575,19 @@
       if (input_str)
         {
           bool ok;
-          resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-          gui_settings *settings = rmgr.get_settings ();
+          gui_settings settings;
 
           used_comment_str
             = QInputDialog::getText (this, tr ("Comment selected text"),
                                      tr ("Comment string to use:\n"),
                                      QLineEdit::Normal,
-                                     settings->value (ed_last_comment_str, comment_str.at (0)).toString (),
+                                     settings.value (ed_last_comment_str, comment_str.at (0)).toString (),
                                      &ok);
 
           if ((! ok) || used_comment_str.isEmpty ())
             return;  // No input, do nothing
           else
-            settings->setValue (ed_last_comment_str, used_comment_str);  // Store last
+            settings.setValue (ed_last_comment_str, used_comment_str);  // Store last
         }
     }
   else
@@ -1620,7 +1622,7 @@
             regexp = regexp + QString ("|");
           regexp = regexp + comment_str_sorted.at (i);
         }
-      rxc = QRegExp (ws + "(" + regexp + ")");
+      rxc = QRegularExpression {ws + "(" + regexp + ")"};
     }
 
   // Do the commenting/uncommenting
@@ -1632,7 +1634,7 @@
       int lineFrom, lineTo, colFrom, colTo;
       int change_col_from = 1;
       int change_col_to = 1;
-      bool removed;
+      bool removed = false;
 
       m_edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);
 
@@ -1648,11 +1650,13 @@
           else
             {
               QString line (m_edit_area->text (i));
-              if ((removed = line.contains (rxc)))
+              QRegularExpressionMatch match = rxc.match (line);
+
+              if (match.hasMatch ())
                 {
-                  len = rxc.matchedLength ();   // complete length
-                  QString matched_text = rxc.capturedTexts ().at (0);
-                  lenc = matched_text.remove (QRegExp (ws)).length ();  // only comment string
+                  len = match.capturedLength ();   // complete length
+                  QString matched_text = match.captured (0);
+                  lenc = matched_text.remove (QRegularExpression {ws}).length ();  // only comment string
                   m_edit_area->setSelection (i, len-lenc, i, len);
                   m_edit_area->removeSelectedText ();
                 }
@@ -1694,11 +1698,12 @@
       else
         {
           QString line (m_edit_area->text (cpline));
-          if (line.contains (rxc))
+          QRegularExpressionMatch match = rxc.match (line);
+          if (match.hasMatch ())
             {
-              len = rxc.matchedLength ();   // complete length
-              QString matched_text = rxc.capturedTexts ().at (0);
-              lenc = matched_text.remove (QRegExp (ws)).length ();  // only comment string
+              len = match.capturedLength ();  // complete length
+              QString matched_text = match.captured (0);
+              lenc = matched_text.remove (QRegularExpression {ws}).length ();  // only comment string
               m_edit_area->setSelection (cpline, len-lenc, cpline, len);
               m_edit_area->removeSelectedText ();
             }
@@ -1753,8 +1758,8 @@
       // editor tab can't be made parent because it may be deleted depending
       // upon the response.  Instead, change the m_edit_area to read only.
       QMessageBox::StandardButtons buttons = QMessageBox::Save |
-        QMessageBox::Discard |
-        QMessageBox::Cancel;
+                                             QMessageBox::Discard |
+                                             QMessageBox::Cancel;
 
       // For now, just a warning message about closing a tab that has been
       // modified seems sufficient.  Exit-condition-specific messages could
@@ -1802,7 +1807,7 @@
   m_edit_area->setModified (modified);
 }
 
-void file_editor_tab::recover_from_exit (void)
+void file_editor_tab::recover_from_exit ()
 {
   // reset the possibly still existing read only state
   m_edit_area->setReadOnly (false);
@@ -1814,7 +1819,7 @@
   check_restore_breakpoints ();
 }
 
-void file_editor_tab::check_restore_breakpoints (void)
+void file_editor_tab::check_restore_breakpoints ()
 {
   if (! m_bp_lines.isEmpty ())
     {
@@ -1856,15 +1861,17 @@
     }
 
   QApplication::setOverrideCursor (Qt::WaitCursor);
+  unwind_action reset_cursor ([] ()
+                              { QApplication::restoreOverrideCursor (); });
 
   // read the file binary, decoding later
   QByteArray text_data = file.readAll ();
 
   // remove newline at end of file if we add one again when saving
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings->value (ed_force_newline).toBool ())
+
+  gui_settings settings;
+
+  if (settings.bool_value (ed_force_newline))
     {
       const QByteArray eol_lf = QByteArray (1, 0x0a);
       const QByteArray eol_cr = QByteArray (1, 0x0d);
@@ -1876,51 +1883,91 @@
         text_data.chop (1);
     }
 
-  // decode
-  QTextCodec::ConverterState st;
-  QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ());
-  if (codec == nullptr)
-    codec = QTextCodec::codecForLocale ();
-
-  const QString text = codec->toUnicode(text_data.constData(),
-                                        text_data.size(), &st);
-
-  // Decoding with invalid characters?
-  if (st.invalidChars > 0)
+  // expected file encoding
+  std::string encoding = m_encoding.toStdString ();
+  if (encoding.compare (0, 6, "SYSTEM") == 0)
+    encoding = octave_locale_charset_wrapper ();
+
+  std::size_t srclen = text_data.length ();
+
+  if (srclen == 0)
+    m_edit_area->setText (QString ());
+  else
     {
-      // Set read only
-      m_edit_area->setReadOnly (true);
-
-      // Message box for user decision
-      QString msg = tr ("There were problems reading the file\n"
-                        "%1\n"
-                        "with the selected encoding %2.\n\n"
-                        "Modifying and saving the file might "
-                        "cause data loss!")
-        .arg (file_to_load).arg (m_encoding);
-      QMessageBox *msg_box = new QMessageBox ();
-      msg_box->setIcon (QMessageBox::Warning);
-      msg_box->setText (msg);
-      msg_box->setWindowTitle (tr ("Octave Editor"));
-      msg_box->addButton (tr ("&Edit anyway"), QMessageBox::YesRole);
-      msg_box->addButton (tr ("Chan&ge encoding"), QMessageBox::AcceptRole);
-      msg_box->addButton (tr ("&Close"), QMessageBox::RejectRole);
-
-      connect (msg_box, &QMessageBox::buttonClicked,
-               this, &file_editor_tab::handle_decode_warning_answer);
-
-      msg_box->setWindowModality (Qt::WindowModal);
-      msg_box->setAttribute (Qt::WA_DeleteOnClose);
-      msg_box->show ();
+      // check if the selected encoding can be used to decode the file
+
+      const char *src = text_data.constData ();
+
+      std::size_t length;
+      uint16_t *u16_str;
+
+      // try to convert encoding in strict mode
+      u16_str = octave_u16_conv_from_encoding_strict (encoding.c_str (),
+                                                      src, srclen, &length);
+
+      // check for invalid characters in input file
+      if (! u16_str)
+        {
+          // Set read only
+          m_edit_area->setReadOnly (true);
+
+          // convert encoding allowing replacements
+          u16_str = octave_u16_conv_from_encoding (encoding.c_str (),
+                                                   src, srclen, &length);
+
+          if (! u16_str)
+            {
+              // FIXME: Can this ever happen?
+
+              // non-modal error message box
+              QMessageBox *msgBox
+                = new QMessageBox (QMessageBox::Critical,
+                                   tr ("Octave Editor"),
+                                   tr ("Unable to read file '%1'\n"
+                                       "with selected encoding '%2': %3")
+                                      .arg (file_to_load).arg (m_encoding)
+                                      .arg (std::strerror (errno)),
+                                   QMessageBox::Ok, nullptr);
+              show_dialog (msgBox, false);
+              return QString ();
+            }
+
+          // Message box for user decision
+          QString msg = tr ("There were problems reading the file\n"
+                            "%1\n"
+                            "with the selected encoding %2.\n\n"
+                            "Modifying and saving the file might "
+                            "cause data loss!")
+                            .arg (file_to_load).arg (m_encoding);
+          QMessageBox *msg_box = new QMessageBox ();
+          msg_box->setIcon (QMessageBox::Warning);
+          msg_box->setText (msg);
+          msg_box->setWindowTitle (tr ("Octave Editor"));
+          msg_box->addButton (tr ("&Edit anyway"), QMessageBox::YesRole);
+          msg_box->addButton (tr ("Chan&ge encoding"),
+                              QMessageBox::AcceptRole);
+          msg_box->addButton (tr ("&Close"), QMessageBox::RejectRole);
+
+          connect (msg_box, &QMessageBox::buttonClicked,
+                   this, &file_editor_tab::handle_decode_warning_answer);
+
+          msg_box->setWindowModality (Qt::WindowModal);
+          msg_box->setAttribute (Qt::WA_DeleteOnClose);
+          msg_box->show ();
+        }
+
+      unwind_action free_u16_str ([=] () { ::free (u16_str); });
+
+      QString text
+        = QString::fromUtf16 (reinterpret_cast<char16_t *> (u16_str), length);
+
+      m_edit_area->setText (text);
     }
 
-  m_edit_area->setText (text);
   m_edit_area->setEolMode (detect_eol_mode ());
 
-  QApplication::restoreOverrideCursor ();
-
-  m_copy_available = false;     // no selection yet available
-  m_edit_area->setModified (false); // loaded file is not modified yet
+  m_copy_available = false;  // no selection yet available
+  m_edit_area->setModified (false);  // loaded file is not modified yet
   set_file_name (file_to_load);
 
   update_eol_indicator ();
@@ -1953,8 +2000,8 @@
                           "This does not change the default encoding.\n"));
 
       QComboBox *enc_combo = new QComboBox ();
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      rmgr.combo_encoding (enc_combo);
+      gui_settings settings;
+      settings.combo_encoding (enc_combo);
       m_new_encoding = enc_combo->currentText ();
       connect (enc_combo, &QComboBox::currentTextChanged,
                this, &file_editor_tab::handle_current_enc_changed);
@@ -1992,7 +2039,7 @@
   m_new_encoding = enc;
 }
 
-QsciScintilla::EolMode file_editor_tab::detect_eol_mode (void)
+QsciScintilla::EolMode file_editor_tab::detect_eol_mode ()
 {
   QByteArray text = m_edit_area->text ().toLatin1 ();
 
@@ -2005,10 +2052,10 @@
   int count_lf = text.count (eol_lf) - count_crlf;  // isolated lf
   int count_cr = text.count (eol_cr) - count_crlf;  // isolated cr
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
+
   QsciScintilla::EolMode eol_mode
-    = static_cast<QsciScintilla::EolMode> (settings->value (ed_default_eol_mode).toInt ());
+    = static_cast<QsciScintilla::EolMode> (settings.int_value (ed_default_eol_mode));
 
   int count_max = 0;
 
@@ -2030,7 +2077,7 @@
   return eol_mode;
 }
 
-void file_editor_tab::update_eol_indicator (void)
+void file_editor_tab::update_eol_indicator ()
 {
   switch (m_edit_area->eolMode ())
     {
@@ -2061,23 +2108,23 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      // We can skip the entire callback function because it does not
-      // make any changes to the interpreter state.
-
-      if (this_fetab.isNull ())
-        return;
-
-      octave_value_list argout = Fdbstatus (interp, ovl (), 1);
-
-      connect (this, &file_editor_tab::update_breakpoints_signal,
-               this, &file_editor_tab::update_breakpoints_handler,
-               Qt::QueuedConnection);
-
-      emit update_breakpoints_signal (argout);
-    });
+     {
+       // INTERPRETER THREAD
+
+       // We can skip the entire callback function because it does not
+       // make any changes to the interpreter state.
+
+       if (this_fetab.isNull ())
+         return;
+
+       octave_value_list argout = Fdbstatus (interp, ovl (), 1);
+
+       connect (this, &file_editor_tab::update_breakpoints_signal,
+                this, &file_editor_tab::update_breakpoints_handler,
+                Qt::QueuedConnection);
+
+       emit update_breakpoints_signal (argout);
+     });
 }
 
 void file_editor_tab::update_breakpoints_handler (const octave_value_list& argout)
@@ -2101,12 +2148,11 @@
 {
   update_window_title (false); // window title (no modification)
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   // set the eol mode from the settings or depending on the OS if the entry is
   // missing in the settings
-  m_edit_area->setEolMode (static_cast<QsciScintilla::EolMode> (settings->value (ed_default_eol_mode).toInt ()));
+  m_edit_area->setEolMode (static_cast<QsciScintilla::EolMode> (settings.int_value (ed_default_eol_mode)));
 
   update_eol_indicator ();
 
@@ -2137,31 +2183,31 @@
 
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          // If THIS_FETAB is no longer valid, we still want to perform
-          // the actions in the interpreter but we can't emit the signal
-          // associated with THIS_FETAB.
-
-          tree_evaluator& tw = interp.get_evaluator ();
-
-          tw.dbquit (true);
-
-          command_editor::interrupt (true);
-
-          std::string std_base_name = base_name.toStdString ();
-
-          symbol_table& symtab = interp.get_symbol_table ();
-
-          symtab.clear_user_function (std_base_name);
-
-          if (this_fetab.isNull ())
-            return;
-
-          emit do_save_file_signal (file_to_save, remove_on_success,
-                                    restore_breakpoints);
-        });
+         {
+           // INTERPRETER THREAD
+
+           // If THIS_FETAB is no longer valid, we still want to
+           // perform the actions in the interpreter but we can't emit
+           // the signal associated with THIS_FETAB.
+
+           tree_evaluator& tw = interp.get_evaluator ();
+
+           tw.dbquit (true);
+
+           command_editor::interrupt (true);
+
+           std::string std_base_name = base_name.toStdString ();
+
+           symbol_table& symtab = interp.get_symbol_table ();
+
+           symtab.clear_user_function (std_base_name);
+
+           if (this_fetab.isNull ())
+             return;
+
+           emit do_save_file_signal (file_to_save, remove_on_success,
+                                     restore_breakpoints);
+         });
     }
 }
 
@@ -2179,9 +2225,8 @@
 
   m_encoding = m_new_encoding;    // consider a possible new encoding
 
-  // set the desired codec (if suitable for contents)
-  QTextCodec *codec = check_valid_codec ();
-  if (! codec)
+  // check if the selected encoding is suitable for the content
+  if (! check_valid_codec ())
     return;   // No valid codec
 
   // Get a list of breakpoint line numbers, before exiting debug mode
@@ -2206,90 +2251,90 @@
 
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          // We are intentionally skipping any side effects that may
-          // occur in the callback function if THIS_FETAB is no longer
-          // valid.  If the editor tab has disappeared, there is not
-          // much point in reloading the function to restore breakpoint
-          // info in the GUI.
-
-          if (this_fetab.isNull ())
-            return;
-
-          // Force reloading of a file after it is saved.
-          // This is needed to get the right line numbers for
-          // breakpoints (bug #46632).
-
-          tree_evaluator& tw = interp.get_evaluator ();
-
-          symbol_table& symtab = interp.get_symbol_table ();
-
-          std::string std_base_name = base_name.toStdString ();
-
-          if (tw.in_debug_repl ())
-            {
-              octave_value sym;
-              try
-                {
-                  sym = symtab.find_user_function (std_base_name);
-                }
-              catch (const execution_exception&)
-                {
-                  interp.recover_from_exception ();
-
-                  // Ignore syntax error.  It was in the old file on disk;
-                  // the user may have fixed it already.
-                }
-
-              // Return early if this file is not loaded in the symbol table
-              if (! sym.is_defined () || ! sym.is_user_code ())
-                {
-                  emit do_save_file_signal (file_to_save, remove_on_success,
-                                            restore_breakpoints);
-                  return;
-                }
-
-              octave_user_code *fcn = sym.user_code_value ();
-
-              std::string full_name = file_to_save.toStdString ();
-
-              if (sys::canonicalize_file_name (full_name)
-                  != sys::canonicalize_file_name (fcn->fcn_file_name ()))
-                {
-                  emit do_save_file_signal (file_to_save, remove_on_success,
-                                            restore_breakpoints);
-                  return;
-                }
-
-              // If this file is loaded, check that we aren't currently
-              // running it.
-              // FIXME: is there a better way to get this info?
-
-              octave_idx_type curr_frame = -1;
-
-              octave_map stk = tw.backtrace (curr_frame, false);
-
-              Cell names = stk.contents ("name");
-
-              for (octave_idx_type i = names.numel () - 1; i >= 0; i--)
-                {
-                  if (names(i).string_value () == std_base_name)
-                    {
-                      emit confirm_dbquit_and_save_signal
-                        (file_to_save, base_name, remove_on_success,
-                         restore_breakpoints);
-                      return;
-                    }
-                }
-            }
-
-          symtab.clear_user_function (std_base_name);
-
-          emit do_save_file_signal (file_to_save, remove_on_success,
-                                    restore_breakpoints);
-        });
+         {
+           // INTERPRETER THREAD
+
+           // We are intentionally skipping any side effects that may
+           // occur in the callback function if THIS_FETAB is no
+           // longer valid.  If the editor tab has disappeared, there
+           // is not much point in reloading the function to restore
+           // breakpoint info in the GUI.
+
+           if (this_fetab.isNull ())
+             return;
+
+           // Force reloading of a file after it is saved.
+           // This is needed to get the right line numbers for
+           // breakpoints (bug #46632).
+
+           tree_evaluator& tw = interp.get_evaluator ();
+
+           symbol_table& symtab = interp.get_symbol_table ();
+
+           std::string std_base_name = base_name.toStdString ();
+
+           if (tw.in_debug_repl ())
+             {
+               octave_value sym;
+               try
+                 {
+                   sym = symtab.find_user_function (std_base_name);
+                 }
+               catch (const execution_exception&)
+                 {
+                   interp.recover_from_exception ();
+
+                   // Ignore syntax error.  It was in the old file on disk;
+                   // the user may have fixed it already.
+                 }
+
+               // Return early if this file is not loaded in the symbol table
+               if (! sym.is_defined () || ! sym.is_user_code ())
+                 {
+                   emit do_save_file_signal (file_to_save, remove_on_success,
+                                             restore_breakpoints);
+                   return;
+                 }
+
+               octave_user_code *fcn = sym.user_code_value ();
+
+               std::string full_name = file_to_save.toStdString ();
+
+               if (sys::canonicalize_file_name (full_name)
+                   != sys::canonicalize_file_name (fcn->fcn_file_name ()))
+                 {
+                   emit do_save_file_signal (file_to_save, remove_on_success,
+                                             restore_breakpoints);
+                   return;
+                 }
+
+               // If this file is loaded, check that we aren't currently
+               // running it.
+               // FIXME: is there a better way to get this info?
+
+               octave_idx_type curr_frame = -1;
+
+               octave_map stk = tw.backtrace (curr_frame, false);
+
+               Cell names = stk.contents ("name");
+
+               for (octave_idx_type i = names.numel () - 1; i >= 0; i--)
+                 {
+                   if (names(i).string_value () == std_base_name)
+                     {
+                       emit confirm_dbquit_and_save_signal
+                         (file_to_save, base_name, remove_on_success,
+                          restore_breakpoints);
+                       return;
+                     }
+                 }
+             }
+
+           symtab.clear_user_function (std_base_name);
+
+           emit do_save_file_signal (file_to_save, remove_on_success,
+                                     restore_breakpoints);
+         });
     }
   else
     emit do_save_file_signal (saveFileName, remove_on_success,
@@ -2308,10 +2353,10 @@
     m_file_system_watcher.removePath (file_to_save);
 
   // Remove trailing white spaces if desired
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings->value (ed_rm_trailing_spaces).toBool ())
+
+  gui_settings settings;
+
+  if (settings.bool_value (ed_rm_trailing_spaces))
     {
       // Replace trailing spaces, make sure edit area is writable,
       // which is not the case when saving at exit or when closing
@@ -2343,27 +2388,72 @@
       return;
     }
 
-  // save the contents into the file
-
-  // write the file
-  QTextStream out (&file);
-
-  // set the desired codec (if suitable for contents)
-  QTextCodec *codec = check_valid_codec ();
-  if (! codec)
-    return;   // No valid codec
-
-  // Save the file
-  out.setCodec (codec);
+  // target encoding
+  std::string encoding = m_encoding.toStdString ();
+  if (encoding.compare (0, 6, "SYSTEM") == 0)
+    encoding = octave_locale_charset_wrapper ();
+
+  // check if selected encoding is suitable for contents
+  if (! check_valid_codec ())
+    {
+      // begin watching file again if it was being watched previously
+      if (trackedFiles.contains (file_to_save))
+        m_file_system_watcher.addPath (file_to_save);
+
+      return;  // no valid codec
+    }
+
+  // save contents of editor in file
 
   QApplication::setOverrideCursor (Qt::WaitCursor);
 
-  out << m_edit_area->text ();
-  if (settings->value (ed_force_newline).toBool ()
-      && m_edit_area->text ().length ())
-    out << m_edit_area->eol_string ();   // Add newline if desired
-
-  out.flush ();
+  if (encoding == "utf-8" || encoding == "UTF-8")
+    {
+      // use Qt encoding conversion for UTF-8
+      QTextStream out (&file);
+
+#if HAVE_QTEXTSTREAM_SETENCODING
+      out.setEncoding (QStringConverter::Utf8);
+#else
+      out.setCodec ("UTF-8");
+#endif
+
+      out << m_edit_area->text ();
+
+      // add newline if desired
+      if (settings.bool_value (ed_force_newline)
+          && m_edit_area->text ().length ())
+        out << m_edit_area->eol_string ();
+
+      out.flush ();
+    }
+  else
+    {
+      // use iconv/gnulib for all other output encodings
+      QDataStream out (&file);
+
+      // get natively UTF-16 encoded content of the QString as STL type
+      std::u16string u16_string = m_edit_area->text ().toStdU16String ();
+
+      // convert to output encoding
+      std::string native_string
+        = string::u16_to_encoding ("file editor", u16_string, encoding);
+
+      // save file
+      out.writeRawData (native_string.c_str (), native_string.size ());
+
+      // add newline if desired
+      if (settings.bool_value (ed_force_newline)
+          && m_edit_area->text ().length ())
+        {
+          std::u16string u16_newline
+            = m_edit_area->eol_string ().toStdU16String ();
+          std::string newline
+            = string::u16_to_encoding ("file editor", u16_newline, encoding);
+          out.writeRawData (newline.c_str (), newline.size ());
+        }
+    }
+
   QApplication::restoreOverrideCursor ();
 
   // Finish writing by committing the changes to disk,
@@ -2403,8 +2493,8 @@
                              tr ("Octave Editor"),
                              tr ("The changes could not be saved to the file\n"
                                  "%1")
-                             .arg (file.fileName ())
-                             );
+                                 .arg (file.fileName ())
+                            );
     }
 }
 
@@ -2464,9 +2554,10 @@
   fileDialog->setOption (QFileDialog::HideNameFilterDetails, false);
 
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     {
       // Qt file dialogs
       fileDialog->setOption(QFileDialog::DontUseNativeDialog);
@@ -2509,13 +2600,14 @@
 
   QFileDialog *file_dialog = qobject_cast<QFileDialog *> (sender ());
 
-  QRegExp rx ("\\*\\.([^ ^\\)]*)[ \\)]");   // regexp for suffix in filter
-  int index = rx.indexIn (filter, 0);       // get first suffix in filter
-
-  if (index > -1)
-    file_dialog->setDefaultSuffix (rx.cap (1)); // found a suffix, set default
+  // regexp for suffix in filter
+  QRegularExpression rx {"\\*\\.([^ ^\\)]*)[ \\)]"};
+  QRegularExpressionMatch match = rx.match (filter);
+
+  if (match.hasMatch ())
+    file_dialog->setDefaultSuffix (match.captured (1)); // found a suffix, set default
   else
-    file_dialog->setDefaultSuffix ("");         // not found, clear default
+    file_dialog->setDefaultSuffix ("");  // not found, clear default
 }
 
 bool file_editor_tab::check_valid_identifier (QString file_name)
@@ -2541,50 +2633,45 @@
   return false;
 }
 
-QTextCodec* file_editor_tab::check_valid_codec ()
+bool file_editor_tab::check_valid_codec ()
 {
-  QTextCodec *codec = QTextCodec::codecForName (m_encoding.toLatin1 ());
-
-  // "SYSTEM" is used as alias for the locale encoding.
-  if ((! codec) && m_encoding.startsWith("SYSTEM"))
-    codec = QTextCodec::codecForLocale ();
-
-  if (! codec)
-    {
-      QMessageBox::critical (nullptr,
-                             tr ("Octave Editor"),
-                             tr ("The current encoding %1\n"
-                                 "can not be applied.\n\n"
-                                 "Please select another one!").arg (m_encoding));
-
-      return nullptr;
-    }
-
   QString editor_text = m_edit_area->text ();
-  bool can_encode = codec->canEncode (editor_text);
-
-  // We cannot rely on QTextCodec::canEncode because it uses the
-  // ConverterState of convertFromUnicode which isn't updated by some
-  // implementations.
-  if (can_encode)
+
+  // target encoding
+  std::string encoding = m_encoding.toStdString ();
+  if (encoding.compare (0, 6, "SYSTEM") == 0)
+    encoding = octave_locale_charset_wrapper ();
+
+  if (encoding == "UTF-8" || encoding == "utf-8")
+    return true;
+
+  // check if encoding is valid
+  void *codec = octave_iconv_open_wrapper (encoding.c_str (), "utf-8");
+  if (codec == reinterpret_cast<void *> (-1))
     {
-      QVector<uint> u32_str = editor_text.toUcs4 ();
-      const uint32_t *src = reinterpret_cast<const uint32_t *>
-        (u32_str.data ());
-
-      std::size_t length;
-      const std::string encoding = m_encoding.toStdString ();
-      char *res_str =
-        octave_u32_conv_to_encoding_strict (encoding.c_str (), src,
-                                            u32_str.size (), &length);
-      if (! res_str)
-        {
-          if (errno == EILSEQ)
-            can_encode = false;
-        }
-      else
-        ::free (static_cast<void *> (res_str));
+      if (errno == EINVAL)
+        return false;
     }
+  else
+    octave_iconv_close_wrapper (codec);
+
+  // check if all characters in the editor can be encoded in the target encoding
+  bool can_encode = true;
+  std::u16string u16_str = editor_text.toStdU16String ();
+  const uint16_t *src = reinterpret_cast<const uint16_t *>
+                        (u16_str.c_str ());
+
+  std::size_t length;
+  char *res_str =
+    octave_u16_conv_to_encoding_strict (encoding.c_str (), src,
+                                        u16_str.size (), &length);
+  if (! res_str)
+    {
+      if (errno == EILSEQ)
+        can_encode = false;
+    }
+  else
+    ::free (static_cast<void *> (res_str));
 
   if (! can_encode)
     {
@@ -2599,12 +2686,10 @@
                                  QMessageBox::Cancel);
 
       if (pressed_button == QMessageBox::Ignore)
-        return codec;
-      else
-        return nullptr;
+        can_encode = true;
     }
 
-  return codec;
+  return can_encode;
 }
 
 void file_editor_tab::handle_save_file_as_answer (const QString& save_file_name)
@@ -2628,10 +2713,10 @@
   if (file_dialog->testOption (QFileDialog::DontConfirmOverwrite) && file.exists ())
     {
       int ans = QMessageBox::question (file_dialog,
-                                       tr ("Octave Editor"),
-                                       tr ("%1\n already exists\n"
-                                           "Do you want to overwrite it?").arg (saveFileName),
-                                       QMessageBox::Yes | QMessageBox::No);
+                            tr ("Octave Editor"),
+                            tr ("%1\n already exists\n"
+                                "Do you want to overwrite it?").arg (saveFileName),
+                            QMessageBox::Yes | QMessageBox::No);
       if (ans != QMessageBox::Yes)
         {
           // Try again, if edit area is read only, remove on success
@@ -2666,7 +2751,7 @@
     emit editor_check_conflict_save (saveFileName, true);
 }
 
-void file_editor_tab::handle_save_file_as_answer_cancel (void)
+void file_editor_tab::handle_save_file_as_answer_cancel ()
 {
   // User canceled, allow editing again.
   m_edit_area->setReadOnly (false);
@@ -2767,16 +2852,15 @@
     }
 }
 
-void file_editor_tab::notice_settings (const gui_settings *settings, bool init)
+void file_editor_tab::notice_settings (bool init)
 {
-  if (! settings)
-    return;
+  gui_settings settings;
 
   if (! init)
     update_lexer_settings ();
 
   // code folding
-  if (settings->value (ed_code_folding).toBool ())
+  if (settings.bool_value (ed_code_folding))
     {
       m_edit_area->setMarginType (3, QsciScintilla::SymbolMargin);
       m_edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle, 3);
@@ -2787,20 +2871,18 @@
     }
 
   // status bar
-  if (settings->value (ed_show_edit_status_bar).toBool ())
+  if (settings.bool_value (ed_show_edit_status_bar))
     m_status_bar->show ();
   else
     m_status_bar->hide ();
 
   //highlight current line color
   m_edit_area->setCaretLineVisible
-    (settings->value (ed_highlight_current_line).toBool ());
+    (settings.bool_value (ed_highlight_current_line));
 
   // auto completion
-  bool match_keywords = settings->value
-    (ed_code_completion_keywords).toBool ();
-  bool match_document = settings->value
-    (ed_code_completion_document).toBool ();
+  bool match_keywords = settings.bool_value (ed_code_completion_keywords);
+  bool match_document = settings.bool_value (ed_code_completion_document);
 
   QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone;
   if (match_keywords)
@@ -2813,30 +2895,30 @@
   m_edit_area->setAutoCompletionSource (source);
 
   m_edit_area->setAutoCompletionReplaceWord
-    (settings->value (ed_code_completion_replace).toBool ());
+    (settings.bool_value (ed_code_completion_replace));
   m_edit_area->setAutoCompletionCaseSensitivity
-    (settings->value (ed_code_completion_case).toBool ());
-
-  if (settings->value (ed_code_completion).toBool ())
+    (settings.bool_value (ed_code_completion_case));
+
+  if (settings.bool_value (ed_code_completion))
     m_edit_area->setAutoCompletionThreshold
-      (settings->value (ed_code_completion_threshold).toInt ());
+      (settings.int_value (ed_code_completion_threshold));
   else
     m_edit_area->setAutoCompletionThreshold (-1);
 
-  if (settings->value (ed_show_white_space).toBool ())
-    if (settings->value (ed_show_white_space_indent).toBool ())
+  if (settings.bool_value (ed_show_white_space))
+    if (settings.bool_value (ed_show_white_space_indent))
       m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent);
     else
       m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible);
   else
     m_edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible);
 
-  m_edit_area->setEolVisibility (settings->value (ed_show_eol_chars).toBool ());
+  m_edit_area->setEolVisibility (settings.bool_value (ed_show_eol_chars));
 
   m_save_as_desired_eol = static_cast<QsciScintilla::EolMode>
-    (settings->value (ed_default_eol_mode).toInt ());
-
-  if (settings->value (ed_show_line_numbers).toBool ())
+                            (settings.int_value (ed_default_eol_mode));
+
+  if (settings.bool_value (ed_show_line_numbers))
     {
       m_edit_area->setMarginLineNumbers (2, true);
       auto_margin_width ();
@@ -2849,47 +2931,46 @@
       disconnect (m_edit_area, SIGNAL (linesChanged ()), nullptr, nullptr);
     }
 
-  m_smart_indent = settings->value (ed_auto_indent).toBool ();
+  m_smart_indent = settings.bool_value (ed_auto_indent);
   m_edit_area->setAutoIndent (m_smart_indent);
   m_edit_area->setTabIndents
-    (settings->value (ed_tab_indents_line).toBool ());
+    (settings.bool_value (ed_tab_indents_line));
   m_edit_area->setBackspaceUnindents
-    (settings->value (ed_backspace_unindents_line).toBool ());
+    (settings.bool_value (ed_backspace_unindents_line));
   m_edit_area->setIndentationGuides
-    (settings->value (ed_show_indent_guides).toBool ());
+    (settings.bool_value (ed_show_indent_guides));
   m_edit_area->setIndentationsUseTabs
-    (settings->value (ed_indent_uses_tabs).toBool ());
+    (settings.bool_value (ed_indent_uses_tabs));
   m_edit_area->setIndentationWidth
-    (settings->value (ed_indent_width).toInt ());
+    (settings.int_value (ed_indent_width));
 
   m_edit_area->setTabWidth
-    (settings->value (ed_tab_width).toInt ());
+    (settings.int_value (ed_tab_width));
 
   m_ind_char_width = 1;
   if (m_edit_area->indentationsUseTabs ())
     m_ind_char_width = m_edit_area->tabWidth ();
 
   m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR,
-                              settings->value (ed_show_hscroll_bar).toBool ());
+                              settings.bool_value (ed_show_hscroll_bar));
   m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1);
   m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING,true);
 
   update_window_title (m_edit_area->isModified ());
 
-  m_auto_endif = settings->value (ed_auto_endif).toInt ();
+  m_auto_endif = settings.int_value (ed_auto_endif);
 
   // long line marker
-  int line_length = settings->value (ed_long_line_column).toInt ();
+  int line_length = settings.int_value (ed_long_line_column);
   m_edit_area->setEdgeColumn (line_length);
 
-  if (settings->value (ed_long_line_marker).toBool ())
+  if (settings.bool_value (ed_long_line_marker))
     {
-      if (settings->value (ed_long_line_marker_line).toBool ())
+      if (settings.bool_value (ed_long_line_marker_line))
         m_edit_area->setEdgeMode (QsciScintilla::EdgeLine);
       else
         {
-          if (settings->value (ed_long_line_marker_background)
-              .toBool ())
+          if (settings.bool_value (ed_long_line_marker_background))
             m_edit_area->setEdgeMode (QsciScintilla::EdgeBackground);
           else
             m_edit_area->setEdgeMode (QsciScintilla::EdgeLine);
@@ -2902,36 +2983,36 @@
   m_edit_area->setWrapVisualFlags (QsciScintilla::WrapFlagByBorder);
   m_edit_area->setWrapIndentMode (QsciScintilla::WrapIndentSame);
 
-  if (settings->value (ed_wrap_lines).toBool ())
+  if (settings.bool_value (ed_wrap_lines))
     m_edit_area->setWrapMode (QsciScintilla::WrapWord);
   else
     m_edit_area->setWrapMode (QsciScintilla::WrapNone);
 
-  if (settings->value (ed_break_lines).toBool ())
+  if (settings.bool_value (ed_break_lines))
     m_line_break = line_length;
   else
     m_line_break = 0;
 
   m_line_break_comments =
-    settings->value (ed_break_lines_comments).toBool ();
+    settings.bool_value (ed_break_lines_comments);
 
   // highlight all occurrences of a word selected by a double click
   m_highlight_all_occurrences =
-    settings->value (ed_highlight_all_occurrences).toBool ();
+    settings.bool_value (ed_highlight_all_occurrences);
 
   // reload changed files
   m_always_reload_changed_files =
-    settings->value (ed_always_reload_changed_files).toBool ();
+    settings.bool_value (ed_always_reload_changed_files);
 
   // Set cursor blinking depending on the settings.
   // QScintilla ignores the application global settings, so some special
   // handling is required
   bool cursor_blinking;
 
-  if (settings->contains (global_cursor_blinking.key))
-    cursor_blinking = settings->value (global_cursor_blinking).toBool ();
+  if (settings.contains (global_cursor_blinking.settings_key ()))
+    cursor_blinking = settings.bool_value (global_cursor_blinking);
   else
-    cursor_blinking = settings->value (cs_cursor_blinking).toBool ();
+    cursor_blinking = settings.bool_value (cs_cursor_blinking);
 
   if (cursor_blinking)
     m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 500);
@@ -2940,7 +3021,7 @@
 
 }
 
-void file_editor_tab::auto_margin_width (void)
+void file_editor_tab::auto_margin_width ()
 {
   m_edit_area->setMarginWidth (2, "1" + QString::number (m_edit_area->lines ()));
 }
@@ -2950,7 +3031,7 @@
 // the tab really was closed (for canceling exiting octave).
 // When emitting a signal, only the return value from the last slot
 // goes back to the sender
-bool file_editor_tab::conditional_close (void)
+bool file_editor_tab::conditional_close ()
 {
   return close ();
 }
@@ -3094,7 +3175,7 @@
           int editor_linenr = -1;
           marker *bp = nullptr;
 
-          // If comes back indicating a non-zero breakpoint marker,
+          // If comes back indicating a nonzero breakpoint marker,
           // reuse it if possible
           emit find_translated_line_number (line, editor_linenr, bp);
           if (bp != nullptr)
@@ -3163,7 +3244,7 @@
     }
 }
 
-void file_editor_tab::handle_lines_changed (void)
+void file_editor_tab::handle_lines_changed ()
 {
   // the related signal is emitted before cursor-move-signal!
   m_lines_changed = true;
@@ -3185,8 +3266,8 @@
 
   // Lines changed? Take care of indentation!
   bool do_smart_indent = m_lines_changed && m_is_octave_file
-    && (line == m_line+1) && (col < m_col)
-    && (m_smart_indent || m_auto_endif);
+                         && (line == m_line+1) && (col < m_col)
+                         && (m_smart_indent || m_auto_endif);
   m_lines_changed = false;
 
   // Update line and column indicator in the status bar
@@ -3321,7 +3402,7 @@
 #if defined (HAVE_QSCI_VERSION_2_6_0)
                                           , true
 #endif
-                                          );
+                                         );
 
               // loop over all occurrences and set the related indicator
               int oline, ocol;
@@ -3350,28 +3431,33 @@
     }
 }
 
-QString file_editor_tab::get_function_name (void)
+QString file_editor_tab::get_function_name ()
 {
-  QRegExp rxfun1 ("^[\t ]*function[^=]+=([^\\(]+)\\([^\\)]*\\)[\t ]*$");
-  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 ]*$");
+  QRegularExpression rxfun1 {"^[\t ]*function[^=]+=([^\\(]+)\\([^\\)]*\\)[\t ]*$"};
+  QRegularExpression rxfun2 {"^[\t ]*function[\t ]+([^\\(]+)\\([^\\)]*\\)[\t ]*$"};
+  QRegularExpression rxfun3 {"^[\t ]*function[^=]+=[\t ]*([^\\s]+)[\t ]*$"};
+  QRegularExpression rxfun4 {"^[\t ]*function[\t ]+([^\\s]+)[\t ]*$"};
+  QRegularExpression rxfun5 {"^[\t ]*classdef[\t ]+([^\\s]+)[\t ]*$"};
 
   QStringList lines = m_edit_area->text ().split ("\n");
 
   for (int i = 0; i < lines.count (); i++)
     {
-      if (rxfun1.indexIn (lines.at (i)) != -1)
-        return rxfun1.cap (1).remove (QRegExp ("[ \t]*"));
-      else if (rxfun2.indexIn (lines.at (i)) != -1)
-        return rxfun2.cap (1).remove (QRegExp ("[ \t]*"));
-      else if (rxfun3.indexIn (lines.at (i)) != -1)
-        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]*"));
+      QRegularExpressionMatch match = rxfun1.match (lines.at (i));
+      if (match.hasMatch ())
+        return match.captured (1).remove (QRegularExpression {"[ \t]*"});
+      match = rxfun2.match (lines.at (i));
+      if (match.hasMatch ())
+        return match.captured (1).remove (QRegularExpression {"[ \t]*"});
+      match = rxfun3.match (lines.at (i));
+      if (match.hasMatch ())
+        return match.captured (1).remove (QRegularExpression {"[ \t]*"});
+      match = rxfun4.match (lines.at (i));
+      if (match.hasMatch ())
+        return match.captured (1).remove (QRegularExpression {"[ \t]*"});
+      match = rxfun5.match (lines.at (i));
+      if (match.hasMatch ())
+        return match.captured (1).remove (QRegularExpression {"[ \t]*"});
     }
 
   return QString ();
--- a/libgui/src/m-editor/file-editor-tab.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/file-editor-tab.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,6 @@
 #include <QWidget>
 #include <Qsci/qsciapis.h>
 
-#include "gui-settings.h"
 #include "marker.h"
 #include "octave-qscintilla.h"
 #include "qt-interpreter-events.h"
@@ -45,7 +44,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class file_editor;
 
 class file_editor_tab : public QWidget
@@ -54,25 +52,25 @@
 
 public:
 
-  file_editor_tab (base_qobject& oct_qobj, const QString& directory = "");
+  file_editor_tab (const QString& directory = "");
 
-  ~file_editor_tab (void);
+  ~file_editor_tab ();
 
-  octave_qscintilla * qsci_edit_area (void) { return m_edit_area; }
+  octave_qscintilla * qsci_edit_area () { return m_edit_area; }
 
   // Will initiate close if associated with the identifier tag.
-  bool conditional_close (void);
+  bool conditional_close ();
 
   void update_breakpoints ();
   void set_file_name (const QString& fileName);
   void enable_file_watcher (bool do_enable);
 
-  QString file_name (void) const { return m_file_name; }
-  QString encoding (void) const { return m_encoding; }
+  QString file_name () const { return m_file_name; }
+  QString encoding () const { return m_encoding; }
 
 signals:
 
-  void tab_ready_to_close (void);
+  void tab_ready_to_close ();
   void file_name_changed (const QString& fileName,
                           const QString& toolTip,
                           bool modified);
@@ -80,7 +78,7 @@
                              bool is_modified);
   void set_focus_editor_signal (QWidget *);
   void edit_area_changed (octave_qscintilla *edit_area);
-  void tab_remove_request (void);
+  void tab_remove_request ();
   void mru_add_file (const QString& file_name, const QString& encoding);
   void editor_check_conflict_save (const QString& saveFileName,
                                    bool remove_on_success);
@@ -89,22 +87,22 @@
   void edit_mfile_request (const QString&, const QString&,
                            const QString&, int);
 
-  void autoc_closed (void);
+  void autoc_closed ();
 
   void update_breakpoints_signal (const octave_value_list& args);
 
   void remove_breakpoint_via_debugger_linenr (int debugger_linenr);
   void request_remove_breakpoint_via_editor_linenr (int editor_linenr);
-  void remove_all_breakpoints_signal (void);
+  void remove_all_breakpoints_signal ();
   void find_translated_line_number (int original_linenr,
                                     int& translated_linenr, marker*&);
   void find_linenr_just_before (int linenr, int& original_linenr,
                                 int& editor_linenr);
   void report_marker_linenr (QIntList& lines, QStringList& conditions);
   void remove_position_via_debugger_linenr (int debugger_linenr);
-  void remove_all_positions (void);
+  void remove_all_positions ();
 
-  void debug_quit_signal (void);
+  void debug_quit_signal ();
 
   void interpreter_event (const fcn_callback& fcn);
   void interpreter_event (const meth_callback& meth);
@@ -114,7 +112,7 @@
   void dbstop_if (const QString& prompt, int line, const QString& cond);
   void request_add_breakpoint (int line, const QString& cond);
   void request_add_octave_apis (const QStringList&);
-  void api_entries_added (void);
+  void api_entries_added ();
 
   void do_save_file_signal (const QString& file_to_save,
                             bool remove_on_success, bool restore_breakpoints);
@@ -138,7 +136,7 @@
                               Qt::KeyboardModifiers state);
 
   // Tells the editor tab to react on changed settings.
-  void notice_settings (const gui_settings *settings, bool init = false);
+  void notice_settings (bool init = false);
 
   // Change to a different editor tab by identifier tag.
   void change_editor_state (const QWidget *ID);
@@ -188,7 +186,7 @@
   void do_breakpoint_marker (bool insert, const QWidget *ID, int line = -1,
                              const QString& cond = "");
 
-  void recover_from_exit (void);
+  void recover_from_exit ();
   void set_modified (bool modified = true);
 
   void set_encoding (const QString& new_encoding);
@@ -223,28 +221,28 @@
   // When user closes QFileDialog box.
   void handle_save_file_as_answer (const QString& fileName);
   void handle_save_file_as_answer_close (const QString& fileName);
-  void handle_save_file_as_answer_cancel (void);
+  void handle_save_file_as_answer_cancel ();
   void handle_save_as_filter_selected (const QString& filter);
 
   // When user changes encoding after decoding errors were found
   void handle_current_enc_changed (const QString& enc);
 
   // When apis preparation has finished and is ready to save
-  void save_apis_info (void);
+  void save_apis_info ();
 
   // When the numer of lines changes -> adapt width of margin
-  void auto_margin_width (void);
+  void auto_margin_width ();
 
   void handle_cursor_moved (int line, int col);
   void handle_char_added (int character);
   void handle_double_click (int p, int l, int modifier);
-  void handle_lines_changed (void);
+  void handle_lines_changed ();
 
   void handle_remove_next (int remove_line);
   void handle_dbstop_if (const QString& prompt, int line,
                          const QString& cond);
   void handle_add_octave_apis (const QStringList& api_entries);
-  void handle_api_entries_added (void);
+  void handle_api_entries_added ();
 
   void do_save_file (const QString& file_to_save, bool remove_on_success,
                      bool restore_breakpoints);
@@ -260,8 +258,6 @@
 
 private:
 
-  base_qobject& m_octave_qobj;
-
   void add_breakpoint_event (int line, const QString& cond);
 
   bool valid_file_name (const QString& file = QString ());
@@ -269,31 +265,31 @@
                   bool restore_breakpoints = true);
   void save_file_as (bool remove_on_success = false);
   bool check_valid_identifier (QString file_name);
-  QTextCodec * check_valid_codec (void);
+  bool check_valid_codec ();
 
-  bool unchanged_or_saved (void);
+  bool unchanged_or_saved ();
 
-  void update_lexer (void);
+  void update_lexer ();
 
   void show_dialog (QDialog *dlg, bool modal);
 
 public:
 
   int check_file_modified (bool remove = false);
-  QString get_all_bookmarks (void);
+  QString get_all_bookmarks ();
 
 private:
   void do_comment_selected_text (bool comment, bool input_str = false);
   void do_indent_selected_text (bool indent);
-  void do_smart_indent_line_or_selected_text (void);
+  void do_smart_indent_line_or_selected_text ();
 
-  void check_restore_breakpoints (void);
+  void check_restore_breakpoints ();
   void center_current_line (bool always=true);
 
-  QString get_function_name (void);
+  QString get_function_name ();
 
-  QsciScintilla::EolMode detect_eol_mode (void);
-  void update_eol_indicator (void);
+  QsciScintilla::EolMode detect_eol_mode ();
+  void update_eol_indicator ();
 
   octave_qscintilla *m_edit_area;
 
--- a/libgui/src/m-editor/file-editor.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/file-editor.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,11 +50,10 @@
 #include "gui-preferences-ed.h"
 #include "gui-preferences-sc.h"
 #include "gui-preferences-global.h"
+#include "gui-settings.h"
 #include "main-window.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
-#include "shortcut-manager.h"
-
+
+#include "lo-sysdep.h"
 #include "oct-env.h"
 
 #include "event-manager.h"
@@ -68,7 +67,7 @@
 // Functions of the the reimplemented tab widget
 
 file_editor_tab_widget::file_editor_tab_widget (QWidget *p, file_editor *fe)
-: QTabWidget (p)
+  : QTabWidget (p)
 {
   tab_bar *bar = new tab_bar (this);
 
@@ -82,13 +81,13 @@
   setMovable (true);
 }
 
-tab_bar *file_editor_tab_widget::get_tab_bar (void) const
+tab_bar *file_editor_tab_widget::get_tab_bar () const
 {
   return qobject_cast<tab_bar *> (tabBar ());
 }
 
 std::list<file_editor_tab *>
-file_editor_tab_widget::tab_list (void) const
+file_editor_tab_widget::tab_list () const
 {
   std::list<file_editor_tab *> retval;
   for (int i = 0; i < count (); i++)
@@ -98,8 +97,8 @@
 
 // File editor
 
-file_editor::file_editor (QWidget *p, base_qobject& oct_qobj)
-  : file_editor_interface (p, oct_qobj)
+file_editor::file_editor (QWidget *p)
+  : file_editor_interface (p)
 {
   // Set current editing directory before construction because loaded
   // files will change ced accordingly.
@@ -178,12 +177,12 @@
   m_edit_menu->insertAction (m_find_action, m_find_files_action);
 }
 
-void file_editor::handle_enter_debug_mode (void)
+void file_editor::handle_enter_debug_mode ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  QString sc_run = settings->sc_value (sc_edit_run_run_file);
-  QString sc_cont = settings->sc_value (sc_main_debug_continue);
+  gui_settings settings;
+
+  QString sc_run = settings.sc_value (sc_edit_run_run_file);
+  QString sc_cont = settings.sc_value (sc_main_debug_continue);
 
   if (sc_run == sc_cont)
     m_run_action->setShortcut (QKeySequence ());  // prevent ambiguous shortcuts
@@ -193,16 +192,16 @@
   emit enter_debug_mode_signal ();
 }
 
-void file_editor::handle_exit_debug_mode (void)
+void file_editor::handle_exit_debug_mode ()
 {
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-  scmgr.set_shortcut (m_run_action, sc_edit_run_run_file);
+  gui_settings settings;
+  settings.set_shortcut (m_run_action, sc_edit_run_run_file);
   m_run_action->setToolTip (tr ("Save File and Run"));  // update tool tip
 
   emit exit_debug_mode_signal ();
 }
 
-void file_editor::check_actions (void)
+void file_editor::check_actions ()
 {
   // Do not include shared actions not only related to the editor
   bool have_tabs = m_tab_widget->count () > 0;
@@ -264,10 +263,10 @@
         return;  // not yet ready but got visibility changed signals
     }
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (settings->value (global_use_custom_editor.key,
-                       global_use_custom_editor.def).toBool ())
+  gui_settings settings;
+
+  if (settings.value (global_use_custom_editor.settings_key (),
+                      global_use_custom_editor.def ()).toBool ())
     return;  // do not open an empty script in the external editor
 
   bool real_visible;
@@ -317,27 +316,29 @@
   request_new_file ("");
 }
 
-void file_editor::restore_session (gui_settings *settings)
+void file_editor::restore_session ()
 {
+  gui_settings settings;
+
   //restore previous session
-  if (! settings->value (ed_restore_session).toBool ())
+  if (! settings.bool_value (ed_restore_session))
     return;
 
   // get the data from the settings file
   QStringList sessionFileNames
-    = settings->value (ed_session_names).toStringList ();
+    = settings.string_list_value (ed_session_names);
 
   QStringList session_encodings
-    = settings->value (ed_session_enc).toStringList ();
+    = settings.string_list_value (ed_session_enc);
 
   QStringList session_index
-    = settings->value (ed_session_ind).toStringList ();
+    = settings.string_list_value (ed_session_ind);
 
   QStringList session_lines
-    = settings->value (ed_session_lines).toStringList ();
+    = settings.string_list_value (ed_session_lines);
 
   QStringList session_bookmarks
-    = settings->value (ed_session_bookmarks).toStringList ();
+    = settings.string_list_value (ed_session_bookmarks);
 
   // fill a list of the struct and sort it (depending on index)
   QList<session_data> s_data;
@@ -354,7 +355,7 @@
         continue;
 
       session_data item = { 0, -1, sessionFileNames.at (n),
-        QString (), QString (), QString ()};
+                            QString (), QString (), QString ()};
       if (do_lines)
         item.line = session_lines.at (n).toInt ();
       if (do_index)
@@ -376,7 +377,7 @@
                        s_data.at (n).bookmarks);
 }
 
-void file_editor::activate (void)
+void file_editor::activate ()
 {
   if (m_no_focus)
     return;  // No focus for the editor if external open/close request
@@ -437,10 +438,9 @@
 // Save open files for restoring in next session
 // (even if last session will not be restored next time)
 // together with encoding and the tab index
-void file_editor::save_session (void)
+void file_editor::save_session ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   QStringList fetFileNames;
   QStringList fet_encodings;
@@ -472,15 +472,16 @@
         }
     }
 
-  settings->setValue (ed_session_names.key, fetFileNames);
-  settings->setValue (ed_session_enc.key, fet_encodings);
-  settings->setValue (ed_session_ind.key, fet_index);
-  settings->setValue (ed_session_lines.key, fet_lines);
-  settings->setValue (ed_session_bookmarks.key, fet_bookmarks);
-  settings->sync ();
+  settings.setValue (ed_session_names.settings_key (), fetFileNames);
+  settings.setValue (ed_session_enc.settings_key (), fet_encodings);
+  settings.setValue (ed_session_ind.settings_key (), fet_index);
+  settings.setValue (ed_session_lines.settings_key (), fet_lines);
+  settings.setValue (ed_session_bookmarks.settings_key (), fet_bookmarks);
+
+  settings.sync ();
 }
 
-bool file_editor::check_closing (void)
+bool file_editor::check_closing ()
 {
   // When the application or the editor is closing and the user wants to
   // close all files, in the latter case all editor tabs are checked whether
@@ -530,7 +531,7 @@
   return true;
 }
 
-void file_editor::handle_tab_ready_to_close (void)
+void file_editor::handle_tab_ready_to_close ()
 {
   if (m_closing_canceled)
     return;
@@ -689,29 +690,29 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      // If THIS_FE is no longer valid, skip the entire callback
-      // function.  With the way things are implemented now, we can't
-      // run the contents of a file unless the file editor and the
-      // corresponding file editor tab are still valid.
-
-      if (this_fe.isNull ())
-        return;
-
-      // Act as though this action was entered at the command propmt
-      // so that the interpreter will check for updated file time
-      // stamps.
-      Vlast_prompt_time.stamp ();
-
-      tree_evaluator& tw = interp.get_evaluator ();
-
-      if (tw.in_debug_repl ())
-        emit request_dbcont_signal ();
-      else
-        emit fetab_run_file (m_tab_widget->currentWidget ());
-    });
+     {
+       // INTERPRETER THREAD
+
+       // If THIS_FE is no longer valid, skip the entire callback
+       // function.  With the way things are implemented now, we can't
+       // run the contents of a file unless the file editor and the
+       // corresponding file editor tab are still valid.
+
+       if (this_fe.isNull ())
+         return;
+
+       // Act as though this action was entered at the command propmt
+       // so that the interpreter will check for updated file time
+       // stamps.
+       Vlast_prompt_time.stamp ();
+
+       tree_evaluator& tw = interp.get_evaluator ();
+
+       if (tw.in_debug_repl ())
+         emit request_dbcont_signal ();
+       else
+         emit fetab_run_file (m_tab_widget->currentWidget ());
+     });
 }
 
 void file_editor::request_step_into_file ()
@@ -914,9 +915,9 @@
     m_find_dialog->close ();
 
   if (isFloating ())
-    m_find_dialog = new find_dialog (m_octave_qobj, this, this);
+    m_find_dialog = new find_dialog (this, this);
   else
-    m_find_dialog = new find_dialog (m_octave_qobj, this, parentWidget ());
+    m_find_dialog = new find_dialog (this, parentWidget ());
 
   // Add required actions
   m_find_dialog->addAction (m_find_next_action);
@@ -987,7 +988,7 @@
   QObject *fileEditorTab = sender ();
   if (fileEditorTab)
     {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+      gui_settings settings;
 
       for (int i = 0; i < m_tab_widget->count (); i++)
         {
@@ -1000,7 +1001,7 @@
               m_current_tab_modified = modified;
 
               if (modified)
-                m_tab_widget->setTabIcon (i, rmgr.icon ("document-save"));
+                m_tab_widget->setTabIcon (i, settings.icon ("document-save"));
               else
                 m_tab_widget->setTabIcon (i, QIcon ());
             }
@@ -1016,7 +1017,7 @@
 }
 
 void
-file_editor::handle_tab_remove_request (void)
+file_editor::handle_tab_remove_request ()
 {
   QObject *fileEditorTab = sender ();
   if (fileEditorTab)
@@ -1268,8 +1269,7 @@
           if (m_tmp_closed_files.at (i).new_file_name.isEmpty ())
             m_tmp_closed_files.at (i).editor_tab->file_has_changed (QString (), true);
           else
-            m_tmp_closed_files.at (i).editor_tab->set_file_name (
-                                                                 m_tmp_closed_files.at (i).new_file_name);
+            m_tmp_closed_files.at (i).editor_tab->set_file_name (m_tmp_closed_files.at (i).new_file_name);
         }
       else
         {
@@ -1286,9 +1286,11 @@
   m_tmp_closed_files.clear ();
 }
 
-void file_editor::notice_settings (const gui_settings *settings)
+void file_editor::notice_settings ()
 {
-  int size_idx = settings->value (global_icon_size).toInt ();
+  gui_settings settings;
+
+  int size_idx = settings.int_value (global_icon_size);
   size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
   QStyle *st = style ();
@@ -1297,14 +1299,14 @@
 
   // Tab position and rotation
   QTabWidget::TabPosition pos
-    = static_cast<QTabWidget::TabPosition> (settings->value (ed_tab_position).toInt ());
-  bool rotated = settings->value (ed_tabs_rotated).toBool ();
+    = static_cast<QTabWidget::TabPosition> (settings.int_value (ed_tab_position));
+  bool rotated = settings.bool_value (ed_tabs_rotated);
 
   m_tab_widget->setTabPosition (pos);
 
   if (rotated)
     m_tab_widget->setTabsClosable (false);  // No close buttons
-  // FIXME: close buttons can not be correctly placed in rotated tabs
+    // FIXME: close buttons can not be correctly placed in rotated tabs
 
   // Get the tab bar and set the rotation
   int rotation = rotated;
@@ -1321,7 +1323,7 @@
     height = is;
 
   // Calculate possibly limited width and set the elide mode
-  int chars = settings->value (ed_tabs_max_width).toInt ();
+  int chars = settings.int_value (ed_tabs_max_width);
   int width = 9999;
   if (chars > 0)
     width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth ();
@@ -1336,9 +1338,9 @@
     }
 
   QString style_sheet
-    = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n"
-               "max-" + width_str + ": %2px; }")
-    .arg (height).arg (width);
+      = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n"
+                               "max-" + width_str + ": %2px; }")
+                        .arg (height).arg (width);
 
 #if defined (Q_OS_MAC)
   // FIXME: This is a workaround for missing tab close buttons on MacOS
@@ -1347,13 +1349,13 @@
     {
       QString icon = global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png";
 
-      QString close_button_css_mac (
-                                    "QTabBar::close-button"
-                                    " { image: url(" + icon + ");"
-                                    " padding: 4px;"
-                                    "   subcontrol-position: bottom; }\n"
-                                    "QTabBar::close-button:hover"
-                                    "  { background-color: #cccccc; }");
+      QString close_button_css_mac
+        ("QTabBar::close-button"
+         " { image: url(" + icon + ");"
+         " padding: 4px;"
+         "   subcontrol-position: bottom; }\n"
+         "QTabBar::close-button:hover"
+         "  { background-color: #cccccc; }");
 
       style_sheet = style_sheet + close_button_css_mac;
     }
@@ -1362,23 +1364,23 @@
   m_tab_widget->setStyleSheet (style_sheet);
 
   bool show_it;
-  show_it = settings->value (ed_show_line_numbers).toBool ();
+  show_it = settings.bool_value (ed_show_line_numbers);
   m_show_linenum_action->setChecked (show_it);
-  show_it = settings->value (ed_show_white_space).toBool ();
+  show_it = settings.bool_value (ed_show_white_space);
   m_show_whitespace_action->setChecked (show_it);
-  show_it = settings->value (ed_show_eol_chars).toBool ();
+  show_it = settings.bool_value (ed_show_eol_chars);
   m_show_eol_action->setChecked (show_it);
-  show_it = settings->value (ed_show_indent_guides).toBool ();
+  show_it = settings.bool_value (ed_show_indent_guides);
   m_show_indguide_action->setChecked (show_it);
-  show_it = settings->value (ed_long_line_marker).toBool ();
+  show_it = settings.bool_value (ed_long_line_marker);
   m_show_longline_action->setChecked (show_it);
 
-  show_it = settings->value (ed_show_toolbar).toBool ();
+  show_it = settings.bool_value (ed_show_toolbar);
   m_show_toolbar_action->setChecked (show_it);
   m_tool_bar->setVisible (show_it);
-  show_it = settings->value (ed_show_edit_status_bar).toBool ();
+  show_it = settings.bool_value (ed_show_edit_status_bar);
   m_show_statusbar_action->setChecked (show_it);
-  show_it = settings->value (ed_show_hscroll_bar).toBool ();
+  show_it = settings.bool_value (ed_show_hscroll_bar);
   m_show_hscrollbar_action->setChecked (show_it);
 
   set_shortcuts ();
@@ -1388,99 +1390,98 @@
     m_find_dialog->setWindowIcon (windowIcon ());
 
   // Relay signal to file editor tabs.
-  emit fetab_settings_changed (settings);
+  emit fetab_settings_changed ();
 }
 
-void file_editor::set_shortcuts (void)
+void file_editor::set_shortcuts ()
 {
   // Shortcuts also available in the main window, as well as the related
   // shortcuts, are defined in main_window and added to the editor
 
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
+  gui_settings settings;
 
   // File menu
-  scmgr.set_shortcut (m_edit_function_action, sc_edit_file_edit_function);
-  scmgr.set_shortcut (m_save_action, sc_edit_file_save);
-  scmgr.set_shortcut (m_save_as_action, sc_edit_file_save_as);
-  scmgr.set_shortcut (m_close_action, sc_edit_file_close);
-  scmgr.set_shortcut (m_close_all_action, sc_edit_file_close_all);
-  scmgr.set_shortcut (m_close_others_action, sc_edit_file_close_other);
-  scmgr.set_shortcut (m_print_action, sc_edit_file_print);
+  settings.set_shortcut (m_edit_function_action, sc_edit_file_edit_function);
+  settings.set_shortcut (m_save_action, sc_edit_file_save);
+  settings.set_shortcut (m_save_as_action, sc_edit_file_save_as);
+  settings.set_shortcut (m_close_action, sc_edit_file_close);
+  settings.set_shortcut (m_close_all_action, sc_edit_file_close_all);
+  settings.set_shortcut (m_close_others_action, sc_edit_file_close_other);
+  settings.set_shortcut (m_print_action, sc_edit_file_print);
 
   // Edit menu
-  scmgr.set_shortcut (m_redo_action, sc_edit_edit_redo);
-  scmgr.set_shortcut (m_cut_action, sc_edit_edit_cut);
-  scmgr.set_shortcut (m_find_action, sc_edit_edit_find_replace);
-  scmgr.set_shortcut (m_find_next_action, sc_edit_edit_find_next);
-  scmgr.set_shortcut (m_find_previous_action, sc_edit_edit_find_previous);
-
-  scmgr.set_shortcut (m_delete_start_word_action, sc_edit_edit_delete_start_word);
-  scmgr.set_shortcut (m_delete_end_word_action, sc_edit_edit_delete_end_word);
-  scmgr.set_shortcut (m_delete_start_line_action, sc_edit_edit_delete_start_line);
-  scmgr.set_shortcut (m_delete_end_line_action, sc_edit_edit_delete_end_line);
-  scmgr.set_shortcut (m_delete_line_action, sc_edit_edit_delete_line);
-  scmgr.set_shortcut (m_copy_line_action, sc_edit_edit_copy_line);
-  scmgr.set_shortcut (m_cut_line_action, sc_edit_edit_cut_line);
-  scmgr.set_shortcut (m_duplicate_selection_action, sc_edit_edit_duplicate_selection);
-  scmgr.set_shortcut (m_transpose_line_action, sc_edit_edit_transpose_line);
-  scmgr.set_shortcut (m_comment_selection_action, sc_edit_edit_comment_selection);
-  scmgr.set_shortcut (m_uncomment_selection_action, sc_edit_edit_uncomment_selection);
-  scmgr.set_shortcut (m_comment_var_selection_action, sc_edit_edit_comment_var_selection);
-
-  scmgr.set_shortcut (m_upper_case_action, sc_edit_edit_upper_case);
-  scmgr.set_shortcut (m_lower_case_action, sc_edit_edit_lower_case);
-  scmgr.set_shortcut (m_indent_selection_action, sc_edit_edit_indent_selection);
-  scmgr.set_shortcut (m_unindent_selection_action, sc_edit_edit_unindent_selection);
-  scmgr.set_shortcut (m_smart_indent_line_or_selection_action, sc_edit_edit_smart_indent_line_or_selection);
-  scmgr.set_shortcut (m_completion_action, sc_edit_edit_completion_list);
-  scmgr.set_shortcut (m_goto_line_action, sc_edit_edit_goto_line);
-  scmgr.set_shortcut (m_move_to_matching_brace, sc_edit_edit_move_to_brace);
-  scmgr.set_shortcut (m_sel_to_matching_brace, sc_edit_edit_select_to_brace);
-  scmgr.set_shortcut (m_toggle_bookmark_action, sc_edit_edit_toggle_bookmark);
-  scmgr.set_shortcut (m_next_bookmark_action, sc_edit_edit_next_bookmark);
-  scmgr.set_shortcut (m_previous_bookmark_action, sc_edit_edit_previous_bookmark);
-  scmgr.set_shortcut (m_remove_bookmark_action, sc_edit_edit_remove_bookmark);
-  scmgr.set_shortcut (m_preferences_action, sc_edit_edit_preferences);
-  scmgr.set_shortcut (m_styles_preferences_action, sc_edit_edit_styles_preferences);
-
-  scmgr.set_shortcut (m_conv_eol_windows_action, sc_edit_edit_conv_eol_winows);
-  scmgr.set_shortcut (m_conv_eol_unix_action,    sc_edit_edit_conv_eol_unix);
-  scmgr.set_shortcut (m_conv_eol_mac_action,     sc_edit_edit_conv_eol_mac);
+  settings.set_shortcut (m_redo_action, sc_edit_edit_redo);
+  settings.set_shortcut (m_cut_action, sc_edit_edit_cut);
+  settings.set_shortcut (m_find_action, sc_edit_edit_find_replace);
+  settings.set_shortcut (m_find_next_action, sc_edit_edit_find_next);
+  settings.set_shortcut (m_find_previous_action, sc_edit_edit_find_previous);
+
+  settings.set_shortcut (m_delete_start_word_action, sc_edit_edit_delete_start_word);
+  settings.set_shortcut (m_delete_end_word_action, sc_edit_edit_delete_end_word);
+  settings.set_shortcut (m_delete_start_line_action, sc_edit_edit_delete_start_line);
+  settings.set_shortcut (m_delete_end_line_action, sc_edit_edit_delete_end_line);
+  settings.set_shortcut (m_delete_line_action, sc_edit_edit_delete_line);
+  settings.set_shortcut (m_copy_line_action, sc_edit_edit_copy_line);
+  settings.set_shortcut (m_cut_line_action, sc_edit_edit_cut_line);
+  settings.set_shortcut (m_duplicate_selection_action, sc_edit_edit_duplicate_selection);
+  settings.set_shortcut (m_transpose_line_action, sc_edit_edit_transpose_line);
+  settings.set_shortcut (m_comment_selection_action, sc_edit_edit_comment_selection);
+  settings.set_shortcut (m_uncomment_selection_action, sc_edit_edit_uncomment_selection);
+  settings.set_shortcut (m_comment_var_selection_action, sc_edit_edit_comment_var_selection);
+
+  settings.set_shortcut (m_upper_case_action, sc_edit_edit_upper_case);
+  settings.set_shortcut (m_lower_case_action, sc_edit_edit_lower_case);
+  settings.set_shortcut (m_indent_selection_action, sc_edit_edit_indent_selection);
+  settings.set_shortcut (m_unindent_selection_action, sc_edit_edit_unindent_selection);
+  settings.set_shortcut (m_smart_indent_line_or_selection_action, sc_edit_edit_smart_indent_line_or_selection);
+  settings.set_shortcut (m_completion_action, sc_edit_edit_completion_list);
+  settings.set_shortcut (m_goto_line_action, sc_edit_edit_goto_line);
+  settings.set_shortcut (m_move_to_matching_brace, sc_edit_edit_move_to_brace);
+  settings.set_shortcut (m_sel_to_matching_brace, sc_edit_edit_select_to_brace);
+  settings.set_shortcut (m_toggle_bookmark_action, sc_edit_edit_toggle_bookmark);
+  settings.set_shortcut (m_next_bookmark_action, sc_edit_edit_next_bookmark);
+  settings.set_shortcut (m_previous_bookmark_action, sc_edit_edit_previous_bookmark);
+  settings.set_shortcut (m_remove_bookmark_action, sc_edit_edit_remove_bookmark);
+  settings.set_shortcut (m_preferences_action, sc_edit_edit_preferences);
+  settings.set_shortcut (m_styles_preferences_action, sc_edit_edit_styles_preferences);
+
+  settings.set_shortcut (m_conv_eol_windows_action, sc_edit_edit_conv_eol_winows);
+  settings.set_shortcut (m_conv_eol_unix_action,    sc_edit_edit_conv_eol_unix);
+  settings.set_shortcut (m_conv_eol_mac_action,     sc_edit_edit_conv_eol_mac);
 
   // View menu
-  scmgr.set_shortcut (m_show_linenum_action, sc_edit_view_show_line_numbers);
-  scmgr.set_shortcut (m_show_whitespace_action, sc_edit_view_show_white_spaces);
-  scmgr.set_shortcut (m_show_eol_action, sc_edit_view_show_eol_chars);
-  scmgr.set_shortcut (m_show_indguide_action, sc_edit_view_show_ind_guides);
-  scmgr.set_shortcut (m_show_longline_action, sc_edit_view_show_long_line);
-  scmgr.set_shortcut (m_show_toolbar_action, sc_edit_view_show_toolbar);
-  scmgr.set_shortcut (m_show_statusbar_action, sc_edit_view_show_statusbar);
-  scmgr.set_shortcut (m_show_hscrollbar_action, sc_edit_view_show_hscrollbar);
-  scmgr.set_shortcut (m_zoom_in_action, sc_edit_view_zoom_in);
-  scmgr.set_shortcut (m_zoom_out_action, sc_edit_view_zoom_out);
-  scmgr.set_shortcut (m_zoom_normal_action, sc_edit_view_zoom_normal);
-  scmgr.set_shortcut (m_sort_tabs_action, sc_edit_view_sort_tabs);
+  settings.set_shortcut (m_show_linenum_action, sc_edit_view_show_line_numbers);
+  settings.set_shortcut (m_show_whitespace_action, sc_edit_view_show_white_spaces);
+  settings.set_shortcut (m_show_eol_action, sc_edit_view_show_eol_chars);
+  settings.set_shortcut (m_show_indguide_action, sc_edit_view_show_ind_guides);
+  settings.set_shortcut (m_show_longline_action, sc_edit_view_show_long_line);
+  settings.set_shortcut (m_show_toolbar_action, sc_edit_view_show_toolbar);
+  settings.set_shortcut (m_show_statusbar_action, sc_edit_view_show_statusbar);
+  settings.set_shortcut (m_show_hscrollbar_action, sc_edit_view_show_hscrollbar);
+  settings.set_shortcut (m_zoom_in_action, sc_edit_view_zoom_in);
+  settings.set_shortcut (m_zoom_out_action, sc_edit_view_zoom_out);
+  settings.set_shortcut (m_zoom_normal_action, sc_edit_view_zoom_normal);
+  settings.set_shortcut (m_sort_tabs_action, sc_edit_view_sort_tabs);
 
   // Debug menu
-  scmgr.set_shortcut (m_toggle_breakpoint_action, sc_edit_debug_toggle_breakpoint);
-  scmgr.set_shortcut (m_next_breakpoint_action, sc_edit_debug_next_breakpoint);
-  scmgr.set_shortcut (m_previous_breakpoint_action, sc_edit_debug_previous_breakpoint);
-  scmgr.set_shortcut (m_remove_all_breakpoints_action, sc_edit_debug_remove_breakpoints);
+  settings.set_shortcut (m_toggle_breakpoint_action, sc_edit_debug_toggle_breakpoint);
+  settings.set_shortcut (m_next_breakpoint_action, sc_edit_debug_next_breakpoint);
+  settings.set_shortcut (m_previous_breakpoint_action, sc_edit_debug_previous_breakpoint);
+  settings.set_shortcut (m_remove_all_breakpoints_action, sc_edit_debug_remove_breakpoints);
 
   // Run menu
-  scmgr.set_shortcut (m_run_action, sc_edit_run_run_file);
-  scmgr.set_shortcut (m_run_selection_action, sc_edit_run_run_selection);
+  settings.set_shortcut (m_run_action, sc_edit_run_run_file);
+  settings.set_shortcut (m_run_selection_action, sc_edit_run_run_selection);
 
   // Help menu
-  scmgr.set_shortcut (m_context_help_action, sc_edit_help_help_keyword);
-  scmgr.set_shortcut (m_context_doc_action,  sc_edit_help_doc_keyword);
+  settings.set_shortcut (m_context_help_action, sc_edit_help_help_keyword);
+  settings.set_shortcut (m_context_doc_action,  sc_edit_help_doc_keyword);
 
   // Tab navigation without menu entries
-  scmgr.set_shortcut (m_switch_left_tab_action, sc_edit_tabs_switch_left_tab);
-  scmgr.set_shortcut (m_switch_right_tab_action, sc_edit_tabs_switch_right_tab);
-  scmgr.set_shortcut (m_move_tab_left_action, sc_edit_tabs_move_tab_left);
-  scmgr.set_shortcut (m_move_tab_right_action, sc_edit_tabs_move_tab_right);
-
+  settings.set_shortcut (m_switch_left_tab_action, sc_edit_tabs_switch_left_tab);
+  settings.set_shortcut (m_switch_right_tab_action, sc_edit_tabs_switch_right_tab);
+  settings.set_shortcut (m_move_tab_left_action, sc_edit_tabs_move_tab_left);
+  settings.set_shortcut (m_move_tab_right_action, sc_edit_tabs_move_tab_right);
 }
 
 // This slot is a reimplementation of the virtual slot in octave_dock_widget.
@@ -1496,9 +1497,8 @@
   if (m_closed && visible)
     {
       m_closed = false;
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
-      restore_session (settings);
+
+      restore_session ();
     }
 
   empty_script (false, visible);
@@ -1525,28 +1525,28 @@
   emit fetab_set_directory (m_ced);  // for save dialog
 }
 
-void file_editor::copyClipboard (void)
+void file_editor::copyClipboard ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                   QsciScintillaBase::SCI_COPY);
 }
 
-void file_editor::pasteClipboard (void)
+void file_editor::pasteClipboard ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                   QsciScintillaBase::SCI_PASTE);
 }
 
-void file_editor::selectAll (void)
+void file_editor::selectAll ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                   QsciScintillaBase::SCI_SELECTALL);
 }
 
-void file_editor::do_undo (void)
+void file_editor::do_undo ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
@@ -1562,10 +1562,9 @@
                                      const QString& cond, int index,
                                      const QString& bookmarks)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings->value (global_use_custom_editor).toBool ())
+  gui_settings settings;
+
+  if (settings.bool_value (global_use_custom_editor))
     {
       // Custom editor
       if (debug_pointer || breakpoint_marker)
@@ -1575,8 +1574,7 @@
         return;   // Custom editor called
     }
 
-  bool show_dbg_file
-    = settings->value (ed_show_dbg_file).toBool ();
+  bool show_dbg_file = settings.bool_value (ed_show_dbg_file);
 
   if (openFileName.isEmpty ())
     {
@@ -1693,7 +1691,7 @@
                   bool create_file = true;
                   QMessageBox *msgBox;
 
-                  if (! settings->value (ed_create_new_file).toBool ())
+                  if (! settings.bool_value (ed_create_new_file))
                     {
                       msgBox = new QMessageBox (QMessageBox::Question,
                                                 tr ("Octave Editor"),
@@ -1865,9 +1863,9 @@
 // handler for the close event
 void file_editor::closeEvent (QCloseEvent *e)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (settings->value (ed_hiding_closes_files).toBool ())
+  gui_settings settings;
+
+  if (settings.bool_value (ed_hiding_closes_files))
     {
       if (check_closing ())
         {
@@ -1906,7 +1904,7 @@
     }
 }
 
-bool file_editor::is_editor_console_tabbed (void)
+bool file_editor::is_editor_console_tabbed ()
 {
   // FIXME: is there a way to do this job that doesn't require casting
   // the parent to a main_window object?
@@ -1929,7 +1927,7 @@
   return false;
 }
 
-void file_editor::construct (void)
+void file_editor::construct ()
 {
   QWidget *editor_widget = new QWidget (this);
 
@@ -1947,13 +1945,12 @@
 
   m_tab_widget = new file_editor_tab_widget (editor_widget, this);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
   // the mru-list and an empty array of actions
-  gui_settings *settings = rmgr.get_settings ();
-  m_mru_files = settings->value (ed_mru_file_list).toStringList ();
-  m_mru_files_encodings = settings->value (ed_mru_file_encodings)
-    .toStringList ();
+
+  gui_settings settings;
+
+  m_mru_files = settings.string_list_value (ed_mru_file_list);
+  m_mru_files_encodings = settings.string_list_value (ed_mru_file_encodings);
 
   if (m_mru_files_encodings.count () != m_mru_files.count ())
     {
@@ -1991,33 +1988,33 @@
   m_fileMenu->addSeparator ();
 
   m_save_action
-    = add_action (m_fileMenu, rmgr.icon ("document-save"),
+    = add_action (m_fileMenu, settings.icon ("document-save"),
                   tr ("&Save File"), SLOT (request_save_file (bool)));
 
   m_save_as_action
-    = add_action (m_fileMenu, rmgr.icon ("document-save-as"),
+    = add_action (m_fileMenu, settings.icon ("document-save-as"),
                   tr ("Save File &As..."),
                   SLOT (request_save_file_as (bool)));
 
   m_fileMenu->addSeparator ();
 
   m_close_action
-    = add_action (m_fileMenu, rmgr.icon ("window-close", false),
+    = add_action (m_fileMenu, settings.icon ("window-close", false),
                   tr ("&Close"), SLOT (request_close_file (bool)));
 
   m_close_all_action
-    = add_action (m_fileMenu, rmgr.icon ("window-close", false),
+    = add_action (m_fileMenu, settings.icon ("window-close", false),
                   tr ("Close All"), SLOT (request_close_all_files (bool)));
 
   m_close_others_action
-    = add_action (m_fileMenu, rmgr.icon ("window-close", false),
+    = add_action (m_fileMenu, settings.icon ("window-close", false),
                   tr ("Close Other Files"),
                   SLOT (request_close_other_files (bool)));
 
   m_fileMenu->addSeparator ();
 
   m_print_action
-    = add_action (m_fileMenu, rmgr.icon ("document-print"),
+    = add_action (m_fileMenu, settings.icon ("document-print"),
                   tr ("Print..."), SLOT (request_print_file (bool)));
 
   // edit menu (undo, copy, paste and select all later via main window)
@@ -2025,19 +2022,19 @@
   m_edit_menu = add_menu (m_menu_bar, tr ("&Edit"));
 
   m_redo_action
-    = add_action (m_edit_menu, rmgr.icon ("edit-redo"),
+    = add_action (m_edit_menu, settings.icon ("edit-redo"),
                   tr ("&Redo"), SLOT (request_redo (bool)));
   m_redo_action->setEnabled (false);
 
   m_edit_menu->addSeparator ();
 
   m_cut_action
-    = add_action (m_edit_menu, rmgr.icon ("edit-cut"),
+    = add_action (m_edit_menu, settings.icon ("edit-cut"),
                   tr ("Cu&t"), SLOT (request_cut (bool)));
   m_cut_action->setEnabled (false);
 
   m_find_action
-    = add_action (m_edit_menu, rmgr.icon ("edit-find-replace"),
+    = add_action (m_edit_menu, settings.icon ("edit-find-replace"),
                   tr ("&Find and Replace..."), SLOT (request_find (bool)));
 
   m_find_next_action
@@ -2134,7 +2131,7 @@
 
   m_smart_indent_line_or_selection_action
     = add_action (m_edit_fmt_menu, tr ("Indent Code"),
-                  SLOT (request_smart_indent_line_or_selected_text (void)));
+                  SLOT (request_smart_indent_line_or_selected_text ()));
 
   m_edit_fmt_menu->addSeparator ();
 
@@ -2189,12 +2186,12 @@
   m_edit_menu->addSeparator ();
 
   m_preferences_action
-    = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
+    = add_action (m_edit_menu, settings.icon ("preferences-system"),
                   tr ("&Preferences..."),
                   SLOT (request_preferences (bool)));
 
   m_styles_preferences_action
-    = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
+    = add_action (m_edit_menu, settings.icon ("preferences-system"),
                   tr ("&Styles Preferences..."),
                   SLOT (request_styles_preferences (bool)));
 
@@ -2249,22 +2246,22 @@
   view_menu->addSeparator ();
 
   m_zoom_in_action
-    = add_action (view_menu, rmgr.icon ("view-zoom-in"), tr ("Zoom &In"),
+    = add_action (view_menu, settings.icon ("view-zoom-in"), tr ("Zoom &In"),
                   SLOT (zoom_in (bool)));
 
   m_zoom_out_action
-    = add_action (view_menu, rmgr.icon ("view-zoom-out"), tr ("Zoom &Out"),
-                  SLOT (zoom_out (bool)));
+    = add_action (view_menu, settings.icon ("view-zoom-out"),
+                  tr ("Zoom &Out"), SLOT (zoom_out (bool)));
 
   m_zoom_normal_action
-    = add_action (view_menu, rmgr.icon ("view-zoom-original"), tr ("&Normal Size"),
-                  SLOT (zoom_normal (bool)));
+    = add_action (view_menu, settings.icon ("view-zoom-original"),
+                  tr ("&Normal Size"), SLOT (zoom_normal (bool)));
 
   view_menu->addSeparator ();
 
   m_sort_tabs_action
     = add_action (view_menu, tr ("&Sort Tabs Alphabetically"),
-                  SLOT (sort_tabs_alph (void)),
+                  SLOT (sort_tabs_alph ()),
                   m_tab_widget->get_tab_bar ());
 
   m_menu_bar->addMenu (view_menu);
@@ -2274,22 +2271,22 @@
   m_debug_menu = add_menu (m_menu_bar, tr ("&Debug"));
 
   m_toggle_breakpoint_action
-    = add_action (m_debug_menu, rmgr.icon ("bp-toggle"),
+    = add_action (m_debug_menu, settings.icon ("bp-toggle"),
                   tr ("Toggle &Breakpoint"),
                   SLOT (request_toggle_breakpoint (bool)));
 
   m_next_breakpoint_action
-    = add_action (m_debug_menu, rmgr.icon ("bp-next"),
+    = add_action (m_debug_menu, settings.icon ("bp-next"),
                   tr ("&Next Breakpoint"),
                   SLOT (request_next_breakpoint (bool)));
 
   m_previous_breakpoint_action
-    = add_action (m_debug_menu, rmgr.icon ("bp-prev"),
+    = add_action (m_debug_menu, settings.icon ("bp-prev"),
                   tr ("Pre&vious Breakpoint"),
                   SLOT (request_previous_breakpoint (bool)));
 
   m_remove_all_breakpoints_action
-    = add_action (m_debug_menu, rmgr.icon ("bp-rm-all"),
+    = add_action (m_debug_menu, settings.icon ("bp-rm-all"),
                   tr ("&Remove All Breakpoints"),
                   SLOT (request_remove_breakpoint (bool)));
 
@@ -2303,7 +2300,7 @@
 
   m_run_action
     = add_action (_run_menu,
-                  rmgr.icon ("system-run"),
+                  settings.icon ("system-run"),
                   tr ("Save File and Run / Continue"),
                   SLOT (request_run_file (bool)));
 
@@ -2330,19 +2327,19 @@
   // tab navigation (no menu, only actions; slots in tab_bar)
 
   m_switch_left_tab_action
-    = add_action (nullptr, "", SLOT (switch_left_tab (void)),
+    = add_action (nullptr, "", SLOT (switch_left_tab ()),
                   m_tab_widget->get_tab_bar ());
 
   m_switch_right_tab_action
-    = add_action (nullptr, "", SLOT (switch_right_tab (void)),
+    = add_action (nullptr, "", SLOT (switch_right_tab ()),
                   m_tab_widget->get_tab_bar ());
 
   m_move_tab_left_action
-    = add_action (nullptr, "", SLOT (move_tab_left (void)),
+    = add_action (nullptr, "", SLOT (move_tab_left ()),
                   m_tab_widget->get_tab_bar ());
 
   m_move_tab_right_action
-    = add_action (nullptr, "", SLOT (move_tab_right (void)),
+    = add_action (nullptr, "", SLOT (move_tab_right ()),
                   m_tab_widget->get_tab_bar ());
 
   // toolbar
@@ -2383,7 +2380,7 @@
   vbox_layout->addWidget (m_menu_bar);
   vbox_layout->addWidget (m_tool_bar);
   vbox_layout->addWidget (m_tab_widget);
-  vbox_layout->setMargin (0);
+  vbox_layout->setContentsMargins (0, 0, 0, 0);
   vbox_layout->setSpacing (0);
   editor_widget->setLayout (vbox_layout);
   setWidget (editor_widget);
@@ -2420,7 +2417,7 @@
 }
 
 // Slot when autocompletion list was cancelled
-void file_editor::handle_autoc_cancelled (void)
+void file_editor::handle_autoc_cancelled ()
 {
   // List was cancelled but somehow still active and blocking the
   // edit area from accepting shortcuts. Only after another keypress
@@ -2444,7 +2441,7 @@
     qsci->undo ();
 }
 
-file_editor_tab *file_editor::reset_focus (void)
+file_editor_tab *file_editor::reset_focus ()
 {
   // Reset the focus of the tab and the related edit area
   file_editor_tab *f
@@ -2456,9 +2453,12 @@
 file_editor_tab *
 file_editor::make_file_editor_tab (const QString& directory)
 {
-  file_editor_tab *f = new file_editor_tab (m_octave_qobj, directory);
+  file_editor_tab *f = new file_editor_tab (directory);
 
   // signals from the qscintilla edit area
+  connect (f->qsci_edit_area (), &octave_qscintilla::show_symbol_tooltip_signal,
+           this, &file_editor::show_symbol_tooltip_signal);
+
   connect (f->qsci_edit_area (), &octave_qscintilla::status_update,
            this, &file_editor::edit_status_update);
 
@@ -2467,10 +2467,10 @@
 
   connect (f->qsci_edit_area (),
            SIGNAL (SCN_AUTOCCOMPLETED (const char *, int, int, int)),
-           this, SLOT (reset_focus (void)));
-
-  connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED (void)),
-           this, SLOT (handle_autoc_cancelled (void)));
+           this, SLOT (reset_focus ()));
+
+  connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED ()),
+           this, SLOT (handle_autoc_cancelled ()));
 
   // signals from the qscintilla edit area
   connect (this, &file_editor::enter_debug_mode_signal,
@@ -2509,7 +2509,7 @@
 
   // Signals from the file_editor or main-win non-trivial operations
   connect (this, &file_editor::fetab_settings_changed,
-           f, [=] (const gui_settings *settings) { f->notice_settings (settings); });
+           f, [=] () { f->notice_settings (); });
 
   connect (this, &file_editor::fetab_change_request,
            f, &file_editor_tab::change_editor_state);
@@ -2663,7 +2663,7 @@
   check_actions ();
 }
 
-void file_editor::mru_menu_update (void)
+void file_editor::mru_menu_update ()
 {
   int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles));
 
@@ -2693,22 +2693,23 @@
     }
 
   // save actual mru-list in settings
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  settings->setValue (ed_mru_file_list.key,  m_mru_files);
-  settings->setValue (ed_mru_file_encodings.key,  m_mru_files_encodings);
-  settings->sync ();
+
+  gui_settings settings;
+
+  settings.setValue (ed_mru_file_list.settings_key (),  m_mru_files);
+  settings.setValue (ed_mru_file_encodings.settings_key (),  m_mru_files_encodings);
+
+  settings.sync ();
 }
 
 bool file_editor::call_custom_editor (const QString& file_name, int line)
 {
   // Check if the user wants to use a custom file editor.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings->value (global_use_custom_editor.key,
-                       global_use_custom_editor.def).toBool ())
+
+  gui_settings settings;
+
+  if (settings.value (global_use_custom_editor.settings_key (),
+                       global_use_custom_editor.def ()).toBool ())
     {
       // use the external editor interface for handling the call
       emit request_open_file_external (file_name, line);
@@ -2725,12 +2726,11 @@
 
 void file_editor::toggle_preference (const gui_pref& preference)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  bool old = settings->value (preference).toBool ();
-  settings->setValue (preference.key, ! old);
-  notice_settings (settings);
+  gui_settings settings;
+
+  bool old = settings.bool_value (preference);
+  settings.setValue (preference.settings_key (), ! old);
+  notice_settings ();
 }
 
 // Function for closing the files in a removed directory
@@ -2802,7 +2802,7 @@
     }
 }
 
-bool file_editor::editor_tab_has_focus (void)
+bool file_editor::editor_tab_has_focus ()
 {
   QWidget *foc_w = focusWidget ();
   if (foc_w && foc_w->inherits ("octave::octave_qscintilla"))
@@ -2827,7 +2827,8 @@
       //
       // is false
 
-      if (same_file (std_file, tab_file.toStdString ()) || file == tab_file)
+      if (sys::same_file (std_file, tab_file.toStdString ())
+          || file == tab_file)
         return fe_tab;
     }
 
--- a/libgui/src/m-editor/file-editor.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/file-editor.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,11 +59,11 @@
 
   file_editor_tab_widget (QWidget *p, file_editor *fe);
 
-  ~file_editor_tab_widget (void) = default;
+  ~file_editor_tab_widget () = default;
 
-  tab_bar * get_tab_bar (void) const;
+  tab_bar * get_tab_bar () const;
 
-  std::list<file_editor_tab *> tab_list (void) const;
+  std::list<file_editor_tab *> tab_list () const;
 };
 
 // the class for the file editor
@@ -96,39 +96,39 @@
     QString new_file_name;
   };
 
-  file_editor (QWidget *p, base_qobject& oct_qobj);
+  file_editor (QWidget *p);
 
-  ~file_editor (void) = default;
+  ~file_editor () = default;
 
-  QMenu * get_mru_menu (void) { return m_mru_file_menu; }
+  QMenu * get_mru_menu () { return m_mru_file_menu; }
 
-  QMenu * debug_menu (void) { return m_debug_menu; }
+  QMenu * debug_menu () { return m_debug_menu; }
 
-  QToolBar * toolbar (void) { return m_tool_bar; }
+  QToolBar * toolbar () { return m_tool_bar; }
 
-  QMenuBar * menubar (void) { return m_menu_bar; }
+  QMenuBar * menubar () { return m_menu_bar; }
 
   void insert_global_actions (QList<QAction *>);
 
   enum shared_actions_idx
-    {
-      NEW_SCRIPT_ACTION = 0,
-      NEW_FUNCTION_ACTION,
-      OPEN_ACTION,
-      FIND_FILES_ACTION,
-      UNDO_ACTION,
-      COPY_ACTION,
-      PASTE_ACTION,
-      SELECTALL_ACTION
-    };
+  {
+    NEW_SCRIPT_ACTION = 0,
+    NEW_FUNCTION_ACTION,
+    OPEN_ACTION,
+    FIND_FILES_ACTION,
+    UNDO_ACTION,
+    COPY_ACTION,
+    PASTE_ACTION,
+    SELECTALL_ACTION
+  };
 
-  void check_actions (void);
+  void check_actions ();
   void empty_script (bool startup, bool visible);
-  void restore_session (gui_settings *settings);
+  void restore_session ();
 
 signals:
 
-  void fetab_settings_changed (const gui_settings *settings);
+  void fetab_settings_changed ();
   void fetab_change_request (const QWidget *ID);
   // Save is a ping-pong type of communication
   void fetab_save_file (const QWidget *ID, const QString& fileName,
@@ -171,38 +171,40 @@
   void fetab_zoom_normal (const QWidget *ID);
 
   void fetab_set_directory (const QString& dir);
-  void fetab_recover_from_exit (void);
+  void fetab_recover_from_exit ();
 
   void edit_area_changed (octave_qscintilla *edit_area);
 
   void request_settings_dialog (const QString&);
   void request_open_file_external (const QString& file_name, int line);
-  void file_loaded_signal (void);
+  void file_loaded_signal ();
 
   void editor_tabs_changed_signal (bool, bool);
-  void request_dbcont_signal (void);
+  void request_dbcont_signal ();
 
-  void enter_debug_mode_signal (void);
-  void exit_debug_mode_signal (void);
+  void enter_debug_mode_signal ();
+  void exit_debug_mode_signal ();
 
   void update_gui_lexer_signal (bool);
   void execute_command_in_terminal_signal (const QString&);
-  void focus_console_after_command_signal (void);
+  void focus_console_after_command_signal ();
   void run_file_signal (const QFileInfo&);
   void edit_mfile_request (const QString&, const QString&, const QString&, int);
-  void debug_quit_signal (void);
+  void debug_quit_signal ();
+
+  void show_symbol_tooltip_signal (const QPoint&, const QString&);
 
 public slots:
 
-  void activate (void);
+  void activate ();
   void set_focus (QWidget *fet);
   void enable_menu_shortcuts (bool);
-  void save_session (void);
-  bool check_closing (void);
-  void handle_tab_ready_to_close (void);
+  void save_session ();
+  bool check_closing ();
+  void handle_tab_ready_to_close ();
 
-  void handle_enter_debug_mode (void);
-  void handle_exit_debug_mode (void);
+  void handle_enter_debug_mode ();
+  void handle_exit_debug_mode ();
 
   void request_new_file (const QString& commands);
   void request_close_file (bool);
@@ -252,7 +254,7 @@
   void request_lower_case (bool);
   void request_indent_selected_text (bool);
   void request_unindent_selected_text (bool);
-  void request_smart_indent_line_or_selected_text (void);
+  void request_smart_indent_line_or_selected_text ();
   void request_conv_eol_windows (bool);
   void request_conv_eol_unix (bool);
   void request_conv_eol_mac (bool);
@@ -268,7 +270,7 @@
                                  const QString& toolTip,
                                  bool modified);
   void handle_tab_close_request (int index);
-  void handle_tab_remove_request (void);
+  void handle_tab_remove_request ();
   void active_tab_changed (int index);
   void handle_editor_state_changed (bool enableCopy, bool is_octave_file,
                                     bool is_modified);
@@ -287,9 +289,9 @@
   void handle_file_renamed (bool load_new = true);
 
   // Tells the editor to react on changed settings.
-  void notice_settings (const gui_settings *settings);
+  void notice_settings ();
 
-  void set_shortcuts (void);
+  void set_shortcuts ();
 
   void handle_visibility (bool visible);
 
@@ -297,16 +299,16 @@
 
   void toplevel_change (bool toplevel);
 
-  void handle_autoc_cancelled (void);
+  void handle_autoc_cancelled ();
 
-  file_editor_tab * reset_focus (void);
+  file_editor_tab * reset_focus ();
 
 protected slots:
 
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
-  void do_undo (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
+  void do_undo ();
 
 private slots:
 
@@ -345,20 +347,20 @@
 
   file_editor_tab * make_file_editor_tab (const QString& directory = "");
 
-  bool is_editor_console_tabbed (void);
-  void construct (void);
+  bool is_editor_console_tabbed ();
+  void construct ();
   void add_file_editor_tab (file_editor_tab *f, const QString& fn,
                             int index = -1);
-  void mru_menu_update (void);
+  void mru_menu_update ();
   bool call_custom_editor (const QString& file_name = QString (), int line = -1);
 
   void toggle_preference (const gui_pref& preference);
 
   void handle_dir_remove (const QString& old_name, const QString& new_name);
 
-  bool editor_tab_has_focus (void);
+  bool editor_tab_has_focus ();
 
-  void find_create (void);
+  void find_create ();
 
   file_editor_tab * find_tab_widget (const QString& openFileName);
   QAction * add_action (QMenu *menu, const QString& text,
--- a/libgui/src/m-editor/find-dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/find-dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -83,15 +83,12 @@
 #include "find-dialog.h"
 #include "gui-preferences-ed.h"
 #include "gui-utils.h"
-#include "resource-manager.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-find_dialog::find_dialog (base_qobject& oct_qobj,
-                          octave_dock_widget *ed, QWidget *p)
-: QDialog (p), m_octave_qobj (oct_qobj), m_editor (ed),
-  m_in_sel (false), m_sel_beg (-1), m_sel_end (-1)
+find_dialog::find_dialog (octave_dock_widget *ed, QWidget *p)
+  : QDialog (p), m_editor (ed), m_in_sel (false),
+    m_sel_beg (-1), m_sel_end (-1)
 {
   setWindowTitle (tr ("Editor: Find and Replace"));
 
@@ -111,9 +108,9 @@
   m_replace_line_edit->completer ()->setCaseSensitivity (Qt::CaseSensitive);
   m_replace_label->setBuddy (m_replace_line_edit);
 
-  int width = QFontMetrics (m_search_line_edit->font ()).averageCharWidth();
-  m_search_line_edit->setFixedWidth (20*width);
-  m_replace_line_edit->setFixedWidth (20*width);
+   int width = QFontMetrics (m_search_line_edit->font ()).averageCharWidth();
+   m_search_line_edit->setFixedWidth (20*width);
+   m_replace_line_edit->setFixedWidth (20*width);
 
   m_case_check_box = new QCheckBox (tr ("Match &case"));
   m_from_start_check_box = new QCheckBox (tr ("Search from &start"));
@@ -162,7 +159,7 @@
            this, &find_dialog::handle_sel_search_changed);
 
   QVBoxLayout *extension_layout = new QVBoxLayout ();
-  extension_layout->setMargin (0);
+  extension_layout->setContentsMargins (0, 0, 0, 0);
   extension_layout->addWidget (m_whole_words_check_box);
   extension_layout->addWidget (m_backward_check_box);
   extension_layout->addWidget (m_search_selection_check_box);
@@ -218,8 +215,7 @@
 
 void find_dialog::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *s = rmgr.get_settings ();
+  gui_settings settings;
 
   // Save position
   QPoint dlg_pos = pos ();
@@ -232,7 +228,7 @@
 
   m_last_position = QPoint (dlg_pos.x (), y);
 
-  s->setValue (ed_fdlg_pos.key, m_last_position);
+  settings.setValue (ed_fdlg_pos.settings_key (), m_last_position);
 
   // Is current search/replace text in the mru list?
   mru_update (m_search_line_edit);
@@ -242,46 +238,45 @@
   QStringList mru;
   for (int i = 0; i < m_search_line_edit->count (); i++)
     mru.append (m_search_line_edit->itemText (i));
-  s->setValue (ed_fdlg_search.key, mru);
+  settings.setValue (ed_fdlg_search.settings_key (), mru);
 
   mru.clear ();
   for (int i = 0; i < m_replace_line_edit->count (); i++)
     mru.append (m_replace_line_edit->itemText (i));
-  s->setValue (ed_fdlg_replace.key, mru);
+  settings.setValue (ed_fdlg_replace.settings_key (), mru);
 
   // Store dialog's options
   int opts = 0
-    + m_extension->isVisible () * FIND_DLG_MORE
-    + m_case_check_box->isChecked () * FIND_DLG_CASE
-    + m_from_start_check_box->isChecked () * FIND_DLG_START
-    + m_wrap_check_box->isChecked () * FIND_DLG_WRAP
-    + m_regex_check_box->isChecked () * FIND_DLG_REGX
-    + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS
-    + m_backward_check_box->isChecked () * FIND_DLG_BACK
-    + m_search_selection_check_box->isChecked () * FIND_DLG_SEL;
-  s->setValue (ed_fdlg_opts.key, opts);
+             + m_extension->isVisible () * FIND_DLG_MORE
+             + m_case_check_box->isChecked () * FIND_DLG_CASE
+             + m_from_start_check_box->isChecked () * FIND_DLG_START
+             + m_wrap_check_box->isChecked () * FIND_DLG_WRAP
+             + m_regex_check_box->isChecked () * FIND_DLG_REGX
+             + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS
+             + m_backward_check_box->isChecked () * FIND_DLG_BACK
+             + m_search_selection_check_box->isChecked () * FIND_DLG_SEL;
+  settings.setValue (ed_fdlg_opts.settings_key (), opts);
 
-  s->sync ();
+  settings.sync ();
 }
 
 void find_dialog::restore_settings (QPoint ed_bottom_right)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *s = rmgr.get_settings ();
+  gui_settings settings;
 
   // Get mru lists for search and replace text
-  QStringList mru = s->value (ed_fdlg_search.key).toStringList ();
+  QStringList mru = settings.value (ed_fdlg_search.settings_key ()).toStringList ();
   while (mru.length () > m_mru_length)
     mru.removeLast ();
   m_search_line_edit->addItems (mru);
 
-  mru = s->value (ed_fdlg_replace.key).toStringList ();
+  mru = settings.value (ed_fdlg_replace.settings_key ()).toStringList ();
   while (mru.length () > m_mru_length)
     mru.removeLast ();
   m_replace_line_edit->addItems (mru);
 
   // Get the dialog's options
-  int opts = s->value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt ();
+  int opts = settings.int_value (ed_fdlg_opts);
 
   m_extension->setVisible (FIND_DLG_MORE & opts);
   m_case_check_box->setChecked (FIND_DLG_CASE & opts);
@@ -298,7 +293,7 @@
   QRect default_geometry (xp, yp, sizeHint ().width (), sizeHint ().height ());
 
   // Last position from settings
-  m_last_position = s->value (ed_fdlg_pos.key, QPoint (xp, yp)).toPoint ();
+  m_last_position = settings.value (ed_fdlg_pos.settings_key (), QPoint (xp, yp)).toPoint ();
   QRect last_geometry (m_last_position,
                        QSize (sizeHint ().width (), sizeHint ().height ()));
 
@@ -319,7 +314,7 @@
 }
 
 // search text has changed: reset the search
-void find_dialog::handle_search_text_changed (void)
+void find_dialog::handle_search_text_changed ()
 {
   // Return if nothing has changed
   if (m_search_line_edit->currentText () == m_search_line_edit->itemText (0))
@@ -332,7 +327,7 @@
 }
 
 // replaced text has changed: reset the search
-void find_dialog::handle_replace_text_changed (void)
+void find_dialog::handle_replace_text_changed ()
 {
   // Return if nothing has changed
   if (m_replace_line_edit->currentText () == m_replace_line_edit->itemText (0))
@@ -384,7 +379,7 @@
 }
 
 // initialize search text with selected text if this is in one single line
-void find_dialog::init_search_text (void)
+void find_dialog::init_search_text ()
 {
   if (m_edit_area && m_edit_area->hasSelectedText ())
     {
@@ -403,12 +398,12 @@
   m_find_next_button->setDefault (true);
 }
 
-void find_dialog::find_next (void)
+void find_dialog::find_next ()
 {
   find (! m_backward_check_box->isChecked ());
 }
 
-void find_dialog::find_prev (void)
+void find_dialog::find_prev ()
 {
   find (m_backward_check_box->isChecked ());
 }
@@ -523,7 +518,7 @@
 #if defined (HAVE_QSCI_VERSION_2_6_0)
                               , true
 #endif
-                              );
+                             );
 
   if (m_find_result_available)
     {
@@ -566,7 +561,7 @@
 
 }
 
-void find_dialog::do_replace (void)
+void find_dialog::do_replace ()
 {
   if (m_edit_area)
     {
@@ -577,15 +572,15 @@
         {
           // Update the length of the selection
           m_sel_end = m_sel_end
-            - m_search_line_edit->currentText ().toUtf8 ().size ()
-            + m_replace_line_edit->currentText ().toUtf8 ().size ();
+                      - m_search_line_edit->currentText ().toUtf8 ().size ()
+                      + m_replace_line_edit->currentText ().toUtf8 ().size ();
         }
 
       m_rep_active = false;
     }
 }
 
-void find_dialog::replace (void)
+void find_dialog::replace ()
 {
   if (m_edit_area)
     {
@@ -599,7 +594,7 @@
     }
 }
 
-void find_dialog::replace_all (void)
+void find_dialog::replace_all ()
 {
   int line, col;
 
@@ -634,7 +629,7 @@
     }
 }
 
-void find_dialog::no_matches_message (void)
+void find_dialog::no_matches_message ()
 {
   QMessageBox msg_box (QMessageBox::Information, tr ("Find Result"),
                        tr ("No more matches found"), QMessageBox::Ok, this);
--- a/libgui/src/m-editor/find-dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/find-dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -79,7 +79,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class file_editor;
 
 class find_dialog : public QDialog
@@ -88,13 +87,13 @@
 
 public:
 
-  find_dialog (base_qobject& oct_qobj, octave_dock_widget *ed, QWidget *p);
+  find_dialog (octave_dock_widget *ed, QWidget *p);
 
   //! Set dialog visible or not and storing the new visibility state
   void set_visible (bool visible);
 
   //! Init the search text with the selected text in the editor tab
-  void init_search_text (void);
+  void init_search_text ();
 
   //! Restore position and the search options from the given settings
   //! where def_pos is the default position suitable for the current
@@ -103,8 +102,8 @@
 
 public slots:
 
-  void find_next (void);
-  void find_prev (void);
+  void find_next ();
+  void find_prev ();
 
   //! Slot for updating the edit area when the active tab has changed
   void update_edit_area (octave_qscintilla *);
@@ -117,13 +116,11 @@
   void handle_backward_search_changed (int);
 
   void find (bool forward = true);
-  void replace (void);
-  void replace_all (void);
+  void replace ();
+  void replace_all ();
 
 private:
 
-  base_qobject& m_octave_qobj;
-
   //! Save position and the search options in the given settings
   void save_settings ();
 
@@ -136,11 +133,11 @@
   //! Update mru lists with new entry
   void mru_update (QComboBox *mru);
 
-  void no_matches_message (void);
-  void do_replace (void);
+  void no_matches_message ();
+  void do_replace ();
 
-  void handle_search_text_changed (void);
-  void handle_replace_text_changed (void);
+  void handle_search_text_changed ();
+  void handle_replace_text_changed ();
 
   octave_dock_widget *m_editor;
 
--- a/libgui/src/m-editor/marker.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/marker.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -81,7 +81,7 @@
     }
 }
 
-void marker::handle_remove (void)
+void marker::handle_remove ()
 {
   m_edit_area->markerDeleteHandle (m_mhandle);
   delete this;
--- a/libgui/src/m-editor/marker.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/marker.h	Fri Jun 23 20:51:51 2023 +0200
@@ -68,9 +68,9 @@
           editor_markers marker_type, int editor_linenr,
           const QString& condition = "");
 
-  ~marker (void) = default;
+  ~marker () = default;
 
-  const QString& get_cond (void) const { return m_condition; }
+  const QString& get_cond () const { return m_condition; }
 
   void set_cond (const QString& cond) { m_condition = cond; }
 
@@ -82,14 +82,14 @@
 
   void handle_remove_via_original_linenr (int original_linenr);
   void handle_request_remove_via_editor_linenr (int editor_linenr);
-  void handle_remove (void);
+  void handle_remove ();
   void handle_find_translation (int original_linenr, int& editor_linenr,
                                 marker*& bp);
   void handle_find_just_before (int linenr, int& original_linenr,
                                 int& editor_linenr);
   void handle_find_just_after (int linenr, int& original_linenr,
                                int& editor_linenr);
-  /*  void handle_lines_changed (void);*/
+  /*  void handle_lines_changed ();*/
   void handle_marker_line_deleted (int mhandle);
   void handle_marker_line_undeleted (int mhandle);
   void handle_report_editor_linenr (QIntList& lines, QStringList& conditions);
--- a/libgui/src/m-editor/octave-qscintilla.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,9 @@
 #include <QKeySequence>
 #include <QMessageBox>
 #include <QMimeData>
-#include <QShortcut>
+#include <QPointer>
+#include <QRegularExpression>
+#include <QTemporaryFile>
 #include <QToolTip>
 #include <QVBoxLayout>
 #if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)
@@ -54,17 +56,17 @@
 
 #include "file-editor-tab.h"
 #include "gui-preferences-ed.h"
+#include "gui-settings.h"
 // FIXME: hardwired marker numbers?
 #include "marker.h"
-#include "octave-qobject.h"
 #include "octave-qscintilla.h"
-#include "shortcut-manager.h"
 #include "workspace-model.h"
 
 #include "builtin-defun-decls.h"
 #include "cmd-edit.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
+#include "oct-env.h"
 
 // Return true if CANDIDATE is a "closing" that matches OPENING,
 // such as "end" or "endif" for "if", or "catch" for "try".
@@ -110,13 +112,13 @@
   return retval;
 }
 
-octave_qscintilla::octave_qscintilla (QWidget *p, base_qobject& oct_qobj)
-  : QsciScintilla (p), m_octave_qobj (oct_qobj), m_debug_mode (false),
-    m_word_at_cursor (), m_selection (), m_selection_replacement (),
-    m_selection_line (-1), m_selection_col (-1), m_indicator_id (1)
+octave_qscintilla::octave_qscintilla (QWidget *p)
+  : QsciScintilla (p), m_debug_mode (false), m_word_at_cursor (),
+    m_selection (), m_selection_replacement (), m_selection_line (-1),
+    m_selection_col (-1), m_indicator_id (1)
 {
-  connect (this, SIGNAL (textChanged (void)),
-           this, SLOT (text_changed (void)));
+  connect (this, SIGNAL (textChanged ()),
+           this, SLOT (text_changed ()));
 
   connect (this, SIGNAL (cursorPositionChanged (int, int)),
            this, SLOT (cursor_position_changed (int, int)));
@@ -334,20 +336,30 @@
 void octave_qscintilla::contextmenu_help_doc (bool documentation)
 {
   if (documentation)
-    m_octave_qobj.show_documentation_window (m_word_at_cursor);
+    {
+      std::string name = m_word_at_cursor.toStdString ();
+
+      emit interpreter_event
+        ([=] (interpreter& interp)
+         {
+           // INTERPRETER THREAD
+
+           F__event_manager_show_documentation__ (interp, ovl (name));
+         });
+    }
   else
     emit execute_command_in_terminal_signal ("help " + m_word_at_cursor);
 }
 
 // call edit the function related to the current word
-void octave_qscintilla::context_edit (void)
+void octave_qscintilla::context_edit ()
 {
   if (get_actual_word ())
     contextmenu_edit (true);
 }
 
 // call edit the function related to the current word
-void octave_qscintilla::context_run (void)
+void octave_qscintilla::context_run ()
 {
   if (hasSelectedText ())
     {
@@ -355,7 +367,7 @@
 
       emit interpreter_event
         ([] (interpreter&)
-        { command_editor::erase_empty_line (false); });
+          { command_editor::erase_empty_line (false); });
     }
 }
 
@@ -370,7 +382,7 @@
 }
 
 // determine the actual word and whether we are in an octave or matlab script
-bool octave_qscintilla::get_actual_word (void)
+bool octave_qscintilla::get_actual_word ()
 {
   QPoint global_pos, local_pos;
   get_global_textcursor_pos (&global_pos, &local_pos);
@@ -381,7 +393,7 @@
 }
 
 // helper function for clearing all indicators of a specific style
-void octave_qscintilla::clear_selection_markers (void)
+void octave_qscintilla::clear_selection_markers ()
 {
   int end_pos = text ().length ();
   int end_line, end_col;
@@ -391,7 +403,7 @@
   markerDeleteAll (marker::selection);
 }
 
-QString octave_qscintilla::eol_string (void)
+QString octave_qscintilla::eol_string ()
 {
   switch (eolMode ())
     {
@@ -430,20 +442,20 @@
     case SCLEX_MATLAB:
 #endif
       {
-        resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-        gui_settings *settings = rmgr.get_settings ();
+        gui_settings settings;
+
         int comment_string;
 
         if (comment)
           {
             // The commenting string is requested
-            if (settings->contains (ed_comment_str.key))
+            if (settings.contains (ed_comment_str.settings_key ()))
               // new version (radio buttons)
-              comment_string = settings->value (ed_comment_str).toInt ();
+              comment_string = settings.int_value (ed_comment_str);
             else
               // old version (combo box)
-              comment_string = settings->value (ed_comment_str_old.key,
-                                                ed_comment_str.def).toInt ();
+              comment_string = settings.value (ed_comment_str_old.settings_key (),
+                                               ed_comment_str.def ()).toInt ();
 
             return (QStringList (ed_comment_strings.at (comment_string)));
           }
@@ -452,7 +464,7 @@
             QStringList c_str;
 
             // The possible uncommenting string(s) are requested
-            comment_string = settings->value (ed_uncomment_str).toInt ();
+            comment_string = settings.int_value (ed_uncomment_str);
 
             for (int i = 0; i < ed_comment_strings_count; i++)
               {
@@ -542,31 +554,32 @@
 {
   QString prevline = text (line);
 
-  QRegExp bkey = QRegExp ("^[\t ]*(if|for|while|switch"
-                          "|do|function|properties|events|classdef"
-                          "|unwind_protect|try"
-                          "|parfor|methods)"
-                          "[\r]?[\n\t #%]");
+  QRegularExpression bkey {"^[\t ]*(if|for|while|switch"
+                           "|do|function|properties|events|classdef"
+                           "|unwind_protect|try"
+                           "|parfor|methods)"
+                           "[\r]?[\n\t #%]"};
   // last word except for comments, assuming no ' or " in comment.
   // rx_end = QRegExp ("(\\w+)[ \t;\r\n]*([%#][^\"']*)?$");
 
   // last word except for comments,
   // allowing % and # in single or double quoted strings
   // FIXME: This will get confused by transpose.
-  QRegExp ekey = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*"
-                          "(\\w+)[ \t;\r\n]*(?:[%#].*)?$");
+  QRegularExpression ekey {"(?:(?:['\"][^'\"]*['\"])?[^%#]*)*"
+                           "(\\w+)[ \t;\r\n]*(?:[%#].*)?$"};
 
-  int bpos = bkey.indexIn (prevline, 0);
-  int epos;
+  QRegularExpressionMatch bmatch = bkey.match (prevline);
 
-  if (bpos > -1)
+  if (bmatch.hasMatch ())
     {
       // Found keyword after that indentation should be added
 
       // Check for existing end statement in the same line
-      epos = ekey.indexIn (prevline, bpos);
-      QString first_word = bkey.cap(1);
-      bool inline_end = (epos > -1) && is_end (ekey.cap(1), first_word);
+      QRegularExpressionMatch ematch = ekey.match (prevline,
+                                                   bmatch.capturedStart ());
+      QString first_word = bmatch.captured (1);
+      bool inline_end = ematch.hasMatch ()
+                        && is_end (ematch.captured (1), first_word);
 
       if (do_smart_indent && ! inline_end)
         {
@@ -577,7 +590,9 @@
 
       if (do_auto_close
           && ! inline_end
-          && ! first_word.contains (QRegExp ("(?:case|otherwise|unwind_protect_cleanup)")))
+          && ! first_word.contains
+                            (QRegularExpression
+                             {"(?:case|otherwise|unwind_protect_cleanup)"}))
         {
           // Do auto close
           auto_close (do_auto_close, line, prevline, first_word);
@@ -586,8 +601,8 @@
       return;
     }
 
-  QRegExp mkey = QRegExp ("^[\t ]*(?:else|elseif|catch|unwind_protect_cleanup)"
-                          "[\r]?[\t #%\n]");
+  QRegularExpression mkey {"^[\t ]*(?:else|elseif|catch|unwind_protect_cleanup)"
+                           "[\r]?[\t #%\n]"};
   if (prevline.contains (mkey))
     {
       int prev_ind = indentation (line-1);
@@ -603,14 +618,14 @@
       return;
     }
 
-  QRegExp case_key = QRegExp ("^[\t ]*(?:case|otherwise)[\r]?[\t #%\n]");
+  QRegularExpression case_key {"^[\t ]*(?:case|otherwise)[\r]?[\t #%\n]"};
   if (prevline.contains (case_key) && do_smart_indent)
     {
       QString last_line = text (line-1);
       int prev_ind = indentation (line-1);
       int act_ind = indentation (line);
 
-      if (last_line.contains (QRegExp ("^[\t ]*switch")))
+      if (last_line.contains (QRegularExpression {"^[\t ]*switch"}))
         {
           indent (line+1);
           act_ind = indentation (line+1);
@@ -627,8 +642,9 @@
       setCursorPosition (line+1, act_ind);
     }
 
-  ekey = QRegExp ("^[\t ]*(?:end|endif|endfor|endwhile|until|endfunction"
-                  "|endswitch|end_try_catch|end_unwind_protect)[\r]?[\t #%\n(;]");
+  ekey = QRegularExpression
+           {"^[\t ]*(?:end|endif|endfor|endwhile|until|endfunction"
+            "|endswitch|end_try_catch|end_unwind_protect)[\r]?[\t #%\n(;]"};
   if (prevline.contains (ekey))
     {
       if (indentation (line-1) <= indentation (line))
@@ -652,38 +668,40 @@
 void octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom,
                                                             int lineTo)
 {
-  QRegExp blank_line_regexp = QRegExp ("^[\t ]*$");
+  QRegularExpression blank_line_regexp {"^[\t ]*$"};
 
   // end[xxxxx] [# comment] at end of a line
-  QRegExp end_word_regexp
-    = QRegExp ("(?:(?:['\"][^'\"]*['\"])?[^%#]*)*"
-               "(?:end\\w*)[\r\n\t ;]*(?:[%#].*)?$");
+  QRegularExpression
+  end_word_regexp {"(?:(?:['\"][^'\"]*['\"])?[^%#]*)*"
+                   "(?:end\\w*)[\r\n\t ;]*(?:[%#].*)?$"};
 
-  QRegExp begin_block_regexp
-    = QRegExp ("^[\t ]*(?:if|elseif|else"
-               "|for|while|do|parfor"
-               "|switch|case|otherwise"
-               "|function"
-               "|classdef|properties|events|enumeration|methods"
-               "|unwind_protect|unwind_protect_cleanup|try|catch)"
-               "[\r\n\t #%]");
+  QRegularExpression
+  begin_block_regexp {"^[\t ]*(?:if|elseif|else"
+                      "|for|while|do|parfor"
+                      "|switch|case|otherwise"
+                      "|function"
+                      "|classdef|properties|events|enumeration|methods"
+                      "|unwind_protect|unwind_protect_cleanup|try|catch)"
+                      "[\r\n\t #%]"};
 
-  QRegExp mid_block_regexp
-    = QRegExp ("^[\t ]*(?:elseif|else"
-               "|unwind_protect_cleanup|catch)"
-               "[\r\n\t #%]");
+  QRegularExpression
+  mid_block_regexp {"^[\t ]*(?:elseif|else"
+                    "|unwind_protect_cleanup|catch)"
+                    "[\r\n\t #%]"};
 
-  QRegExp end_block_regexp
-    = QRegExp ("^[\t ]*(?:end"
-               "|end(for|function|if|parfor|switch|while"
-               "|classdef|enumeration|events|methods|properties)"
-               "|end_(try_catch|unwind_protect)"
-               "|until)"
-               "[\r\n\t #%]");
+  QRegularExpression
+  end_block_regexp {"^[\t ]*(?:end"
+                    "|end(for|function|if|parfor|switch|while"
+                    "|classdef|enumeration|events|methods|properties)"
+                    "|end_(try_catch|unwind_protect)"
+                    "|until)"
+                    "[\r\n\t #%]"};
 
-  QRegExp case_block_regexp
-    = QRegExp ("^[\t ]*(?:case|otherwise)"
-               "[\r\n\t #%]");
+  QRegularExpression
+  case_block_regexp {"^[\t ]*(?:case|otherwise)"
+                     "[\r\n\t #%]"};
+
+  QRegularExpressionMatch match;
 
   int indent_column = -1;
   int indent_increment = indentationWidth ();
@@ -693,7 +711,8 @@
     {
       QString line_text = text (line);
 
-      if (blank_line_regexp.indexIn (line_text) < 0)
+      match = blank_line_regexp.match (line_text);
+      if (! match.hasMatch ())
         {
           // Found first non-blank line above beginning of region or
           // current line.  Base indentation from this line, increasing
@@ -702,7 +721,8 @@
 
           indent_column = indentation (line);
 
-          if (begin_block_regexp.indexIn (line_text) > -1)
+          match = begin_block_regexp.match (line_text);
+          if (match.hasMatch ())
             {
               indent_column += indent_increment;
               if (line_text.contains ("switch"))
@@ -721,7 +741,8 @@
     {
       QString line_text = text (line);
 
-      if (end_block_regexp.indexIn (line_text) > -1)
+      match = end_block_regexp.match (line_text);
+      if (match.hasMatch ())
         {
           indent_column -= indent_increment;
           if (line_text.contains ("endswitch"))
@@ -733,31 +754,35 @@
             }
         }
 
-      if (mid_block_regexp.indexIn (line_text) > -1)
+      match = mid_block_regexp.match (line_text);
+      if (match.hasMatch ())
         indent_column -= indent_increment;
 
-      if (case_block_regexp.indexIn (line_text) > -1)
+      match = case_block_regexp.match (line_text);
+      if (match.hasMatch ())
         {
-          if (case_block_regexp.indexIn (prev_line) < 0
-              && !prev_line.contains("switch"))
+          match = case_block_regexp.match (prev_line);
+          if (! match.hasMatch ()
+              && ! prev_line.contains ("switch"))
             indent_column -= indent_increment;
           in_switch = true;
         }
 
       setIndentation (line, indent_column);
 
-      int bpos = begin_block_regexp.indexIn (line_text);
-      if (bpos > -1)
+      match = begin_block_regexp.match (line_text);
+      if (match.hasMatch ())
         {
           // Check for existing end statement in the same line
-          int epos = end_word_regexp.indexIn (line_text, bpos);
-          if (epos == -1)
+          match = end_word_regexp.match (line_text, match.capturedStart ());
+          if (! match.hasMatch ())
             indent_column += indent_increment;
           if (line_text.contains ("switch"))
             in_switch = true;
         }
 
-      if (blank_line_regexp.indexIn (line_text) < 0)
+      match = blank_line_regexp.match (line_text);
+      if (! match.hasMatch ())
         prev_line = line_text;
     }
 }
@@ -813,7 +838,7 @@
   emit context_menu_edit_signal (m_word_at_cursor);
 }
 
-void octave_qscintilla::contextmenu_run_temp_error (void)
+void octave_qscintilla::contextmenu_run_temp_error ()
 {
   QMessageBox::critical (this, tr ("Octave Editor"),
                          tr ("Creating temporary files failed.\n"
@@ -824,222 +849,217 @@
 
 void octave_qscintilla::contextmenu_run (bool)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
   // Take selected code and extend it by commands for echoing each
   // evaluated line and for adding the line to the history (use script)
   QString code = QString ();
   QString hist = QString ();
 
   // Split contents into single lines and complete commands
-  QStringList lines = selectedText ().split (QRegExp ("[\r\n]"),
+  QStringList lines = selectedText ().split (QRegularExpression {"[\r\n]"},
 #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
                                              Qt::SkipEmptyParts);
 #else
-  QString::SkipEmptyParts);
+                                             QString::SkipEmptyParts);
 #endif
-for (int i = 0; i < lines.count (); i++)
-  {
-    QString line = lines.at (i);
-    if (line.trimmed ().isEmpty ())
-      continue;
-    QString line_escaped = line;
-    line_escaped.replace (QString ("'"), QString ("''"));
-    QString line_history = line;
+  for (int i = 0; i < lines.count (); i++)
+    {
+      QString line = lines.at (i);
+      if (line.trimmed ().isEmpty ())
+        continue;
+      QString line_escaped = line;
+      line_escaped.replace (QString ("'"), QString ("''"));
+      QString line_history = line;
 
-    // Prevent output of breakpoint in temp. file for keyboard
-    QString next_bp_quiet;
-    QString next_bp_quiet_reset;
-    if (line.contains ("keyboard"))
-      {
-        // Define commands for not showing bp location and for resetting
-        // this in case "keyboard" was within a comment
-        next_bp_quiet = "__db_next_breakpoint_quiet__;\n";
-        next_bp_quiet_reset = "\n__db_next_breakpoint_quiet__(false);";
-      }
+      // Prevent output of breakpoint in temp. file for keyboard
+      QString next_bp_quiet;
+      QString next_bp_quiet_reset;
+      if (line.contains ("keyboard"))
+        {
+          // Define commands for not showing bp location and for resetting
+          // this in case "keyboard" was within a comment
+          next_bp_quiet = "__db_next_breakpoint_quiet__;\n";
+          next_bp_quiet_reset = "\n__db_next_breakpoint_quiet__(false);";
+        }
 
-    // Add codeline
-    code += next_bp_quiet + line + next_bp_quiet_reset + "\n";
-    hist += line_history + "\n";
-  }
+      // Add codeline
+      code += next_bp_quiet + line + next_bp_quiet_reset + "\n";
+      hist += line_history + "\n";
+    }
 
-octave_stdout << hist.toStdString ();
+  octave_stdout << hist.toStdString ();
 
-// Create tmp file with the code to be executed by the interpreter
-QPointer<QTemporaryFile> tmp_file
-= rmgr.create_tmp_file ("m", code);
+  // Create tmp file with the code to be executed by the interpreter
+  QPointer<QTemporaryFile> tmp_file = create_tmp_file ("m", code);
 
-bool tmp = (tmp_file && tmp_file->open ());
-if (! tmp)
-  {
-    // tmp files not working: use old way to run selection
-    contextmenu_run_temp_error ();
-    return;
-  }
-
-tmp_file->close ();
+  if (tmp_file && tmp_file->open ())
+    tmp_file->close ();
+  else
+    {
+      // tmp files not working: use old way to run selection
+      contextmenu_run_temp_error ();
+      return;
+    }
 
-// Create tmp file required for adding command to history
-QPointer<QTemporaryFile> tmp_hist
-= rmgr.create_tmp_file ("", hist); // empty tmp file for history
+  // Create tmp file required for adding command to history
+  QPointer<QTemporaryFile> tmp_hist = create_tmp_file ("", hist);
 
-tmp = (tmp_hist && tmp_hist->open ());
-if (! tmp)
-  {
-    // tmp files not working: use old way to run selection
-    contextmenu_run_temp_error ();
-    return;
-  }
+  if (tmp_hist && tmp_hist->open ())
+    tmp_hist->close ();
+  else
+    {
+      // tmp files not working: use old way to run selection
+      contextmenu_run_temp_error ();
+      return;
+    }
 
-tmp_hist->close ();
+  // Add commands to the history
+  emit interpreter_event
+    ([=] (interpreter& interp)
+      {
+        // INTERPRETER THREAD
 
-// Add commands to the history
-emit interpreter_event
-([=] (interpreter& interp)
- {
-   // INTERPRETER THREAD
+        if (tmp_hist.isNull ())
+          return;
 
-   if (tmp_hist.isNull ())
-     return;
+        std::string opt = "-r";
+        std::string  path = tmp_hist->fileName ().toStdString ();
 
-   std::string opt = "-r";
-   std::string  path = tmp_hist->fileName ().toStdString ();
+        Fhistory (interp, ovl (opt, path));
+      });
+
+  // Disable opening a file at a breakpoint in case keyboard () is used
+  gui_settings settings;
 
-   Fhistory (interp, ovl (opt, path));
- });
+  bool show_dbg_file = settings.bool_value (ed_show_dbg_file);
+  settings.setValue (ed_show_dbg_file.settings_key (), false);
 
-// Disable opening a file at a breakpoint in case keyboard () is used
-gui_settings *settings = rmgr.get_settings ();
-bool show_dbg_file = settings->value (ed_show_dbg_file).toBool ();
-settings->setValue (ed_show_dbg_file.key, false);
+  // The interpreter_event callback function below emits a signal.
+  // Because we don't control when that happens, use a guarded pointer
+  // so that the callback can abort if this object is no longer valid.
 
-// The interpreter_event callback function below emits a signal.
-// Because we don't control when that happens, use a guarded pointer
-// so that the callback can abort if this object is no longer valid.
-
-QPointer<octave_qscintilla> this_oq (this);
-
-// Let the interpreter execute the tmp file
-emit interpreter_event
-([=] (interpreter& interp)
- {
-   // INTERPRETER THREAD
-
-   // FIXME: For now, just skip the entire callback if THIS_OQ is no
-   // longer valid.  Maybe there is a better way to do this job?
-
-   if (this_oq.isNull ())
-     return;
+  QPointer<octave_qscintilla> this_oq (this);
 
-   std::string file = tmp_file->fileName ().toStdString ();
-
-   std::string pending_input = command_editor::get_current_line ();
-
-   int err_line = -1;   // For storing the line of a poss. error
-
-   // Get current state of auto command repeat in debug mode
-   octave_value_list ovl_dbg = Fisdebugmode (interp);
-   bool dbg = ovl_dbg(0).bool_value ();
-   octave_value_list ovl_auto_repeat = ovl (true);
-   if (dbg)
-     ovl_auto_repeat = Fauto_repeat_debug_command (interp, ovl (false), 1);
-   bool auto_repeat = ovl_auto_repeat(0).bool_value ();
-
-   try
-     {
-       // Do the job
-       interp.source_file (file);
-     }
-   catch (const execution_exception& ee)
+  // Let the interpreter execute the tmp file
+  emit interpreter_event
+    ([=] (interpreter& interp)
      {
-       // Catch errors otherwise the rest of the interpreter
-       // will not be executed (cleaning up).
+       // INTERPRETER THREAD
+
+       // FIXME: For now, just skip the entire callback if THIS_OQ is
+       // no longer valid.  Maybe there is a better way to do this
+       // job?
 
-       // New error message and error stack
-       QString new_msg = QString::fromStdString (ee.message ());
-       std::list<frame_info> stack = ee.stack_info ();
+       if (this_oq.isNull ())
+         return;
+
+       std::string file = tmp_file->fileName ().toStdString ();
+
+       std::string pending_input = command_editor::get_current_line ();
+
+       int err_line = -1;   // For storing the line of a poss. error
 
-       // Remove line and column from first line of error message only
-       // if it is related to the tmp itself, i.e. only if the
-       // the error stack size is 0, 1, or, if in debug mode, 2
-       size_t max_stack_size = 1;
+       // Get current state of auto command repeat in debug mode
+       octave_value_list ovl_dbg = Fisdebugmode (interp);
+       bool dbg = ovl_dbg(0).bool_value ();
+       octave_value_list ovl_auto_repeat = ovl (true);
        if (dbg)
-         max_stack_size = 2;
-       if (stack.size () <= max_stack_size)
+         ovl_auto_repeat = Fauto_repeat_debug_command (interp, ovl (false), 1);
+       bool auto_repeat = ovl_auto_repeat(0).bool_value ();
+
+       try
+         {
+           // Do the job
+           interp.source_file (file);
+         }
+       catch (const execution_exception& ee)
          {
-           QRegExp rx ("source: error sourcing file [^\n]*$");
-           if (new_msg.contains (rx))
+           // Catch errors otherwise the rest of the interpreter
+           // will not be executed (cleaning up).
+
+           // New error message and error stack
+           QString new_msg = QString::fromStdString (ee.message ());
+           std::list<frame_info> stack = ee.stack_info ();
+
+           // Remove line and column from first line of error message only
+           // if it is related to the tmp itself, i.e. only if the
+           // the error stack size is 0, 1, or, if in debug mode, 2
+           size_t max_stack_size = 1;
+           if (dbg)
+             max_stack_size = 2;
+           if (stack.size () <= max_stack_size)
              {
-               // Selected code has syntax errors
-               new_msg.replace (rx, "error sourcing selected code");
-               err_line = 0;  // Nothing into history?
-             }
-           else
-             {
-               // Normal error, detect line and remove file
-               // name from message
-               QStringList rx_list;
-               rx_list << "near line (\\d+),[^\n]*\n";
-               rx_list << "near line (\\d+),[^\n]*$";
+               QRegularExpression rx {"source: error sourcing file [^\n]*$"};
+               if (new_msg.contains (rx))
+                 {
+                   // Selected code has syntax errors
+                   new_msg.replace (rx, "error sourcing selected code");
+                   err_line = 0;  // Nothing into history?
+                 }
+               else
+                 {
+                   // Normal error, detect line and remove file
+                   // name from message
+                   QStringList rx_list;
+                   rx_list << "near line (\\d+),[^\n]*\n";
+                   rx_list << "near line (\\d+),[^\n]*$";
 
-               QStringList replace_list;
-               replace_list << "\n";
-               replace_list << "";
+                   QStringList replace_list;
+                   replace_list << "\n";
+                   replace_list << "";
 
-               for (int i = 0; i < rx_list.length (); i++)
-                 {
-                   int pos = 0;
-                   rx = QRegExp (rx_list.at (i));
-                   pos = rx.indexIn (new_msg, pos);
-                   if (pos != -1)
+                   for (int i = 0; i < rx_list.length (); i++)
                      {
-                       err_line = rx.cap (1).toInt ();
-                       new_msg = new_msg.replace (rx, replace_list.at (i));
+                       rx = QRegularExpression {rx_list.at (i)};
+                       QRegularExpressionMatch match = rx.match(new_msg);
+                       if (match.hasMatch ())
+                         {
+                           err_line = match.captured (1).toInt ();
+                           new_msg = new_msg.replace (rx, replace_list.at (i));
+                         }
                      }
                  }
              }
+
+           // Drop first stack level, which is the temporary function file,
+           // or, if in debug mode, drop first two stack levels
+           if (stack.size () > 0)
+             stack.pop_back ();
+           if (dbg && (stack.size () > 0))
+             stack.pop_back ();
+
+           // Clean up before throwing the modified error.
+           emit ctx_menu_run_finished_signal (show_dbg_file, err_line,
+                                              tmp_file, tmp_hist,
+                                              dbg, auto_repeat);
+
+           // New exception with updated message and stack
+           execution_exception nee (ee.err_type (), ee.identifier (),
+                                    new_msg.toStdString (), stack);
+
+           // Throw
+           throw (nee);
          }
 
-       // Drop first stack level, which is the temporary function file,
-       // or, if in debug mode, drop first two stack levels
-       if (stack.size () > 0)
-         stack.pop_back ();
-       if (dbg && (stack.size () > 0))
-         stack.pop_back ();
+       // Clean up
 
-       // Clean up before throwing the modified error.
        emit ctx_menu_run_finished_signal (show_dbg_file, err_line,
                                           tmp_file, tmp_hist,
                                           dbg, auto_repeat);
 
-       // New exception with updated message and stack
-       execution_exception nee (ee.err_type (), ee.identifier (),
-                                new_msg.toStdString (), stack);
-
-       // Throw
-       throw (nee);
-     }
-
-   // Clean up
+       command_editor::erase_empty_line (true);
+       command_editor::replace_line ("");
+       command_editor::set_initial_input (pending_input);
+       command_editor::redisplay ();
+       command_editor::interrupt_event_loop ();
+       command_editor::accept_line ();
+       command_editor::erase_empty_line (true);
 
-   emit ctx_menu_run_finished_signal (show_dbg_file, err_line,
-                                      tmp_file, tmp_hist,
-                                      dbg, auto_repeat);
-
-   command_editor::erase_empty_line (true);
-   command_editor::replace_line ("");
-   command_editor::set_initial_input (pending_input);
-   command_editor::redisplay ();
-   command_editor::interrupt_event_loop ();
-   command_editor::accept_line ();
-   command_editor::erase_empty_line (true);
-
- });
+     });
 }
 
-void octave_qscintilla::ctx_menu_run_finished (bool show_dbg_file, int,
-                                               QTemporaryFile* tmp_file, QTemporaryFile* tmp_hist,
-                                               bool dbg, bool auto_repeat)
+void octave_qscintilla::ctx_menu_run_finished
+  (bool show_dbg_file, int, QPointer<QTemporaryFile> tmp_file,
+   QPointer<QTemporaryFile> tmp_hist, bool dbg, bool auto_repeat)
 {
   emit focus_console_after_command_signal ();
 
@@ -1047,19 +1067,24 @@
   //       lines from history that were never executed. For this,
   //       possible lines from commands at a debug prompt must be
   //       taken into consideration.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  settings->setValue (ed_show_dbg_file.key, show_dbg_file);
-  rmgr.remove_tmp_file (tmp_file);
-  rmgr.remove_tmp_file (tmp_hist);
+
+  gui_settings settings;
+
+  settings.setValue (ed_show_dbg_file.settings_key (), show_dbg_file);
+
+  if (tmp_file && tmp_file->exists ())
+    tmp_file->remove ();
+
+  if (tmp_hist && tmp_hist->exists ())
+    tmp_hist->remove ();
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-      if (dbg)
-        Fauto_repeat_debug_command (interp, ovl (auto_repeat));
-    });
+     {
+       // INTERPRETER THREAD
+       if (dbg)
+         Fauto_repeat_debug_command (interp, ovl (auto_repeat));
+     });
 }
 
 // wrappers for dbstop related context menu items
@@ -1088,7 +1113,7 @@
 #endif
 }
 
-void octave_qscintilla::text_changed (void)
+void octave_qscintilla::text_changed ()
 {
   emit status_update (isUndoAvailable (), isRedoAvailable ());
 }
@@ -1113,14 +1138,14 @@
   QsciScintilla::focusInEvent (focusEvent);
 }
 
-void octave_qscintilla::show_replace_action_tooltip (void)
+void octave_qscintilla::show_replace_action_tooltip ()
 {
   int pos;
   get_current_position (&pos, &m_selection_line, &m_selection_col);
 
   // Offer to replace other instances.
 
-  QKeySequence keyseq = Qt::SHIFT + Qt::Key_Return;
+  QKeySequence keyseq = Qt::SHIFT | Qt::Key_Return;
 
   QString msg = (tr ("Press '%1' to replace all occurrences of '%2' with '%3'.")
                  . arg (keyseq.toString ())
@@ -1187,23 +1212,13 @@
 {
   if (m_debug_mode && e->type() == QEvent::ToolTip)
     {
-      QHelpEvent *help_e = static_cast<QHelpEvent *>(e);
-      QString variable = wordAtPoint (help_e->pos());
-      QStringList symbol_names
-        = m_octave_qobj.get_workspace_model ()->get_symbol_names ();
-      int symbol_idx = symbol_names.indexOf (variable);
-      if (symbol_idx > -1)
-        {
-          QStringList symbol_values
-            = m_octave_qobj.get_workspace_model ()->get_symbol_values ();
-          QToolTip::showText (help_e->globalPos(), variable
-                              + " = " + symbol_values.at (symbol_idx));
-        }
-      else
-        {
-          QToolTip::hideText();
-          e->ignore();
-        }
+      // FIXME: can we handle display of a tooltip using an
+      // interpreter event or a custom signal/slot connection?
+
+      QHelpEvent *help_e = static_cast<QHelpEvent *> (e);
+      QString symbol = wordAtPoint (help_e->pos());
+
+      emit show_symbol_tooltip_signal (help_e->globalPos (), symbol);
 
       return true;
     }
@@ -1286,7 +1301,7 @@
   if (linenr < lines () - 1)
     {
       int offset = 2;     // linenr is the old line, thus, linnr+1 is the
-      // new one and can not be taken into account
+                          // new one and can not be taken into account
       std::size_t next_start;
       QString next_line;
 
@@ -1306,9 +1321,9 @@
         return;
       if (next_start == start)      // same => check if already is "end"
         {
-          QRegExp rx_start = QRegExp (R"((\w+))");
-          int tmp = rx_start.indexIn (next_line, start);
-          if (tmp != -1 && is_end (rx_start.cap(1), first_word))
+          QRegularExpression rx_start {R"((\w+))"};
+          QRegularExpressionMatch match = rx_start.match (next_line, start);
+          if (match.hasMatch () && is_end (match.captured (1), first_word))
             return;
         }
     }
@@ -1367,16 +1382,40 @@
     }
 }
 
-void octave_qscintilla::handle_enter_debug_mode (void)
+void octave_qscintilla::handle_enter_debug_mode ()
 {
   m_debug_mode = true;
 }
 
-void octave_qscintilla::handle_exit_debug_mode (void)
+void octave_qscintilla::handle_exit_debug_mode ()
 {
   m_debug_mode = false;
 }
 
+QPointer<QTemporaryFile>
+octave_qscintilla::create_tmp_file (const QString& extension,
+                                    const QString& contents)
+{
+  QString ext = extension;
+  if ((! ext.isEmpty ()) && (! ext.startsWith ('.')))
+    ext = QString (".") + ext;
+
+  // Create octave dir within temp. dir
+  QString tmp_dir = QString::fromStdString (sys::env::get_temp_directory ());
+
+  QString tmp_name = tmp_dir + QDir::separator() + "octave_XXXXXX" + ext;
+
+  QPointer<QTemporaryFile> tmp_file (new QTemporaryFile (tmp_name, this));
+
+  if (! contents.isEmpty () && tmp_file && tmp_file->open ())
+    {
+      tmp_file->write (contents.toUtf8 ());
+      tmp_file->close ();
+    }
+
+  return tmp_file;
+}
+
 OCTAVE_END_NAMESPACE(octave)
 
 #endif
--- a/libgui/src/m-editor/octave-qscintilla.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,25 +30,24 @@
 #include <QKeyEvent>
 #include <QLabel>
 #include <QMenu>
+#include <QPointer>
+#include <QTemporaryFile>
 #include <Qsci/qsciscintilla.h>
-#include <QTemporaryFile>
 
 #include "gui-settings.h"
 #include "qt-interpreter-events.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class octave_qscintilla : public QsciScintilla
 {
   Q_OBJECT
 
 public:
 
-  octave_qscintilla (QWidget *p, base_qobject& oct_qobj);
+  octave_qscintilla (QWidget *p);
 
-  ~octave_qscintilla (void) = default;
+  ~octave_qscintilla () = default;
 
   enum
     {
@@ -61,12 +60,12 @@
   virtual void setCursorPosition (int line, int col);
 
   void context_help_doc (bool);
-  void context_edit (void);
-  void context_run (void);
+  void context_edit ();
+  void context_run ();
   void get_global_textcursor_pos (QPoint *global_pos, QPoint *local_pos);
-  bool get_actual_word (void);
-  void clear_selection_markers (void);
-  QString eol_string (void);
+  bool get_actual_word ();
+  void clear_selection_markers ();
+  QString eol_string ();
   void get_current_position (int *pos, int *line, int *col);
   QStringList comment_string (bool comment = true);
   int get_style (int pos = -1);
@@ -94,43 +93,44 @@
   void qsci_has_focus_signal (bool);
   void status_update (bool, bool);
   void show_doc_signal (const QString&);
+  void show_symbol_tooltip_signal (const QPoint&, const QString&);
   void context_menu_break_condition_signal (int);
   void context_menu_break_once (int);
-  void ctx_menu_run_finished_signal (bool, int, QTemporaryFile *,
-                                     QTemporaryFile *, bool, bool);
-  void focus_console_after_command_signal (void);
+  void ctx_menu_run_finished_signal (bool, int, QPointer<QTemporaryFile>,
+                                     QPointer<QTemporaryFile>, bool, bool);
+  void focus_console_after_command_signal ();
 
   void interpreter_event (const fcn_callback& fcn);
   void interpreter_event (const meth_callback& meth);
 
 public slots:
 
-  void handle_enter_debug_mode (void);
-  void handle_exit_debug_mode (void);
+  void handle_enter_debug_mode ();
+  void handle_exit_debug_mode ();
 
 private slots:
 
-  void ctx_menu_run_finished (bool, int, QTemporaryFile *, QTemporaryFile *,
-                              bool, bool);
+  void ctx_menu_run_finished (bool, int, QPointer<QTemporaryFile>,
+                              QPointer<QTemporaryFile>, bool, bool);
 
   void contextmenu_help (bool);
   void contextmenu_doc (bool);
   void contextmenu_help_doc (bool);
   void contextmenu_edit (bool);
   void contextmenu_run (bool);
-  void contextmenu_run_temp_error (void);
+  void contextmenu_run_temp_error ();
 
   void contextmenu_break_condition (bool);
   void contextmenu_break_once (const QPoint&);
 
-  void text_changed (void);
+  void text_changed ();
   void cursor_position_changed (int, int);
 
 protected:
 
   void focusInEvent (QFocusEvent *focusEvent);
 
-  void show_replace_action_tooltip (void);
+  void show_replace_action_tooltip ();
 
   bool event (QEvent *e);
 
@@ -143,7 +143,8 @@
   void auto_close (int auto_endif, int l,
                    const QString& line, QString& first_word);
 
-  base_qobject& m_octave_qobj;
+  QPointer<QTemporaryFile> create_tmp_file (const QString& extension,
+                                            const QString& contents);
 
   bool m_debug_mode;
 
--- a/libgui/src/m-editor/octave-txt-lexer.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/octave-txt-lexer.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,12 +43,12 @@
     return QString ();
 };
 
-const char * octave_txt_lexer::language (void) const
+const char * octave_txt_lexer::language () const
 {
   return "Text";
 }
 
-const char * octave_txt_lexer::lexer (void) const
+const char * octave_txt_lexer::lexer () const
 {
   return "text";
 }
--- a/libgui/src/m-editor/octave-txt-lexer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/m-editor/octave-txt-lexer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,9 +37,9 @@
 
 public:
 
-  virtual const char * language (void) const;
+  virtual const char * language () const;
 
-  virtual const char * lexer (void) const;
+  virtual const char * lexer () const;
 
   virtual QString description (int style) const;
 };
--- a/libgui/src/main-window.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/main-window.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -73,9 +73,7 @@
 #include "main-window.h"
 #include "news-reader.h"
 #include "octave-qobject.h"
-#include "octave-qtutils.h"
 #include "settings-dialog.h"
-#include "shortcut-manager.h"
 #include "welcome-wizard.h"
 
 #include "cmd-edit.h"
@@ -93,41 +91,43 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 main_window::main_window (base_qobject& oct_qobj)
-: QMainWindow (), m_octave_qobj (oct_qobj),
-  m_status_bar (nullptr),
-  m_command_window (nullptr),
-  m_history_window (nullptr),
-  m_file_browser_window (nullptr),
-  m_editor_window (nullptr),
-  m_workspace_window (nullptr),
-  m_external_editor (new external_editor_interface (this, m_octave_qobj)),
-  m_active_editor (m_external_editor), m_settings_dlg (nullptr),
-  m_find_files_dlg (nullptr), m_set_path_dlg (nullptr),
-  m_clipboard (QApplication::clipboard ()),
-  m_prevent_readline_conflicts (true),
-  m_prevent_readline_conflicts_menu (false),
-  m_suppress_dbg_location (true),
-  m_closing (false), m_file_encoding (QString ())
+  : QMainWindow (), m_octave_qobj (oct_qobj),
+    m_status_bar (nullptr),
+    m_command_window (nullptr),
+    m_history_window (nullptr),
+    m_file_browser_window (nullptr),
+    m_editor_window (nullptr),
+    m_workspace_window (nullptr),
+    m_external_editor (new external_editor_interface (this)),
+    m_active_editor (m_external_editor), m_settings_dlg (nullptr),
+    m_find_files_dlg (nullptr), m_set_path_dlg (nullptr),
+    m_clipboard (QApplication::clipboard ()),
+    m_prevent_readline_conflicts (true),
+    m_prevent_readline_conflicts_menu (false),
+    m_suppress_dbg_location (true),
+    m_closing (false), m_file_encoding (QString ())
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  if (rmgr.is_first_run ())
+  gui_settings settings;
+
+  if (! settings.bool_value (global_skip_welcome_wizard))
     {
       // Before wizard.
       m_octave_qobj.config_translators ();
 
-      welcome_wizard welcomeWizard (m_octave_qobj);
+      welcome_wizard welcomeWizard;
 
       if (welcomeWizard.exec () == QDialog::Rejected)
         exit (1);
 
+      settings.setValue (global_skip_welcome_wizard.settings_key (), QVariant (true));
+
       // Install settings file.
-      rmgr.reload_settings ();
+      settings.reload ();
     }
   else
     {
       // Get settings file.
-      rmgr.reload_settings ();
+      settings.reload ();
 
       // After settings.
       m_octave_qobj.config_translators ();
@@ -135,9 +135,9 @@
 
   setObjectName (gui_obj_name_main_window);
 
-  rmgr.config_icon_theme ();
-
-  rmgr.update_network_settings ();
+  settings.config_icon_theme ();
+
+  settings.update_network_settings ();
 
   // We provide specific terminal capabilities, so ensure that
   // TERM is always set appropriately.
@@ -148,13 +148,6 @@
   sys::env::putenv ("TERM", "xterm");
 #endif
 
-  // FIXME: can we do this job when creating the shortcut manager?
-  // A quick look shows that it may require some coordination with the
-  // resource manager.  Startup is complicated, but maybe we can make
-  // it simpler?
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-  scmgr.init_data ();
-
   construct_central_widget ();
 
   m_status_bar = new QStatusBar (this);
@@ -165,33 +158,22 @@
 
   adopt_dock_widgets ();
 
-#if defined (HAVE_QGUIAPPLICATION_SETDESKTOPFILENAME)
   QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop");
-#endif
 
   QApplication *qapp = m_octave_qobj.qapplication ();
 
   m_default_style = qapp->style ()->objectName ();
   m_default_palette = qapp->palette ();
 
-  gui_settings *settings = rmgr.get_settings ();
-
   bool connect_to_web = true;
   QDateTime last_checked;
   int serial = 0;
   m_active_dock = nullptr;
 
-  if (settings)
-    {
-      connect_to_web
-        = settings->value (nr_allow_connection).toBool ();
-
-      last_checked
-        = settings->value (nr_last_time).toDateTime ();
-
-      serial = settings->value (nr_last_news).toInt ();
-      m_default_encoding = settings->value (ed_default_enc).toString ();
-    }
+  connect_to_web = settings.bool_value (nr_allow_connection);
+  last_checked = settings.date_time_value (nr_last_time);
+  serial = settings.int_value (nr_last_news);
+  m_default_encoding = settings.string_value (ed_default_enc);
 
   QDateTime current = QDateTime::currentDateTime ();
   QDateTime one_day_ago = current.addDays (-1);
@@ -216,9 +198,9 @@
   focus_command_window ();
 }
 
-main_window::~main_window (void) { }
-
-void main_window::adopt_dock_widgets (void)
+main_window::~main_window () { }
+
+void main_window::adopt_dock_widgets ()
 {
   adopt_terminal_widget ();
   adopt_documentation_widget ();
@@ -231,7 +213,7 @@
   m_previous_dock = m_command_window;
 }
 
-void main_window::adopt_terminal_widget (void)
+void main_window::adopt_terminal_widget ()
 {
   m_command_window = m_octave_qobj.terminal_widget (this);
 
@@ -289,14 +271,14 @@
     }
 }
 
-void main_window::adopt_documentation_widget (void)
+void main_window::adopt_documentation_widget ()
 {
   m_doc_browser_window = m_octave_qobj.documentation_widget (this);
 
   make_dock_widget_connections (m_doc_browser_window);
 }
 
-void main_window::adopt_file_browser_widget (void)
+void main_window::adopt_file_browser_widget ()
 {
   m_file_browser_window = m_octave_qobj.file_browser_widget (this);
 
@@ -324,7 +306,7 @@
            this, &main_window::find_files);
 }
 
-void main_window::adopt_history_widget (void)
+void main_window::adopt_history_widget ()
 {
   m_history_window = m_octave_qobj.history_widget (this);
 
@@ -337,7 +319,7 @@
            this, &main_window::execute_command_in_terminal);
 }
 
-void main_window::adopt_workspace_widget (void)
+void main_window::adopt_workspace_widget ()
 {
   m_workspace_window = m_octave_qobj.workspace_widget (this);
 
@@ -347,14 +329,14 @@
            this, &main_window::execute_command_in_terminal);
 }
 
-void main_window::adopt_editor_widget (void)
+void main_window::adopt_editor_widget ()
 {
   interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
   qt_interpreter_events *qt_link = interp_qobj->qt_link ();
 
 #if defined (HAVE_QSCINTILLA)
-  file_editor *editor = new file_editor (this, m_octave_qobj);
+  file_editor *editor = new file_editor (this);
 
   make_dock_widget_connections (editor);
 
@@ -363,6 +345,10 @@
   // connections here instead of in base_qobject::editor_widget.
   m_octave_qobj.connect_interpreter_events (editor);
 
+  connect (editor, &file_editor::show_symbol_tooltip_signal,
+           m_octave_qobj.get_workspace_model (),
+           &workspace_model::show_symbol_tooltip);
+
   connect (editor, &file_editor::request_settings_dialog,
            this, QOverload<const QString&>::of (&main_window::process_settings_dialog_request));
 
@@ -451,7 +437,7 @@
            m_active_editor, SLOT (handle_edit_file_request (const QString&)));
 }
 
-void main_window::adopt_variable_editor_widget (void)
+void main_window::adopt_variable_editor_widget ()
 {
   m_variable_editor_window = m_octave_qobj.variable_editor_widget (this);
 
@@ -482,12 +468,12 @@
            dw, &octave_dock_widget::save_settings);
 }
 
-bool main_window::command_window_has_focus (void) const
+bool main_window::command_window_has_focus () const
 {
   return m_command_window->has_focus ();
 }
 
-void main_window::focus_command_window (void)
+void main_window::focus_command_window ()
 {
   m_command_window->activate ();
 }
@@ -504,15 +490,14 @@
     m_file_browser_window->activate ();
 }
 
-bool main_window::confirm_shutdown (void)
+bool main_window::confirm_shutdown ()
 {
   bool closenow = true;
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings->value (global_prompt_to_exit.key,
-                       global_prompt_to_exit.def).toBool ())
+  gui_settings settings;
+
+  if (settings.value (global_prompt_to_exit.settings_key (),
+                      global_prompt_to_exit.def ()).toBool ())
     {
       int ans = QMessageBox::question (this, tr ("Octave"),
                                        tr ("Are you sure you want to exit Octave?"),
@@ -646,13 +631,9 @@
     }
 }
 
-void main_window::request_reload_settings (void)
+void main_window::request_reload_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (settings)
-    emit settings_changed (settings);
+  emit settings_changed ();
 }
 
 void main_window::report_status_message (const QString& statusMessage)
@@ -660,13 +641,14 @@
   m_status_bar->showMessage (statusMessage, 1000);
 }
 
-void main_window::handle_save_workspace_request (void)
+void main_window::handle_save_workspace_request ()
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = 0;  // No options by default.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts = QFileDialog::DontUseNativeDialog;
 
   QString file
@@ -677,11 +659,11 @@
     {
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          Fsave (interp, ovl (file.toStdString ()));
-        });
+         {
+           // INTERPRETER THREAD
+
+           Fsave (interp, ovl (file.toStdString ()));
+         });
     }
 }
 
@@ -689,9 +671,10 @@
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = 0;  // No options by default.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts = QFileDialog::DontUseNativeDialog;
 
   QString file = file_arg;
@@ -704,17 +687,17 @@
     {
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          Fload (interp, ovl (file.toStdString ()));
-
-          tree_evaluator& tw = interp.get_evaluator ();
-
-          event_manager& xevmgr = interp.get_event_manager ();
-
-          xevmgr.set_workspace (true, tw.get_symbol_info ());
-        });
+         {
+           // INTERPRETER THREAD
+
+           Fload (interp, ovl (file.toStdString ()));
+
+           tree_evaluator& tw = interp.get_evaluator ();
+
+           event_manager& xevmgr = interp.get_event_manager ();
+
+           xevmgr.set_workspace (true, tw.get_symbol_info ());
+         });
     }
 }
 
@@ -726,70 +709,70 @@
 
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          interp.feval ("open", ovl (file));
-
-          // Update the workspace since open.m may have loaded new
-          // variables.
-          tree_evaluator& tw = interp.get_evaluator ();
-
-          event_manager& xevmgr = interp.get_event_manager ();
-
-          xevmgr.set_workspace (true, tw.get_symbol_info ());
-        });
+         {
+           // INTERPRETER THREAD
+
+           interp.feval ("open", ovl (file));
+
+           // Update the workspace since open.m may have loaded new
+           // variables.
+           tree_evaluator& tw = interp.get_evaluator ();
+
+           event_manager& xevmgr = interp.get_event_manager ();
+
+           xevmgr.set_workspace (true, tw.get_symbol_info ());
+         });
     }
 }
 
-void main_window::handle_clear_workspace_request (void)
+void main_window::handle_clear_workspace_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Fclear (interp);
-    });
+     {
+       // INTERPRETER THREAD
+
+       Fclear (interp);
+     });
 }
 
-void main_window::handle_clear_command_window_request (void)
+void main_window::handle_clear_command_window_request ()
 {
   emit interpreter_event
-    ([] (void)
-    {
-      // INTERPRETER THREAD
-
-      command_editor::kill_full_line ();
-      command_editor::clear_screen ();
-    });
+    ([] ()
+     {
+       // INTERPRETER THREAD
+
+       command_editor::kill_full_line ();
+       command_editor::clear_screen ();
+     });
 }
 
-void main_window::handle_clear_history_request (void)
+void main_window::handle_clear_history_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      history_system& history_sys = interp.get_history_system ();
-
-      history_sys.do_history (ovl ("-c"));
-    });
+     {
+       // INTERPRETER THREAD
+
+       history_system& history_sys = interp.get_history_system ();
+
+       history_sys.do_history (ovl ("-c"));
+     });
 }
 
-void main_window::handle_undo_request (void)
+void main_window::handle_undo_request ()
 {
   if (command_window_has_focus ())
     {
       emit interpreter_event
-        ([] (void)
-        {
-          // INTERPRETER THREAD
-
-          command_editor::undo ();
-          command_editor::redisplay ();
-        });
+        ([] ()
+         {
+           // INTERPRETER THREAD
+
+           command_editor::undo ();
+           command_editor::redisplay ();
+         });
     }
   else
     emit undo_signal ();
@@ -849,28 +832,28 @@
   qt_link->wake_all ();
 }
 
-void main_window::open_online_documentation_page (void)
+void main_window::open_online_documentation_page ()
 {
   QDesktopServices::openUrl
     (QUrl ("https://octave.org/doc/interpreter/index.html"));
 }
 
-void main_window::open_bug_tracker_page (void)
+void main_window::open_bug_tracker_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/bugs.html"));
 }
 
-void main_window::open_octave_packages_page (void)
+void main_window::open_octave_packages_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://packages.octave.org/index.html"));
 }
 
-void main_window::open_contribute_page (void)
+void main_window::open_contribute_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/contribute.html"));
 }
 
-void main_window::open_donate_page (void)
+void main_window::open_donate_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/donate.html"));
 }
@@ -885,17 +868,13 @@
       return;
     }
 
-  m_settings_dlg = new settings_dialog (this, m_octave_qobj, desired_tab);
+  m_settings_dlg = new settings_dialog (this, desired_tab);
 
   connect (m_settings_dlg, &settings_dialog::apply_new_settings,
            this, &main_window::request_reload_settings);
-
-  m_settings_dlg->setModal (false);
-  m_settings_dlg->setAttribute (Qt::WA_DeleteOnClose);
-  m_settings_dlg->show ();
 }
 
-void main_window::show_about_octave (void)
+void main_window::show_about_octave ()
 {
   std::string message
     = octave_name_version_copyright_copying_warranty_and_bugs (true);
@@ -904,17 +883,15 @@
                       QString::fromStdString (message));
 }
 
-void main_window::notice_settings (const gui_settings *settings,
-                                   bool update_by_worker)
+void main_window::notice_settings (bool update_by_worker)
 {
-  if (! settings)
-    return;
+  gui_settings settings;
 
   // Get desired style from preferences or take the default one if
   // the desired one is not found
-  QString preferred_style = settings->value (global_style).toString ();
-
-  if (preferred_style == global_style.def.toString ())
+  QString preferred_style = settings.string_value (global_style);
+
+  if (preferred_style == global_style.def ().toString ())
     preferred_style = m_default_style;
 
   QApplication* qapp = m_octave_qobj.qapplication();
@@ -938,7 +915,7 @@
     }
 
   // the widget's icons (when floating)
-  QString icon_set = settings->value (dw_icon_set).toString ();
+  QString icon_set = settings.string_value (dw_icon_set);
 
   QString icon;
   for (auto *widget : dock_widget_list ())
@@ -954,29 +931,28 @@
         }
     }
 
-  int size_idx = settings->value (global_icon_size).toInt ();
+  int size_idx = settings.int_value (global_icon_size);
   size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
   QStyle *st = style ();
   int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
   m_main_tool_bar->setIconSize (QSize (icon_size, icon_size));
 
-  if (settings->value (global_status_bar).toBool ())
+  if (settings.bool_value (global_status_bar))
     m_status_bar->show ();
   else
     m_status_bar->hide ();
 
   m_prevent_readline_conflicts
-    = settings->value (sc_prevent_rl_conflicts).toBool ();
+    = settings.bool_value (sc_prevent_rl_conflicts);
 
   m_prevent_readline_conflicts_menu
-    = settings->value (sc_prevent_rl_conflicts_menu).toBool ();
+    = settings.bool_value (sc_prevent_rl_conflicts_menu);
 
   m_suppress_dbg_location
-    = ! settings->value (cs_dbg_location).toBool ();
-
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  rmgr.update_network_settings ();
+    = ! settings.bool_value (cs_dbg_location);
+
+  settings.update_network_settings ();
 
   emit active_dock_changed (nullptr, m_active_dock); // update dock widget styles
 
@@ -984,14 +960,14 @@
 
   bool do_disable_main_menu_shortcuts
     = (m_active_dock == m_editor_window)
-    || (m_prevent_readline_conflicts_menu
-        && (m_active_dock == m_command_window));
+      || (m_prevent_readline_conflicts_menu
+          && (m_active_dock == m_command_window));
 
   disable_menu_shortcuts (do_disable_main_menu_shortcuts);
 
   // Check whether some octave internal preferences have to be updated
   QString new_default_encoding
-    = settings->value (ed_default_enc).toString ();
+    = settings.string_value (ed_default_enc);
   // Do not update internal pref only if a) this update was not initiated
   // by the worker and b) the pref has really changes
   if (! update_by_worker && (new_default_encoding != m_default_encoding))
@@ -1003,10 +979,10 @@
   //       getting the cursor blink preferences from all OS environments
   bool cursor_blinking;
 
-  if (settings->contains (global_cursor_blinking.key))
-    cursor_blinking = settings->value (global_cursor_blinking).toBool ();
+  if (settings.contains (global_cursor_blinking.settings_key ()))
+    cursor_blinking = settings.bool_value (global_cursor_blinking);
   else
-    cursor_blinking = settings->value (cs_cursor_blinking).toBool ();
+    cursor_blinking = settings.bool_value (cs_cursor_blinking);
 
   if (cursor_blinking)
     QApplication::setCursorFlashTime (1000);  // 1000 ms flash time
@@ -1042,7 +1018,7 @@
   return darkPalette;
 }
 
-void main_window::prepare_to_exit (void)
+void main_window::prepare_to_exit ()
 {
   // Find files dialog is constructed dynamically, not at time of main_window
   // construction.  Connecting it to qApp aboutToQuit signal would have
@@ -1060,7 +1036,7 @@
   m_active_dock = nullptr;
 }
 
-void main_window::go_to_previous_widget (void)
+void main_window::go_to_previous_widget ()
 {
   m_previous_dock->activate ();
 }
@@ -1080,13 +1056,14 @@
   m_current_directory_combo_box->setCurrentIndex (0);
 }
 
-void main_window::browse_for_directory (void)
+void main_window::browse_for_directory ()
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly;
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts = QFileDialog::DontUseNativeDialog;
 
   QString dir
@@ -1113,15 +1090,15 @@
     {
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          interp.chdir (xdir.toStdString ());
-        });
+         {
+           // INTERPRETER THREAD
+
+           interp.chdir (xdir.toStdString ());
+         });
     }
 }
 
-void main_window::change_directory_up (void)
+void main_window::change_directory_up ()
 {
   set_current_working_directory ("..");
 }
@@ -1130,7 +1107,7 @@
 // combobox to change to a new directory or a directory that is already
 // in the drop down list.
 
-void main_window::accept_directory_line_edit (void)
+void main_window::accept_directory_line_edit ()
 {
   // Get new directory name, and change to it if it is new.  Otherwise,
   // the combo box will trigger the "activated" signal to change to the
@@ -1153,18 +1130,18 @@
   else
     {
       emit interpreter_event
-        ([=] (void)
-        {
-          // INTERPRETER THREAD
-
-          std::string pending_input = command_editor::get_current_line ();
-
-          command_editor::set_initial_input (pending_input);
-          command_editor::replace_line (command.toStdString ());
-          command_editor::redisplay ();
-          command_editor::interrupt_event_loop ();
-          command_editor::accept_line ();
-        });
+        ([=] ()
+         {
+           // INTERPRETER THREAD
+
+           std::string pending_input = command_editor::get_current_line ();
+
+           command_editor::set_initial_input (pending_input);
+           command_editor::replace_line (command.toStdString ());
+           command_editor::redisplay ();
+           command_editor::interrupt_event_loop ();
+           command_editor::accept_line ();
+         });
     }
 
   focus_console_after_command ();
@@ -1174,59 +1151,59 @@
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      QString function_name = info.fileName ();
-      function_name.chop (info.suffix ().length () + 1);
-      std::string file_path = info.absoluteFilePath ().toStdString ();
-
-      std::string pending_input = command_editor::get_current_line ();
-
-      if (valid_identifier (function_name.toStdString ()))
-        {
-          // Valid identifier: call as function with possibility to
-          // debug.
-
-          load_path& lp = interp.get_load_path ();
-
-          std::string path = info.absolutePath ().toStdString ();
-
-          if (lp.contains_file_in_dir (file_path, path))
-            command_editor::replace_line (function_name.toStdString ());
-        }
-      else
-        {
-          // No valid identifier: use equivalent of Fsource (), no
-          // debug possible.
-
-          interp.source_file (file_path);
-
-          command_editor::replace_line ("");
-        }
-
-      command_editor::set_initial_input (pending_input);
-      command_editor::redisplay ();
-      command_editor::interrupt_event_loop ();
-      command_editor::accept_line ();
-    });
+     {
+       // INTERPRETER THREAD
+
+       QString function_name = info.fileName ();
+       function_name.chop (info.suffix ().length () + 1);
+       std::string file_path = info.absoluteFilePath ().toStdString ();
+
+       std::string pending_input = command_editor::get_current_line ();
+
+       if (valid_identifier (function_name.toStdString ()))
+         {
+           // Valid identifier: call as function with possibility to
+           // debug.
+
+           load_path& lp = interp.get_load_path ();
+
+           std::string path = info.absolutePath ().toStdString ();
+
+           if (lp.contains_file_in_dir (file_path, path))
+             command_editor::replace_line (function_name.toStdString ());
+         }
+       else
+         {
+           // No valid identifier: use equivalent of Fsource (), no
+           // debug possible.
+
+           interp.source_file (file_path);
+
+           command_editor::replace_line ("");
+         }
+
+       command_editor::set_initial_input (pending_input);
+       command_editor::redisplay ();
+       command_editor::interrupt_event_loop ();
+       command_editor::accept_line ();
+     });
 
   focus_console_after_command ();
 }
 
-void main_window::handle_new_figure_request (void)
+void main_window::handle_new_figure_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Fbuiltin (interp, ovl ("figure"));
-      Fdrawnow (interp);
-    });
+     {
+       // INTERPRETER THREAD
+
+       Fbuiltin (interp, ovl ("figure"));
+       Fdrawnow (interp);
+     });
 }
 
-void main_window::handle_enter_debugger (void)
+void main_window::handle_enter_debugger ()
 {
   setWindowTitle ("Octave (Debugging)");
 
@@ -1237,7 +1214,7 @@
   m_debug_quit->setEnabled (true);
 }
 
-void main_window::handle_exit_debugger (void)
+void main_window::handle_exit_debugger ()
 {
   setWindowTitle ("Octave");
 
@@ -1248,35 +1225,35 @@
   m_debug_quit->setEnabled (false);
 }
 
-void main_window::debug_continue (void)
+void main_window::debug_continue ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
-      Fdbcont (interp);
-
-      command_editor::interrupt (true);
-    });
+     {
+       // INTERPRETER THREAD
+
+       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+       Fdbcont (interp);
+
+       command_editor::interrupt (true);
+     });
 }
 
-void main_window::debug_step_into (void)
+void main_window::debug_step_into ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
-      Fdbstep (interp, ovl ("in"));
-
-      command_editor::interrupt (true);
-    });
+     {
+       // INTERPRETER THREAD
+
+       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+       Fdbstep (interp, ovl ("in"));
+
+       command_editor::interrupt (true);
+     });
 }
 
-void main_window::debug_step_over (void)
+void main_window::debug_step_over ()
 {
   if (m_debug_quit->isEnabled ())
     {
@@ -1284,15 +1261,15 @@
 
       emit interpreter_event
         ([=] (interpreter& interp)
-        {
-          // INTERPRETER THREAD
-
-          F__db_next_breakpoint_quiet__ (interp,
-                                         ovl (m_suppress_dbg_location));
-          Fdbstep (interp);
-
-          command_editor::interrupt (true);
-        });
+         {
+           // INTERPRETER THREAD
+
+           F__db_next_breakpoint_quiet__ (interp,
+                                          ovl (m_suppress_dbg_location));
+           Fdbstep (interp);
+
+           command_editor::interrupt (true);
+         });
     }
   else
     {
@@ -1301,31 +1278,31 @@
     }
 }
 
-void main_window::debug_step_out (void)
+void main_window::debug_step_out ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
-      Fdbstep (interp, ovl ("out"));
-
-      command_editor::interrupt (true);
-    });
+     {
+       // INTERPRETER THREAD
+
+       F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+       Fdbstep (interp, ovl ("out"));
+
+       command_editor::interrupt (true);
+     });
 }
 
-void main_window::debug_quit (void)
+void main_window::debug_quit ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Fdbquit (interp);
-
-      command_editor::interrupt (true);
-    });
+     {
+       // INTERPRETER THREAD
+
+       Fdbquit (interp);
+
+       command_editor::interrupt (true);
+     });
 }
 
 //
@@ -1334,16 +1311,16 @@
 // These are moved from editor to here for also using them when octave
 // is built without qscintilla
 //
-void main_window::request_open_file (void)
+void main_window::request_open_file ()
 {
   // Open file isn't a file_editor_tab or editor function since the file
   // might be opened in an external editor.  Hence, functionality is here.
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
+
   bool is_internal = m_editor_window
-    && ! settings->value (global_use_custom_editor.key,
-                          global_use_custom_editor.def).toBool ();
+                     && ! settings.value (global_use_custom_editor.settings_key (),
+                                           global_use_custom_editor.def ()).toBool ();
 
   // Create a NonModal message.
   QWidget *p = this;
@@ -1358,7 +1335,7 @@
   fileDialog->setDirectory (m_current_directory_combo_box->itemText (0));
 
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-  if (! settings->value (global_use_native_dialogs).toBool ())
+  if (! settings.bool_value (global_use_native_dialogs))
     fileDialog->setOption(QFileDialog::DontUseNativeDialog);
 
   connect (fileDialog, &QFileDialog::filesSelected,
@@ -1383,10 +1360,11 @@
   // editor window or the main window.  The latter is chosen, if a custom
   // editor is used or qscintilla is not available
   QWidget *p = m_editor_window;
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! p || settings->value (global_use_custom_editor.key,
-                              global_use_custom_editor.def).toBool ())
+
+  gui_settings settings;
+
+  if (! p || settings.value (global_use_custom_editor.settings_key (),
+                              global_use_custom_editor.def ()).toBool ())
     p = this;
   QString new_name = QInputDialog::getText (p, tr ("New Function"),
                                             tr ("New function name:\n"), QLineEdit::Normal, "", &ok);
@@ -1394,15 +1372,15 @@
   if (ok && new_name.length () > 0)
     {
       // append suffix if it does not already exist
-      if (new_name.rightRef (2) != ".m")
+      if (new_name.right (2) != ".m")
         new_name.append (".m");
       // check whether new files are created without prompt
-      if (! settings->value (ed_create_new_file).toBool ())
+      if (! settings.bool_value (ed_create_new_file))
         {
           // no, so enable this settings and wait for end of new file loading
-          settings->setValue (ed_create_new_file.key, true);
-          connect (m_editor_window, SIGNAL (file_loaded_signal (void)),
-                   this, SLOT (restore_create_file_setting (void)));
+          settings.setValue (ed_create_new_file.settings_key (), true);
+          connect (m_editor_window, SIGNAL (file_loaded_signal ()),
+                   this, SLOT (restore_create_file_setting ()));
         }
       // start the edit command
       execute_command_in_terminal ("edit " + new_name);
@@ -1422,92 +1400,92 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      // We can skip the entire callback function because it does not
-      // make any changes to the interpreter state.
-
-      if (this_mw.isNull ())
-        return;
-
-      // Split possible subfunctions
-      QStringList fcn_list = fname.split ('>');
-      QString fcn_name = fcn_list.at (0) + ".m";
-
-      // FIXME: could use symbol_exist directly, but we may also want
-      // to fix that to be a member function in the interpreter
-      // class?
-
-      // Is it a regular function within the search path? (Call Fexist)
-      octave_value_list fct = Fexist (interp, ovl (fname.toStdString ()),0);
-      int type = fct (0).int_value ();
-
-      QString message = QString ();
-      QString filename = QString ();
-
-      switch (type)
-        {
-        case 3:
-        case 5:
-        case 103:
-          message = tr ("%1 is a built-in, compiled or inline\n"
-                        "function and can not be edited.");
-          break;
-
-        case 2:
-          // FIXME: could use a load_path function directly.
-          octave_value_list file_path
-            = Ffile_in_loadpath (interp, ovl (fcn_name.toStdString ()), 0);
-          if (file_path.length () > 0)
-            filename = QString::fromStdString (file_path (0).string_value ());
-          break;
-        }
-
-      if (filename.isEmpty () && message.isEmpty ())
-        {
-          // No error so far, but function still not known
-          // -> try directory of edited file
-          // get directory
-          QDir dir;
-          if (ffile.isEmpty ())
-            {
-              if (curr_dir.isEmpty ())
-                dir = QDir (m_current_directory_combo_box->itemText (0));
-              else
-                dir = QDir (curr_dir);
-            }
-          else
-            dir = QDir (QFileInfo (ffile).canonicalPath ());
-
-          QFileInfo file = QFileInfo (dir, fcn_name);
-          if (file.exists ())
-            filename = file.canonicalFilePath (); // local file exists
-          else
-            {
-              // local file does not exist -> try private directory
-              file = QFileInfo (ffile);
-              file = QFileInfo (QDir (file.canonicalPath () + "/private"),
-                                fcn_name);
-              if (file.exists ())
-                filename = file.canonicalFilePath ();  // private function exists
-              else
-                message = tr ("Can not find function %1");  // no file found
-            }
-        }
-
-      if (! message.isEmpty ())
-        {
-          emit warning_function_not_found_signal (message.arg (fname));
-          return;
-        }
-
-      if (! filename.endsWith (".m"))
-        filename.append (".m");
-
-      // default encoding
-      emit open_file_signal (filename, QString (), line);
-    });
+     {
+       // INTERPRETER THREAD
+
+       // We can skip the entire callback function because it does not
+       // make any changes to the interpreter state.
+
+       if (this_mw.isNull ())
+         return;
+
+       // Split possible subfunctions
+       QStringList fcn_list = fname.split ('>');
+       QString fcn_name = fcn_list.at (0) + ".m";
+
+       // FIXME: could use symbol_exist directly, but we may also want
+       // to fix that to be a member function in the interpreter
+       // class?
+
+       // Is it a regular function within the search path? (Call Fexist)
+       octave_value_list fct = Fexist (interp, ovl (fname.toStdString ()),0);
+       int type = fct (0).int_value ();
+
+       QString message = QString ();
+       QString filename = QString ();
+
+       switch (type)
+         {
+         case 3:
+         case 5:
+         case 103:
+           message = tr ("%1 is a built-in, compiled or inline\n"
+                         "function and can not be edited.");
+           break;
+
+         case 2:
+           // FIXME: could use a load_path function directly.
+           octave_value_list file_path
+             = Ffile_in_loadpath (interp, ovl (fcn_name.toStdString ()), 0);
+           if (file_path.length () > 0)
+             filename = QString::fromStdString (file_path (0).string_value ());
+           break;
+         }
+
+       if (filename.isEmpty () && message.isEmpty ())
+         {
+           // No error so far, but function still not known
+           // -> try directory of edited file
+           // get directory
+           QDir dir;
+           if (ffile.isEmpty ())
+             {
+               if (curr_dir.isEmpty ())
+                 dir = QDir (m_current_directory_combo_box->itemText (0));
+               else
+                 dir = QDir (curr_dir);
+             }
+           else
+             dir = QDir (QFileInfo (ffile).canonicalPath ());
+
+           QFileInfo file = QFileInfo (dir, fcn_name);
+           if (file.exists ())
+             filename = file.canonicalFilePath (); // local file exists
+           else
+             {
+               // local file does not exist -> try private directory
+               file = QFileInfo (ffile);
+               file = QFileInfo (QDir (file.canonicalPath () + "/private"),
+                                 fcn_name);
+               if (file.exists ())
+                 filename = file.canonicalFilePath ();  // private function exists
+               else
+                 message = tr ("Can not find function %1");  // no file found
+             }
+         }
+
+       if (! message.isEmpty ())
+         {
+           emit warning_function_not_found_signal (message.arg (fname));
+           return;
+         }
+
+       if (! filename.endsWith (".m"))
+         filename.append (".m");
+
+       // default encoding
+       emit open_file_signal (filename, QString (), line);
+     });
 }
 
 void main_window::warning_function_not_found (const QString& message)
@@ -1555,42 +1533,38 @@
     focus_command_window ();
 }
 
-void main_window::read_settings (void)
+void main_window::read_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (! settings)
-    {
-      qDebug ("Error: gui_settings pointer from resource manager is NULL.");
-      return;
-    }
-
-  set_window_layout (settings);
+  gui_settings settings;
+
+  set_window_layout ();
 
   // restore the list of the last directories
-  QStringList curr_dirs = settings->value (mw_dir_list).toStringList ();
+  QStringList curr_dirs = settings.string_list_value (mw_dir_list);
   for (int i=0; i < curr_dirs.size (); i++)
     {
       m_current_directory_combo_box->addItem (curr_dirs.at (i));
     }
-  emit settings_changed (settings);
+
+  emit settings_changed ();
 }
 
-void main_window::init_terminal_size (void)
+void main_window::init_terminal_size ()
 {
   emit init_terminal_size_signal ();
 }
 
-void main_window::set_window_layout (gui_settings *settings)
+void main_window::set_window_layout ()
 {
+  gui_settings settings;
+
   // For resetting from some inconsistent state, first reset layout
   // without saving or showing it
   do_reset_windows (true, false);
 
   // Restore main window state and geometry from settings file or, in case
   // of an error (no pref values yet), from the default layout.
-  if (! restoreGeometry (settings->value (mw_geometry).toByteArray ()))
+  if (! restoreGeometry (settings.byte_array_value (mw_geometry)))
     {
       do_reset_windows (true);
       return;
@@ -1619,7 +1593,7 @@
                      | Qt::WindowCloseButtonHint);
     }
 
-  if (! restoreState (settings->value (mw_state).toByteArray ()))
+  if (! restoreState (settings.byte_array_value (mw_state)))
     {
       do_reset_windows (true);
       return;
@@ -1642,10 +1616,10 @@
           bool floating = false;
           bool visible = true;
 
-          floating = settings->value
-            (dw_is_floating.key.arg (name), dw_is_floating.def).toBool ();
-          visible = settings->value
-            (dw_is_visible.key.arg (name), dw_is_visible.def).toBool ();
+          floating = settings.value
+            (dw_is_floating.settings_key ().arg (name), dw_is_floating.def ()).toBool ();
+          visible = settings.value
+            (dw_is_visible.settings_key ().arg (name), dw_is_visible.def ()).toBool ();
 
           // If floating, make window from widget.
           if (floating)
@@ -1654,8 +1628,8 @@
 
               if (visible)
                 {
-                  if (settings->value (dw_is_minimized.key.arg (name),
-                                       dw_is_minimized.def).toBool ())
+                  if (settings.value (dw_is_minimized.settings_key ().arg (name),
+                                      dw_is_minimized.def ()).toBool ())
                     widget->showMinimized ();
                   else
                     widget->setVisible (true);
@@ -1677,29 +1651,23 @@
   show ();
 }
 
-void main_window::write_settings (void)
+void main_window::write_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings)
-    {
-      qDebug ("Error: gui_settings pointer from resource manager is NULL.");
-      return;
-    }
-
-  settings->setValue (mw_geometry.key, saveGeometry ());
-  settings->setValue (mw_state.key, saveState ());
+  gui_settings settings;
+
+  settings.setValue (mw_geometry.settings_key (), saveGeometry ());
+  settings.setValue (mw_state.settings_key (), saveState ());
   // write the list of recently used directories
   QStringList curr_dirs;
   for (int i=0; i<m_current_directory_combo_box->count (); i++)
     {
       curr_dirs.append (m_current_directory_combo_box->itemText (i));
     }
-  settings->setValue (mw_dir_list.key, curr_dirs);
-  settings->sync ();
+  settings.setValue (mw_dir_list.settings_key (), curr_dirs);
+  settings.sync ();
 }
 
-void main_window::copyClipboard (void)
+void main_window::copyClipboard ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1714,7 +1682,7 @@
     emit copyClipboard_signal ();
 }
 
-void main_window::pasteClipboard (void)
+void main_window::pasteClipboard ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1730,7 +1698,7 @@
     emit pasteClipboard_signal ();
 }
 
-void main_window::selectAll (void)
+void main_window::selectAll ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1759,33 +1727,30 @@
     }
 }
 
-void main_window::handle_octave_ready (void)
+void main_window::handle_octave_ready ()
 {
   // actions after the startup files are executed
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+
+  gui_settings settings;
 
   QDir startup_dir = QDir ();    // current octave dir after startup
 
-  if (settings)
+  if (settings.bool_value (global_restore_ov_dir))
     {
-      if (settings->value (global_restore_ov_dir).toBool ())
-        {
-          // restore last dir from previous session
-          QStringList curr_dirs
-            = settings->value (mw_dir_list).toStringList ();
-          if (curr_dirs.length () > 0)
-            startup_dir = QDir (curr_dirs.at (0));  // last dir prev. session
-        }
-      else if (! settings->value (global_ov_startup_dir).toString ().isEmpty ())
-        {
-          // do not restore but there is a startup dir configured
-          startup_dir
-            = QDir (settings->value (global_ov_startup_dir).toString ());
-        }
-
-      update_default_encoding (settings->value (ed_default_enc).toString ());
+      // restore last dir from previous session
+      QStringList curr_dirs
+        = settings.string_list_value (mw_dir_list);
+      if (curr_dirs.length () > 0)
+        startup_dir = QDir (curr_dirs.at (0));  // last dir prev. session
     }
+  else if (! settings.string_value (global_ov_startup_dir).isEmpty ())
+    {
+      // do not restore but there is a startup dir configured
+      startup_dir
+        = QDir (settings.string_value (global_ov_startup_dir));
+    }
+
+  update_default_encoding (settings.string_value (ed_default_enc));
 
   if (! startup_dir.exists ())
     {
@@ -1802,7 +1767,7 @@
       // This can not be done when the editor is created because all functions
       // must be known for the lexer's auto completion information
       m_editor_window->empty_script (true, false);
-      m_editor_window->restore_session (settings);
+      m_editor_window->restore_session ();
 #endif
     }
 
@@ -1810,18 +1775,31 @@
     {
       // Set initial prompt.
 
+      // The interpreter_event callback function below emits a
+      // signal.  Because we don't control when that happens, use a
+      // guarded pointer so that the callback can abort if this object
+      // is no longer valid.
+
+      QPointer<main_window> this_mw (this);
+
       emit interpreter_event
-        ([] (interpreter& interp)
+        ([=] (interpreter& interp)
         {
           // INTERPRETER_THREAD
 
-          event_manager& evmgr = interp.get_event_manager ();
-          input_system& input_sys = interp.get_input_system ();
-
-          input_sys.PS1 (">> ");
-          std::string prompt = input_sys.PS1 ();
-
-          evmgr.update_prompt (command_editor::decode_prompt_string (prompt));
+          // We can skip the entire callback function because it does
+          // not make any changes to the interpreter state.
+
+          if (this_mw.isNull ())
+            return;
+
+          interp.PS1 (">> ");
+          std::string prompt = interp.PS1 ();
+
+          std::string decoded_prompt
+            = command_editor::decode_prompt_string (prompt);
+
+          emit update_prompt_signal (QString::fromStdString (decoded_prompt));
         });
     }
 
@@ -1829,12 +1807,12 @@
   focus_command_window ();  // make sure that the command window has focus
 }
 
-void main_window::handle_set_path_dialog_request (void)
+void main_window::handle_set_path_dialog_request ()
 {
   if (m_set_path_dlg)  // m_set_path_dlg is a guarded pointer!
     return;
 
-  m_set_path_dlg = new set_path_dialog (this, m_octave_qobj);
+  m_set_path_dlg = new set_path_dialog (this);
 
   m_set_path_dlg->setModal (false);
   m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose);
@@ -1870,7 +1848,7 @@
 
   if (! m_find_files_dlg)
     {
-      m_find_files_dlg = new find_files_dialog (this, m_octave_qobj);
+      m_find_files_dlg = new find_files_dialog (this);
 
       connect (m_find_files_dlg, &find_files_dialog::finished,
                this, &main_window::find_files_finished);
@@ -1898,15 +1876,15 @@
 void main_window::set_screen_size (int ht, int wd)
 {
   emit interpreter_event
-    ([=] (void)
-    {
-      // INTERPRETER THREAD
-
-      command_editor::set_screen_size (ht, wd);
-    });
+    ([=] ()
+     {
+       // INTERPRETER THREAD
+
+       command_editor::set_screen_size (ht, wd);
+     });
 }
 
-void main_window::clipboard_has_changed (void)
+void main_window::clipboard_has_changed ()
 {
   if (m_clipboard->text ().isEmpty ())
     {
@@ -1920,7 +1898,7 @@
     }
 }
 
-void main_window::clear_clipboard (void)
+void main_window::clear_clipboard ()
 {
   m_clipboard->clear (QClipboard::Clipboard);
 }
@@ -1936,14 +1914,15 @@
     }
 }
 
-void main_window::restore_create_file_setting (void)
+void main_window::restore_create_file_setting ()
 {
   // restore the new files creation setting
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  settings->setValue (ed_create_new_file.key, false);
-  disconnect (m_editor_window, SIGNAL (file_loaded_signal (void)),
-              this, SLOT (restore_create_file_setting (void)));
+
+  gui_settings settings;
+
+  settings.setValue (ed_create_new_file.settings_key (), false);
+  disconnect (m_editor_window, SIGNAL (file_loaded_signal ()),
+              this, SLOT (restore_create_file_setting ()));
 }
 
 void main_window::set_file_encoding (const QString& new_encoding)
@@ -1960,37 +1939,34 @@
     emit open_file_signal (open_file_names.at (i), m_file_encoding, -1);
 }
 
-void main_window::profiler_session (void)
+void main_window::profiler_session ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Ffeval (interp, ovl ("profile","on"));
-    });
+      {
+        // INTERPRETER THREAD
+        F__profiler_enable__ (interp, ovl (true));
+      });
 }
 
-void main_window::profiler_session_resume (void)
+void main_window::profiler_session_resume ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Ffeval (interp, ovl ("profile","resume"));
-    });
+      {
+        // INTERPRETER THREAD
+        F__profiler_enable__ (interp, ovl (true));
+      });
 }
 
-void main_window::profiler_stop (void)
+void main_window::profiler_stop ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      Ffeval (interp, ovl ("profile","off"));
-    });
+      {
+        // INTERPRETER THREAD
+        F__profiler_enable__ (interp, ovl (false));
+      });
 }
 
 void main_window::handle_profiler_status_update (bool active)
@@ -2005,7 +1981,7 @@
   m_profiler_status_indicator->set_state (state);
 }
 
-void main_window::profiler_show (void)
+void main_window::profiler_show ()
 {
   // Do not use a separate interpreter event as in the other
   // profiler slots since the output of the command "profshow"
@@ -2036,18 +2012,18 @@
         {
           emit interpreter_event
             ([] (interpreter& interp)
-            {
-              // INTERPRETER THREAD
-
-              interp.quit (0, false, false);
-            });
+             {
+               // INTERPRETER THREAD
+
+               interp.quit (0, false, false);
+             });
         }
     }
   else
     e->ignore ();
 }
 
-void main_window::construct_central_widget (void)
+void main_window::construct_central_widget ()
 {
   // Create and set the central widget.  QMainWindow takes ownership of
   // the widget (pointer) so there is no need to delete the object upon
@@ -2063,7 +2039,7 @@
 
 // Main subroutine of the constructor
 
-void main_window::construct (void)
+void main_window::construct ()
 {
   setWindowIcon (QIcon (dw_icon_set_names["NONE"]));
 
@@ -2083,8 +2059,9 @@
   connect (qApp, &QApplication::focusChanged,
            this, &main_window::focus_changed);
 
+  // Default argument requires wrapper.
   connect (this, &main_window::settings_changed,
-           this, [=] (const gui_settings *settings) { notice_settings (settings); });
+           this, [=] () { notice_settings (); });
 
   // Connections for signals from the interpreter thread where the slot
   // should be executed by the gui thread
@@ -2109,7 +2086,7 @@
   configure_shortcuts ();
 }
 
-void main_window::construct_octave_qt_link (void)
+void main_window::construct_octave_qt_link ()
 {
   interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
@@ -2186,7 +2163,7 @@
   return menu;
 }
 
-void main_window::construct_menu_bar (void)
+void main_window::construct_menu_bar ()
 {
   QMenuBar *menu_bar = menuBar ();
 
@@ -2227,11 +2204,11 @@
 
   construct_new_menu (file_menu);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  m_open_action = add_action (
-                              file_menu, rmgr.icon ("document-open"), tr ("Open..."),
-                              SLOT (request_open_file (void)), this);
+  gui_settings settings;
+
+  m_open_action
+    = add_action (file_menu, settings.icon ("document-open"), tr ("Open..."),
+                  SLOT (request_open_file ()), this);
   m_open_action->setToolTip (tr ("Open an existing file in editor"));
 
 #if defined (HAVE_QSCINTILLA)
@@ -2240,19 +2217,19 @@
 
   file_menu->addSeparator ();
 
-  m_load_workspace_action = add_action (
-                                        file_menu, QIcon (), tr ("Load Workspace..."),
-                                        SLOT (handle_load_workspace_request (void)), this);
-
-  m_save_workspace_action = add_action (
-                                        file_menu, QIcon (), tr ("Save Workspace As..."),
-                                        SLOT (handle_save_workspace_request (void)), this);
+  m_load_workspace_action
+    = add_action (file_menu, QIcon (), tr ("Load Workspace..."),
+                  SLOT (handle_load_workspace_request ()), this);
+
+  m_save_workspace_action
+    = add_action (file_menu, QIcon (), tr ("Save Workspace As..."),
+                  SLOT (handle_save_workspace_request ()), this);
 
   file_menu->addSeparator ();
 
-  m_exit_action = add_action (
-                              file_menu, QIcon (), tr ("Exit"),
-                              SLOT (close (void)), this);
+  m_exit_action
+    = add_action (file_menu, QIcon (), tr ("Exit"),
+                  SLOT (close ()), this);
   m_exit_action->setMenuRole (QAction::QuitRole);
 
   // Connect signal related to opening or creating editor files
@@ -2272,41 +2249,40 @@
 {
   QMenu *new_menu = p->addMenu (tr ("New"));
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  m_new_script_action = add_action (
-                                    new_menu, rmgr.icon ("document-new"), tr ("New Script"),
-                                    SLOT (request_new_script (void)), this);
-
-  m_new_function_action = add_action (
-                                      new_menu, QIcon (), tr ("New Function..."),
-                                      SLOT (request_new_function (void)), this);
-
-  m_new_figure_action = add_action (
-                                    new_menu, QIcon (), tr ("New Figure"),
-                                    SLOT (handle_new_figure_request (void)), this);
+  gui_settings settings;
+
+  m_new_script_action
+    = add_action (new_menu, settings.icon ("document-new"), tr ("New Script"),
+                  SLOT (request_new_script ()), this);
+
+  m_new_function_action
+    = add_action (new_menu, QIcon (), tr ("New Function..."),
+                  SLOT (request_new_function ()), this);
+
+  m_new_figure_action
+    = add_action (new_menu, QIcon (), tr ("New Figure"),
+                  SLOT (handle_new_figure_request ()), this);
 }
 
 void main_window::construct_edit_menu (QMenuBar *p)
 {
   QMenu *edit_menu = m_add_menu (p, tr ("&Edit"));
 
-  QKeySequence ctrl_shift = Qt::ControlModifier + Qt::ShiftModifier;
-
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
+
   m_undo_action
-    = edit_menu->addAction (rmgr.icon ("edit-undo"), tr ("Undo"));
+    = edit_menu->addAction (settings.icon ("edit-undo"), tr ("Undo"));
   m_undo_action->setShortcutContext (Qt::ApplicationShortcut);
 
   edit_menu->addSeparator ();
 
   m_copy_action
-    = edit_menu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this,
+    = edit_menu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this,
                             &main_window::copyClipboard);
   m_copy_action->setShortcutContext (Qt::ApplicationShortcut);
 
   m_paste_action
-    = edit_menu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this,
+    = edit_menu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this,
                             &main_window::pasteClipboard);
   m_paste_action->setShortcutContext (Qt::ApplicationShortcut);
 
@@ -2322,7 +2298,8 @@
   edit_menu->addSeparator ();
 
   m_find_files_action
-    = edit_menu->addAction (rmgr.icon ("edit-find"), tr ("Find Files..."));
+    = edit_menu->addAction (settings.icon ("edit-find"),
+                            tr ("Find Files..."));
 
   edit_menu->addSeparator ();
 
@@ -2341,7 +2318,7 @@
     = edit_menu->addAction (tr ("Set Path"));
 
   m_preferences_action
-    = edit_menu->addAction (rmgr.icon ("preferences-system"),
+    = edit_menu->addAction (settings.icon ("preferences-system"),
                             tr ("Preferences..."));
 
   connect (m_find_files_action, &QAction::triggered,
@@ -2379,8 +2356,9 @@
                                                   const QString& item,
                                                   const char *member)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  QAction *action = add_action (m_debug_menu, rmgr.icon (QString (icon)),
+  gui_settings settings;
+
+  QAction *action = add_action (m_debug_menu, settings.icon (QString (icon)),
                                 item, member);
 
   action->setEnabled (false);
@@ -2399,19 +2377,19 @@
 
   m_debug_step_over
     = construct_debug_menu_item ("db-step", tr ("Step"),
-                                 SLOT (debug_step_over (void)));
+                                 SLOT (debug_step_over ()));
 
   m_debug_step_into
     = construct_debug_menu_item ("db-step-in", tr ("Step In"),
-                                 SLOT (debug_step_into (void)));
+                                 SLOT (debug_step_into ()));
 
   m_debug_step_out
     = construct_debug_menu_item ("db-step-out", tr ("Step Out"),
-                                 SLOT (debug_step_out (void)));
+                                 SLOT (debug_step_out ()));
 
   m_debug_continue
     = construct_debug_menu_item ("db-cont", tr ("Continue"),
-                                 SLOT (debug_continue (void)));
+                                 SLOT (debug_continue ()));
 
   m_debug_menu->addSeparator ();
 #if defined (HAVE_QSCINTILLA)
@@ -2420,7 +2398,7 @@
 
   m_debug_quit
     = construct_debug_menu_item ("db-stop", tr ("Quit Debug Mode"),
-                                 SLOT (debug_quit (void)));
+                                 SLOT (debug_quit ()));
 }
 
 void main_window::construct_tools_menu (QMenuBar *p)
@@ -2428,17 +2406,17 @@
   QMenu *tools_menu = m_add_menu (p, tr ("&Tools"));
 
   m_profiler_start = add_action (tools_menu, QIcon (),
-                                 tr ("Start &Profiler Session"), SLOT (profiler_session ()));
+        tr ("Start &Profiler Session"), SLOT (profiler_session ()));
 
   m_profiler_resume = add_action (tools_menu, QIcon (),
-                                  tr ("&Resume Profiler Session"), SLOT (profiler_session_resume ()));
+        tr ("&Resume Profiler Session"), SLOT (profiler_session_resume ()));
 
   m_profiler_stop = add_action (tools_menu, QIcon (),
-                                tr ("&Stop Profiler"), SLOT (profiler_stop ()));
+        tr ("&Stop Profiler"), SLOT (profiler_stop ()));
   m_profiler_stop->setEnabled (false);
 
   m_profiler_show = add_action (tools_menu, QIcon (),
-                                tr ("&Show Profile Data"), SLOT (profiler_show ()));
+        tr ("&Show Profile Data"), SLOT (profiler_show ()));
 }
 
 void main_window::editor_tabs_changed (bool have_tabs, bool is_octave)
@@ -2474,8 +2452,8 @@
       else
         {
           // action for focus of dock widget
-          connect (action, SIGNAL (triggered (void)),
-                   widget, SLOT (activate (void)));
+          connect (action, SIGNAL (triggered ()),
+                   widget, SLOT (activate ()));
         }
     }
   else
@@ -2537,12 +2515,12 @@
   window_menu->addSeparator ();
 
   m_previous_dock_action = add_action (window_menu, QIcon (),
-                                       tr ("Previous Widget"), SLOT (go_to_previous_widget (void)));
+                                         tr ("Previous Widget"), SLOT (go_to_previous_widget ()));
 
   window_menu->addSeparator ();
 
   m_reset_windows_action = add_action (window_menu, QIcon (),
-                                       tr ("Reset Default Window Layout"), SLOT (reset_windows (void)));
+                                       tr ("Reset Default Window Layout"), SLOT (reset_windows ()));
 }
 
 void main_window::construct_help_menu (QMenuBar *p)
@@ -2603,7 +2581,7 @@
   m_current_news_action->setShortcutContext (Qt::ApplicationShortcut);
 }
 
-void main_window::construct_tool_bar (void)
+void main_window::construct_tool_bar ()
 {
   m_main_tool_bar = addToolBar (tr ("Toolbar"));
   m_main_tool_bar->setStyleSheet (m_main_tool_bar->styleSheet ()
@@ -2627,8 +2605,8 @@
   m_current_directory_combo_box->setEditable (true);
   m_current_directory_combo_box->setInsertPolicy (QComboBox::NoInsert);
   m_current_directory_combo_box->setToolTip (tr ("Enter directory name"));
-  m_current_directory_combo_box->setMaxVisibleItems (current_directory_max_visible);
-  m_current_directory_combo_box->setMaxCount (current_directory_max_count);
+  m_current_directory_combo_box->setMaxVisibleItems (CURRENT_DIRECTORY_MAX_VISIBLE);
+  m_current_directory_combo_box->setMaxCount (CURRENT_DIRECTORY_MAX_COUNT);
   QSizePolicy sizePol (QSizePolicy::Preferred, QSizePolicy::Preferred);
   m_current_directory_combo_box->setSizePolicy (sizePol);
 
@@ -2636,12 +2614,14 @@
   // need to delete these upon destroying this main_window.
   m_main_tool_bar->addWidget (new QLabel (tr ("Current Directory: ")));
   m_main_tool_bar->addWidget (m_current_directory_combo_box);
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+
+  gui_settings settings;
+
   QAction *current_dir_up
-    = m_main_tool_bar->addAction (rmgr.icon ("folder-up", false, "go-up"),
+    = m_main_tool_bar->addAction (settings.icon ("folder-up", false, "go-up"),
                                   tr ("One directory up"));
   QAction *current_dir_search
-    = m_main_tool_bar->addAction (rmgr.icon ("folder"),
+    = m_main_tool_bar->addAction (settings.icon ("folder"),
                                   tr ("Browse directories"));
 
   connect (m_current_directory_combo_box, SIGNAL (activated (const QString&)),
@@ -2661,90 +2641,90 @@
            this, &main_window::handle_undo_request);
 }
 
-void main_window::focus_console_after_command (void)
+void main_window::focus_console_after_command ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (settings->value (cs_focus_cmd).toBool ())
+  gui_settings settings;
+
+  if (settings.bool_value (cs_focus_cmd))
     focus_command_window ();
 }
 
-void main_window::configure_shortcuts (void)
+void main_window::configure_shortcuts ()
 {
+  gui_settings settings;
+
   bool enable
     = ! ((m_active_dock == m_command_window) && m_prevent_readline_conflicts);
 
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-
   // file menu
-  scmgr.set_shortcut (m_open_action, sc_main_file_open_file, enable);
-  scmgr.set_shortcut (m_new_script_action, sc_main_file_new_file, enable);
-  scmgr.set_shortcut (m_new_function_action, sc_main_file_new_function, enable);
-  scmgr.set_shortcut (m_new_figure_action, sc_main_file_new_figure, enable);
-  scmgr.set_shortcut (m_load_workspace_action, sc_main_file_load_workspace, enable);
-  scmgr.set_shortcut (m_save_workspace_action, sc_main_file_save_workspace, enable);
-  scmgr.set_shortcut (m_exit_action, sc_main_file_exit, enable);
+  settings.set_shortcut (m_open_action, sc_main_file_open_file, enable);
+  settings.set_shortcut (m_new_script_action, sc_main_file_new_file, enable);
+  settings.set_shortcut (m_new_function_action, sc_main_file_new_function, enable);
+  settings.set_shortcut (m_new_figure_action, sc_main_file_new_figure, enable);
+  settings.set_shortcut (m_load_workspace_action, sc_main_file_load_workspace, enable);
+  settings.set_shortcut (m_save_workspace_action, sc_main_file_save_workspace, enable);
+  settings.set_shortcut (m_exit_action, sc_main_file_exit, enable);
 
   // edit menu
-  scmgr.set_shortcut (m_copy_action, sc_main_edit_copy, enable);
-  scmgr.set_shortcut (m_paste_action, sc_main_edit_paste, enable);
-  scmgr.set_shortcut (m_undo_action, sc_main_edit_undo, enable);
-  scmgr.set_shortcut (m_select_all_action, sc_main_edit_select_all, enable);
-  scmgr.set_shortcut (m_clear_clipboard_action, sc_main_edit_clear_clipboard, enable);
-  scmgr.set_shortcut (m_find_files_action, sc_main_edit_find_in_files, enable);
-  scmgr.set_shortcut (m_clear_command_history_action, sc_main_edit_clear_history, enable);
-  scmgr.set_shortcut (m_clear_command_window_action, sc_main_edit_clear_command_window, enable);
-  scmgr.set_shortcut (m_clear_workspace_action, sc_main_edit_clear_workspace, enable);
-  scmgr.set_shortcut (m_set_path_action, sc_main_edit_set_path, enable);
-  scmgr.set_shortcut (m_preferences_action, sc_main_edit_preferences, enable);
+  settings.set_shortcut (m_copy_action, sc_main_edit_copy, enable);
+  settings.set_shortcut (m_paste_action, sc_main_edit_paste, enable);
+  settings.set_shortcut (m_undo_action, sc_main_edit_undo, enable);
+  settings.set_shortcut (m_select_all_action, sc_main_edit_select_all, enable);
+  settings.set_shortcut (m_clear_clipboard_action, sc_main_edit_clear_clipboard, enable);
+  settings.set_shortcut (m_find_files_action, sc_main_edit_find_in_files, enable);
+  settings.set_shortcut (m_clear_command_history_action, sc_main_edit_clear_history, enable);
+  settings.set_shortcut (m_clear_command_window_action, sc_main_edit_clear_command_window, enable);
+  settings.set_shortcut (m_clear_workspace_action, sc_main_edit_clear_workspace, enable);
+  settings.set_shortcut (m_set_path_action, sc_main_edit_set_path, enable);
+  settings.set_shortcut (m_preferences_action, sc_main_edit_preferences, enable);
 
   // debug menu
-  scmgr.set_shortcut (m_debug_step_over, sc_main_debug_step_over, enable);
-  scmgr.set_shortcut (m_debug_step_into, sc_main_debug_step_into, enable);
-  scmgr.set_shortcut (m_debug_step_out, sc_main_debug_step_out, enable);
-  scmgr.set_shortcut (m_debug_continue, sc_main_debug_continue, enable);
-  scmgr.set_shortcut (m_debug_quit, sc_main_debug_quit, enable);
+  settings.set_shortcut (m_debug_step_over, sc_main_debug_step_over, enable);
+  settings.set_shortcut (m_debug_step_into, sc_main_debug_step_into, enable);
+  settings.set_shortcut (m_debug_step_out, sc_main_debug_step_out, enable);
+  settings.set_shortcut (m_debug_continue, sc_main_debug_continue, enable);
+  settings.set_shortcut (m_debug_quit, sc_main_debug_quit, enable);
 
   // tools menu
-  scmgr.set_shortcut (m_profiler_start, sc_main_tools_start_profiler, enable);
-  scmgr.set_shortcut (m_profiler_resume, sc_main_tools_resume_profiler, enable);
-  scmgr.set_shortcut (m_profiler_stop, sc_main_tools_start_profiler, enable); // same, toggling
-  scmgr.set_shortcut (m_profiler_show, sc_main_tools_show_profiler, enable);
+  settings.set_shortcut (m_profiler_start, sc_main_tools_start_profiler, enable);
+  settings.set_shortcut (m_profiler_resume, sc_main_tools_resume_profiler, enable);
+  settings.set_shortcut (m_profiler_stop, sc_main_tools_start_profiler, enable); // same, toggling
+  settings.set_shortcut (m_profiler_show, sc_main_tools_show_profiler, enable);
 
   // window menu
-  scmgr.set_shortcut (m_show_command_window_action, sc_main_window_show_command, enable);
-  scmgr.set_shortcut (m_show_history_action, sc_main_window_show_history, enable);
-  scmgr.set_shortcut (m_show_workspace_action, sc_main_window_show_workspace, enable);
-  scmgr.set_shortcut (m_show_file_browser_action, sc_main_window_show_file_browser, enable);
-  scmgr.set_shortcut (m_show_editor_action, sc_main_window_show_editor, enable);
-  scmgr.set_shortcut (m_show_documentation_action, sc_main_window_show_doc, enable);
-  scmgr.set_shortcut (m_show_variable_editor_action, sc_main_window_show_variable_editor, enable);
-  scmgr.set_shortcut (m_reset_windows_action, sc_main_window_reset, enable);
-  scmgr.set_shortcut (m_command_window_action, sc_main_window_command, enable);
+  settings.set_shortcut (m_show_command_window_action, sc_main_window_show_command, enable);
+  settings.set_shortcut (m_show_history_action, sc_main_window_show_history, enable);
+  settings.set_shortcut (m_show_workspace_action, sc_main_window_show_workspace, enable);
+  settings.set_shortcut (m_show_file_browser_action, sc_main_window_show_file_browser, enable);
+  settings.set_shortcut (m_show_editor_action, sc_main_window_show_editor, enable);
+  settings.set_shortcut (m_show_documentation_action, sc_main_window_show_doc, enable);
+  settings.set_shortcut (m_show_variable_editor_action, sc_main_window_show_variable_editor, enable);
+  settings.set_shortcut (m_reset_windows_action, sc_main_window_reset, enable);
+  settings.set_shortcut (m_command_window_action, sc_main_window_command, enable);
   // Switching to the other widgets (including the previous one) is always enabled
-  scmgr.set_shortcut (m_history_action, sc_main_window_history, true);
-  scmgr.set_shortcut (m_workspace_action, sc_main_window_workspace, true);
-  scmgr.set_shortcut (m_file_browser_action, sc_main_window_file_browser, true);
-  scmgr.set_shortcut (m_editor_action, sc_main_window_editor, true);
-  scmgr.set_shortcut (m_documentation_action, sc_main_window_doc, true);
-  scmgr.set_shortcut (m_variable_editor_action, sc_main_window_variable_editor, true);
-  scmgr.set_shortcut (m_previous_dock_action, sc_main_window_previous_dock, true);
+  settings.set_shortcut (m_history_action, sc_main_window_history, true);
+  settings.set_shortcut (m_workspace_action, sc_main_window_workspace, true);
+  settings.set_shortcut (m_file_browser_action, sc_main_window_file_browser, true);
+  settings.set_shortcut (m_editor_action, sc_main_window_editor, true);
+  settings.set_shortcut (m_documentation_action, sc_main_window_doc, true);
+  settings.set_shortcut (m_variable_editor_action, sc_main_window_variable_editor, true);
+  settings.set_shortcut (m_previous_dock_action, sc_main_window_previous_dock, true);
 
   // help menu
-  scmgr.set_shortcut (m_ondisk_doc_action, sc_main_help_ondisk_doc, enable);
-  scmgr.set_shortcut (m_online_doc_action, sc_main_help_online_doc, enable);
-  scmgr.set_shortcut (m_report_bug_action, sc_main_help_report_bug, enable);
-  scmgr.set_shortcut (m_octave_packages_action, sc_main_help_packages, enable);
-  scmgr.set_shortcut (m_contribute_action, sc_main_help_contribute, enable);
-  scmgr.set_shortcut (m_developer_action, sc_main_help_developer, enable);
-  scmgr.set_shortcut (m_about_octave_action, sc_main_help_about, enable);
+  settings.set_shortcut (m_ondisk_doc_action, sc_main_help_ondisk_doc, enable);
+  settings.set_shortcut (m_online_doc_action, sc_main_help_online_doc, enable);
+  settings.set_shortcut (m_report_bug_action, sc_main_help_report_bug, enable);
+  settings.set_shortcut (m_octave_packages_action, sc_main_help_packages, enable);
+  settings.set_shortcut (m_contribute_action, sc_main_help_contribute, enable);
+  settings.set_shortcut (m_developer_action, sc_main_help_developer, enable);
+  settings.set_shortcut (m_about_octave_action, sc_main_help_about, enable);
 
   // news menu
-  scmgr.set_shortcut (m_release_notes_action, sc_main_news_release_notes, enable);
-  scmgr.set_shortcut (m_current_news_action, sc_main_news_community_news, enable);
+  settings.set_shortcut (m_release_notes_action, sc_main_news_release_notes, enable);
+  settings.set_shortcut (m_current_news_action, sc_main_news_community_news, enable);
 }
 
-QList<octave_dock_widget *> main_window::dock_widget_list (void)
+QList<octave_dock_widget *> main_window::dock_widget_list ()
 {
   QList<octave_dock_widget *> list = QList<octave_dock_widget *> ();
   list.append (static_cast<octave_dock_widget *> (m_command_window));
@@ -2768,32 +2748,20 @@
 
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
-
-      F__mfile_encoding__ (interp, ovl (mfile_encoding));
-    });
+     {
+       // INTERPRETER THREAD
+
+       Fmfile_encoding (interp, ovl (mfile_encoding));
+     });
 }
 
 void main_window::resize_dock (QDockWidget *dw, int width, int height)
 {
-#if defined (HAVE_QMAINWINDOW_RESIZEDOCKS)
   // resizeDockWidget was added to Qt in Qt 5.6
   if (width >= 0)
     resizeDocks ({dw}, {width}, Qt::Horizontal);
   if (height >= 0)
     resizeDocks ({dw}, {height}, Qt::Vertical);
-#else
-  // This replacement of resizeDockWidget is not very reliable.
-  // But even if Qt4 is not yet
-  QSize s = dw->widget ()->size ();
-  if (width >= 0)
-    s.setWidth (width);
-  if (height >= 0)
-    s.setHeight (height);
-  dw->widget ()->resize (s);
-  dw->adjustSize ();
-#endif
 }
 
 // The default main window size relative to the desktop size
@@ -2806,7 +2774,7 @@
   resize (2*win_x/3, 7*win_y/8);
 }
 
-void main_window::reset_windows (void)
+void main_window::reset_windows ()
 {
   // Slot for resetting the window layout to the default one
   hide ();
@@ -2913,11 +2881,10 @@
 
       if (save)
         {
-          resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-          gui_settings *settings = rmgr.get_settings ();
-
-          settings->setValue (mw_geometry.key, saveGeometry ());
-          settings->setValue (mw_state.key, saveState ());
+          gui_settings settings;
+
+          settings.setValue (mw_geometry.settings_key (), saveGeometry ());
+          settings.setValue (mw_state.settings_key (), saveState ());
         }
 
       focus_command_window ();
--- a/libgui/src/main-window.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/main-window.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,6 @@
 #include "interpreter-qobject.h"
 #include "led-indicator.h"
 #include "octave-dock-widget.h"
-#include "octave-qobject.h"
 #include "qt-interpreter-events.h"
 #include "set-path-dialog.h"
 #include "terminal-dock-widget.h"
@@ -65,6 +64,7 @@
 
 class interpreter;
 
+class base_qobject;
 class settings_dialog;
 
 //! Represents the main window.
@@ -80,35 +80,35 @@
 
   main_window (base_qobject& oct_qobj);
 
-  ~main_window (void);
+  ~main_window ();
 
   void make_dock_widget_connections (octave_dock_widget *dw);
 
-  bool command_window_has_focus (void) const;
+  bool command_window_has_focus () const;
 
-  void focus_command_window (void);
+  void focus_command_window ();
 
-  bool confirm_shutdown (void);
+  bool confirm_shutdown ();
 
 signals:
 
   // Note: CLOSE_GUI_SIGNAL is currently only used by the new
   // experimental terminal widget.
-  void close_gui_signal (void);
+  void close_gui_signal ();
 
   void active_dock_changed (octave_dock_widget *, octave_dock_widget *);
   void editor_focus_changed (bool);
 
-  void settings_changed (const gui_settings *);
-  void init_terminal_size_signal (void);
-  void init_window_menu (void);
+  void settings_changed ();
+  void init_terminal_size_signal ();
+  void init_window_menu ();
   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 step_into_file_signal ();
 
   void show_community_news_signal (int serial);
-  void show_release_notes_signal (void);
+  void show_release_notes_signal ();
 
   void update_gui_lexer_signal (bool);
 
@@ -117,10 +117,10 @@
   void update_breakpoint_marker_signal (bool insert, const QString& file,
                                         int line, const QString& cond);
 
-  void copyClipboard_signal (void);
-  void pasteClipboard_signal (void);
-  void selectAll_signal (void);
-  void undo_signal (void);
+  void copyClipboard_signal ();
+  void pasteClipboard_signal ();
+  void selectAll_signal ();
+  void undo_signal ();
 
   void add_actions_signal (QList <QAction *> action_list);
 
@@ -131,61 +131,62 @@
 
   void execute_command_signal (const QString& command);
 
+  void update_prompt_signal (const QString& prompt);
+
 public slots:
 
   void focus_changed (QWidget *w_old, QWidget *w_new);
   void focus_window (const QString& win_name);
-  void request_reload_settings (void);
+  void request_reload_settings ();
 
   void report_status_message (const QString& statusMessage);
-  void handle_save_workspace_request (void);
+  void handle_save_workspace_request ();
   void handle_load_workspace_request (const QString& file = QString ());
   void handle_open_any_request (const QString& file = QString ());
-  void handle_clear_workspace_request (void);
-  void handle_clear_command_window_request (void);
-  void handle_clear_history_request (void);
-  void handle_undo_request (void);
+  void handle_clear_workspace_request ();
+  void handle_clear_command_window_request ();
+  void handle_clear_history_request ();
+  void handle_undo_request ();
   void modify_path (const QStringList& dir_list, bool rm, bool subdirs);
   void edit_mfile (const QString&, int);
   void file_remove_proxy (const QString& o, const QString& n);
-  void open_online_documentation_page (void);
-  void open_bug_tracker_page (void);
-  void open_octave_packages_page (void);
-  void open_contribute_page (void);
-  void open_donate_page (void);
+  void open_online_documentation_page ();
+  void open_bug_tracker_page ();
+  void open_octave_packages_page ();
+  void open_contribute_page ();
+  void open_donate_page ();
   void process_settings_dialog_request (const QString& desired_tab
                                         = QString ());
-  void show_about_octave (void);
-  void notice_settings (const gui_settings *settings,
-                        bool update_by_worker = false);
+  void show_about_octave ();
+  void notice_settings (bool update_by_worker = false);
   QPalette getFusionDarkPalette();
-  void prepare_to_exit (void);
-  void go_to_previous_widget (void);
-  void reset_windows (void);
+  void prepare_to_exit ();
+  void go_to_previous_widget ();
+  void reset_windows ();
   void do_reset_windows (bool show = true, bool save = true,
                          bool force_all = false);
 
   void update_octave_directory (const QString& dir);
-  void browse_for_directory (void);
+  void browse_for_directory ();
   void set_current_working_directory (const QString& dir);
-  void change_directory_up (void);
-  void accept_directory_line_edit (void);
+  void change_directory_up ();
+  void accept_directory_line_edit ();
 
   void execute_command_in_terminal (const QString& dir);
   void run_file_in_terminal (const QFileInfo& info);
 
-  void handle_new_figure_request (void);
+  void handle_new_figure_request ();
 
-  void handle_enter_debugger (void);
-  void handle_exit_debugger (void);
-  void debug_continue (void);
-  void debug_step_into (void);
-  void debug_step_over (void);
-  void debug_step_out (void);
-  void debug_quit (void);
+  void handle_enter_debugger ();
+  void handle_exit_debugger ();
+  void debug_continue ();
+  void debug_step_into ();
+  void debug_step_over ();
+  void debug_step_out ();
+  void debug_quit ();
   void editor_tabs_changed (bool, bool);
 
-  void request_open_file (void);
+  void request_open_file ();
   void request_new_script (const QString& commands = QString ());
   void request_new_function (bool triggered = true);
   void handle_edit_mfile_request (const QString& name, const QString& file,
@@ -197,28 +198,28 @@
                                                 const QString& file, int line,
                                                 const QString& cond);
 
-  void read_settings (void);
-  void init_terminal_size (void);
-  void set_window_layout (gui_settings *settings);
-  void write_settings (void);
+  void read_settings ();
+  void init_terminal_size ();
+  void set_window_layout ();
+  void write_settings ();
 
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
 
   void handle_gui_status_update (const QString& feature, const QString& status);
 
-  void focus_console_after_command (void);
+  void focus_console_after_command ();
 
-  void profiler_session (void);
-  void profiler_session_resume (void);
-  void profiler_stop (void);
+  void profiler_session ();
+  void profiler_session_resume ();
+  void profiler_stop ();
   void handle_profiler_status_update (bool);
-  void profiler_show (void);
+  void profiler_show ();
 
   void handle_octave_ready ();
 
-  void handle_set_path_dialog_request (void);
+  void handle_set_path_dialog_request ();
 
   //! Find files dialog.
   //!@{
@@ -230,13 +231,13 @@
 
   //! Handling the clipboard.
   //!@{
-  void clipboard_has_changed (void);
+  void clipboard_has_changed ();
   void clear_clipboard ();
   //!@}
 
   //! Returns a list of dock widgets.
 
-  QList<octave_dock_widget *> get_dock_widget_list (void)
+  QList<octave_dock_widget *> get_dock_widget_list ()
   {
     return dock_widget_list ();
   }
@@ -244,7 +245,7 @@
 private slots:
 
   void disable_menu_shortcuts (bool disable);
-  void restore_create_file_setting (void);
+  void restore_create_file_setting ();
   void set_file_encoding (const QString& new_encoding);
   void request_open_files (const QStringList& open_file_names);
 
@@ -256,28 +257,28 @@
 
 private:
 
-  void adopt_dock_widgets (void);
+  void adopt_dock_widgets ();
 
-  void adopt_terminal_widget (void);
-  void adopt_documentation_widget (void);
-  void adopt_file_browser_widget (void);
-  void adopt_history_widget (void);
-  void adopt_workspace_widget (void);
-  void adopt_editor_widget (void);
-  void adopt_variable_editor_widget (void);
+  void adopt_terminal_widget ();
+  void adopt_documentation_widget ();
+  void adopt_file_browser_widget ();
+  void adopt_history_widget ();
+  void adopt_workspace_widget ();
+  void adopt_editor_widget ();
+  void adopt_variable_editor_widget ();
 
-  void construct_central_widget (void);
+  void construct_central_widget ();
 
-  void construct (void);
+  void construct ();
 
-  void construct_octave_qt_link (void);
+  void construct_octave_qt_link ();
 
   QAction * add_action (QMenu *menu, const QIcon& icon,
                         const QString& text, const char *member,
                         const QWidget *receiver = nullptr);
 
   QMenu * m_add_menu (QMenuBar *p, QString text);
-  void construct_menu_bar (void);
+  void construct_menu_bar ();
   void construct_file_menu (QMenuBar *p);
   void construct_new_menu (QMenu *p);
   void construct_edit_menu (QMenuBar *p);
@@ -293,15 +294,15 @@
 
   void construct_news_menu (QMenuBar *p);
 
-  void construct_tool_bar (void);
+  void construct_tool_bar ();
 
-  void configure_shortcuts (void);
+  void configure_shortcuts ();
 
-  QList<octave_dock_widget *> dock_widget_list (void);
+  QList<octave_dock_widget *> dock_widget_list ();
 
   void update_default_encoding (const QString& default_encoding);
 
-  void set_default_geometry (void);
+  void set_default_geometry ();
   void resize_dock (QDockWidget *dw, int width, int height);
 
   base_qobject& m_octave_qobj;
@@ -403,8 +404,8 @@
   //! For Toolbars.
   //!@{
   QComboBox *m_current_directory_combo_box;
-  static const int current_directory_max_visible = 16;
-  static const int current_directory_max_count = 16;
+  static const int CURRENT_DIRECTORY_MAX_VISIBLE = 16;
+  static const int CURRENT_DIRECTORY_MAX_COUNT = 16;
   QLineEdit *m_current_directory_line_edit;
   //!@}
 
--- a/libgui/src/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -301,8 +301,7 @@
   %reldir%/moc-color-picker.cc \
   %reldir%/moc-tab-bar.cc \
   %reldir%/moc-qt-interpreter-events.cc \
-  %reldir%/moc-resource-manager.cc \
-  %reldir%/moc-shortcut-manager.cc \
+  %reldir%/moc-shortcuts-tree-widget.cc \
   %reldir%/moc-welcome-wizard.cc \
   %reldir%/moc-workspace-model.cc \
   %reldir%/moc-workspace-view.cc \
@@ -378,14 +377,12 @@
   %reldir%/main-window.h \
   %reldir%/news-reader.h \
   %reldir%/octave-qobject.h \
-  %reldir%/octave-qtutils.h \
   %reldir%/qt-application.h \
   %reldir%/qt-interpreter-events.h \
   %reldir%/qt-utils.h \
   %reldir%/release-notes.h \
-  %reldir%/resource-manager.h \
   %reldir%/settings-dialog.h \
-  %reldir%/shortcut-manager.h \
+  %reldir%/shortcuts-tree-widget.h \
   %reldir%/tab-bar.h \
   %reldir%/terminal-dock-widget.h \
   %reldir%/color-picker.h \
@@ -412,6 +409,23 @@
   %reldir%/external-editor-interface.cc \
   %reldir%/files-dock-widget.cc \
   %reldir%/graphics-init.cc \
+  %reldir%/gui-preferences-cs.cc \
+  %reldir%/gui-preferences-dc.cc \
+  %reldir%/gui-preferences-dw.cc \
+  %reldir%/gui-preferences-ed.cc \
+  %reldir%/gui-preferences-fb.cc \
+  %reldir%/gui-preferences-ff.cc \
+  %reldir%/gui-preferences-global.cc \
+  %reldir%/gui-preferences-gp.cc \
+  %reldir%/gui-preferences-hw.cc \
+  %reldir%/gui-preferences-mw.cc \
+  %reldir%/gui-preferences-nr.cc \
+  %reldir%/gui-preferences-pd.cc \
+  %reldir%/gui-preferences-sc.cc \
+  %reldir%/gui-preferences-sd.cc \
+  %reldir%/gui-preferences-ve.cc \
+  %reldir%/gui-preferences-ws.cc \
+  %reldir%/gui-preferences.cc \
   %reldir%/gui-settings.cc \
   %reldir%/history-dock-widget.cc \
   %reldir%/interpreter-qobject.cc \
@@ -429,9 +443,8 @@
   %reldir%/qt-interpreter-events.cc \
   %reldir%/qt-application.cc \
   %reldir%/release-notes.cc \
-  %reldir%/resource-manager.cc \
   %reldir%/settings-dialog.cc \
-  %reldir%/shortcut-manager.cc \
+  %reldir%/shortcuts-tree-widget.cc \
   %reldir%/tab-bar.cc \
   %reldir%/terminal-dock-widget.cc \
   %reldir%/color-picker.cc \
--- a/libgui/src/news-reader.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/news-reader.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,15 +33,15 @@
 #include <QString>
 
 #include "news-reader.h"
-#include "octave-qobject.h"
 #include "gui-preferences-nr.h"
+#include "gui-settings.h"
 
 #include "url-transfer.h"
 #include "version.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-void news_reader::process (void)
+void news_reader::process ()
 {
   QString html_text;
 
@@ -68,16 +68,12 @@
         {
           if (m_serial >= 0)
             {
-              resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-              gui_settings *settings = rmgr.get_settings ();
+              gui_settings settings;
 
-              if (settings)
-                {
-                  settings->setValue (nr_last_time.key,
-                                      QDateTime::currentDateTime ());
+              settings.setValue (nr_last_time.settings_key (),
+                                 QDateTime::currentDateTime ());
 
-                  settings->sync ();
-                }
+              settings.sync ();
 
               QString tag ("community-news-page-serial=");
 
@@ -95,13 +91,8 @@
 
                   if (curr_page_serial > m_serial)
                     {
-                      if (settings)
-                        {
-                          settings->setValue (nr_last_news.key,
-                                              curr_page_serial);
-
-                          settings->sync ();
-                        }
+                      settings.setValue (nr_last_news.settings_key (), curr_page_serial);
+                      settings.sync ();
                     }
                   else
                     return;
--- a/libgui/src/news-reader.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/news-reader.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,18 +31,15 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class news_reader : public QObject
 {
   Q_OBJECT
 
 public:
 
-  news_reader (base_qobject& oct_qobj, const QString& base_url,
-               const QString& page, int serial = -1,
-               bool connect_to_web = false)
-    : QObject (), m_octave_qobj (oct_qobj), m_base_url (base_url),
+  news_reader (const QString& base_url, const QString& page,
+               int serial = -1, bool connect_to_web = false)
+    : QObject (), m_base_url (base_url),
       m_page (page), m_serial (serial), m_connect_to_web (connect_to_web)
   { }
 
@@ -50,16 +47,14 @@
 
   void display_news_signal (const QString& news);
 
-  void finished (void);
+  void finished ();
 
 public slots:
 
-  void process (void);
+  void process ();
 
 private:
 
-  base_qobject& m_octave_qobj;
-
   QString m_base_url;
   QString m_page;
   int m_serial;
--- a/libgui/src/octave-dock-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/octave-dock-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -45,13 +45,12 @@
 #include "gui-utils.h"
 #include "main-window.h"
 #include "octave-dock-widget.h"
-#include "octave-qobject.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-label_dock_widget::label_dock_widget (QWidget *p, base_qobject& oct_qobj)
-: QDockWidget (p), m_octave_qobj (oct_qobj),
-  m_default_float_button (nullptr), m_default_close_button (nullptr)
+label_dock_widget::label_dock_widget (QWidget *p)
+  : QDockWidget (p), m_default_float_button (nullptr),
+    m_default_close_button (nullptr)
 {
   QStyle *st = style ();
   m_icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize);
@@ -73,13 +72,13 @@
         }
     }
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   // the custom (extra) title bar of the widget
   m_title_widget = new QWidget ();
 
   m_dock_action = new QAction
-    (rmgr.icon ("widget-undock", true), "", this);
+    (settings.icon ("widget-undock", true), "", this);
   m_dock_action->setToolTip (tr ("Undock widget"));
   m_dock_button = new QToolButton (m_title_widget);
   m_dock_button->setDefaultAction (m_dock_action);
@@ -87,7 +86,7 @@
   m_dock_button->setIconSize (QSize (m_icon_size, m_icon_size));
 
   m_close_action = new QAction
-    (rmgr.icon ("widget-close", true), "", this);
+    (settings.icon ("widget-close", true), "", this);
   m_close_action->setToolTip (tr ("Close widget"));
   m_close_button = new QToolButton (m_title_widget);
   m_close_button->setDefaultAction (m_close_action);
@@ -184,14 +183,13 @@
                   "  top: 3px;\n"
                   "}\n"
                   ).arg (close_icon).arg (float_icon).arg (icon_size)
-    .arg (close_tooltip).arg (float_tooltip)
-    .arg (titlebar_foreground).arg (titlebar_background)
-    .arg ((icon_size*2)/3).arg((icon_size*7)/3);
+                   .arg (close_tooltip).arg (float_tooltip)
+                   .arg (titlebar_foreground).arg (titlebar_background)
+                   .arg ((icon_size*2)/3).arg((icon_size*7)/3);
 }
 
-octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p,
-                                        base_qobject& oct_qobj)
-  : label_dock_widget (p, oct_qobj), m_adopted (false),
+octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p)
+  : label_dock_widget (p), m_main_window (nullptr),  m_adopted (false),
     m_custom_style (false), m_focus_follows_mouse (false),
     m_recent_float_geom (), m_recent_dock_geom (),
     m_waiting_for_mouse_button_release (false)
@@ -219,14 +217,15 @@
   connect (this, &octave_dock_widget::queue_make_widget,
            this, [=] () { make_widget (); }, Qt::QueuedConnection);
 
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-  scmgr.set_shortcut (m_dock_action, sc_dock_widget_dock);
+  gui_settings settings;
+
+  settings.set_shortcut (m_dock_action, sc_dock_widget_dock);
   m_dock_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   addAction (m_dock_action);
   connect (m_dock_action, &QAction::triggered,
            this, &octave_dock_widget::make_window);
 
-  scmgr.set_shortcut (m_close_action, sc_dock_widget_close);
+  settings.set_shortcut (m_close_action, sc_dock_widget_close);
   m_close_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   addAction (m_close_action);
   connect (m_close_action, &QAction::triggered,
@@ -234,17 +233,14 @@
 
   m_close_action->setToolTip (tr ("Hide widget"));
 
-  setStyleSheet (qdockwidget_css (
-                                  global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png",
-                                  QString ("Close widget"),
-                                  global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-undock.png",
-                                  QString ("Undock widget"),
-                                  m_icon_size,
-                                  QString (""),
-                                  QString ("")));
+  setStyleSheet (qdockwidget_css
+                 (global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png",
+                  QString ("Close widget"),
+                  global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-undock.png",
+                  QString ("Undock widget"), m_icon_size, "", ""));
 
   if (widget ())
-    widget ()->setToolTip (QString (""));
+    widget ()->setToolTip ("");
 
   m_icon_color = "";
   m_title_3d = 50;
@@ -257,12 +253,11 @@
                | QDockWidget::DockWidgetMovable
                | QDockWidget::DockWidgetFloatable);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  handle_settings (rmgr.get_settings ());
+  handle_settings ();
 }
 
 void
-octave_dock_widget::init_window_menu_entry (void)
+octave_dock_widget::init_window_menu_entry ()
 {
   emit active_changed (isVisible ());  // emit once for init of window menu
 }
@@ -303,7 +298,7 @@
   // the window outside the main window
   if (! widget_was_dragged)
     geom = m_recent_float_geom.isNull () ? QRect (50,100,480,480)
-      : m_recent_float_geom;
+                                         : m_recent_float_geom;
   setGeometry (geom);
 
   // adjust the (un)dock action
@@ -314,8 +309,9 @@
   // adjust the (un)dock icon
   if (titleBarWidget ())
     {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      m_dock_action->setIcon (rmgr.icon ("widget-dock" + m_icon_color, true));
+      gui_settings settings;
+
+      m_dock_action->setIcon (settings.icon ("widget-dock" + m_icon_color, true));
       m_dock_action->setToolTip (tr ("Dock widget"));
     }
   else
@@ -342,15 +338,15 @@
 void
 octave_dock_widget::make_widget (bool)
 {
+  gui_settings settings;
+
   bool vis = isVisible ();
 
   // Since floating widget has no parent, we have to read it
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
 
   if (m_main_window)
     {
-      settings->setValue (mw_state.key, m_main_window->saveState ());
+      settings.setValue (mw_state.settings_key (), m_main_window->saveState ());
 
       // Stay window, otherwise will bounce back to window by default
       // because there is no layout information for this widget in the
@@ -359,7 +355,7 @@
       m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this);
       m_adopted = false;
       // recover old window states, hide and re-show new added widget
-      m_main_window->restoreState (settings->value (mw_state.key).toByteArray ());
+      m_main_window->restoreState (settings.value (mw_state.settings_key ()).toByteArray ());
       setFloating (false);
       // restore size using setGeometry instead of restoreGeometry
       // following this post:
@@ -373,7 +369,7 @@
            this, &octave_dock_widget::make_window);
   if (titleBarWidget ())
     {
-      m_dock_action->setIcon (rmgr.icon ("widget-undock" + m_icon_color, true));
+      m_dock_action->setIcon (settings.icon ("widget-undock" + m_icon_color, true));
       m_dock_action->setToolTip (tr ("Undock widget"));
     }
   else
@@ -442,7 +438,7 @@
 
 // get focus widget
 QWidget *
-octave_dock_widget::focusWidget (void)
+octave_dock_widget::focusWidget ()
 {
   QWidget *w = QApplication::focusWidget ();
   if (w && w->focusProxy ()) w = w->focusProxy ();
@@ -471,28 +467,24 @@
 }
 
 void
-octave_dock_widget::handle_settings (const gui_settings *settings)
+octave_dock_widget::handle_settings ()
 {
-  if (! settings)
-    return;
+  gui_settings settings;
 
-  m_focus_follows_mouse = settings->value (dw_focus_follows_mouse).toBool ();
+  m_focus_follows_mouse = settings.bool_value (dw_focus_follows_mouse);
 
   m_custom_style
-    = settings->value (dw_title_custom_style).toBool ();
+    = settings.bool_value (dw_title_custom_style);
 
-  m_title_3d = settings->value (dw_title_3d.key, dw_title_3d.def).toInt ();
+  m_title_3d = settings.int_value (dw_title_3d);
 
-  m_fg_color
-    = settings->value (dw_title_fg_color).value<QColor> ();
+  m_fg_color = settings.color_value (dw_title_fg_color);
 
-  m_fg_color_active
-    = settings->value (dw_title_fg_color_active).value<QColor> ();
+  m_fg_color_active = settings.color_value (dw_title_fg_color_active);
 
-  m_bg_color = settings->value (dw_title_bg_color).value<QColor> ();
+  m_bg_color = settings.color_value (dw_title_bg_color);
 
-  m_bg_color_active
-    = settings->value (dw_title_bg_color_active).value<QColor> ();
+  m_bg_color_active = settings.color_value (dw_title_bg_color_active);
 
   QColor bcol (m_bg_color);
   QColor bcola (m_bg_color_active);
@@ -534,7 +526,7 @@
     }
 
   m_recent_float_geom
-    = settings->value (dw_float_geometry.key.arg (objectName ()),
+    = settings.value (dw_float_geometry.settings_key ().arg (objectName ()),
                        default_floating_size).toRect ();
 
   adjust_to_screen (m_recent_float_geom, default_floating_size);
@@ -543,14 +535,14 @@
   // saveGeomety to new QRect setting (see comment for restoring size
   // of docked widgets)
   QVariant dock_geom
-    = settings->value (dw_dock_geometry.key.arg (objectName ()),
-                       default_dock_size);
+    = settings.value (dw_dock_geometry.settings_key ().arg (objectName ()),
+                      default_dock_size);
   if (dock_geom.canConvert (QMetaType::QRect))
     m_recent_dock_geom = dock_geom.toRect ();
   else
-    m_recent_dock_geom = dw_dock_geometry.def.toRect ();
+    m_recent_dock_geom = dw_dock_geometry.def ().toRect ();
 
-  notice_settings (settings);  // call individual handler
+  notice_settings ();  // call individual handler
 
   set_style (false);
 
@@ -583,29 +575,26 @@
 }
 
 void
-octave_dock_widget::save_settings (void)
+octave_dock_widget::save_settings ()
 {
+  gui_settings settings;
+
   // save state of this dock-widget
   QString name = objectName ();
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  if (! settings)
-    return;
 
   store_geometry ();
 
   // conditional needed?
   if (! m_recent_float_geom.isNull ())
-    settings->setValue (dw_float_geometry.key.arg (name), m_recent_float_geom);
+    settings.setValue (dw_float_geometry.settings_key ().arg (name), m_recent_float_geom);
 
   if (! m_recent_dock_geom.isEmpty ())
-    settings->setValue (dw_dock_geometry.key.arg (name), m_recent_dock_geom);
-  settings->setValue (dw_is_visible.key.arg (name), isVisible ()); // store visibility
-  settings->setValue (dw_is_floating.key.arg (name), isFloating ()); // store floating
-  settings->setValue (dw_is_minimized.key.arg (name), isMinimized ()); // store minimized
+    settings.setValue (dw_dock_geometry.settings_key ().arg (name), m_recent_dock_geom);
+  settings.setValue (dw_is_visible.settings_key ().arg (name), isVisible ()); // store visibility
+  settings.setValue (dw_is_floating.settings_key ().arg (name), isFloating ()); // store floating
+  settings.setValue (dw_is_minimized.settings_key ().arg (name), isMinimized ()); // store minimized
 
-  settings->sync ();
+  settings.sync ();
 }
 
 bool octave_dock_widget::eventFilter (QObject *obj, QEvent *e)
@@ -627,7 +616,7 @@
 }
 
 void
-octave_dock_widget::store_geometry (void)
+octave_dock_widget::store_geometry ()
 {
   if (isFloating ())
     {
@@ -664,7 +653,7 @@
   emit active_changed (false);
 }
 
-void octave_dock_widget::activate (void)
+void octave_dock_widget::activate ()
 {
   if (! isVisible ())
     setVisible (true);
@@ -795,21 +784,22 @@
     }
   else
     {
-      css_foreground = QString ("");
-      css_background = QString ("");
+      css_foreground = "";
+      css_background = "";
     }
 
   QString full_dock_icon = dock_icon + icon_col;
   QString full_close_icon = "widget-close" + icon_col;
   if (titleBarWidget ())
     {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+      gui_settings settings;
+
       titleBarWidget ()->setStyleSheet (css_foreground + css_background);
       css_button = QString ("QToolButton {background: transparent; border: 0px;}");
       m_dock_button->setStyleSheet (css_button);
       m_close_button->setStyleSheet (css_button);
-      m_dock_action->setIcon (rmgr.icon (full_dock_icon, true));
-      m_close_action->setIcon (rmgr.icon (full_close_icon, true));
+      m_dock_action->setIcon (settings.icon (full_dock_icon, true));
+      m_close_action->setIcon (settings.icon (full_close_icon, true));
     }
   else
     {
@@ -825,34 +815,13 @@
 
 // set focus to previously active widget in tabbed widget stack
 void
-octave_dock_widget::set_focus_predecessor (void)
+octave_dock_widget::set_focus_predecessor ()
 {
   // only != 0 if widget was tabbed
   if (m_predecessor_widget && m_predecessor_widget->isVisible ())
     m_predecessor_widget->setFocus ();
 
   m_predecessor_widget = nullptr;
-
-  // FIXME: Until cset bda0c5b38bda, the wrong keys "Dockwidget/..." were used
-  // here.  This had no effect in Qt4, but does in Qt5.  In the following, the
-  // four incorrect keys are updated if still present in the settings files.
-  // The keys are also used in the settings dialog, but
-  // octave_dock_widget::handle_settings is already called at program start.
-  // These tests can be removed in a future version of Octave (version 6).
-
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
-  rmgr.update_settings_key ("Dockwidgets/title_bg_color",
-                            dw_title_bg_color.key);
-
-  rmgr.update_settings_key ("Dockwidgets/title_bg_color_active",
-                            dw_title_bg_color_active.key);
-
-  rmgr.update_settings_key ("Dockwidgets/title_fg_color",
-                            dw_title_fg_color.key);
-
-  rmgr.update_settings_key ("Dockwidgets/title_fg_color_active",
-                            dw_title_fg_color_active.key);
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/octave-dock-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/octave-dock-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,12 +31,10 @@
 #include <QMouseEvent>
 #include <QToolButton>
 
-#include "gui-settings.h"
 #include "qt-interpreter-events.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
 class main_window;
 
 // The few decoration items common to both main window and variable editor.
@@ -47,9 +45,9 @@
 
 public:
 
-  label_dock_widget (QWidget *p, base_qobject& oct_qobj);
+  label_dock_widget (QWidget *p);
 
-  ~label_dock_widget (void) = default;
+  ~label_dock_widget () = default;
 
   // set_title() uses the custom title bar while setWindowTitle() uses
   // the default title bar (with style sheets)
@@ -59,19 +57,17 @@
 
   //! Slots to handle copy & paste.
   //!@{
-  virtual void copyClipboard (void) { }
-  virtual void pasteClipboard (void) { }
-  virtual void selectAll (void) { }
+  virtual void copyClipboard () { }
+  virtual void pasteClipboard () { }
+  virtual void selectAll () { }
   //!@}
 
   //! Slot to handle undo.
 
-  virtual void do_undo (void) { }
+  virtual void do_undo () { }
 
 protected:
 
-  base_qobject& m_octave_qobj;
-
   int m_icon_size;
   QWidget *m_title_widget;
   QToolButton *m_dock_button;
@@ -89,17 +85,16 @@
 
 public:
 
-  octave_dock_widget (const QString& obj_name, QWidget *p,
-                      base_qobject& oct_qobj);
+  octave_dock_widget (const QString& obj_name, QWidget *p);
 
-  ~octave_dock_widget (void) = default;
+  ~octave_dock_widget () = default;
 
   void set_predecessor_widget (octave_dock_widget *prev_widget);
 
   void set_main_window (main_window *mw);
 
   void set_adopted (bool adopted = true) { m_adopted = adopted; }
-  bool adopted (void) const { return m_adopted; }
+  bool adopted () const { return m_adopted; }
 
 signals:
 
@@ -110,29 +105,29 @@
 
   void queue_make_window (bool widget_was_dragged);
 
-  void queue_make_widget (void);
+  void queue_make_widget ();
 
 protected:
 
   virtual void closeEvent (QCloseEvent *e);
 
-  QWidget * focusWidget (void);
+  QWidget * focusWidget ();
 
   bool event (QEvent *event);
 
 public slots:
 
-  virtual void activate (void);
+  virtual void activate ();
 
   virtual void handle_visibility (bool visible);
 
-  virtual void notice_settings (const gui_settings *) { }
+  virtual void notice_settings () { }
 
-  virtual void save_settings (void);
+  virtual void save_settings ();
 
-  void init_window_menu_entry (void);
+  void init_window_menu_entry ();
 
-  void handle_settings (const gui_settings *);
+  void handle_settings ();
 
   void handle_active_dock_changed (octave_dock_widget *, octave_dock_widget *);
 
@@ -161,8 +156,10 @@
 private:
 
   void set_style (bool active);
-  void set_focus_predecessor (void);
-  void store_geometry (void);
+  void set_focus_predecessor ();
+  void store_geometry ();
+
+private:
 
   //! Stores the parent, since we are reparenting to 0.
 
--- a/libgui/src/octave-qobject.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/octave-qobject.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,9 @@
 #include <QApplication>
 #include <QClipboard>
 #include <QFile>
-#include <QTextCodec>
+#if ! defined (Q_OS_WIN32)
+#  include <QTextCodec>
+#endif
 #include <QThread>
 #include <QTimer>
 #include <QTranslator>
@@ -46,6 +48,7 @@
 #include "community-news.h"
 #include "documentation-dock-widget.h"
 #include "files-dock-widget.h"
+#include "gui-settings.h"
 #include "history-dock-widget.h"
 #include "interpreter-qobject.h"
 #include "main-window.h"
@@ -53,8 +56,6 @@
 #include "qt-application.h"
 #include "qt-interpreter-events.h"
 #include "release-notes.h"
-#include "resource-manager.h"
-#include "shortcut-manager.h"
 #include "terminal-dock-widget.h"
 #include "variable-editor.h"
 #include "workspace-model.h"
@@ -74,7 +75,7 @@
 
 // Bug #55940 (Disable App Nap on Mac)
 #if defined (Q_OS_MAC)
-static void disable_app_nap (void)
+static void disable_app_nap ()
 {
   Class process_info_class;
   SEL process_info_selector;
@@ -149,11 +150,11 @@
   catch (execution_exception& ee)
     {
       emit interpreter_event
-        ([=] (void)
-        {
-          // INTERPRETER THREAD
-          throw ee;
-        });
+        ([=] ()
+         {
+           // INTERPRETER THREAD
+           throw ee;
+         });
     }
 
   return false;
@@ -174,8 +175,6 @@
     m_argc (m_app_context.sys_argc ()),
     m_argv (m_app_context.sys_argv ()),
     m_qapplication (new octave_qapplication (m_argc, m_argv)),
-    m_resource_manager (),
-    m_shortcut_manager (*this),
     m_qt_tr (new QTranslator ()),
     m_gui_tr (new QTranslator ()),
     m_qsci_tr (new QTranslator ()),
@@ -194,24 +193,18 @@
     m_variable_editor_widget (),
     m_main_window (nullptr)
 {
-  std::string show_gui_msgs =
-    sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+  std::string show_gui_msgs = sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
 
   // Installing our handler suppresses the messages.
 
   if (show_gui_msgs.empty ())
     qInstallMessageHandler (message_handler);
 
+#if ! defined (Q_OS_WIN32)
   // Set the codec for all strings (before wizard or any GUI object)
-#if ! defined (Q_OS_WIN32)
   QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
 #endif
 
-  // Initialize global Qt application metadata.
-
-  QCoreApplication::setApplicationName ("GNU Octave");
-  QCoreApplication::setApplicationVersion (OCTAVE_VERSION);
-
   // Register octave_value_list for connecting thread crossing signals.
 
   qRegisterMetaType<octave_value_list> ("octave_value_list");
@@ -221,6 +214,9 @@
   // Mac App Nap feature causes pause() and sleep() to misbehave.
   // Disable it for the entire program run.
   disable_app_nap ();
+
+  // Don't let Qt interpret CMD key ("Meta" in Qt terminology) as Ctrl.
+  QCoreApplication::setAttribute (Qt::AA_MacDontSwapCtrlAndMeta, true);
 #endif
 
   // Force left-to-right alignment (see bug #46204)
@@ -310,14 +306,14 @@
       else
         {
           // Get settings file.
-          m_resource_manager.reload_settings ();
+          gui_settings settings;
+
+          settings.reload ();
 
           // After settings.
           config_translators ();
-          m_resource_manager.config_icon_theme ();
 
-          // Initilize the shortcut-manager
-          m_shortcut_manager.init_data ();
+          settings.config_icon_theme ();
 
           m_qapplication->setQuitOnLastWindowClosed (false);
         }
@@ -326,7 +322,7 @@
   start_main_thread ();
 }
 
-base_qobject::~base_qobject (void)
+base_qobject::~base_qobject ()
 {
   // Note that we don't delete m_main_thread here.  That is handled by
   // deleteLater slot that is called when the m_main_thread issues a
@@ -389,12 +385,14 @@
   string_vector::delete_c_str_vec (m_argv);
 }
 
-void base_qobject::config_translators (void)
+void base_qobject::config_translators ()
 {
   if (m_translators_installed)
     return;
 
-  m_resource_manager.config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);
+  gui_settings settings;
+
+  settings.config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);
 
   m_qapplication->installTranslator (m_qt_tr);
   m_qapplication->installTranslator (m_gui_tr);
@@ -403,7 +401,7 @@
   m_translators_installed = true;
 }
 
-void base_qobject::start_main_thread (void)
+void base_qobject::start_main_thread ()
 {
   // Note: if using the new experimental terminal widget, we defer
   // initializing and executing the interpreter until the main event
@@ -413,14 +411,14 @@
   // the interpreter until after the main window and QApplication are
   // running to prevent race conditions.
 
-  QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute (void)));
+  QTimer::singleShot (0, m_interpreter_qobj, SLOT (execute ()));
 
   m_interpreter_qobj->moveToThread (m_main_thread);
 
   m_main_thread->start ();
 }
 
-int base_qobject::exec (void)
+int base_qobject::exec ()
 {
   int status = m_qapplication->exec ();
 
@@ -437,12 +435,12 @@
 
 // Provided for convenience.  Will be removed once we eliminate the
 // old terminal widget.
-bool base_qobject::experimental_terminal_widget (void) const
+bool base_qobject::experimental_terminal_widget () const
 {
   return m_app_context.experimental_terminal_widget ();
 }
 
-bool base_qobject::gui_running (void) const
+bool base_qobject::gui_running () const
 {
   return m_app_context.gui_running ();
 }
@@ -457,9 +455,12 @@
     }
   else if (! m_terminal_widget)
     {
+      bool etw = m_app_context.experimental_terminal_widget ();
+
       m_terminal_widget
-        = QPointer<terminal_dock_widget> (new terminal_dock_widget (mw, *this));
-      if (experimental_terminal_widget ())
+        = QPointer<terminal_dock_widget> (new terminal_dock_widget (mw, etw));
+
+      if (etw)
         {
 #if defined (HAVE_QSCINTILLA)
           command_widget *cmd_widget
@@ -483,6 +484,9 @@
           connect (qt_link (), &qt_interpreter_events::new_command_line_signal,
                    m_terminal_widget, &terminal_dock_widget::new_command_line_signal);
 
+          connect (mw, &main_window::update_prompt_signal,
+                   m_terminal_widget, &terminal_dock_widget::update_prompt_signal);
+
           connect_interpreter_events (cmd_widget);
 #endif
         }
@@ -493,6 +497,8 @@
           // Connect the interrupt signal (emitted by Ctrl-C)
           connect (cmd_widget, &QTerminal::interrupt_signal,
                    this, &base_qobject::interpreter_interrupt);
+
+          connect_interpreter_events (cmd_widget);
         }
     }
 
@@ -510,7 +516,7 @@
   else if (! m_documentation_widget)
     {
       m_documentation_widget
-        = QPointer<documentation_dock_widget> (new documentation_dock_widget (mw, *this));
+        = QPointer<documentation_dock_widget> (new documentation_dock_widget (mw));
 
       connect (qt_link (),
                &qt_interpreter_events::register_documentation_signal,
@@ -536,7 +542,7 @@
     }
   else if (! m_file_browser_widget)
     m_file_browser_widget
-      = QPointer<files_dock_widget> (new files_dock_widget (mw, *this));
+      = QPointer<files_dock_widget> (new files_dock_widget (mw));
 
   connect (qt_link (), &qt_interpreter_events::directory_changed_signal,
            m_file_browser_widget, &files_dock_widget::update_octave_directory);
@@ -555,7 +561,7 @@
   else if (! m_history_widget)
     {
       m_history_widget
-        = QPointer<history_dock_widget> (new history_dock_widget (mw, *this));
+        = QPointer<history_dock_widget> (new history_dock_widget (mw));
 
       connect (qt_link (), &qt_interpreter_events::set_history_signal,
                m_history_widget, &history_dock_widget::set_history);
@@ -590,7 +596,7 @@
   else if (! m_workspace_widget)
     {
       m_workspace_widget
-        = QPointer<workspace_view> (new workspace_view (mw, *this));
+        = QPointer<workspace_view> (new workspace_view (mw));
 
       m_workspace_widget->setModel (m_workspace_model);
 
@@ -608,23 +614,23 @@
                [=] (const QString& var_name) {
                  emit interpreter_event
                    ([=] (interpreter& interp)
-                   {
-                     // INTERPRETER THREAD
+                    {
+                      // INTERPRETER THREAD
 
-                     octave_value val = interp.varval (var_name.toStdString ());
+                      octave_value val = interp.varval (var_name.toStdString ());
 
-                     if (val.is_undefined ())
-                       val = 0;
+                      if (val.is_undefined ())
+                        val = 0;
 
-                     std::ostringstream buf;
-                     val.print_raw (buf, true);
+                      std::ostringstream buf;
+                      val.print_raw (buf, true);
 
-                     // FIXME: is the following operation thread safe or should
-                     // it be done with a signal/slot connection?
+                      // FIXME: is the following operation thread safe or should
+                      // it be done with a signal/slot connection?
 
-                     QClipboard *clipboard = QApplication::clipboard ();
-                     clipboard->setText (QString::fromStdString (buf.str ()));
-                   });
+                      QClipboard *clipboard = QApplication::clipboard ();
+                      clipboard->setText (QString::fromStdString (buf.str ()));
+                    });
                });
 
       connect (m_workspace_widget, &workspace_view::rename_variable_signal,
@@ -683,16 +689,6 @@
 QPointer<file_editor_interface>
 base_qobject::editor_widget (main_window */*mw*/)
 {
-#if 0
-  if (m_editor_widget && mw)
-    {
-      m_editor_widget->set_main_window (mw);
-      m_editor_widget->set_adopted (true);
-    }
-  else if (! m_editor_widget)
-    m_editor_widget = new file_editor (mw, *this);
-#endif
-
   return m_editor_widget;
 }
 
@@ -707,7 +703,7 @@
   else if (! m_variable_editor_widget)
     {
       m_variable_editor_widget
-        = QPointer<variable_editor> (new variable_editor (mw, *this));
+        = QPointer<variable_editor> (new variable_editor (mw));
 
       connect (m_variable_editor_widget, &variable_editor::updated,
                this, &base_qobject::handle_variable_editor_update);
@@ -729,20 +725,20 @@
 {
   if (! m_community_news)
     m_community_news
-      = QPointer<community_news> (new community_news (*this, serial));
+      = QPointer<community_news> (new community_news (serial));
 
   return m_community_news;
 }
 
-QPointer<release_notes> base_qobject::release_notes_widget (void)
+QPointer<release_notes> base_qobject::release_notes_widget ()
 {
   if (! m_release_notes)
-    m_release_notes = QPointer<release_notes> (new release_notes (*this));
+    m_release_notes = QPointer<release_notes> (new release_notes ());
 
   return m_release_notes;
 }
 
-bool base_qobject::confirm_shutdown (void)
+bool base_qobject::confirm_shutdown ()
 {
   // Currently, we forward to main_window::confirm_shutdown instead of
   // just displaying a dialog box here because the main_window also
@@ -795,7 +791,7 @@
     }
 }
 
-void base_qobject::show_terminal_window (void)
+void base_qobject::show_terminal_window ()
 {
   terminal_dock_widget *widget
     = (m_terminal_widget
@@ -823,7 +819,7 @@
     }
 }
 
-void base_qobject::show_file_browser_window (void)
+void base_qobject::show_file_browser_window ()
 {
   files_dock_widget *widget
     = m_file_browser_widget ? m_file_browser_widget : file_browser_widget ();
@@ -835,7 +831,7 @@
     }
 }
 
-void base_qobject::show_command_history_window (void)
+void base_qobject::show_command_history_window ()
 {
   history_dock_widget *widget
     = m_history_widget ? m_history_widget : history_widget ();
@@ -847,7 +843,7 @@
     }
 }
 
-void base_qobject::show_workspace_window (void)
+void base_qobject::show_workspace_window ()
 {
   workspace_view *widget
     = m_workspace_widget ? m_workspace_widget : workspace_widget ();
@@ -876,7 +872,7 @@
   widget->edit_variable (name, value);
 }
 
-void base_qobject::handle_variable_editor_update (void)
+void base_qobject::handle_variable_editor_update ()
 {
   // Called when the variable editor emits the updated signal.  The size
   // of a variable may have changed, so we refresh the workspace in the
@@ -885,15 +881,15 @@
 
   interpreter_event
     ([] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
+     {
+       // INTERPRETER THREAD
 
-      tree_evaluator& tw = interp.get_evaluator ();
+       tree_evaluator& tw = interp.get_evaluator ();
 
-      event_manager& xevmgr = interp.get_event_manager ();
+       event_manager& xevmgr = interp.get_event_manager ();
 
-      xevmgr.set_workspace (true, tw.get_symbol_info (), false);
-    });
+       xevmgr.set_workspace (true, tw.get_symbol_info (), false);
+     });
 }
 
 void base_qobject::show_community_news (int serial)
@@ -904,7 +900,7 @@
   m_community_news->display ();
 }
 
-void base_qobject::show_release_notes (void)
+void base_qobject::show_release_notes ()
 {
   // Ensure widget exists.
   release_notes_widget ();
@@ -930,7 +926,7 @@
     });
 }
 
-void base_qobject::close_gui (void)
+void base_qobject::close_gui ()
 {
   if (m_app_context.experimental_terminal_widget ())
     {
@@ -964,7 +960,7 @@
     }
 }
 
-void base_qobject::interpreter_ready (void)
+void base_qobject::interpreter_ready ()
 {
   m_interpreter_ready = true;
 }
@@ -993,7 +989,7 @@
   m_interpreter_qobj->interpreter_event (meth);
 }
 
-void base_qobject::interpreter_interrupt (void)
+void base_qobject::interpreter_interrupt ()
 {
   m_interpreter_qobj->interrupt ();
 }
@@ -1001,19 +997,19 @@
 // FIXME: Should we try to make the pause, stop, and resume actions
 // work for both the old and new terminal widget?
 
-void base_qobject::interpreter_pause (void)
+void base_qobject::interpreter_pause ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->pause ();
 }
 
-void base_qobject::interpreter_stop (void)
+void base_qobject::interpreter_stop ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->stop ();
 }
 
-void base_qobject::interpreter_resume (void)
+void base_qobject::interpreter_resume ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->resume ();
--- a/libgui/src/octave-qobject.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/octave-qobject.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,12 +31,11 @@
 #include <QApplication>
 #include <QList>
 #include <QObject>
+#include <QPointer>
 #include <QString>
 #include <QStringList>
 
 #include "interpreter-qobject.h"
-#include "resource-manager.h"
-#include "shortcut-manager.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -65,7 +64,7 @@
 
   virtual bool notify (QObject *receiver, QEvent *e) override;
 
-  ~octave_qapplication (void) { };
+  ~octave_qapplication () { };
 
 signals:
 
@@ -105,63 +104,53 @@
   // experimental terminal widget.
   base_qobject (qt_application& app_context, bool gui_app = false);
 
-  ~base_qobject (void);
+  ~base_qobject ();
 
-  void config_translators (void);
+  void config_translators ();
 
-  void start_main_thread (void);
+  void start_main_thread ();
 
-  int exec (void);
+  int exec ();
 
   // The Octave application context.
-  qt_application& app_context (void) { return m_app_context; }
+  qt_application& app_context () { return m_app_context; }
 
   // The Qt QApplication.
-  QApplication * qapplication (void) { return m_qapplication; };
+  QApplication * qapplication () { return m_qapplication; };
 
   // Provided for convenience.  Will be removed once we eliminate the
   // old terminal widget.
-  bool experimental_terminal_widget (void) const;
+  bool experimental_terminal_widget () const;
 
   // Provided for convenience.
-  bool gui_running (void) const;
+  bool gui_running () const;
 
-  bool have_terminal_window (void) const
+  bool have_terminal_window () const
   {
     return ! m_terminal_widget.isNull ();
   }
 
-  main_window * get_main_window (void)
+  main_window * get_main_window ()
   {
     return m_main_window;
   }
 
-  resource_manager& get_resource_manager (void)
-  {
-    return m_resource_manager;
-  }
-
-  shortcut_manager& get_shortcut_manager (void)
-  {
-    return m_shortcut_manager;
-  }
-
-  std::shared_ptr<qt_interpreter_events> get_qt_interpreter_events (void)
+  std::shared_ptr<qt_interpreter_events> get_qt_interpreter_events ()
   {
     return m_qt_interpreter_events;
   }
 
-  qt_interpreter_events * qt_link (void)
+  qt_interpreter_events * qt_link ()
   {
     return m_qt_interpreter_events.get ();
   }
 
-  interpreter_qobject * interpreter_qobj (void)
+  interpreter_qobject * interpreter_qobj ()
   {
     return m_interpreter_qobj;
   }
 
-  workspace_model * get_workspace_model (void)
+  workspace_model * get_workspace_model ()
   {
     return m_workspace_model;
   }
@@ -192,16 +181,16 @@
 
   QPointer<community_news> community_news_widget (int serial = -1);
 
-  QPointer<release_notes> release_notes_widget (void);
+  QPointer<release_notes> release_notes_widget ();
 
-  QThread * main_thread (void) { return m_main_thread; }
+  QThread * main_thread () { return m_main_thread; }
 
   // Declared virtual so that a derived class may redefine this
   // method.
 
-  virtual bool confirm_shutdown (void);
+  virtual bool confirm_shutdown ();
 
-  bool is_gui_app (void) const { return m_gui_app; }
+  bool is_gui_app () const { return m_gui_app; }
 
   template <typename T> void connect_interpreter_events (T *widget)
   {
@@ -219,40 +208,40 @@
   // Note: START_GUI and CLOSE_GUI don't currently perform any work
   // with the old terminal widget.
   void start_gui (bool gui_app);
-  void close_gui (void);
+  void close_gui ();
 
-  void show_terminal_window (void);
+  void show_terminal_window ();
 
   void show_documentation_window (const QString& file);
 
-  void show_file_browser_window (void);
+  void show_file_browser_window ();
 
-  void show_command_history_window (void);
+  void show_command_history_window ();
 
-  void show_workspace_window (void);
+  void show_workspace_window ();
 
   void show_variable_editor_window (const QString& name,
                                     const octave_value& value);
 
-  void handle_variable_editor_update (void);
+  void handle_variable_editor_update ();
 
   void show_community_news (int serial);
 
-  void show_release_notes (void);
+  void show_release_notes ();
 
-  void interpreter_ready (void);
+  void interpreter_ready ();
 
   void interpreter_event (const fcn_callback& fcn);
 
   void interpreter_event (const meth_callback& meth);
 
-  void interpreter_interrupt (void);
+  void interpreter_interrupt ();
 
   // Note: these currently only work with the new experimental
   // terminal widget.
-  void interpreter_pause (void);
-  void interpreter_stop (void);
-  void interpreter_resume (void);
+  void interpreter_pause ();
+  void interpreter_stop ();
+  void interpreter_resume ();
 
   void copy_image_to_clipboard (const QString& file, bool remove_file);
 
@@ -268,10 +257,6 @@
 
   octave_qapplication *m_qapplication;
 
-  resource_manager m_resource_manager;
-
-  shortcut_manager m_shortcut_manager;
-
   QTranslator *m_qt_tr;
   QTranslator *m_gui_tr;
   QTranslator *m_qsci_tr;
--- a/libgui/src/octave-qtutils.h	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2021-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// This file is part of Octave.
-//
-// Octave is free software: you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Octave is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Octave; see the file COPYING.  If not, see
-// <https://www.gnu.org/licenses/>.
-//
-////////////////////////////////////////////////////////////////////////
-
-#if ! defined (octave_octave_qtutils_h)
-#define octave_octave_qtutils_h 1
-
-// This file should not be installed and should only be included in C++
-// source files after config.h is included, not in other header files.
-
-#if ! defined (HAVE_QOVERLOAD_TEMPLATE)
-
-// The following are copied directly from qglobal.h from Qt 5.15.2 with
-// Q_DECL_CONSTEXPR replaced by constexpr so that we don't have to
-// include any Qt headers or define any other special magic here.
-// Octave requires C++11 so using constexpr should be OK.
-
-template <typename... Args>
-struct QNonConstOverload
-{
-  template <typename R, typename T>
-  constexpr auto operator()(R (T::*ptr)(Args...)) const noexcept -> decltype(ptr)
-  { return ptr; }
-
-  template <typename R, typename T>
-  static constexpr auto of(R (T::*ptr)(Args...)) noexcept -> decltype(ptr)
-  { return ptr; }
-};
-
-template <typename... Args>
-struct QConstOverload
-{
-  template <typename R, typename T>
-  constexpr auto operator()(R (T::*ptr)(Args...) const) const noexcept -> decltype(ptr)
-  { return ptr; }
-
-  template <typename R, typename T>
-  static constexpr auto of(R (T::*ptr)(Args...) const) noexcept -> decltype(ptr)
-  { return ptr; }
-};
-
-template <typename... Args>
-struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
-{
-  using QConstOverload<Args...>::of;
-  using QConstOverload<Args...>::operator();
-  using QNonConstOverload<Args...>::of;
-  using QNonConstOverload<Args...>::operator();
-
-  template <typename R>
-  constexpr auto operator()(R (*ptr)(Args...)) const noexcept -> decltype(ptr)
-  { return ptr; }
-
-  template <typename R>
-  static constexpr auto of(R (*ptr)(Args...)) noexcept -> decltype(ptr)
-  { return ptr; }
-};
-
-#endif
-
-#endif
--- a/libgui/src/qt-application.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/qt-application.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,10 @@
 #  include "config.h"
 #endif
 
+#include <QCoreApplication>
+#include <QSettings>
+#include <QString>
+
 #include "main-window.h"
 #include "octave-qobject.h"
 #include "qt-application.h"
@@ -42,14 +46,39 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+qt_application::qt_application (const std::string& organization_name,
+                                const std::string& application_name,
+                                const std::string& application_version,
+                                int argc, char **argv)
+  : application (argc, argv)
+{
+  if (! organization_name.empty ())
+    QCoreApplication::setOrganizationName
+      (QString::fromStdString (organization_name));
+
+  if (! application_name.empty ())
+    QCoreApplication::setApplicationName
+      (QString::fromStdString (application_name));
+
+  if (! application_version.empty ())
+    QCoreApplication::setApplicationVersion
+      (QString::fromStdString (application_version));
+
+  // FIXME: Is there a better place for this?
+  QSettings::setDefaultFormat (QSettings::IniFormat);
+
+  // This should probably happen early.
+  sysdep_init ();
+}
+
 qt_application::qt_application (int argc, char **argv)
-: application (argc, argv)
+  : application (argc, argv)
 {
   // This should probably happen early.
   sysdep_init ();
 }
 
-bool qt_application::start_gui_p (void) const
+bool qt_application::start_gui_p () const
 {
   // Note: this function is not needed if using the experimental
   // terminal widget, so return a dummy value of false in that case.
@@ -57,7 +86,7 @@
   return experimental_terminal_widget () ? false : m_options.gui ();
 }
 
-int qt_application::execute (void)
+int qt_application::execute ()
 {
   octave_block_interrupt_signal ();
 
--- a/libgui/src/qt-application.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/qt-application.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,6 +26,10 @@
 #if ! defined (octave_qt_application_h)
 #define octave_qt_application_h 1
 
+#include "octave-config.h"
+
+#include <string>
+
 #include "octave.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -41,29 +45,30 @@
 //! allows Qt graphics to be used or it may start an interface that
 //! provides the full GUI experience.
 
-  class OCTGUI_API qt_application  : public application
+class OCTGUI_API qt_application  : public application
 {
- public:
+public:
+
+  qt_application (const std::string& organization_name,
+                  const std::string& application_name,
+                  const std::string& application_version,
+                  int argc, char **argv);
 
   qt_application (int argc, char **argv);
 
-  // No copying, at least not yet.
-
-  qt_application (const qt_application&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (qt_application)
 
-  qt_application& operator = (const qt_application&) = delete;
-
-  ~qt_application (void) = default;
+  ~qt_application () = default;
 
   // Should we start the GUI or fall back to the CLI?
-  bool start_gui_p (void) const;
+  bool start_gui_p () const;
 
-  int execute (void);
+  int execute ();
 
-  bool gui_running (void) const { return m_gui_running; }
+  bool gui_running () const { return m_gui_running; }
   void gui_running (bool arg) { m_gui_running = arg; }
 
- private:
+private:
 
   // If TRUE, the GUI should be started.
   bool m_gui_running = false;
--- a/libgui/src/qt-interpreter-events.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/qt-interpreter-events.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,10 +35,12 @@
 #include <QIcon>
 #include <QMetaType>
 #include <QPushButton>
+#include <QRegularExpression>
 #include <QStringList>
 
 #include "dialog.h"
 #include "gui-preferences-ed.h"
+#include "gui-settings.h"
 #include "octave-qobject.h"
 #include "qt-interpreter-events.h"
 #include "qt-utils.h"
@@ -92,7 +94,7 @@
 
       // Strip out extensions from name and replace ';' with spaces in list.
 
-      name.replace (QRegExp (R"(\(.*\))"), "");
+      name.replace (QRegularExpression {R"(\(.*\))"}, "");
       ext.replace (";", " ");
 
       if (name.isEmpty ())
@@ -109,7 +111,7 @@
 
 qt_interpreter_events::qt_interpreter_events (base_qobject& oct_qobj)
   : interpreter_events (), m_octave_qobj (oct_qobj),
-    m_uiwidget_creator (oct_qobj), m_result (), m_mutex (),
+    m_uiwidget_creator (), m_result (), m_mutex (),
     m_waitcondition ()
 {
   qRegisterMetaType<QIntList> ("QIntList");
@@ -137,7 +139,7 @@
     emit start_gui_signal (gui_app);
 }
 
-void qt_interpreter_events::close_gui (void)
+void qt_interpreter_events::close_gui ()
 {
   if (m_octave_qobj.experimental_terminal_widget ())
     emit close_gui_signal ();
@@ -244,22 +246,22 @@
   return answer.toStdString ();
 }
 
-void qt_interpreter_events::update_path_dialog (void)
+void qt_interpreter_events::update_path_dialog ()
 {
   emit update_path_dialog_signal ();
 }
 
-void qt_interpreter_events::show_preferences (void)
+void qt_interpreter_events::show_preferences ()
 {
   emit show_preferences_signal ();
 }
 
-void qt_interpreter_events::apply_preferences (void)
+void qt_interpreter_events::apply_preferences ()
 {
   emit apply_new_settings ();
 }
 
-void qt_interpreter_events::show_terminal_window (void)
+void qt_interpreter_events::show_terminal_window ()
 {
   emit show_terminal_window_signal ();
 }
@@ -271,17 +273,17 @@
   return true;
 }
 
-void qt_interpreter_events::show_file_browser (void)
+void qt_interpreter_events::show_file_browser ()
 {
   emit show_file_browser_signal ();
 }
 
-void qt_interpreter_events::show_command_history (void)
+void qt_interpreter_events::show_command_history ()
 {
   emit show_command_history_signal ();
 }
 
-void qt_interpreter_events::show_workspace (void)
+void qt_interpreter_events::show_workspace ()
 {
   emit show_workspace_signal ();
 }
@@ -291,7 +293,7 @@
   emit show_community_news_signal (serial);
 }
 
-void qt_interpreter_events::show_release_notes (void)
+void qt_interpreter_events::show_release_notes ()
 {
   emit show_release_notes_signal ();
 }
@@ -309,7 +311,7 @@
   emit edit_variable_signal (QString::fromStdString (expr), val);
 }
 
-bool qt_interpreter_events::confirm_shutdown (void)
+bool qt_interpreter_events::confirm_shutdown ()
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -323,10 +325,9 @@
 
 bool qt_interpreter_events::prompt_new_edit_file (const std::string& file)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  if (! settings || settings->value (ed_create_new_file).toBool ())
+  if (settings.bool_value (ed_create_new_file))
     return true;
 
   std::string abs_fname = sys::env::make_absolute (file);
@@ -438,8 +439,9 @@
 {
   QMutexLocker autolock (&m_mutex);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  m_result = QVariant::fromValue (rmgr.icon (name));
+  gui_settings settings;
+
+  m_result = QVariant::fromValue (settings.icon (name));
 
   wake_all ();
 }
@@ -533,7 +535,7 @@
                                  QString::fromStdString (status));
 }
 
-void qt_interpreter_events::update_gui_lexer (void)
+void qt_interpreter_events::update_gui_lexer ()
 {
   emit update_gui_lexer_signal (true);
 }
@@ -574,7 +576,7 @@
     emit refresh_variable_editor_signal ();
 }
 
-void qt_interpreter_events::clear_workspace (void)
+void qt_interpreter_events::clear_workspace ()
 {
   emit clear_workspace_signal ();
 }
@@ -599,15 +601,15 @@
   emit append_history_signal (QString::fromStdString (hist_entry));
 }
 
-void qt_interpreter_events::clear_history (void)
+void qt_interpreter_events::clear_history ()
 {
   emit clear_history_signal ();
 }
 
-void qt_interpreter_events::pre_input_event (void)
+void qt_interpreter_events::pre_input_event ()
 { }
 
-void qt_interpreter_events::post_input_event (void)
+void qt_interpreter_events::post_input_event ()
 { }
 
 void qt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/,
@@ -629,7 +631,7 @@
   delete_debugger_pointer (file, line);
 }
 
-void qt_interpreter_events::exit_debugger_event (void)
+void qt_interpreter_events::exit_debugger_event ()
 {
   emit exit_debugger_signal ();
 }
@@ -660,7 +662,7 @@
 }
 
 void
-qt_interpreter_events::confirm_shutdown_octave (void)
+qt_interpreter_events::confirm_shutdown_octave ()
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -684,10 +686,10 @@
 {
   QMutexLocker autolock (&m_mutex);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  QString read_value = settings->value (key).toString ();
+  // We don't want to apply default value here.
+  QString read_value = settings.value (key).toString ();
 
   // Some preferences need extra handling
   QString adjusted_value = gui_preference_adjust (key, value);
@@ -695,9 +697,9 @@
   if (! adjusted_value.isEmpty () && (read_value != adjusted_value))
     {
       // Change settings only for new, non-empty values
-      settings->setValue (key, QVariant (adjusted_value));
+      settings.setValue (key, QVariant (adjusted_value));
 
-      emit settings_changed (settings, true);   // true: changed by worker
+      emit settings_changed (true);   // true: changed by worker
     }
 
   m_result = read_value;
@@ -716,35 +718,15 @@
 
   QString adjusted_value = value;
 
-  // Not all encodings are available.  Encodings are uppercase and do
-  // not use CPxxx but IBMxxx or WINDOWS-xxx.
-
-  if (key == ed_default_enc.key)
+  if (key == ed_default_enc.settings_key ())
     {
       adjusted_value = adjusted_value.toUpper ();
 
-      QStringList codecs;
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      rmgr.get_codecs (&codecs);
-
-      QRegExp re ("^CP(\\d+)$");
-
       if (adjusted_value == "SYSTEM")
         adjusted_value =
           QString ("SYSTEM (") +
           QString (octave_locale_charset_wrapper ()).toUpper () +
           QString (")");
-      else if (re.indexIn (adjusted_value) > -1)
-        {
-          if (codecs.contains ("IBM" + re.cap (1)))
-            adjusted_value = "IBM" + re.cap (1);
-          else if (codecs.contains ("WINDOWS-" + re.cap (1)))
-            adjusted_value = "WINDOWS-" + re.cap (1);
-          else
-            adjusted_value.clear ();
-        }
-      else if (! codecs.contains (adjusted_value))
-        adjusted_value.clear ();
     }
 
   return adjusted_value;
--- a/libgui/src/qt-interpreter-events.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/qt-interpreter-events.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,6 +26,8 @@
 #if ! defined (octave_qt_interpreter_events_h)
 #define octave_qt_interpreter_events_h 1
 
+#include "octave-config.h"
+
 #include <list>
 #include <string>
 
@@ -36,7 +38,6 @@
 #include <QWaitCondition>
 
 #include "dialog.h"
-#include "gui-settings.h"
 
 #include "event-manager.h"
 
@@ -73,20 +74,16 @@
 
   qt_interpreter_events (base_qobject& oct_qobj);
 
-  // No copying!
-
-  qt_interpreter_events (const qt_interpreter_events&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (qt_interpreter_events)
 
-  qt_interpreter_events& operator = (const qt_interpreter_events&) = delete;
-
-  ~qt_interpreter_events (void) = default;
+  ~qt_interpreter_events () = default;
 
   // Note: these functions currently do nothing with the old terminal
   // widget.
   void start_gui (bool gui_app = false);
-  void close_gui (void);
+  void close_gui ();
 
-  bool have_dialogs (void) const { return true; }
+  bool have_dialogs () const { return true; }
 
   std::list<std::string>
   file_dialog (const filter_list& filter, const std::string& title,
@@ -113,30 +110,30 @@
                    const std::string& btn1, const std::string& btn2,
                    const std::string& btn3, const std::string& btndef);
 
-  void update_path_dialog (void);
+  void update_path_dialog ();
 
-  void show_preferences (void);
+  void show_preferences ();
 
-  void apply_preferences (void);
+  void apply_preferences ();
 
-  void show_terminal_window (void);
+  void show_terminal_window ();
 
   bool show_documentation (const std::string& file);
 
-  void show_file_browser (void);
+  void show_file_browser ();
 
-  void show_command_history (void);
+  void show_command_history ();
 
-  void show_workspace (void);
+  void show_workspace ();
 
   void show_community_news (int serial);
-  void show_release_notes (void);
+  void show_release_notes ();
 
   bool edit_file (const std::string& file);
 
   void edit_variable (const std::string& name, const octave_value& val);
 
-  bool confirm_shutdown (void);
+  bool confirm_shutdown ();
 
   bool prompt_new_edit_file (const std::string& file);
 
@@ -167,7 +164,7 @@
 
   void gui_status_update (const std::string& feature, const std::string& status);
 
-  void update_gui_lexer (void);
+  void update_gui_lexer ();
 
   void directory_changed (const std::string& dir);
 
@@ -180,7 +177,7 @@
                       const symbol_info_list& syminfo,
                       bool update_variable_editor);
 
-  void clear_workspace (void);
+  void clear_workspace ();
 
   void update_prompt (const std::string& prompt);
 
@@ -188,33 +185,33 @@
 
   void append_history (const std::string& hist_entry);
 
-  void clear_history (void);
+  void clear_history ();
 
-  void pre_input_event (void);
+  void pre_input_event ();
 
-  void post_input_event (void);
+  void post_input_event ();
 
   void enter_debugger_event (const std::string& fcn_name,
                              const std::string& fcn_file_name, int line);
 
   void execute_in_debugger_event (const std::string& file, int line);
 
-  void exit_debugger_event (void);
+  void exit_debugger_event ();
 
   void update_breakpoint (bool insert, const std::string& file, int line,
                           const std::string& cond);
 
-  void lock (void) { m_mutex.lock (); }
+  void lock () { m_mutex.lock (); }
 
-  void wait (void) { m_waitcondition.wait (&m_mutex); }
+  void wait () { m_waitcondition.wait (&m_mutex); }
 
-  void unlock (void) { m_mutex.unlock (); }
+  void unlock () { m_mutex.unlock (); }
 
-  void wake_all (void) { m_waitcondition.wakeAll (); }
+  void wake_all () { m_waitcondition.wakeAll (); }
 
 public slots:
 
-  void confirm_shutdown_octave (void);
+  void confirm_shutdown_octave ();
 
   void get_named_icon_slot (const QString& name);
 
@@ -224,7 +221,7 @@
 
   // Note: these signals are not currently used by the old terminal widget.
   void start_gui_signal (bool gui_app);
-  void close_gui_signal (void);
+  void close_gui_signal ();
 
   void copy_image_to_clipboard_signal (const QString& file, bool remove_file);
 
@@ -234,7 +231,7 @@
 
   void directory_changed_signal (const QString& dir);
 
-  void update_path_dialog_signal (void);
+  void update_path_dialog_signal ();
 
   void file_remove_signal (const QString& old_name, const QString& new_name);
 
@@ -245,7 +242,7 @@
   void set_workspace_signal (bool top_level, bool debug,
                              const symbol_info_list& syminfo);
 
-  void clear_workspace_signal (void);
+  void clear_workspace_signal ();
 
   void update_prompt_signal (const QString& prompt);
 
@@ -253,11 +250,11 @@
 
   void append_history_signal (const QString& hist_entry);
 
-  void clear_history_signal (void);
+  void clear_history_signal ();
 
-  void enter_debugger_signal (void);
+  void enter_debugger_signal ();
 
-  void exit_debugger_signal (void);
+  void exit_debugger_signal ();
 
   void update_breakpoint_marker_signal (bool insert, const QString& file,
                                         int line, const QString& cond);
@@ -266,11 +263,11 @@
 
   void delete_debugger_pointer_signal (const QString&, int);
 
-  void show_preferences_signal (void);
+  void show_preferences_signal ();
 
   void gui_preference_signal (const QString& key, const QString& value);
 
-  void show_terminal_window_signal (void);
+  void show_terminal_window_signal ();
 
   void show_documentation_signal (const QString& file);
 
@@ -278,14 +275,14 @@
 
   void unregister_documentation_signal (const QString& file);
 
-  void show_file_browser_signal (void);
+  void show_file_browser_signal ();
 
-  void show_command_history_signal (void);
+  void show_command_history_signal ();
 
-  void show_workspace_signal (void);
+  void show_workspace_signal ();
 
   void show_community_news_signal (int serial);
-  void show_release_notes_signal (void);
+  void show_release_notes_signal ();
 
   // Note: the next two signals are currently not used by the old terminal widget.
   void interpreter_output_signal (const QString& msg);
@@ -297,15 +294,15 @@
 
   void edit_variable_signal (const QString& name, const octave_value& val);
 
-  void refresh_variable_editor_signal (void);
+  void refresh_variable_editor_signal ();
 
-  void confirm_shutdown_signal (void);
+  void confirm_shutdown_signal ();
 
   void get_named_icon_signal (const QString& name);
 
-  void settings_changed (const gui_settings *, bool);
+  void settings_changed (bool);
 
-  void apply_new_settings (void);
+  void apply_new_settings ();
 
 private:
 
--- a/libgui/src/release-notes.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/release-notes.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -40,25 +40,25 @@
 #include "gui-utils.h"
 #include "gui-preferences-dw.h"
 #include "gui-preferences-nr.h"
+#include "gui-settings.h"
 #include "news-reader.h"
-#include "octave-qobject.h"
 
 #include "defaults.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-release_notes::release_notes (base_qobject& oct_qobj)
-: QWidget (nullptr), m_browser (nullptr)
+release_notes::release_notes ()
+  : QWidget (nullptr), m_browser (nullptr)
 {
 
-  resource_manager& rmgr = oct_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   // The icon
-  QString icon_set = settings->value (dw_icon_set).toString ();
+  QString icon_set = settings.string_value (dw_icon_set);
+
   if (icon_set != "NONE")
     m_release_notes_icon = dw_icon_set_names[icon_set]
-      + "ReleaseWidget.png";
+                           + "ReleaseWidget.png";
   else
     m_release_notes_icon = dw_icon_set_names[icon_set];
 
@@ -106,7 +106,7 @@
   move (20, 20);  // move to the top left corner
 }
 
-void release_notes::display (void)
+void release_notes::display ()
 {
   if (! isVisible ())
     show ();
--- a/libgui/src/release-notes.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/release-notes.h	Fri Jun 23 20:51:51 2023 +0200
@@ -33,21 +33,19 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class release_notes : public QWidget
 {
   Q_OBJECT
 
 public:
 
-  release_notes (base_qobject& qct_qobj);
+  release_notes ();
 
-  ~release_notes (void) = default;
+  ~release_notes () = default;
 
 public slots:
 
-  void display (void);
+  void display ();
 
 private:
 
--- a/libgui/src/resource-manager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,794 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2011-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// 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 <unistd.h>
-
-#include <algorithm>
-#include <array>
-#include <string>
-
-#include <QDir>
-#include <QFile>
-#include <QFontComboBox>
-#include <QFontDatabase>
-#include <QLibraryInfo>
-#include <QMessageBox>
-#include <QNetworkProxy>
-#include <QStandardPaths>
-
-#include <QTextCodec>
-
-#include "QTerminal.h"
-#include "gui-preferences-cs.h"
-#include "gui-preferences-ed.h"
-#include "gui-preferences-global.h"
-#include "octave-qobject.h"
-#include "resource-manager.h"
-#include "variable-editor.h"
-#include "workspace-model.h"
-
-#include "file-ops.h"
-#include "localcharset-wrapper.h"
-#include "oct-env.h"
-
-#include "defaults.h"
-#include "error.h"
-#include "help.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-resource_manager::resource_manager (void)
-: m_settings_directory (), m_settings_file (), m_settings (nullptr),
-  m_default_settings (nullptr), m_temporary_files (), m_icon_fallbacks ()
-{
-  // Let gui_settings decide where to put the ini file with gui preferences
-  m_default_settings
-    = new gui_settings (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 nonexistent 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);
-#else
-      QString home_path
-        = QDesktopServices::storageLocation (QDesktopServices::HomeLocation);
-#endif
-
-      QString old_settings_directory = home_path + "/.config/octave";
-      QString old_settings_file = old_settings_directory + "/qt-settings";
-
-      QFile ofile (old_settings_file);
-
-      if (ofile.exists ())
-        {
-          // Old settings file exists; create a gui_settings object related
-          // to it and copy all available keys to the new settings
-          gui_settings old_settings (old_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)
-{
-  delete m_settings;
-  delete m_default_settings;
-
-  for (int i = m_temporary_files.count () - 1; i >=0; i--)
-    remove_tmp_file (m_temporary_files.at (i));
-}
-
-QString resource_manager::get_gui_translation_dir (void)
-{
-  // get environment variable for the locale dir (e.g. from run-octave)
-  std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR");
-  if (dldir.empty ())
-    dldir = config::oct_locale_dir (); // env-var empty, load the default location
-  return QString::fromStdString (dldir);
-}
-
-void resource_manager::config_translators (QTranslator *qt_tr,
-                                           QTranslator *qsci_tr,
-                                           QTranslator *gui_tr)
-{
-  bool loaded;
-
-  QString qt_trans_dir
-    = QLibraryInfo::location (QLibraryInfo::TranslationsPath);
-
-  QString language = "SYSTEM";  // take system language per default
-
-  // FIXME: can we somehow ensure that the settings object will always
-  // be initialize and valid?
-
-  if (m_settings)
-    {
-      // get the locale from the settings if already available
-      language = m_settings->value (global_language.key,
-                                    global_language.def).toString ();
-    }
-
-  // load the translations depending on the settings
-  if (language == "SYSTEM")
-    {
-      // get the system locale and pass it to the translators for loading
-      // the suitable translation files
-      QLocale sys_locale = QLocale::system ();
-
-      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);
-
-      loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir);
-      if (! loaded) // try lower case
-        qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir);
-
-      gui_tr->load (language, get_gui_translation_dir ());
-    }
-
-}
-
-void resource_manager::config_icon_theme (void)
-{
-  m_icon_fallbacks.clear ();
-
-  int theme = global_icon_theme_index.def.toInt ();
-
-  if (m_settings)
-    {
-      // check for new and old setting and use old if required
-      if (! m_settings->contains (global_icon_theme_index.key))
-        {
-          // new pref does not exist
-          if (m_settings->value (global_icon_theme).toBool ())
-            theme = ICON_THEME_SYSTEM;
-          else
-            theme = ICON_THEME_OCTAVE;
-          m_settings->setValue (global_icon_theme_index.key, theme);  // add new
-          m_settings->remove (global_icon_theme.key); // remove deprecated key
-        }
-      else
-        {
-          // get new settings
-          theme = m_settings->value (global_icon_theme_index).toInt ();
-        }
-    }
-
-  QIcon::setThemeName (global_all_icon_themes.at (theme));
-
-  // set the required fallback search paths
-  switch (theme)
-    {
-    case ICON_THEME_SYSTEM:
-      m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);
-      m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);
-      break;
-    case ICON_THEME_TANGO:
-      m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE);
-      break;
-    case ICON_THEME_OCTAVE:
-      m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO);
-      break;
-    }
-
-  m_icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS);
-}
-
-gui_settings * resource_manager::get_settings (void) const
-{
-  if (! m_settings)
-    {
-      QString msg (QT_TR_NOOP ("Octave has lost its settings.\n"
-                               "This should not happen.\n\n"
-                               "Please report this bug.\n\n"
-                               "Octave GUI must be closed now."));
-
-      QMessageBox::critical (nullptr,
-                             QString (QT_TR_NOOP ("Octave Critical Error")),
-                             msg);
-      exit (1);
-    }
-
-  return m_settings;
-}
-
-gui_settings * resource_manager::get_default_settings (void) const
-{
-  if (! m_default_settings)
-    {
-      QString msg (QT_TR_NOOP ("Octave has lost its default settings.\n"
-                               "This should not happen.\n"
-                               "Please report this bug.\n\n"
-                               "Octave GUI must be closed now."));
-
-      QMessageBox::critical (nullptr,
-                             QString (QT_TR_NOOP ("Octave Critical Error")),
-                             msg);
-      exit (1);
-    }
-
-  return m_default_settings;
-}
-
-QString resource_manager::get_settings_directory (void)
-{
-  return m_settings_directory;
-}
-
-QString resource_manager::get_settings_file (void)
-{
-  return m_settings_file;
-}
-
-QString resource_manager::get_default_font_family (void)
-{
-  QString default_family;
-
-  // Get all available fixed width fonts via a font combobox
-  QFontComboBox font_combo_box;
-  font_combo_box.setFontFilters (QFontComboBox::MonospacedFonts);
-  QStringList fonts;
-
-  for (int index = 0; index < font_combo_box.count(); index++)
-    fonts << font_combo_box.itemText(index);
-
-#if defined (Q_OS_MAC)
-  // Use hard coded default on macOS, since selection of fixed width
-  // default font is unreliable (see bug #59128).
-  // Test for macOS default fixed width font
-  if (fonts.contains (global_mono_font.def.toString ()))
-    default_family = global_mono_font.def.toString ();
-#endif
-
-  // If default font is still empty (on all other platforms or
-  // if macOS default font is not available): use QFontDatabase
-  if (default_family.isEmpty ())
-    {
-      // Get the system's default monospaced font
-      QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont);
-      default_family = fixed_font.defaultFamily ();
-
-      // Since this might be unreliable, test all available fixed width fonts
-      if (! fonts.contains (default_family))
-        {
-          // Font returned by QFontDatabase is not in fixed fonts list.
-          // Fallback: take first from this list
-          default_family = fonts[0];
-        }
-    }
-
-  // Test env variable which has preference
-  std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT");
-  if (! env_default_family.empty ())
-    default_family = QString::fromStdString (env_default_family);
-
-  return default_family;
-}
-
-QStringList resource_manager::get_default_font (void)
-{
-  QString default_family = get_default_font_family ();
-
-  // determine the fefault font size of the system
-  // FIXME: QApplication::font () does not return the monospace font,
-  //        but the size should be probably near to the monospace font
-  QFont font = QApplication::font ();
-
-  int font_size = font.pointSize ();
-  if (font_size == -1)
-    font_size = static_cast <int> (std::floor(font.pointSizeF ()));
-
-  // check for valid font size, otherwise take default 10
-  QString default_font_size = "10";
-  if (font_size > 0)
-    default_font_size = QString::number (font_size);
-
-  std::string env_default_font_size
-    = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE");
-
-  if (! env_default_font_size.empty ())
-    default_font_size = QString::fromStdString (env_default_font_size);
-
-  QStringList result;
-  result << default_family;
-  result << default_font_size;
-  return result;
-}
-
-void resource_manager::reload_settings (void)
-{
-  // Declare some empty options, which may be set at first startup for
-  // writing them into the newly created settings file
-  QString custom_editor;
-  QStringList def_font;
-
-  // Check whether the settings file does not yet exist
-  if (! QFile::exists (m_settings_file))
-    {
-      // Get the default font (for terminal)
-      def_font = get_default_font ();
-
-      // Get a custom editor defined as env variable
-      std::string env_default_editor
-        = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR");
-
-      if (! env_default_editor.empty ())
-        custom_editor = QString::fromStdString (env_default_editor);
-    }
-
-  set_settings (m_settings_file);
-
-  // Write some settings that were dynamically determined at first startup
-  if (m_settings)
-    {
-      // Custom editor
-      if (! custom_editor.isEmpty ())
-        m_settings->setValue (global_custom_editor.key, custom_editor);
-
-      // Default monospace font for the terminal
-      if (def_font.count () > 1)
-        {
-          m_settings->setValue (cs_font.key, def_font[0]);
-          m_settings->setValue (cs_font_size.key, def_font[1].toInt ());
-        }
-
-      // Write the default monospace font into the settings for later use by
-      // console and editor as fallbacks of their font preferences.
-      m_settings->setValue (global_mono_font.key, get_default_font_family ());
-    }
-}
-
-#if defined (HAVE_QSCINTILLA)
-int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles)
-{
-  int max_style = 0;
-  int actual_style = 0;
-  while (actual_style < ed_max_style_number && max_style < ed_max_lexer_styles)
-    {
-      if ((lexer->description (actual_style)) != "")  // valid style
-        styles[max_style++] = actual_style;
-      actual_style++;
-    }
-  return max_style;
-}
-#endif
-
-QFont resource_manager::copy_font_attributes (const QFont& attr,
-                                              const QFont& base) const
-{
-  QFont dest (base);
-
-  dest.setBold (attr.bold ());
-  dest.setItalic (attr.italic ());
-  dest.setUnderline (attr.underline ());
-
-  return dest;
-}
-
-#if defined (HAVE_QSCINTILLA)
-void resource_manager::read_lexer_settings (QsciLexer *lexer,
-                                            gui_settings *settings,
-                                            int mode, int def)
-{
-  // Test whether the settings for lexer is already contained in the
-  // given gui settings file. If yes, load them, if not copy them from the
-  // default settings file.
-  // This is useful when a new language support is implemented and the
-  // existing settings file is used (which is of course the common case).
-  int m = mode;
-  if (m > 1)
-    m = 1;
-
-  QString group ("Scintilla" + settings_color_modes_ext[m]);
-
-  settings->beginGroup (group);
-  settings->beginGroup (lexer->language ());
-
-  QStringList lexer_keys = settings->allKeys ();
-
-  settings->endGroup ();
-  settings->endGroup ();
-
-  if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0)
-    {
-      // We have to reload the default values or no Lexer keys found:
-      // If mode == 0, take all settings except font from default lexer
-      // If Mode == 1, take all settings except font from default lexer
-      //               and convert the color by inverting the lightness
-
-      // Get the default font
-      QStringList def_font = get_default_font ();
-      QFont df (def_font[0], def_font[1].toInt ());
-      QFont dfa = copy_font_attributes (lexer->defaultFont (), df);
-      lexer->setDefaultFont (dfa);
-
-      QColor c, p;
-
-      int styles[ed_max_lexer_styles];  // array for saving valid styles
-      int max_style = get_valid_lexer_styles (lexer, styles);
-
-      for (int i = 0; i < max_style; i++)
-        {
-          c = settings->get_color_value (QVariant (lexer->color (styles[i])), m);
-          lexer->setColor (c, styles[i]);
-          p = settings->get_color_value (QVariant (lexer->paper (styles[i])), m);
-          lexer->setPaper (p, styles[i]);
-          dfa = copy_font_attributes (lexer->font (styles[i]), df);
-          lexer->setFont (dfa, styles[i]);
-        }
-      // Set defaults last for not changing the defaults of the styles
-      lexer->setDefaultColor (lexer->color (styles[0]));
-      lexer->setDefaultPaper (lexer->paper (styles[0]));
-
-      // Write settings if not just reload the default values
-      if (def != settings_reload_default_colors_flag)
-        {
-          const std::string group_str = group.toStdString ();
-          lexer->writeSettings (*settings, group_str.c_str ());
-          settings->sync ();
-        }
-    }
-  else
-    {
-      // Found lexer keys, read the settings
-      const std::string group_str = group.toStdString ();
-      lexer->readSettings (*settings, group_str.c_str ());
-    }
-}
-#endif
-
-void resource_manager::set_settings (const QString& file)
-{
-  delete m_settings;
-  m_settings = new gui_settings (file, QSettings::IniFormat);
-
-  if (m_settings->status () == QSettings::NoError)
-    {
-      // Test usability (force file to be really created)
-      m_settings->setValue ("dummy", 0);
-      m_settings->sync ();
-    }
-
-  if (! (QFile::exists (m_settings->fileName ())
-         && m_settings->isWritable ()
-         && m_settings->status () == QSettings::NoError))
-    {
-      QString msg
-        = QString (QT_TR_NOOP ("The settings file\n%1\n"
-                               "does not exist and can not be created.\n"
-                               "Make sure you have read and write permissions to\n%2\n\n"
-                               "Octave GUI must be closed now."));
-
-      QMessageBox::critical (nullptr,
-                             QString (QT_TR_NOOP ("Octave Critical Error")),
-                             msg.arg (get_settings_file ()).arg (get_settings_directory ()));
-
-      exit (1);
-    }
-  else
-    m_settings->remove ("dummy"); // Remove test entry
-}
-
-bool resource_manager::update_settings_key (const QString& old_key,
-                                            const QString& new_key)
-{
-  if (m_settings->contains (old_key))
-    {
-      QVariant preference = m_settings->value (old_key);
-      m_settings->setValue (new_key, preference);
-      m_settings->remove (old_key);
-      return true;
-    }
-
-  return false;
-}
-
-bool resource_manager::is_first_run (void) const
-{
-  return ! QFile::exists (m_settings_file);
-}
-
-void resource_manager::update_network_settings (void)
-{
-  if (! m_settings)
-    return;
-
-  QNetworkProxy proxy;
-
-  // Assume no proxy and empty proxy data
-  QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy;
-  QString scheme;
-  QString host;
-  int port = 0;
-  QString user;
-  QString pass;
-  QUrl proxy_url = QUrl ();
-
-  if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ())
-    {
-      // Use a proxy, collect all required information
-      QString proxy_type_string
-        = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
-
-      // The proxy type for the Qt proxy settings
-      if (proxy_type_string == "Socks5Proxy")
-        proxy_type = QNetworkProxy::Socks5Proxy;
-      else if (proxy_type_string == "HttpProxy")
-        proxy_type = QNetworkProxy::HttpProxy;
-
-      // The proxy data from the settings
-      if (proxy_type_string == "HttpProxy"
-          || proxy_type_string == "Socks5Proxy")
-        {
-          host = m_settings->value (global_proxy_host.key,
-                                    global_proxy_host.def).toString ();
-          port = m_settings->value (global_proxy_port.key,
-                                    global_proxy_port.def).toInt ();
-          user = m_settings->value (global_proxy_user.key,
-                                    global_proxy_user.def).toString ();
-          pass = m_settings->value (global_proxy_pass.key,
-                                    global_proxy_pass.def).toString ();
-          if (proxy_type_string == "HttpProxy")
-            scheme = "http";
-          else if (proxy_type_string == "Socks5Proxy")
-            scheme = "socks5";
-
-          QUrl env_var_url = QUrl ();
-          proxy_url.setScheme (scheme);
-          proxy_url.setHost (host);
-          proxy_url.setPort (port);
-          if (! user.isEmpty ())
-            proxy_url.setUserName (user);
-          if (! pass.isEmpty ())
-            proxy_url.setPassword (pass);
-        }
-
-      // The proxy data from environment variables
-      if (proxy_type_string == global_proxy_all_types.at (2))
-        {
-          const std::array<std::string, 6> env_vars =
-            {
-              "ALL_PROXY", "all_proxy",
-              "HTTP_PROXY", "http_proxy",
-              "HTTPS_PROXY", "https_proxy"
-            };
-
-          unsigned int count = 0;
-          while (! proxy_url.isValid () && count < env_vars.size ())
-            {
-              proxy_url = QUrl (QString::fromStdString
-                                (sys::env::getenv (env_vars[count])));
-              count++;
-            }
-
-          if (proxy_url.isValid ())
-            {
-              // Found an entry, get the data from the string
-              scheme = proxy_url.scheme ();
-
-              if (scheme.contains ("socks", Qt::CaseInsensitive))
-                proxy_type = QNetworkProxy::Socks5Proxy;
-              else
-                proxy_type = QNetworkProxy::HttpProxy;
-
-              host = proxy_url.host ();
-              port = proxy_url.port ();
-              user = proxy_url.userName ();
-              pass = proxy_url.password ();
-            }
-        }
-    }
-
-  // Set proxy for Qt framework
-  proxy.setType (proxy_type);
-  proxy.setHostName (host);
-  proxy.setPort (port);
-  proxy.setUser (user);
-  proxy.setPassword (pass);
-
-  QNetworkProxy::setApplicationProxy (proxy);
-
-  // Set proxy for curl library if not based on environment variables
-  std::string proxy_url_str = proxy_url.toString().toStdString ();
-  sys::env::putenv ("http_proxy", proxy_url_str);
-  sys::env::putenv ("HTTP_PROXY", proxy_url_str);
-  sys::env::putenv ("https_proxy", proxy_url_str);
-  sys::env::putenv ("HTTPS_PROXY", proxy_url_str);
-}
-
-QIcon resource_manager::icon (const QString& icon_name, bool octave_only,
-                              const QString& icon_alt_name)
-{
-  if (octave_only)
-    return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png");
-
-  if (QIcon::hasThemeIcon (icon_name))
-    return QIcon (QIcon::fromTheme (icon_name));
-  else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name))
-    return QIcon (QIcon::fromTheme (icon_alt_name));
-
-  for (int i = 0; i < m_icon_fallbacks.length (); i++ )
-    {
-      QString icon_file (m_icon_fallbacks.at (i) + icon_name + ".png");
-      if (QFile (icon_file).exists ())
-        return QIcon (icon_file);
-    }
-
-  //QIcon::setThemeName (current_theme);
-  return QIcon ();
-}
-
-// get a list of all available encodings
-void resource_manager::get_codecs (QStringList *codecs)
-{
-  // get the codec name for each mib
-  QList<int> all_mibs = QTextCodec::availableMibs ();
-  for (auto mib : all_mibs)
-    {
-      QTextCodec *c = QTextCodec::codecForMib (mib);
-      codecs->append (c->name ().toUpper ());
-    }
-
-  // Append SYSTEM
-  codecs->append (QString ("SYSTEM (") +
-                  QString (octave_locale_charset_wrapper ()).toUpper () +
-                  QString (")"));
-
-  // Clean up and sort list of codecs
-  codecs->removeDuplicates ();
-  std::sort (codecs->begin (), codecs->end ());
-}
-
-// initialize a given combo box with available text encodings
-void resource_manager::combo_encoding (QComboBox *combo,
-                                       const QString& current)
-{
-  QStringList all_codecs;
-  get_codecs (&all_codecs);
-
-  // get the value from the settings file if no current encoding is given
-  QString enc = current;
-
-  // Check for valid codec for the default.  If this fails, "SYSTEM" (i.e.
-  // locale_charset) will be chosen.
-  // FIXME: The default is "SYSTEM" on all platforms.  So can this fallback
-  // logic be removed completely?
-  bool default_exists = false;
-  bool show_system = false;
-  if (ed_default_enc.def.toString ().startsWith ("SYSTEM"))
-    show_system = true;
-  else if (QTextCodec::codecForName (ed_default_enc.def.toString ().toLatin1 ()))
-    default_exists = true;
-
-  QString default_enc =
-    QString ("SYSTEM (") +
-    QString (octave_locale_charset_wrapper ()).toUpper () + QString (")");
-
-  if (enc.isEmpty ())
-    {
-      enc = m_settings->value (ed_default_enc).toString ();
-
-      if (enc.isEmpty ())  // still empty?
-        {
-          if (default_exists)
-            enc = ed_default_enc.def.toString ();
-          else
-            enc = default_enc;
-        }
-    }
-
-  // fill the combo box
-  for (const auto& c : all_codecs)
-    combo->addItem (c);
-
-  // prepend the default item
-  combo->insertSeparator (0);
-  if (show_system || ! default_exists)
-    combo->insertItem (0, default_enc);
-  else
-    combo->insertItem (0, ed_default_enc.def.toString ());
-
-  // select the default or the current one
-  int idx = combo->findText (enc, Qt::MatchExactly);
-  if (idx >= 0)
-    combo->setCurrentIndex (idx);
-  else
-    combo->setCurrentIndex (0);
-
-  combo->setMaxVisibleItems (12);
-}
-
-QPointer<QTemporaryFile>
-resource_manager::create_tmp_file (const QString& extension,
-                                   const QString& contents)
-{
-  QString ext = extension;
-  if ((! ext.isEmpty ()) && (! ext.startsWith ('.')))
-    ext = QString (".") + ext;
-
-  // Create octave dir within temp. dir
-  QString tmp_dir = QString::fromStdString (sys::env::get_temp_directory ());
-
-  // Create temp. file
-  QPointer<QTemporaryFile> tmp_file
-    = new QTemporaryFile (tmp_dir + QDir::separator() +
-                          "octave_XXXXXX" + ext, this);
-
-  if (tmp_file->open ())
-    {
-      tmp_file->write (contents.toUtf8 ());
-      tmp_file->close ();
-
-      m_temporary_files << tmp_file;
-    }
-
-  return tmp_file;
-}
-
-void resource_manager::remove_tmp_file (QPointer<QTemporaryFile> tmp_file)
-{
-  if (tmp_file)
-    {
-      if (tmp_file->exists ())
-        tmp_file->remove ();
-
-      m_temporary_files.removeAll (tmp_file);
-    }
-}
-
-OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/resource-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2011-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// 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_resource_manager_h)
-#define octave_resource_manager_h 1
-
-#include <QComboBox>
-#include <QIcon>
-#include <QPointer>
-#if defined (HAVE_QSCINTILLA)
-#  include <Qsci/qscilexer.h>
-#endif
-#include <QTranslator>
-#include <QTemporaryFile>
-
-#include "gui-settings.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-class resource_manager : public QObject
-{
-  Q_OBJECT
-
-protected:
-
-  public:
-
-  resource_manager (void);
-
-  // No copying!
-
-  resource_manager (const resource_manager&) = delete;
-
-  resource_manager& operator = (const resource_manager&) = delete;
-
-  ~resource_manager ();
-
-  QString get_gui_translation_dir (void);
-
-  void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr,
-                           QTranslator *gui_tr);
-  void config_icon_theme (void);
-
-  gui_settings * get_settings (void) const;
-
-  gui_settings * get_default_settings (void) const;
-
-  QString get_settings_directory (void);
-
-  QString get_settings_file (void);
-
-  QString get_default_font_family (void);
-
-  QStringList get_default_font (void);
-
-  QPointer<QTemporaryFile>
-  create_tmp_file (const QString& extension = QString (),
-                   const QString& contents = QString ());
-
-  void remove_tmp_file (QPointer<QTemporaryFile> tmp_file);
-
-  void reload_settings (void);
-
-#if defined (HAVE_QSCINTILLA)
-  int get_valid_lexer_styles (QsciLexer *lexer, int *styles);
-  void read_lexer_settings (QsciLexer *lexer, gui_settings *settings,
-                            int mode = 0, int def = 0);
-#endif
-
-  void set_settings (const QString& file);
-
-  bool update_settings_key (const QString& new_key, const QString& old_key);
-
-  bool is_first_run (void) const;
-
-  void update_network_settings (void);
-
-  QIcon icon (const QString& icon_name, bool octave_only = false,
-              const QString& icon_alt_name = QString ());
-
-  void get_codecs (QStringList *codecs);
-
-  void combo_encoding (QComboBox *combo, const QString& current = QString ());
-
-private:
-
-  /*!
-   * Copys the attributes bold, italic and underline from QFont
-   * @p attr to the font @p base and returns the result without
-   * changing @p base,
-   * @param attr QFont with the desired attributes
-   * @param base QFont with desired family and size
-   */
-  QFont copy_font_attributes (const QFont& attr, const QFont& base) const;
-
-  QString m_settings_directory;
-
-  QString m_settings_file;
-
-  gui_settings *m_settings;
-
-  gui_settings *m_default_settings;
-
-  QList<QTemporaryFile *> m_temporary_files;
-
-  QStringList m_icon_fallbacks;
-};
-
-OCTAVE_END_NAMESPACE(octave)
-
-#endif
--- a/libgui/src/set-path-dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/set-path-dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,8 +50,7 @@
 #include <QVBoxLayout>
 
 #include "gui-preferences-pd.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
+#include "gui-settings.h"
 #include "set-path-dialog.h"
 #include "set-path-model.h"
 
@@ -59,8 +58,8 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-set_path_dialog::set_path_dialog (QWidget *parent, base_qobject& oct_qobj)
-: QDialog (parent), m_octave_qobj (oct_qobj)
+set_path_dialog::set_path_dialog (QWidget *parent)
+  : QDialog (parent)
 {
   setWindowTitle (tr ("Set Path"));
 
@@ -168,13 +167,12 @@
 
   setLayout (main_layout);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  restoreGeometry (
-                   settings->value(pd_geometry.key).toByteArray());
+  gui_settings settings;
+
+  restoreGeometry (settings.value(pd_geometry.settings_key ()).toByteArray());
 }
 
-void set_path_dialog::update_model (void)
+void set_path_dialog::update_model ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   m->path_to_model ();
@@ -205,17 +203,17 @@
     }
 }
 
-void set_path_dialog::add_dir(void)
+void set_path_dialog::add_dir()
 {
   add_dir_common (false);
 }
 
-void set_path_dialog::add_dir_subdirs (void)
+void set_path_dialog::add_dir_subdirs ()
 {
   add_dir_common (true);
 }
 
-void set_path_dialog::rm_dir (void)
+void set_path_dialog::rm_dir ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   QItemSelectionModel *selmodel = m_path_list->selectionModel ();
@@ -225,7 +223,7 @@
   selmodel->clearSelection ();
 }
 
-void set_path_dialog::move_dir_up (void)
+void set_path_dialog::move_dir_up ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   QItemSelectionModel *selmodel = m_path_list->selectionModel ();
@@ -245,7 +243,7 @@
   m_path_list->scrollTo (m->index (min_row));
 }
 
-void set_path_dialog::move_dir_down (void)
+void set_path_dialog::move_dir_down ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   QItemSelectionModel *selmodel = m_path_list->selectionModel ();
@@ -265,7 +263,7 @@
   m_path_list->scrollTo (m->index (max_row));
 }
 
-void set_path_dialog::move_dir_top (void)
+void set_path_dialog::move_dir_top ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   QItemSelectionModel *selmodel = m_path_list->selectionModel ();
@@ -280,7 +278,7 @@
   m_path_list->scrollTo (m->index (0));
 }
 
-void set_path_dialog::move_dir_bottom (void)
+void set_path_dialog::move_dir_bottom ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   QItemSelectionModel *selmodel = m_path_list->selectionModel ();
@@ -299,9 +297,9 @@
 
 void set_path_dialog::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  settings->setValue (pd_geometry.key, saveGeometry ());
+  gui_settings settings;
+
+  settings.setValue (pd_geometry.settings_key (), saveGeometry ());
 }
 
 void set_path_dialog::closeEvent (QCloseEvent *e)
--- a/libgui/src/set-path-dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/set-path-dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,8 +41,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class set_path_dialog : public QDialog
 {
   Q_OBJECT
@@ -53,11 +51,11 @@
   // in the dialog.  That may only be done after the intepreter_event
   // signal connections are made to the Octave interpreter.
 
-  set_path_dialog (QWidget *parent, base_qobject& oct_qobj);
+  set_path_dialog (QWidget *parent);
 
-  virtual ~set_path_dialog (void) = default;
+  virtual ~set_path_dialog () = default;
 
-  void save_settings (void);
+  void save_settings ();
 
 signals:
 
@@ -71,7 +69,7 @@
 
 public slots:
 
-  void update_model (void);
+  void update_model ();
 
 protected:
 
@@ -79,25 +77,23 @@
 
 private slots:
 
-  void add_dir (void);
-  void add_dir_subdirs (void);
+  void add_dir ();
+  void add_dir_subdirs ();
 
-  void rm_dir (void);
+  void rm_dir ();
 
-  void move_dir_up (void);
+  void move_dir_up ();
 
-  void move_dir_down (void);
+  void move_dir_down ();
 
-  void move_dir_top (void);
+  void move_dir_top ();
 
-  void move_dir_bottom (void);
+  void move_dir_bottom ();
 
 private:
 
   void add_dir_common (bool subdirs);
 
-  base_qobject& m_octave_qobj;
-
   QLabel *m_info_label;
   QPushButton *m_reload_button;
   QPushButton *m_save_button;
--- a/libgui/src/set-path-model.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/set-path-model.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
   m_revertible = false;
 }
 
-std::string set_path_model::to_string (void)
+std::string set_path_model::to_string ()
 {
   std::string path_sep = directory_path::path_sep_str ();
 
@@ -73,7 +73,7 @@
   return path_str;
 }
 
-void set_path_model::model_to_path (void)
+void set_path_model::model_to_path ()
 {
   std::string path_str = to_string ();
 
@@ -88,7 +88,7 @@
     });
 }
 
-void set_path_model::clear (void)
+void set_path_model::clear ()
 {
   beginResetModel ();
 
@@ -97,7 +97,7 @@
   endResetModel ();
 }
 
-void set_path_model::save (void)
+void set_path_model::save ()
 {
   model_to_path ();
 
@@ -110,7 +110,7 @@
     });
 }
 
-void set_path_model::revert (void)
+void set_path_model::revert ()
 {
   clear ();
 
@@ -121,7 +121,7 @@
   model_to_path ();
 }
 
-void set_path_model::revert_last (void)
+void set_path_model::revert_last ()
 {
   clear ();
 
@@ -281,7 +281,7 @@
   return retval;
 }
 
-void set_path_model::path_to_model (void)
+void set_path_model::path_to_model ()
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
--- a/libgui/src/set-path-model.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/set-path-model.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,9 +44,9 @@
 
   set_path_model (QObject *p = nullptr);
 
-  ~set_path_model (void) = default;
+  ~set_path_model () = default;
 
-  void clear (void);
+  void clear ();
 
   void add_dir (const QString& p);
 
@@ -60,11 +60,11 @@
 
   void move_dir_bottom (const QModelIndexList& indices);
 
-  std::string to_string (void);
+  std::string to_string ();
 
   // Overloaded Qt methods
 
-  void model_to_path (void);
+  void model_to_path ();
 
   int rowCount (const QModelIndex& p = QModelIndex ()) const;
 
@@ -79,13 +79,13 @@
 
 public slots:
 
-  void path_to_model (void);
+  void path_to_model ();
 
-  void save (void);
+  void save ();
 
-  void revert (void);
+  void revert ();
 
-  void revert_last (void);
+  void revert_last ();
 
 private slots:
 
--- a/libgui/src/settings-dialog.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/settings-dialog.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 #include <QMessageBox>
 #include <QScrollBar>
 #include <QStyleFactory>
-#include <QTextCodec>
+#include <QThread>
 #include <QVector>
 
 #if defined (HAVE_QSCINTILLA)
@@ -64,48 +64,69 @@
 #endif
 
 #include "gui-preferences-all.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
+#include "gui-settings.h"
 #include "settings-dialog.h"
+#include "shortcuts-tree-widget.h"
 #include "variable-editor.h"
 #include "workspace-model.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-settings_dialog::settings_dialog (QWidget *p, base_qobject& oct_qobj,
-                                  const QString& desired_tab)
-: QDialog (p), Ui::settings_dialog (), m_octave_qobj (oct_qobj)
+settings_dialog::settings_dialog (QWidget *p, const QString& desired_tab)
+  : QDialog (p), Ui::settings_dialog ()
 {
   setupUi (this);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  QMessageBox *info = wait_message_box (
+                      tr ("Loading current preferences ... "), this);
+
+  read_settings (true);  // it's the first read, prepare everything
+
+  close_wait_message_box (info);
+
+  // which tab is the desired one?
+  show_tab (desired_tab);
+
+  // connect button box signal
+  connect (button_box, &QDialogButtonBox::clicked,
+           this, &settings_dialog::button_clicked);
+
+  // restore last geometry
+  gui_settings settings;
 
-  if (! settings)
+  if (settings.contains (sd_geometry.settings_key ()))
+    restoreGeometry (settings.byte_array_value (sd_geometry));
+  else
+    setGeometry (QRect (10, 50, 1000, 600));
+
+  // show as non-modal dialog
+  setModal (false);
+  setAttribute (Qt::WA_DeleteOnClose);
+  show ();
+}
+
+void settings_dialog::read_settings (bool first)
+{
+  gui_settings settings;
+
+  if (first)
     {
-      QMessageBox msgBox
-        (QMessageBox::Warning, tr ("Octave Preferences"),
-         tr ("Unable to save preferences.  Missing preferences file or unknown directory."));
+      // look for available language files and the actual settings
+      QString qm_dir_name = settings.get_gui_translation_dir ();
 
-      msgBox.exec ();
+      QDir qm_dir (qm_dir_name);
+      QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"),
+                               QDir::Files | QDir::Readable, QDir::Name);
 
-      return;
+      for (int i = 0; i < qm_files.length (); i++)   // insert available languages
+        comboBox_language->addItem (qm_files.at (i).baseName ());
+      // System at beginning
+      comboBox_language->insertItem (0, tr ("System setting"));
+      comboBox_language->insertSeparator (1);    // separator after System
     }
 
-  // look for available language files and the actual settings
-  QString qm_dir_name = rmgr.get_gui_translation_dir ();
-  QDir qm_dir (qm_dir_name);
-  QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"),
-                                                 QDir::Files | QDir::Readable, QDir::Name);
-
-  for (int i = 0; i < qm_files.length (); i++)   // insert available languages
-    comboBox_language->addItem (qm_files.at (i).baseName ());
-  // System at beginning
-  comboBox_language->insertItem (0, tr ("System setting"));
-  comboBox_language->insertSeparator (1);    // separator after System
-  QString language = settings->value (global_language.key,
-                                      global_language.def).toString ();
-  if (language == global_language.def.toString ())
+  QString language = settings.string_value (global_language);
+  if (language == global_language.def ().toString ())
     language = tr ("System setting");
   int selected = comboBox_language->findText (language);
   if (selected >= 0)
@@ -113,238 +134,249 @@
   else
     comboBox_language->setCurrentIndex (0);  // System is default
 
-  // Global style
-  QStringList styles = QStyleFactory::keys();
-  styles.append (global_extra_styles);
-  combo_styles->addItems (styles);
-  combo_styles->insertItem (0, global_style.def.toString ());
-  combo_styles->insertSeparator (1);
-  QString current_style = settings->value (global_style).toString ();
-  if (current_style == global_style.def.toString ())
-    current_style = global_style.def.toString ();
+  if (first)
+    {
+      // Global style
+      QStringList styles = QStyleFactory::keys();
+      styles.append (global_extra_styles);
+      combo_styles->addItems (styles);
+      combo_styles->insertItem (0, global_style.def ().toString ());
+      combo_styles->insertSeparator (1);
+    }
+
+  QString current_style = settings.string_value (global_style);
+  if (current_style == global_style.def ().toString ())
+    current_style = global_style.def ().toString ();
   selected = combo_styles->findText (current_style);
   if (selected >= 0)
     combo_styles->setCurrentIndex (selected);
   else
     combo_styles->setCurrentIndex (0);
 
-  // icon size and theme
-  QButtonGroup *icon_size_group = new QButtonGroup (this);
-  icon_size_group->addButton (icon_size_small);
-  icon_size_group->addButton (icon_size_normal);
-  icon_size_group->addButton (icon_size_large);
-  int icon_size = settings->value (global_icon_size).toInt ();
+  if (first)
+    {
+      // icon size and theme
+      QButtonGroup *icon_size_group = new QButtonGroup (this);
+      icon_size_group->addButton (icon_size_small);
+      icon_size_group->addButton (icon_size_normal);
+      icon_size_group->addButton (icon_size_large);
+    }
+  int icon_size = settings.int_value (global_icon_size);
   icon_size_normal->setChecked (true);  // the default
   icon_size_small->setChecked (icon_size < 0);
   icon_size_large->setChecked (icon_size > 0);
-  combo_box_icon_theme->addItems (global_all_icon_theme_names);
-  int theme = settings->value (global_icon_theme_index.key).toInt ();
+
+  if (first)
+    combo_box_icon_theme->addItems (global_all_icon_theme_names);
+  int theme = settings.value (global_icon_theme_index.settings_key ()).toInt ();
   combo_box_icon_theme->setCurrentIndex (theme);
 
-  // which icon has to be selected
-  QButtonGroup *icon_group = new QButtonGroup (this);
-  icon_group->addButton (general_icon_octave);
-  icon_group->addButton (general_icon_graphic);
-  icon_group->addButton (general_icon_letter);
+  if (first)
+    {
+      // which icon has to be selected
+      QButtonGroup *icon_group = new QButtonGroup (this);
+      icon_group->addButton (general_icon_octave);
+      icon_group->addButton (general_icon_graphic);
+      icon_group->addButton (general_icon_letter);
+    }
   QString widget_icon_set =
-    settings->value (dw_icon_set).toString ();
+    settings.string_value (dw_icon_set);
   general_icon_octave->setChecked (true);  // the default (if invalid set)
   general_icon_octave->setChecked (widget_icon_set == "NONE");
   general_icon_graphic->setChecked (widget_icon_set == "GRAPHIC");
   general_icon_letter->setChecked (widget_icon_set == "LETTER");
 
-  // custom title bar of dock widget
-  QColor bg_color = settings->value (dw_title_bg_color).value<QColor> ();
-  m_widget_title_bg_color = new color_picker (bg_color);
-  m_widget_title_bg_color->setEnabled (false);
-  layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0);
+  if (first)
+    {
+      // custom title bar of dock widget
+      m_widget_title_bg_color = new color_picker ();
+      m_widget_title_bg_color->setEnabled (false);
+      layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0);
 
-  connect (cb_widget_custom_style, &QCheckBox::toggled,
-           m_widget_title_bg_color, &color_picker::setEnabled);
+      connect (cb_widget_custom_style, &QCheckBox::toggled,
+               m_widget_title_bg_color, &color_picker::setEnabled);
 
-  QColor bg_color_active = settings->value (dw_title_bg_color_active).value<QColor> ();
-  m_widget_title_bg_color_active = new color_picker (bg_color_active);
-  m_widget_title_bg_color_active->setEnabled (false);
-  layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0);
+      m_widget_title_bg_color_active = new color_picker ();
+      m_widget_title_bg_color_active->setEnabled (false);
+      layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0);
 
-  connect (cb_widget_custom_style, &QCheckBox::toggled,
-           m_widget_title_bg_color_active, &color_picker::setEnabled);
+      connect (cb_widget_custom_style, &QCheckBox::toggled,
+               m_widget_title_bg_color_active, &color_picker::setEnabled);
 
-  QColor fg_color = settings->value (dw_title_fg_color).value<QColor> ();
-  m_widget_title_fg_color = new color_picker (fg_color);
-  m_widget_title_fg_color->setEnabled (false);
-  layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0);
+      m_widget_title_fg_color = new color_picker ();
+      m_widget_title_fg_color->setEnabled (false);
+      layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0);
 
-  connect (cb_widget_custom_style, &QCheckBox::toggled,
-           m_widget_title_fg_color, &color_picker::setEnabled);
+      connect (cb_widget_custom_style, &QCheckBox::toggled,
+               m_widget_title_fg_color, &color_picker::setEnabled);
+
+      m_widget_title_fg_color_active = new color_picker ();
+      m_widget_title_fg_color_active->setEnabled (false);
+      layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0);
 
-  QColor fg_color_active = settings->value (dw_title_fg_color_active).value<QColor> ();
-  m_widget_title_fg_color_active = new color_picker (fg_color_active);
-  m_widget_title_fg_color_active->setEnabled (false);
-  layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0);
+      connect (cb_widget_custom_style, &QCheckBox::toggled,
+               m_widget_title_fg_color_active, &color_picker::setEnabled);
+    }
 
-  connect (cb_widget_custom_style, &QCheckBox::toggled,
-           m_widget_title_fg_color_active, &color_picker::setEnabled);
+  m_widget_title_bg_color->set_color (settings.color_value (dw_title_bg_color));
+  m_widget_title_bg_color_active->set_color (settings.color_value (dw_title_bg_color_active));
+  m_widget_title_fg_color->set_color (settings.color_value (dw_title_fg_color));
+  m_widget_title_fg_color_active->set_color (settings.color_value (dw_title_fg_color_active));
 
-  sb_3d_title->setValue (settings->value (dw_title_3d.key,
-                                          dw_title_3d.def).toInt ());
-  cb_widget_custom_style->setChecked (settings->value (dw_title_custom_style).toBool ());
+  sb_3d_title->setValue (settings.int_value (dw_title_3d));
+  cb_widget_custom_style->setChecked (settings.bool_value (dw_title_custom_style));
 
   // Native file dialogs.
   // FIXME: This preference can be deprecated / removed if all display
   //       managers, especially KDE, run those dialogs without hangs or
   //       delays from the start (bug #54607).
-  cb_use_native_file_dialogs->setChecked (settings->value (global_use_native_dialogs).toBool ());
+  cb_use_native_file_dialogs->setChecked (settings.bool_value (global_use_native_dialogs));
 
   // Cursor blinking: consider old terminal related setting if not yet set
   // FIXME: This pref. can be deprecated / removed if Qt adds support for
   //       getting the cursor blink preferences from all OS environments
-  if (settings->contains (global_cursor_blinking.key))
+  if (settings.contains (global_cursor_blinking.settings_key ()))
     {
       // Preference exists, read its value
-      cb_cursor_blinking->setChecked (settings->value
-                                      (global_cursor_blinking.key, global_cursor_blinking.def).toBool ());
+      cb_cursor_blinking->setChecked (settings.bool_value (global_cursor_blinking));
     }
   else
     {
       // Pref. does not exist, so take old terminal related pref.
-      cb_cursor_blinking->setChecked (settings->value
-                                      (cs_cursor_blinking.key, cs_cursor_blinking.def).toBool ());
+      cb_cursor_blinking->setChecked (settings.bool_value (cs_cursor_blinking));
     }
 
   // focus follows mouse
-  cb_focus_follows_mouse->setChecked (
-                                      settings->value (dw_focus_follows_mouse).toBool ());
+  cb_focus_follows_mouse->setChecked (settings.bool_value (dw_focus_follows_mouse));
 
   // prompt on exit
-  cb_prompt_to_exit->setChecked (
-                                 settings->value (global_prompt_to_exit.key, global_prompt_to_exit.def).toBool ());
+  cb_prompt_to_exit->setChecked (settings.bool_value (global_prompt_to_exit));
 
   // Main status bar
-  cb_status_bar->setChecked (
-                             settings->value (global_status_bar.key, global_status_bar.def).toBool ());
+  cb_status_bar->setChecked (settings.bool_value (global_status_bar));
 
   // Octave startup
-  cb_restore_octave_dir->setChecked (
-                                     settings->value (global_restore_ov_dir.key, global_restore_ov_dir.def).toBool ());
-  le_octave_dir->setText (settings->value (global_ov_startup_dir.key,
-                                           global_ov_startup_dir.def).toString ());
+  cb_restore_octave_dir->setChecked (settings.bool_value (global_restore_ov_dir));
+  le_octave_dir->setText (settings.string_value (global_ov_startup_dir));
 
-  connect (pb_octave_dir, &QPushButton::pressed,
-           this, &settings_dialog::get_octave_dir);
+  if (first)
+    connect (pb_octave_dir, &QPushButton::pressed,
+             this, &settings_dialog::get_octave_dir);
 
   //
   // editor
   //
-  useCustomFileEditor->setChecked (
-                                   settings->value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ());
-  customFileEditor->setText (
-                             settings->value (global_custom_editor.key, global_custom_editor.def).toString ());
-  editor_showLineNumbers->setChecked (settings->value (ed_show_line_numbers).toBool ());
-  editor_linenr_size->setValue (settings->value (ed_line_numbers_size).toInt ());
+  useCustomFileEditor->setChecked (settings.bool_value (global_use_custom_editor));
+  customFileEditor->setText (settings.string_value (global_custom_editor));
+  editor_showLineNumbers->setChecked (settings.bool_value (ed_show_line_numbers));
+  editor_linenr_size->setValue (settings.int_value (ed_line_numbers_size));
 
-  rmgr.combo_encoding (editor_combo_encoding);
+  settings.combo_encoding (editor_combo_encoding);
 
-  editor_highlightCurrentLine->setChecked (settings->value (ed_highlight_current_line).toBool ());
-  editor_long_line_marker->setChecked (settings->value (ed_long_line_marker).toBool ());
+  editor_highlightCurrentLine->setChecked (settings.bool_value (ed_highlight_current_line));
+  editor_long_line_marker->setChecked (settings.bool_value (ed_long_line_marker));
   bool long_line =
-    settings->value (ed_long_line_marker_line).toBool ();
+    settings.bool_value (ed_long_line_marker_line);
   editor_long_line_marker_line->setChecked (long_line);
   bool long_back =
-    settings->value (ed_long_line_marker_background).toBool ();
+    settings.bool_value (ed_long_line_marker_background);
   editor_long_line_marker_background->setChecked (long_back);
   if (! (long_line || long_back))
     editor_long_line_marker_line->setChecked (true);
-  editor_long_line_column->setValue (settings->value (ed_long_line_column).toInt ());
-  editor_break_checkbox->setChecked (settings->value (ed_break_lines).toBool ());
-  editor_break_comments_checkbox->setChecked (settings->value (ed_break_lines_comments).toBool ());
-  editor_wrap_checkbox->setChecked (settings->value (ed_wrap_lines).toBool ());
-  cb_edit_status_bar->setChecked (settings->value (ed_show_edit_status_bar).toBool ());
-  cb_edit_tool_bar->setChecked (settings->value (ed_show_toolbar).toBool ());
-  cb_code_folding->setChecked (settings->value (ed_code_folding).toBool ());
-  editor_highlight_all_occurrences->setChecked (settings->value (ed_highlight_all_occurrences).toBool ());
+  editor_long_line_column->setValue (settings.int_value (ed_long_line_column));
+  editor_break_checkbox->setChecked (settings.bool_value (ed_break_lines));
+  editor_break_comments_checkbox->setChecked (settings.bool_value (ed_break_lines_comments));
+  editor_wrap_checkbox->setChecked (settings.bool_value (ed_wrap_lines));
+  cb_edit_status_bar->setChecked (settings.bool_value (ed_show_edit_status_bar));
+  cb_edit_tool_bar->setChecked (settings.bool_value (ed_show_toolbar));
+  cb_code_folding->setChecked (settings.bool_value (ed_code_folding));
+  editor_highlight_all_occurrences->setChecked (settings.bool_value (ed_highlight_all_occurrences));
 
-  editor_auto_endif->setCurrentIndex (settings->value (ed_auto_endif).toInt () );
-  editor_codeCompletion->setChecked (settings->value (ed_code_completion).toBool ());
-  editor_spinbox_ac_threshold->setValue (settings->value (ed_code_completion_threshold).toInt ());
-  editor_checkbox_ac_keywords->setChecked (settings->value (ed_code_completion_keywords).toBool ());
+  editor_auto_endif->setCurrentIndex (settings.int_value (ed_auto_endif) );
+  editor_codeCompletion->setChecked (settings.bool_value (ed_code_completion));
+  editor_spinbox_ac_threshold->setValue (settings.int_value (ed_code_completion_threshold));
+  editor_checkbox_ac_keywords->setChecked (settings.bool_value (ed_code_completion_keywords));
   editor_checkbox_ac_builtins->setEnabled (editor_checkbox_ac_keywords->isChecked ());
   editor_checkbox_ac_functions->setEnabled (editor_checkbox_ac_keywords->isChecked ());
-  editor_checkbox_ac_builtins->setChecked (settings->value (ed_code_completion_octave_builtins).toBool ());
-  editor_checkbox_ac_functions->setChecked (settings->value (ed_code_completion_octave_functions).toBool ());
-  editor_checkbox_ac_document->setChecked (settings->value (ed_code_completion_document).toBool ());
-  editor_checkbox_ac_case->setChecked (settings->value (ed_code_completion_case).toBool ());
-  editor_checkbox_ac_replace->setChecked (settings->value (ed_code_completion_replace).toBool ());
-  editor_ws_checkbox->setChecked (settings->value (ed_show_white_space).toBool ());
-  editor_ws_indent_checkbox->setChecked (settings->value (ed_show_white_space_indent).toBool ());
-  cb_show_eol->setChecked (settings->value (ed_show_eol_chars).toBool ());
-  cb_show_hscrollbar->setChecked (settings->value (ed_show_hscroll_bar).toBool ());
+  editor_checkbox_ac_builtins->setChecked (settings.bool_value (ed_code_completion_octave_builtins));
+  editor_checkbox_ac_functions->setChecked (settings.bool_value (ed_code_completion_octave_functions));
+  editor_checkbox_ac_document->setChecked (settings.bool_value (ed_code_completion_document));
+  editor_checkbox_ac_case->setChecked (settings.bool_value (ed_code_completion_case));
+  editor_checkbox_ac_replace->setChecked (settings.bool_value (ed_code_completion_replace));
+  editor_ws_checkbox->setChecked (settings.bool_value (ed_show_white_space));
+  editor_ws_indent_checkbox->setChecked (settings.bool_value (ed_show_white_space_indent));
+  cb_show_eol->setChecked (settings.bool_value (ed_show_eol_chars));
+  cb_show_hscrollbar->setChecked (settings.bool_value (ed_show_hscroll_bar));
 
-  for (int i = 0; i < ed_tab_position_names.length (); i++)
-    editor_combox_tab_pos->insertItem (i,
-                                       tr (ed_tab_position_names.at (i).toStdString ().data ()));
-  editor_combox_tab_pos->setCurrentIndex
-    (settings->value (ed_tab_position).toInt ());
+  if (first)
+    {
+      for (int i = 0; i < ed_tab_position_names.length (); i++)
+        editor_combox_tab_pos->insertItem (i,
+                tr (ed_tab_position_names.at (i).toStdString ().data ()));
+    }
+  editor_combox_tab_pos->setCurrentIndex (settings.int_value (ed_tab_position));
 
-  editor_cb_tabs_rotated->setChecked (settings->value (ed_tabs_rotated).toBool ());
-  editor_sb_tabs_max_width->setValue (settings->value (ed_tabs_max_width).toInt ());
+  editor_cb_tabs_rotated->setChecked (settings.bool_value (ed_tabs_rotated));
+  editor_sb_tabs_max_width->setValue (settings.int_value (ed_tabs_max_width));
 
   int selected_comment_string, selected_uncomment_string;
 
-  if (settings->contains (ed_comment_str.key))   // new version (radio buttons)
-    selected_comment_string = settings->value (ed_comment_str).toInt ();
+  if (settings.contains (ed_comment_str.settings_key ()))   // new version (radio buttons)
+    selected_comment_string = settings.int_value (ed_comment_str);
   else                                         // old version (combo box)
-    selected_comment_string = settings->value (ed_comment_str_old.key,                                                 ed_comment_str.def).toInt ();
+    selected_comment_string = settings.value (ed_comment_str_old.settings_key (),                                                 ed_comment_str.def ()).toInt ();
 
-  selected_uncomment_string = settings->value (ed_uncomment_str).toInt ();
+  selected_uncomment_string = settings.int_value (ed_uncomment_str);
 
   for (int i = 0; i < ed_comment_strings_count; i++)
     {
-      m_rb_comment_strings[i] = new QRadioButton ();
-      m_rb_uncomment_strings[i] = new QCheckBox ();
+      if (first)
+        {
+          m_rb_comment_strings[i] = new QRadioButton ();
+          m_rb_uncomment_strings[i] = new QCheckBox ();
+          layout_comment_strings->addWidget (m_rb_comment_strings[i]);
+          layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]);
 
-      connect (m_rb_comment_strings[i], &QRadioButton::clicked,
-               m_rb_uncomment_strings[i], &QCheckBox::setChecked);
-      connect (m_rb_comment_strings[i], &QRadioButton::toggled,
-               m_rb_uncomment_strings[i], &QCheckBox::setDisabled);
+          connect (m_rb_comment_strings[i], &QRadioButton::clicked,
+                   m_rb_uncomment_strings[i], &QCheckBox::setChecked);
+          connect (m_rb_comment_strings[i], &QRadioButton::toggled,
+                   m_rb_uncomment_strings[i], &QCheckBox::setDisabled);
+        }
 
       m_rb_comment_strings[i]->setText (ed_comment_strings.at(i));
       m_rb_comment_strings[i]->setChecked (i == selected_comment_string);
-      layout_comment_strings->addWidget (m_rb_comment_strings[i]);
 
       m_rb_uncomment_strings[i]->setText (ed_comment_strings.at(i));
       m_rb_uncomment_strings[i]->setAutoExclusive (false);
       m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string);
-      layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]);
     }
 
-  combo_eol_mode->setCurrentIndex (settings->value (ed_default_eol_mode).toInt ());
-  editor_auto_ind_checkbox->setChecked (settings->value (ed_auto_indent).toBool ());
-  editor_tab_ind_checkbox->setChecked (settings->value (ed_tab_indents_line).toBool ());
-  editor_bs_unind_checkbox->setChecked (settings->value (ed_backspace_unindents_line).toBool ());
-  editor_ind_guides_checkbox->setChecked (settings->value (ed_show_indent_guides).toBool ());
-  editor_ind_width_spinbox->setValue (settings->value (ed_indent_width).toInt ());
-  editor_ind_uses_tabs_checkbox->setChecked (settings->value (ed_indent_uses_tabs).toBool ());
-  editor_tab_width_spinbox->setValue (settings->value (ed_tab_width).toInt ());
-  editor_restoreSession->setChecked (settings->value (ed_restore_session).toBool ());
-  editor_create_new_file->setChecked (settings->value (ed_create_new_file).toBool ());
-  editor_reload_changed_files->setChecked (settings->value (ed_always_reload_changed_files).toBool ());
-  editor_force_newline->setChecked (settings->value (ed_force_newline).toBool ());
-  editor_remove_trailing_spaces->setChecked (settings->value (ed_rm_trailing_spaces).toBool ());
-  editor_hiding_closes_files->setChecked (settings->value (ed_hiding_closes_files).toBool ());
-  editor_show_dbg_file->setChecked (settings->value (ed_show_dbg_file).toBool ());
+  combo_eol_mode->setCurrentIndex (settings.int_value (ed_default_eol_mode));
+  editor_auto_ind_checkbox->setChecked (settings.bool_value (ed_auto_indent));
+  editor_tab_ind_checkbox->setChecked (settings.bool_value (ed_tab_indents_line));
+  editor_bs_unind_checkbox->setChecked (settings.bool_value (ed_backspace_unindents_line));
+  editor_ind_guides_checkbox->setChecked (settings.bool_value (ed_show_indent_guides));
+  editor_ind_width_spinbox->setValue (settings.int_value (ed_indent_width));
+  editor_ind_uses_tabs_checkbox->setChecked (settings.bool_value (ed_indent_uses_tabs));
+  editor_tab_width_spinbox->setValue (settings.int_value (ed_tab_width));
+  editor_restoreSession->setChecked (settings.bool_value (ed_restore_session));
+  editor_create_new_file->setChecked (settings.bool_value (ed_create_new_file));
+  editor_reload_changed_files->setChecked (settings.bool_value (ed_always_reload_changed_files));
+  editor_force_newline->setChecked (settings.bool_value (ed_force_newline));
+  editor_remove_trailing_spaces->setChecked (settings.bool_value (ed_rm_trailing_spaces));
+  editor_hiding_closes_files->setChecked (settings.bool_value (ed_hiding_closes_files));
+  editor_show_dbg_file->setChecked (settings.bool_value (ed_show_dbg_file));
 
   // terminal
-  QString default_font = settings->value (global_mono_font).toString ();
-  terminal_fontName->setCurrentFont (QFont (settings->value (cs_font.key, default_font).toString ()));
-  terminal_fontSize->setValue (settings->value (cs_font_size).toInt ());
-  terminal_history_buffer->setValue (settings->value (cs_hist_buffer).toInt ());
-  terminal_cursorUseForegroundColor->setChecked (settings->value (cs_cursor_use_fgcol).toBool ());
-  terminal_focus_command->setChecked (settings->value (cs_focus_cmd).toBool ());
-  terminal_print_dbg_location->setChecked (settings->value (cs_dbg_location).toBool ());
+  QString default_font = settings.string_value (global_mono_font);
+  terminal_fontName->setCurrentFont (QFont (settings.value (cs_font.settings_key (), default_font).toString ()));
+  terminal_fontSize->setValue (settings.int_value (cs_font_size));
+  terminal_history_buffer->setValue (settings.int_value (cs_hist_buffer));
+  terminal_cursorUseForegroundColor->setChecked (settings.bool_value (cs_cursor_use_fgcol));
+  terminal_focus_command->setChecked (settings.bool_value (cs_focus_cmd));
+  terminal_print_dbg_location->setChecked (settings.bool_value (cs_dbg_location));
 
-  QString cursor_type
-    = settings->value (cs_cursor).toString ();
+  QString cursor_type = settings.string_value (cs_cursor);
 
   QStringList items;
   items << QString ("0") << QString ("1") << QString ("2");
@@ -362,29 +394,54 @@
         }
     }
 
-  read_terminal_colors (settings);
+  if (first)
+    read_terminal_colors ();
+  else
+    {
+      QCheckBox *cb_color_mode
+        = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.settings_key ());
+      bool sec_color_mode = settings.bool_value (cs_color_mode);
+      if (cb_color_mode->isChecked () == sec_color_mode)
+        {
+          // color mode does not change, update colors manually
+          update_terminal_colors ();
+        }
+      else
+        {
+          // toggling check-state calls related slot updating colors
+          cb_color_mode->setChecked (sec_color_mode);
+        }
+    }
 
   // file browser
-  connect (sync_octave_directory, &QCheckBox::toggled,
-           this, &settings_dialog::set_disabled_pref_file_browser_dir);
-
-  sync_octave_directory->setChecked (settings->value (fb_sync_octdir).toBool ());
-  cb_restore_file_browser_dir->setChecked (settings->value (fb_restore_last_dir).toBool ());
-  le_file_browser_dir->setText (settings->value (fb_startup_dir.key).toString ());
+  if (first)
+    {
+      connect (sync_octave_directory, &QCheckBox::toggled,
+               this, &settings_dialog::set_disabled_pref_file_browser_dir);
+      connect (pb_file_browser_dir, &QPushButton::pressed,
+               this, &settings_dialog::get_file_browser_dir);
+    }
 
-  connect (pb_file_browser_dir, &QPushButton::pressed,
-           this, &settings_dialog::get_file_browser_dir);
-
-  le_file_browser_extensions->setText (settings->value (fb_txt_file_ext).toString ());
-
-  checkbox_allow_web_connect->setChecked (settings->value (nr_allow_connection).toBool ());
+  sync_octave_directory->setChecked (settings.bool_value (fb_sync_octdir));
+  cb_restore_file_browser_dir->setChecked (settings.bool_value (fb_restore_last_dir));
+  le_file_browser_dir->setText (settings.value (fb_startup_dir.settings_key ()).toString ());
+  le_file_browser_extensions->setText (settings.string_value (fb_txt_file_ext));
+  checkbox_allow_web_connect->setChecked (settings.bool_value (nr_allow_connection));
 
   // Proxy
-  bool use_proxy = settings->value (global_use_proxy.key, global_use_proxy.def).toBool ();
+  bool use_proxy = settings.bool_value (global_use_proxy);
   use_proxy_server->setChecked (use_proxy);
   // Fill combo box and activate current one
-  QString proxy_type_string = settings->value (global_proxy_type.key, global_proxy_type.def).toString ();
-  proxy_type->addItems (global_proxy_all_types);
+  if (first)
+    {
+      proxy_type->addItems (global_proxy_all_types);
+      // Connect relevant signals for dis-/enabling some elements
+      connect (proxy_type, QOverload<int>::of (&QComboBox::currentIndexChanged),
+               this, &settings_dialog::proxy_items_update);
+      connect (use_proxy_server, &QCheckBox::toggled,
+               this, &settings_dialog::proxy_items_update);
+    }
+  QString proxy_type_string = settings.string_value (global_proxy_type);
   for (int i = 0; i < global_proxy_all_types.length (); i++)
     {
       if (proxy_type->itemText (i) == proxy_type_string)
@@ -394,134 +451,164 @@
         }
     }
   // Fill all line edits
-  proxy_host_name->setText (settings->value (global_proxy_host.key, global_proxy_host.def).toString ());
-  proxy_port->setText (settings->value (global_proxy_port.key, global_proxy_port.def).toString ());
-  proxy_username->setText (settings->value (global_proxy_user.key, global_proxy_user.def).toString ());
-  proxy_password->setText (settings->value (global_proxy_pass.key, global_proxy_pass.def).toString ());
-  // Connect relevant signals for dis-/enabling some elements
-  connect (proxy_type, QOverload<int>::of (&QComboBox::currentIndexChanged),
-           this, &settings_dialog::proxy_items_update);
-  connect (use_proxy_server, &QCheckBox::toggled,
-           this, &settings_dialog::proxy_items_update);
+  proxy_host_name->setText (settings.string_value (global_proxy_host));
+  proxy_port->setText (settings.string_value (global_proxy_port));
+  proxy_username->setText (settings.string_value (global_proxy_user));
+  proxy_password->setText (settings.string_value (global_proxy_pass));
   // Check whehter line edits have to be enabled
   proxy_items_update ();
 
   // Workspace
-  read_workspace_colors (settings);
+  if (first)
+    read_workspace_colors ();
+  else
+    {
+      m_ws_enable_colors->setChecked (settings.bool_value (ws_enable_colors));
+      QCheckBox *cb_color_mode
+        = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.settings_key ());
+      bool sec_color_mode = settings.bool_value (ws_color_mode);
+      if (cb_color_mode->isChecked () == sec_color_mode)
+        {
+          // color mode does not change, update colors manually
+          update_workspace_colors ();
+        }
+      else
+        {
+          // toggling check-state calls related slot updating colors
+          cb_color_mode->setChecked (sec_color_mode);
+        }
+    }
 
   // variable editor
-  varedit_columnWidth->setValue (settings->value (ve_column_width).toInt ());
-  varedit_rowHeight->setValue (settings->value (ve_row_height).toInt ());
-
-  varedit_font->setCurrentFont (QFont (settings->value (ve_font_name.key,
-                                                        settings->value (cs_font.key, default_font)).toString ()));
-  varedit_fontSize->setValue (settings->value (ve_font_size).toInt ());
-  connect (varedit_useTerminalFont, &QCheckBox::toggled,
-           varedit_font, &QFontComboBox::setDisabled);
-  connect (varedit_useTerminalFont, &QCheckBox::toggled,
-           varedit_fontSize, &QSpinBox::setDisabled);
-  varedit_useTerminalFont->setChecked (settings->value (ve_use_terminal_font).toBool ());
+  if (first)
+    {
+      connect (varedit_useTerminalFont, &QCheckBox::toggled,
+               varedit_font, &QFontComboBox::setDisabled);
+      connect (varedit_useTerminalFont, &QCheckBox::toggled,
+               varedit_fontSize, &QSpinBox::setDisabled);
+    }
+  varedit_columnWidth->setValue (settings.int_value (ve_column_width));
+  varedit_rowHeight->setValue (settings.int_value (ve_row_height));
+  varedit_font->setCurrentFont (QFont (settings.value (ve_font_name.settings_key (),
+                                                        settings.value (cs_font.settings_key (), default_font)).toString ()));
+  varedit_fontSize->setValue (settings.int_value (ve_font_size));
+  varedit_useTerminalFont->setChecked (settings.bool_value (ve_use_terminal_font));
   varedit_font->setDisabled (varedit_useTerminalFont->isChecked ());
   varedit_fontSize->setDisabled (varedit_useTerminalFont->isChecked ());
-
-  varedit_alternate->setChecked (settings->value (ve_alternate_rows).toBool ());
+  varedit_alternate->setChecked (settings.bool_value (ve_alternate_rows));
 
   // variable editor colors
-  read_varedit_colors (settings);
+  if (first)
+    read_varedit_colors ();
+  else
+    {
+      QCheckBox *cb_color_mode
+        = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.settings_key ());
+      bool sec_color_mode = settings.bool_value (ve_color_mode);
+      if (cb_color_mode->isChecked () == sec_color_mode)
+        {
+          // color mode does not change, update colors manually
+          update_varedit_colors ();
+        }
+      else
+        {
+          // toggling check-state calls related slot updating colors
+          cb_color_mode->setChecked (sec_color_mode);
+        }
+    }
 
   // shortcuts
 
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-
-  cb_prevent_readline_conflicts->setChecked (
-                                             settings->value (sc_prevent_rl_conflicts.key,
-                                                              sc_prevent_rl_conflicts.def).toBool ());
-  cb_prevent_readline_conflicts_menu->setChecked (
-                                                  settings->value (sc_prevent_rl_conflicts_menu.key,
-                                                                   sc_prevent_rl_conflicts_menu.def).toBool ());
-
-  // initialize the tree view with all shortcut data
-  scmgr.fill_treewidget (shortcuts_treewidget);
+  cb_prevent_readline_conflicts->setChecked (settings.bool_value (sc_prevent_rl_conflicts));
+  cb_prevent_readline_conflicts_menu->setChecked (settings.bool_value (sc_prevent_rl_conflicts_menu));
 
   // connect the buttons for import/export of the shortcut sets
-  connect (btn_import_shortcut_set, &QPushButton::clicked,
-           this, &settings_dialog::import_shortcut_set);
+  // FIXME: Should there also be a button to discard changes?
+
+  if (first)
+    {
+      connect (btn_import_shortcut_set, &QPushButton::clicked,
+               this, &settings_dialog::import_shortcut_set);
 
-  connect (btn_export_shortcut_set, &QPushButton::clicked,
-           this, &settings_dialog::export_shortcut_set);
+      connect (btn_export_shortcut_set, &QPushButton::clicked,
+               this, &settings_dialog::export_shortcut_set);
 
-  connect (btn_default_shortcut_set, &QPushButton::clicked,
-           this, &settings_dialog::default_shortcut_set);
+      connect (btn_default_shortcut_set, &QPushButton::clicked,
+               this, &settings_dialog::default_shortcut_set);
+    }
 
 #if defined (HAVE_QSCINTILLA)
 
-  int mode = settings->value (ed_color_mode).toInt ();
+  if (first)
+    {
+      int mode = settings.int_value (ed_color_mode);
 
-  QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()),
-                                            group_box_editor_styles);
-  cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));
-  cb_color_mode->setChecked (mode > 0);
-  cb_color_mode->setObjectName (ed_color_mode.key);
+      QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()),
+                                                group_box_editor_styles);
+      cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));
+      cb_color_mode->setChecked (mode > 0);
+      cb_color_mode->setObjectName (ed_color_mode.settings_key ());
+
+      QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_styles.toStdString ().data ()));
+      pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ()));
 
-  QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_styles.toStdString ().data ()));
-  pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ()));
+      color_picker *current_line_color = new color_picker (
+        settings.value (ed_highlight_current_line_color.settings_key ()
+                        + settings_color_modes_ext[mode],
+                        ed_highlight_current_line_color.def ()).value<QColor> ());
+      current_line_color->setObjectName (ed_highlight_current_line_color.settings_key ());
 
-  color_picker *current_line_color = new color_picker (
-                                                       settings->value (ed_highlight_current_line_color.key +
-                                                                        settings_color_modes_ext[mode],
-                                                                        ed_highlight_current_line_color.def).value<QColor> (), this);
-  current_line_color->setObjectName (ed_highlight_current_line_color.key);
-  QLabel *current_line_color_label = new QLabel(
-                                                tr ("Color of highlighted current line (magenta (255,0,255) for automatic color)")
-                                                );
+      QLabel *current_line_color_label
+        = new QLabel(tr ("Color of highlighted current line (magenta (255,0,255) for automatic color)"));
+
+      QHBoxLayout *color_mode = new QHBoxLayout ();
+      color_mode->addWidget (cb_color_mode);
+      color_mode->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));
+      color_mode->addWidget (pb_reload_default_colors);
 
-  QHBoxLayout *color_mode = new QHBoxLayout ();
-  color_mode->addWidget (cb_color_mode);
-  color_mode->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));
-  color_mode->addWidget (pb_reload_default_colors);
+      QHBoxLayout *current_line = new QHBoxLayout ();
+      current_line->addWidget (current_line_color_label);
+      current_line->addWidget (current_line_color);
+      current_line->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));
 
-  QHBoxLayout *current_line = new QHBoxLayout ();
-  current_line->addWidget (current_line_color_label);
-  current_line->addWidget (current_line_color);
-  current_line->addItem (new QSpacerItem (5, 5, QSizePolicy::Expanding));
+      editor_styles_layout->addLayout (color_mode);
+      editor_styles_layout->addLayout (current_line);
+
+      // update colors depending on second theme selection
+      connect (cb_color_mode, &QCheckBox::stateChanged,
+               this, &settings_dialog::update_editor_lexers);
+      connect (pb_reload_default_colors, &QPushButton::clicked,
+               [=] () { update_editor_lexers (settings_reload_default_colors_flag); });
 
-  editor_styles_layout->addLayout (color_mode);
-  editor_styles_layout->addLayout (current_line);
-
-  // update colors depending on second theme selection
-  connect (cb_color_mode, &QCheckBox::stateChanged,
-           this, &settings_dialog::update_editor_lexers);
-  connect (pb_reload_default_colors, &QPushButton::clicked,
-           [=] () { update_editor_lexers (settings_reload_default_colors_flag); });
-
-  // finally read the lexer colors using the update slot
-  update_editor_lexers ();
+      // finally read the lexer colors using the update slot
+      update_editor_lexers ();
+    }
+  else
+    {
+      QCheckBox *cb_color_mode
+        = group_box_editor_styles->findChild <QCheckBox *> (ed_color_mode.settings_key ());
+      bool sec_color_mode = settings.bool_value (ed_color_mode);
+      if (cb_color_mode->isChecked () == sec_color_mode)
+        {
+          // color mode does not change, update colors manually
+          update_editor_lexers ();
+        }
+      else
+        {
+          // toggling check-state calls related slot updating colors
+          cb_color_mode->setChecked (sec_color_mode);
+        }
+    }
 
 #endif
-
-  // which tab is the desired one?
-  show_tab (desired_tab);
-
-  // connect button box signal
-  connect (button_box, &QDialogButtonBox::clicked,
-           this, &settings_dialog::button_clicked);
-
-  // restore last geometry
-  if (settings->contains (sd_geometry.key))
-    restoreGeometry (settings->value (sd_geometry).toByteArray ());
-  else
-    setGeometry (QRect (10, 50, 1000, 600));
 }
 
 void settings_dialog::show_tab (const QString& tab)
 {
+  gui_settings settings;
+
   if (tab.isEmpty ())
-    {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
-      if (settings)
-        tabWidget->setCurrentIndex (settings->value (sd_last_tab).toInt ());
-    }
+    tabWidget->setCurrentIndex (settings.int_value (sd_last_tab));
   else
     {
       QHash <QString, QWidget *> tab_hash;
@@ -533,12 +620,12 @@
     }
 }
 
-void settings_dialog::get_octave_dir (void)
+void settings_dialog::get_octave_dir ()
 {
   get_dir (le_octave_dir, tr ("Set Octave Startup Directory"));
 }
 
-void settings_dialog::get_file_browser_dir (void)
+void settings_dialog::get_file_browser_dir ()
 {
   get_dir (le_file_browser_dir, tr ("Set File Browser Startup Directory"));
 }
@@ -547,9 +634,10 @@
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks;
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts |= QFileDialog::DontUseNativeDialog;
 
   QString dir = QFileDialog::getExistingDirectory
@@ -565,23 +653,33 @@
   if (button_role == QDialogButtonBox::ApplyRole
       || button_role == QDialogButtonBox::AcceptRole)
     {
-      write_changed_settings (button_role == QDialogButtonBox::AcceptRole);
+      write_changed_settings ();
+      if (button_role == QDialogButtonBox::AcceptRole)
+        hide ();  // already hide here, reloading settings takes some time
+
+      QMessageBox *info = wait_message_box (tr ("Applying preferences ... "), this);
       emit apply_new_settings ();
+      close_wait_message_box (info);
     }
 
   if (button_role == QDialogButtonBox::RejectRole
       || button_role == QDialogButtonBox::AcceptRole)
     {
       // save last settings dialog's geometry and close
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
+
+      gui_settings settings;
 
-      settings->setValue (sd_last_tab.key, tabWidget->currentIndex ());
-      settings->setValue (sd_geometry.key, saveGeometry ());
-      settings->sync ();
+      settings.setValue (sd_last_tab.settings_key (), tabWidget->currentIndex ());
+      settings.setValue (sd_geometry.settings_key (), saveGeometry ());
+      settings.sync ();
 
       close ();
     }
+
+  if (button_role == QDialogButtonBox::ResetRole)
+    {
+      read_settings (false);  // not the first read, only update existing items
+    }
 }
 
 void settings_dialog::set_disabled_pref_file_browser_dir (bool disable)
@@ -601,7 +699,7 @@
 }
 
 // slot for updating enabled state of proxy settings
-void settings_dialog::proxy_items_update (void)
+void settings_dialog::proxy_items_update ()
 {
   bool use_proxy = use_proxy_server->isChecked ();
 
@@ -628,53 +726,85 @@
 
 // slots for import/export of shortcut sets
 
-void settings_dialog::import_shortcut_set (void)
+// Prompt for file name and import shortcuts from it.  Importing will
+// change values in tree view but does not apply values to
+// gui_settings_object so that the user may choose to apply or cancel
+// the action.
+
+void settings_dialog::import_shortcut_set ()
 {
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
+  if (! overwrite_all_shortcuts ())
+    return;
+
+  QString file = get_shortcuts_file_name (OSC_IMPORT);
 
-  scmgr.import_export (shortcut_manager::OSC_IMPORT);
+  gui_settings osc_settings (file, QSettings::IniFormat);
+
+  if (osc_settings.status () ==  QSettings::NoError)
+    shortcuts_treewidget->import_shortcuts (osc_settings);
+  else
+    qWarning () << (tr ("Failed to open %1 as Octave shortcut file")
+                    .arg (file));
 }
 
-void settings_dialog::export_shortcut_set (void)
+// Prompt for file name and export shortcuts to it.
+
+// FIXME: Should exported settings values come from the gui_settings
+// object or the tree view?  If modified values in the tree view have
+// not been applied, should we offer to apply them first?  Offer a
+// choice to save current application settings or the modified values
+// in the dialog?
+
+void settings_dialog::export_shortcut_set ()
 {
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
+  QString file = get_shortcuts_file_name (OSC_EXPORT);
+
+  gui_settings osc_settings (file, QSettings::IniFormat);
 
-  scmgr.import_export (shortcut_manager::OSC_EXPORT);
+  if (osc_settings.status () ==  QSettings::NoError)
+    shortcuts_treewidget->export_shortcuts (osc_settings);
+  else
+    qWarning () << (tr ("Failed to open %1 as Octave shortcut file")
+                    .arg (file));
 }
 
-void settings_dialog::default_shortcut_set (void)
+// Reset the tree view to default values.  Does not apply values to
+// gui_settings object so that the user may choose to apply or cancel
+// the action.
+
+void settings_dialog::default_shortcut_set ()
 {
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
+  if (! overwrite_all_shortcuts ())
+    return;
 
-  scmgr.import_export (shortcut_manager::OSC_DEFAULT);
+  shortcuts_treewidget->set_default_shortcuts ();
 }
 
 void settings_dialog::update_editor_lexers (int def)
 {
 #if defined (HAVE_QSCINTILLA)
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
   QCheckBox *cb_color_mode
-    = group_box_editor_styles->findChild <QCheckBox *> (ed_color_mode.key);
+    = group_box_editor_styles->findChild <QCheckBox *> (ed_color_mode.settings_key ());
 
   int m = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     m = 1;
 
-  color_picker *c_picker = findChild <color_picker *> (ed_highlight_current_line_color.key);
+  color_picker *c_picker = findChild <color_picker *> (ed_highlight_current_line_color.settings_key ());
   if (c_picker)
     {
+      gui_settings settings;
+
       if (def != settings_reload_default_colors_flag)
         {
           // Get current value from settings or the default
-          c_picker->set_color (settings->color_value (ed_highlight_current_line_color, m));
+          c_picker->set_color (settings.color_value (ed_highlight_current_line_color, m));
         }
       else
         {
           // Get the default value
-          c_picker->set_color (settings->get_color_value (ed_highlight_current_line_color.def, m));
+          c_picker->set_color (settings.get_color_value (ed_highlight_current_line_color.def (), m));
         }
     }
 
@@ -684,40 +814,40 @@
 
 #  if defined (HAVE_LEXER_OCTAVE)
   lexer = new QsciLexerOctave ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 #  elif defined (HAVE_LEXER_MATLAB)
   lexer = new QsciLexerMatlab ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 #  endif
 
   lexer = new QsciLexerCPP ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new QsciLexerJava ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new QsciLexerPerl ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new QsciLexerBatch ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new QsciLexerDiff ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new QsciLexerBash ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
   lexer = new octave_txt_lexer ();
-  update_lexer (lexer, settings, m, def);
+  update_lexer (lexer, m, def);
   delete lexer;
 
 #else
@@ -729,13 +859,12 @@
 
 #if defined (HAVE_QSCINTILLA)
 
-void settings_dialog::update_lexer (QsciLexer *lexer, gui_settings *settings,
-                                    int mode, int def)
+void settings_dialog::update_lexer (QsciLexer *lexer, int mode, int def)
 {
   // Get lexer settings and copy from default settings if not yet
   // available in normal settings file
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  rmgr.read_lexer_settings (lexer, settings, mode, def);
+  gui_settings settings;
+  settings.read_lexer_settings (lexer, mode, def);
 
   // When reloading default styles, the style tabs do already exists.
   // Otherwise, check if they exist or not.
@@ -755,13 +884,13 @@
     {
       // This is not an update, call get_lexer_settings for building
       // the settings tab
-      get_lexer_settings (lexer, settings);
+      get_lexer_settings (lexer);
       return;
     }
 
   // Update the styles elements in all styles
   int styles[ed_max_lexer_styles];  // array for saving valid styles
-  int max_style = rmgr.get_valid_lexer_styles (lexer, styles);
+  int max_style = settings.get_valid_lexer_styles (lexer, styles);
   QWidget *tab = tabs_editor_lexers->widget (index);
   int default_size = 0;
   QString default_family;
@@ -832,14 +961,13 @@
 
 }
 
-void settings_dialog::get_lexer_settings (QsciLexer *lexer,
-                                          gui_settings *settings)
+void settings_dialog::get_lexer_settings (QsciLexer *lexer)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   int styles[ed_max_lexer_styles];  // array for saving valid styles
   // (enum is not continuous)
-  int max_style = rmgr.get_valid_lexer_styles (lexer, styles);
+  int max_style = settings.get_valid_lexer_styles (lexer, styles);
   QGridLayout *style_grid = new QGridLayout ();
   QVector<QLabel *> description (max_style);
   QVector<QFontComboBox *> select_font (max_style);
@@ -924,27 +1052,28 @@
   scroll_area->setWidget (scroll_area_contents);
   tabs_editor_lexers->addTab (scroll_area, lexer->language ());
 
-  tabs_editor_lexers->setCurrentIndex (settings->value (sd_last_editor_styles_tab).toInt ());
+  tabs_editor_lexers->setCurrentIndex (settings.int_value (sd_last_editor_styles_tab));
 }
 
-void settings_dialog::write_lexer_settings (QsciLexer *lexer,
-                                            gui_settings *settings)
+void settings_dialog::write_lexer_settings (QsciLexer *lexer)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   QCheckBox *cb_color_mode
-    = group_box_editor_styles->findChild <QCheckBox *> (ed_color_mode.key);
+    = group_box_editor_styles->findChild <QCheckBox *> (ed_color_mode.settings_key ());
   int mode = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     mode = 1;
 
-  settings->setValue (ed_color_mode.key, mode);
+  settings.setValue (ed_color_mode.settings_key (), mode);
 
   QWidget *tab = tabs_editor_lexers->
     findChild <QWidget *> (QString (lexer->language ()) + "_styles");
   int styles[ed_max_lexer_styles];  // array for saving valid styles
   // (enum is not continuous)
-  int max_style = rmgr.get_valid_lexer_styles (lexer, styles);
+
+  int max_style = settings.get_valid_lexer_styles (lexer, styles);
+
   QFontComboBox *select_font;
   QSpinBox *font_size;
   QCheckBox *attrib_font[3];
@@ -952,13 +1081,13 @@
   color_picker *bg_color;
   int default_size = 10;
 
-  color = findChild <color_picker *> (ed_highlight_current_line_color.key);
+  color = findChild <color_picker *> (ed_highlight_current_line_color.settings_key ());
   if (color)
-    settings->setValue (ed_highlight_current_line_color.key
+    settings.setValue (ed_highlight_current_line_color.settings_key ()
                         + settings_color_modes_ext[mode], color->color ());
 
   QString default_font_name
-    = settings->value (global_mono_font).toString ();
+    = settings.string_value (global_mono_font);
   QFont default_font = QFont (default_font_name, 10, -1, 0);
   QColor default_color = QColor ();
 
@@ -1023,19 +1152,19 @@
   const std::string group =
     QString ("Scintilla" + settings_color_modes_ext[mode]).toStdString ();
 
-  lexer->writeSettings (*settings, group.c_str ());
+  lexer->writeSettings (settings, group.c_str ());
 
-  settings->setValue (sd_last_editor_styles_tab.key,
-                      tabs_editor_lexers->currentIndex ());
-  settings->sync ();
+  settings.setValue (sd_last_editor_styles_tab.settings_key (),
+                     tabs_editor_lexers->currentIndex ());
+  settings.sync ();
 }
 
 #endif
 
-void settings_dialog::write_changed_settings (bool closing)
+void settings_dialog::write_changed_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+
+  gui_settings settings;
 
   // the icon set
   QString widget_icon_set = "NONE";
@@ -1043,87 +1172,87 @@
     widget_icon_set = "LETTER";
   else if (general_icon_graphic->isChecked ())
     widget_icon_set = "GRAPHIC";
-  settings->setValue (dw_icon_set.key, widget_icon_set);
+  settings.setValue (dw_icon_set.settings_key (), widget_icon_set);
 
   // language
   QString language = comboBox_language->currentText ();
   if (language == tr ("System setting"))
-    language = global_language.def.toString ();
-  settings->setValue (global_language.key, language);
+    language = global_language.def ().toString ();
+  settings.setValue (global_language.settings_key (), language);
 
   // style
   QString selected_style = combo_styles->currentText ();
-  if (selected_style == global_style.def.toString ())
-    selected_style = global_style.def.toString ();
-  settings->setValue (global_style.key, selected_style);
+  if (selected_style == global_style.def ().toString ())
+    selected_style = global_style.def ().toString ();
+  settings.setValue (global_style.settings_key (), selected_style);
 
   // dock widget title bar
-  settings->setValue (dw_title_custom_style.key, cb_widget_custom_style->isChecked ());
-  settings->setValue (dw_title_3d.key, sb_3d_title->value ());
-  settings->setValue (dw_title_bg_color.key, m_widget_title_bg_color->color ());
-  settings->setValue (dw_title_bg_color_active.key, m_widget_title_bg_color_active->color ());
-  settings->setValue (dw_title_fg_color.key, m_widget_title_fg_color->color ());
-  settings->setValue (dw_title_fg_color_active.key, m_widget_title_fg_color_active->color ());
+  settings.setValue (dw_title_custom_style.settings_key (), cb_widget_custom_style->isChecked ());
+  settings.setValue (dw_title_3d.settings_key (), sb_3d_title->value ());
+  settings.setValue (dw_title_bg_color.settings_key (), m_widget_title_bg_color->color ());
+  settings.setValue (dw_title_bg_color_active.settings_key (), m_widget_title_bg_color_active->color ());
+  settings.setValue (dw_title_fg_color.settings_key (), m_widget_title_fg_color->color ());
+  settings.setValue (dw_title_fg_color_active.settings_key (), m_widget_title_fg_color_active->color ());
 
   // icon size and theme
   int icon_size = icon_size_large->isChecked () - icon_size_small->isChecked ();
-  settings->setValue (global_icon_size.key, icon_size);
-  settings->setValue (global_icon_theme_index.key, combo_box_icon_theme->currentIndex ());
+  settings.setValue (global_icon_size.settings_key (), icon_size);
+  settings.setValue (global_icon_theme_index.settings_key (), combo_box_icon_theme->currentIndex ());
 
   // native file dialogs
-  settings->setValue (global_use_native_dialogs.key, cb_use_native_file_dialogs->isChecked ());
+  settings.setValue (global_use_native_dialogs.settings_key (), cb_use_native_file_dialogs->isChecked ());
 
   // cursor blinking
-  settings->setValue (global_cursor_blinking.key, cb_cursor_blinking->isChecked ());
+  settings.setValue (global_cursor_blinking.settings_key (), cb_cursor_blinking->isChecked ());
 
   // focus follows mouse
-  settings->setValue (dw_focus_follows_mouse.key, cb_focus_follows_mouse->isChecked ());
+  settings.setValue (dw_focus_follows_mouse.settings_key (), cb_focus_follows_mouse->isChecked ());
 
   // promp to exit
-  settings->setValue (global_prompt_to_exit.key, cb_prompt_to_exit->isChecked ());
+  settings.setValue (global_prompt_to_exit.settings_key (), cb_prompt_to_exit->isChecked ());
 
   // status bar
-  settings->setValue (global_status_bar.key, cb_status_bar->isChecked ());
+  settings.setValue (global_status_bar.settings_key (), cb_status_bar->isChecked ());
 
   // Octave startup
-  settings->setValue (global_restore_ov_dir.key, cb_restore_octave_dir->isChecked ());
-  settings->setValue (global_ov_startup_dir.key, le_octave_dir->text ());
+  settings.setValue (global_restore_ov_dir.settings_key (), cb_restore_octave_dir->isChecked ());
+  settings.setValue (global_ov_startup_dir.settings_key (), le_octave_dir->text ());
 
   //editor
-  settings->setValue (global_use_custom_editor.key, useCustomFileEditor->isChecked ());
-  settings->setValue (global_custom_editor.key, customFileEditor->text ());
-  settings->setValue (ed_show_line_numbers.key, editor_showLineNumbers->isChecked ());
-  settings->setValue (ed_line_numbers_size.key, editor_linenr_size->value ());
-  settings->setValue (ed_highlight_current_line.key, editor_highlightCurrentLine->isChecked ());
-  settings->setValue (ed_long_line_marker.key, editor_long_line_marker->isChecked ());
-  settings->setValue (ed_long_line_marker_line.key, editor_long_line_marker_line->isChecked ());
-  settings->setValue (ed_long_line_marker_background.key, editor_long_line_marker_background->isChecked ());
-  settings->setValue (ed_long_line_column.key, editor_long_line_column->value ());
-  settings->setValue (ed_break_lines.key, editor_break_checkbox->isChecked ());
-  settings->setValue (ed_break_lines_comments.key, editor_break_comments_checkbox->isChecked ());
-  settings->setValue (ed_wrap_lines.key, editor_wrap_checkbox->isChecked ());
-  settings->setValue (ed_code_folding.key, cb_code_folding->isChecked ());
-  settings->setValue (ed_show_edit_status_bar.key, cb_edit_status_bar->isChecked ());
-  settings->setValue (ed_show_toolbar.key, cb_edit_tool_bar->isChecked ());
-  settings->setValue (ed_highlight_all_occurrences.key, editor_highlight_all_occurrences->isChecked ());
-  settings->setValue (ed_code_completion.key, editor_codeCompletion->isChecked ());
-  settings->setValue (ed_code_completion_threshold.key, editor_spinbox_ac_threshold->value ());
-  settings->setValue (ed_code_completion_keywords.key, editor_checkbox_ac_keywords->isChecked ());
-  settings->setValue (ed_code_completion_octave_builtins.key, editor_checkbox_ac_builtins->isChecked ());
-  settings->setValue (ed_code_completion_octave_functions.key, editor_checkbox_ac_functions->isChecked ());
-  settings->setValue (ed_code_completion_document.key, editor_checkbox_ac_document->isChecked ());
-  settings->setValue (ed_code_completion_case.key, editor_checkbox_ac_case->isChecked ());
-  settings->setValue (ed_code_completion_replace.key, editor_checkbox_ac_replace->isChecked ());
-  settings->setValue (ed_auto_endif.key, editor_auto_endif->currentIndex ());
-  settings->setValue (ed_show_white_space.key, editor_ws_checkbox->isChecked ());
-  settings->setValue (ed_show_white_space_indent.key, editor_ws_indent_checkbox->isChecked ());
-  settings->setValue (ed_show_eol_chars.key, cb_show_eol->isChecked ());
-  settings->setValue (ed_show_hscroll_bar.key, cb_show_hscrollbar->isChecked ());
-  settings->setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ());
+  settings.setValue (global_use_custom_editor.settings_key (), useCustomFileEditor->isChecked ());
+  settings.setValue (global_custom_editor.settings_key (), customFileEditor->text ());
+  settings.setValue (ed_show_line_numbers.settings_key (), editor_showLineNumbers->isChecked ());
+  settings.setValue (ed_line_numbers_size.settings_key (), editor_linenr_size->value ());
+  settings.setValue (ed_highlight_current_line.settings_key (), editor_highlightCurrentLine->isChecked ());
+  settings.setValue (ed_long_line_marker.settings_key (), editor_long_line_marker->isChecked ());
+  settings.setValue (ed_long_line_marker_line.settings_key (), editor_long_line_marker_line->isChecked ());
+  settings.setValue (ed_long_line_marker_background.settings_key (), editor_long_line_marker_background->isChecked ());
+  settings.setValue (ed_long_line_column.settings_key (), editor_long_line_column->value ());
+  settings.setValue (ed_break_lines.settings_key (), editor_break_checkbox->isChecked ());
+  settings.setValue (ed_break_lines_comments.settings_key (), editor_break_comments_checkbox->isChecked ());
+  settings.setValue (ed_wrap_lines.settings_key (), editor_wrap_checkbox->isChecked ());
+  settings.setValue (ed_code_folding.settings_key (), cb_code_folding->isChecked ());
+  settings.setValue (ed_show_edit_status_bar.settings_key (), cb_edit_status_bar->isChecked ());
+  settings.setValue (ed_show_toolbar.settings_key (), cb_edit_tool_bar->isChecked ());
+  settings.setValue (ed_highlight_all_occurrences.settings_key (), editor_highlight_all_occurrences->isChecked ());
+  settings.setValue (ed_code_completion.settings_key (), editor_codeCompletion->isChecked ());
+  settings.setValue (ed_code_completion_threshold.settings_key (), editor_spinbox_ac_threshold->value ());
+  settings.setValue (ed_code_completion_keywords.settings_key (), editor_checkbox_ac_keywords->isChecked ());
+  settings.setValue (ed_code_completion_octave_builtins.settings_key (), editor_checkbox_ac_builtins->isChecked ());
+  settings.setValue (ed_code_completion_octave_functions.settings_key (), editor_checkbox_ac_functions->isChecked ());
+  settings.setValue (ed_code_completion_document.settings_key (), editor_checkbox_ac_document->isChecked ());
+  settings.setValue (ed_code_completion_case.settings_key (), editor_checkbox_ac_case->isChecked ());
+  settings.setValue (ed_code_completion_replace.settings_key (), editor_checkbox_ac_replace->isChecked ());
+  settings.setValue (ed_auto_endif.settings_key (), editor_auto_endif->currentIndex ());
+  settings.setValue (ed_show_white_space.settings_key (), editor_ws_checkbox->isChecked ());
+  settings.setValue (ed_show_white_space_indent.settings_key (), editor_ws_indent_checkbox->isChecked ());
+  settings.setValue (ed_show_eol_chars.settings_key (), cb_show_eol->isChecked ());
+  settings.setValue (ed_show_hscroll_bar.settings_key (), cb_show_hscrollbar->isChecked ());
+  settings.setValue (ed_default_eol_mode.settings_key (), combo_eol_mode->currentIndex ());
 
-  settings->setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ());
-  settings->setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ());
-  settings->setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ());
+  settings.setValue (ed_tab_position.settings_key (), editor_combox_tab_pos->currentIndex ());
+  settings.setValue (ed_tabs_rotated.settings_key (), editor_cb_tabs_rotated->isChecked ());
+  settings.setValue (ed_tabs_max_width.settings_key (), editor_sb_tabs_max_width->value ());
 
   // Comment strings
   int rb_uncomment = 0;
@@ -1131,56 +1260,56 @@
     {
       if (m_rb_comment_strings[i]->isChecked ())
         {
-          settings->setValue (ed_comment_str.key, i);
+          settings.setValue (ed_comment_str.settings_key (), i);
           if (i < 3)
-            settings->setValue (ed_comment_str_old.key, i);
+            settings.setValue (ed_comment_str_old.settings_key (), i);
           else
-            settings->setValue (ed_comment_str_old.key, ed_comment_str.def);
+            settings.setValue (ed_comment_str_old.settings_key (), ed_comment_str.def ());
         }
       if (m_rb_uncomment_strings[i]->isChecked ())
         rb_uncomment = rb_uncomment + (1 << i);
     }
-  settings->setValue (ed_uncomment_str.key, rb_uncomment);
+  settings.setValue (ed_uncomment_str.settings_key (), rb_uncomment);
 
-  settings->setValue (ed_default_enc.key, editor_combo_encoding->currentText ());
-  settings->setValue (ed_auto_indent.key, editor_auto_ind_checkbox->isChecked ());
-  settings->setValue (ed_tab_indents_line.key, editor_tab_ind_checkbox->isChecked ());
-  settings->setValue (ed_backspace_unindents_line.key, editor_bs_unind_checkbox->isChecked ());
-  settings->setValue (ed_show_indent_guides.key, editor_ind_guides_checkbox->isChecked ());
-  settings->setValue (ed_indent_width.key, editor_ind_width_spinbox->value ());
-  settings->setValue (ed_indent_uses_tabs.key, editor_ind_uses_tabs_checkbox->isChecked ());
-  settings->setValue (ed_tab_width.key, editor_tab_width_spinbox->value ());
-  settings->setValue (ed_restore_session.key, editor_restoreSession->isChecked ());
-  settings->setValue (ed_create_new_file.key, editor_create_new_file->isChecked ());
-  settings->setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ());
-  settings->setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ());
-  settings->setValue (ed_force_newline.key, editor_force_newline->isChecked ());
-  settings->setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ());
-  settings->setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ());
+  settings.setValue (ed_default_enc.settings_key (), editor_combo_encoding->currentText ());
+  settings.setValue (ed_auto_indent.settings_key (), editor_auto_ind_checkbox->isChecked ());
+  settings.setValue (ed_tab_indents_line.settings_key (), editor_tab_ind_checkbox->isChecked ());
+  settings.setValue (ed_backspace_unindents_line.settings_key (), editor_bs_unind_checkbox->isChecked ());
+  settings.setValue (ed_show_indent_guides.settings_key (), editor_ind_guides_checkbox->isChecked ());
+  settings.setValue (ed_indent_width.settings_key (), editor_ind_width_spinbox->value ());
+  settings.setValue (ed_indent_uses_tabs.settings_key (), editor_ind_uses_tabs_checkbox->isChecked ());
+  settings.setValue (ed_tab_width.settings_key (), editor_tab_width_spinbox->value ());
+  settings.setValue (ed_restore_session.settings_key (), editor_restoreSession->isChecked ());
+  settings.setValue (ed_create_new_file.settings_key (), editor_create_new_file->isChecked ());
+  settings.setValue (ed_hiding_closes_files.settings_key (), editor_hiding_closes_files->isChecked ());
+  settings.setValue (ed_always_reload_changed_files.settings_key (), editor_reload_changed_files->isChecked ());
+  settings.setValue (ed_force_newline.settings_key (), editor_force_newline->isChecked ());
+  settings.setValue (ed_rm_trailing_spaces.settings_key (), editor_remove_trailing_spaces->isChecked ());
+  settings.setValue (ed_show_dbg_file.settings_key (), editor_show_dbg_file->isChecked ());
 
   // file browser
-  settings->setValue (fb_sync_octdir.key, sync_octave_directory->isChecked ());
-  settings->setValue (fb_restore_last_dir.key, cb_restore_file_browser_dir->isChecked ());
-  settings->setValue (fb_startup_dir.key, le_file_browser_dir->text ());
-  settings->setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ());
+  settings.setValue (fb_sync_octdir.settings_key (), sync_octave_directory->isChecked ());
+  settings.setValue (fb_restore_last_dir.settings_key (), cb_restore_file_browser_dir->isChecked ());
+  settings.setValue (fb_startup_dir.settings_key (), le_file_browser_dir->text ());
+  settings.setValue (fb_txt_file_ext.settings_key (), le_file_browser_extensions->text ());
 
   // network
-  settings->setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ());
-  settings->setValue (global_use_proxy.key, use_proxy_server->isChecked ());
-  settings->setValue (global_proxy_type.key, proxy_type->currentText ());
-  settings->setValue (global_proxy_host.key, proxy_host_name->text ());
-  settings->setValue (global_proxy_port.key, proxy_port->text ());
-  settings->setValue (global_proxy_user.key, proxy_username->text ());
-  settings->setValue (global_proxy_pass.key, proxy_password->text ());
+  settings.setValue (nr_allow_connection.settings_key (), checkbox_allow_web_connect->isChecked ());
+  settings.setValue (global_use_proxy.settings_key (), use_proxy_server->isChecked ());
+  settings.setValue (global_proxy_type.settings_key (), proxy_type->currentText ());
+  settings.setValue (global_proxy_host.settings_key (), proxy_host_name->text ());
+  settings.setValue (global_proxy_port.settings_key (), proxy_port->text ());
+  settings.setValue (global_proxy_user.settings_key (), proxy_username->text ());
+  settings.setValue (global_proxy_pass.settings_key (), proxy_password->text ());
 
   // command window
-  settings->setValue (cs_font_size.key, terminal_fontSize->value ());
-  settings->setValue (cs_font.key, terminal_fontName->currentFont ().family ());
-  settings->setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ());
-  settings->setValue (cs_focus_cmd.key, terminal_focus_command->isChecked ());
-  settings->setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ());
-  settings->setValue (cs_hist_buffer.key, terminal_history_buffer->value ());
-  write_terminal_colors (settings);
+  settings.setValue (cs_font_size.settings_key (), terminal_fontSize->value ());
+  settings.setValue (cs_font.settings_key (), terminal_fontName->currentFont ().family ());
+  settings.setValue (cs_cursor_use_fgcol.settings_key (), terminal_cursorUseForegroundColor->isChecked ());
+  settings.setValue (cs_focus_cmd.settings_key (), terminal_focus_command->isChecked ());
+  settings.setValue (cs_dbg_location.settings_key (), terminal_print_dbg_location->isChecked ());
+  settings.setValue (cs_hist_buffer.settings_key (), terminal_history_buffer->value ());
+  write_terminal_colors ();
 
   // the cursor
   QString cursor_type;
@@ -1188,9 +1317,9 @@
   if ((cursor_int > 0) && (cursor_int < cs_cursor_types.size ()))
     cursor_type = QString (cs_cursor_types[cursor_int].data ());
   else
-    cursor_type = cs_cursor.def.toString ();
+    cursor_type = cs_cursor.def ().toString ();
 
-  settings->setValue (cs_cursor.key, cursor_type);
+  settings.setValue (cs_cursor.settings_key (), cursor_type);
 
 #if defined (HAVE_QSCINTILLA)
   // editor styles: create lexer, get dialog contents, and write settings
@@ -1199,71 +1328,73 @@
 #if defined (HAVE_LEXER_OCTAVE)
 
   lexer = new QsciLexerOctave ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
 #elif defined (HAVE_LEXER_MATLAB)
 
   lexer = new QsciLexerMatlab ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
 #endif
 
   lexer = new QsciLexerCPP ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new QsciLexerJava ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new QsciLexerPerl ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new QsciLexerBatch ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new QsciLexerDiff ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new QsciLexerBash ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
   lexer = new octave_txt_lexer ();
-  write_lexer_settings (lexer, settings);
+  write_lexer_settings (lexer);
   delete lexer;
 
 #endif
 
   // Workspace
-  write_workspace_colors (settings);
+  write_workspace_colors ();
 
   // Variable editor
-  settings->setValue (ve_column_width.key, varedit_columnWidth->value ());
-  settings->setValue (ve_row_height.key, varedit_rowHeight->value ());
-  settings->setValue (ve_use_terminal_font.key, varedit_useTerminalFont->isChecked ());
-  settings->setValue (ve_alternate_rows.key, varedit_alternate->isChecked ());
-  settings->setValue (ve_font_name.key, varedit_font->currentFont ().family ());
-  settings->setValue (ve_font_size.key, varedit_fontSize->value ());
-  write_varedit_colors (settings);
+  settings.setValue (ve_column_width.settings_key (), varedit_columnWidth->value ());
+  settings.setValue (ve_row_height.settings_key (), varedit_rowHeight->value ());
+  settings.setValue (ve_use_terminal_font.settings_key (), varedit_useTerminalFont->isChecked ());
+  settings.setValue (ve_alternate_rows.settings_key (), varedit_alternate->isChecked ());
+  settings.setValue (ve_font_name.settings_key (), varedit_font->currentFont ().family ());
+  settings.setValue (ve_font_size.settings_key (), varedit_fontSize->value ());
+  write_varedit_colors ();
 
   // shortcuts
 
-  settings->setValue (sc_prevent_rl_conflicts.key, cb_prevent_readline_conflicts->isChecked ());
-  settings->setValue (sc_prevent_rl_conflicts_menu.key, cb_prevent_readline_conflicts_menu->isChecked ());
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-  scmgr.write_shortcuts (settings, closing);
+  settings.setValue (sc_prevent_rl_conflicts.settings_key (), cb_prevent_readline_conflicts->isChecked ());
+  settings.setValue (sc_prevent_rl_conflicts_menu.settings_key (), cb_prevent_readline_conflicts_menu->isChecked ());
 
-  settings->sync ();
+  shortcuts_treewidget->write_settings ();
+
+  settings.sync ();
 }
 
-void settings_dialog::read_workspace_colors (gui_settings *settings)
+void settings_dialog::read_workspace_colors ()
 {
+  gui_settings settings;
+
   // Construct the grid with all color related settings
   QGridLayout *style_grid = new QGridLayout ();
   QVector<QLabel *> description (ws_colors_count);
@@ -1272,7 +1403,7 @@
   int column = 0;
   const int color_columns = 3;  // place colors in so many columns
   int row = 0;
-  int mode = settings->value (ws_color_mode).toInt ();
+  int mode = settings.int_value (ws_color_mode);
 
   m_ws_enable_colors = new QCheckBox (tr ("Enable attribute colors"));
   style_grid->addWidget (m_ws_enable_colors, row++, column, 1, 4);
@@ -1282,12 +1413,12 @@
   connect (m_ws_enable_colors, &QCheckBox::toggled,
            m_ws_hide_tool_tips, &QCheckBox::setEnabled);
   m_ws_hide_tool_tips->setChecked
-    (settings->value (ws_hide_tool_tips).toBool ());
+    (settings.bool_value (ws_hide_tool_tips));
 
   QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));
   cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));
   cb_color_mode->setChecked (mode == 1);
-  cb_color_mode->setObjectName (ws_color_mode.key);
+  cb_color_mode->setObjectName (ws_color_mode.settings_key ());
   connect (m_ws_enable_colors, &QCheckBox::toggled,
            cb_color_mode, &QCheckBox::setEnabled);
   style_grid->addWidget (cb_color_mode, row, column);
@@ -1298,20 +1429,20 @@
            pb_reload_default_colors, &QPushButton::setEnabled);
   style_grid->addWidget (pb_reload_default_colors, row+1, column++);
 
-  bool colors_enabled = settings->value (ws_enable_colors).toBool ();
+  bool colors_enabled = settings.bool_value (ws_enable_colors);
 
   for (int i = 0; i < ws_colors_count; i++)
     {
       description[i] = new QLabel ("    "
-                                   + tr (ws_color_names.at (i).toStdString ().data ()));
+        + tr (ws_color_names.at (i).toStdString ().data ()));
       description[i]->setAlignment (Qt::AlignRight);
       description[i]->setEnabled (colors_enabled);
       connect (m_ws_enable_colors, &QCheckBox::toggled,
                description[i], &QLabel::setEnabled);
 
-      QColor setting_color = settings->color_value (ws_colors[i], mode);
+      QColor setting_color = settings.color_value (ws_colors[i], mode);
       color[i] = new color_picker (setting_color);
-      color[i]->setObjectName (ws_colors[i].key);
+      color[i]->setObjectName (ws_colors[i].settings_key ());
       color[i]->setMinimumSize (30, 10);
       color[i]->setEnabled (colors_enabled);
       connect (m_ws_enable_colors, &QCheckBox::toggled,
@@ -1347,43 +1478,44 @@
 void settings_dialog::update_workspace_colors (int def)
 {
   QCheckBox *cb_color_mode
-    = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.key);
+    = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.settings_key ());
 
   int m = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     m = 1;
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   color_picker *c_picker;
 
   for (unsigned int i = 0; i < ws_colors_count; i++)
     {
-      c_picker = workspace_colors_box->findChild <color_picker *> (ws_colors[i].key);
+      c_picker = workspace_colors_box->findChild <color_picker *> (ws_colors[i].settings_key ());
       if (c_picker)
         {
           if (def != settings_reload_default_colors_flag)
             {
               // Get current value from settings or the default
-              c_picker->set_color (settings->color_value (ws_colors[i], m));
+              c_picker->set_color (settings.color_value (ws_colors[i], m));
             }
           else
             {
               // Get the default value
-              c_picker->set_color (settings->get_color_value (ws_colors[i].def, m));
+              c_picker->set_color (settings.get_color_value (ws_colors[i].def (), m));
             }
         }
     }
 }
 
-void settings_dialog::write_workspace_colors (gui_settings *settings)
+void settings_dialog::write_workspace_colors ()
 {
-  settings->setValue (ws_enable_colors.key, m_ws_enable_colors->isChecked ());
-  settings->setValue (ws_hide_tool_tips.key, m_ws_hide_tool_tips->isChecked ());
+  gui_settings settings;
+
+  settings.setValue (ws_enable_colors.settings_key (), m_ws_enable_colors->isChecked ());
+  settings.setValue (ws_hide_tool_tips.settings_key (), m_ws_hide_tool_tips->isChecked ());
 
   QCheckBox *cb_color_mode
-    = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.key);
+    = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.settings_key ());
 
   int mode = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
@@ -1393,28 +1525,30 @@
 
   for (int i = 0; i < ws_colors_count; i++)
     {
-      color = workspace_colors_box->findChild <color_picker *> (ws_colors[i].key);
+      color = workspace_colors_box->findChild <color_picker *> (ws_colors[i].settings_key ());
       if (color)
-        settings->set_color_value (ws_colors[i], color->color (), mode);
+        settings.set_color_value (ws_colors[i], color->color (), mode);
     }
 
-  settings->setValue (ws_color_mode.key, mode);
+  settings.setValue (ws_color_mode.settings_key (), mode);
 
-  settings->sync ();
+  settings.sync ();
 }
 
-void settings_dialog::read_terminal_colors (gui_settings *settings)
+void settings_dialog::read_terminal_colors ()
 {
+  gui_settings settings;
+
   QGridLayout *style_grid = new QGridLayout ();
   QVector<QLabel *> description (cs_colors_count);
   QVector<color_picker *> color (cs_colors_count);
 
-  int mode = settings->value (cs_color_mode).toInt ();
+  int mode = settings.int_value (cs_color_mode);
 
   QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));
   cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));
   cb_color_mode->setChecked (mode == 1);
-  cb_color_mode->setObjectName (cs_color_mode.key);
+  cb_color_mode->setObjectName (cs_color_mode.settings_key ());
   style_grid->addWidget (cb_color_mode, 0, 0);
 
   QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ()));
@@ -1427,11 +1561,11 @@
   for (unsigned int i = 0; i < cs_colors_count; i++)
     {
       description[i] = new QLabel ("    "
-                                   + tr (cs_color_names.at (i).toStdString ().data ()));
+          + tr (cs_color_names.at (i).toStdString ().data ()));
       description[i]->setAlignment (Qt::AlignRight);
-      QColor setting_color = settings->color_value (cs_colors[i], mode);
+      QColor setting_color = settings.color_value (cs_colors[i], mode);
       color[i] = new color_picker (setting_color);
-      color[i]->setObjectName (cs_colors[i].key);
+      color[i]->setObjectName (cs_colors[i].settings_key ());
       color[i]->setMinimumSize (30, 10);
       style_grid->addWidget (description[i], row, 2*column);
       style_grid->addWidget (color[i], row, 2*column+1);
@@ -1456,71 +1590,74 @@
 void settings_dialog::update_terminal_colors (int def)
 {
   QCheckBox *cb_color_mode
-    = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.key);
+    = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.settings_key ());
 
   int m = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     m = 1;
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   color_picker *c_picker;
 
   for (unsigned int i = 0; i < cs_colors_count; i++)
     {
-      c_picker = terminal_colors_box->findChild <color_picker *> (cs_colors[i].key);
+      c_picker = terminal_colors_box->findChild <color_picker *> (cs_colors[i].settings_key ());
       if (c_picker)
         {
           if (def != settings_reload_default_colors_flag)
             {
               // Get current value from settings or the default
-              c_picker->set_color (settings->color_value (cs_colors[i], m));
+              c_picker->set_color (settings.color_value (cs_colors[i], m));
             }
           else
             {
               // Get the default value
-              c_picker->set_color (settings->get_color_value (cs_colors[i].def, m));
+              c_picker->set_color (settings.get_color_value (cs_colors[i].def (), m));
             }
         }
     }
 }
 
-void settings_dialog::write_terminal_colors (gui_settings *settings)
+void settings_dialog::write_terminal_colors ()
 {
   QCheckBox *cb_color_mode
-    = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.key);
+    = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.settings_key ());
 
   int mode = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     mode = 1;
 
+  gui_settings settings;
+
   color_picker *color;
 
   for (int i = 0; i < cs_color_names.size (); i++)
     {
-      color = terminal_colors_box->findChild <color_picker *> (cs_colors[i].key);
+      color = terminal_colors_box->findChild <color_picker *> (cs_colors[i].settings_key ());
       if (color)
-        settings->set_color_value (cs_colors[i], color->color (), mode);
+        settings.set_color_value (cs_colors[i], color->color (), mode);
     }
 
-  settings->setValue (cs_color_mode.key, mode);
+  settings.setValue (cs_color_mode.settings_key (), mode);
 
-  settings->sync ();
+  settings.sync ();
 }
 
-void settings_dialog::read_varedit_colors (gui_settings *settings)
+void settings_dialog::read_varedit_colors ()
 {
+  gui_settings settings;
+
   QGridLayout *style_grid = new QGridLayout ();
   QVector<QLabel *> description (ve_colors_count);
   QVector<color_picker *> color (ve_colors_count);
 
-  int mode = settings->value (ve_color_mode).toInt ();
+  int mode = settings.int_value (ve_color_mode);
 
   QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()));
   cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ()));
   cb_color_mode->setChecked (mode == 1);
-  cb_color_mode->setObjectName (ve_color_mode.key);
+  cb_color_mode->setObjectName (ve_color_mode.settings_key ());
   style_grid->addWidget (cb_color_mode, 0, 0);
 
   QPushButton *pb_reload_default_colors = new QPushButton (tr (settings_reload_colors.toStdString ().data ()));
@@ -1533,12 +1670,12 @@
   for (int i = 0; i < ve_colors_count; i++)
     {
       description[i] = new QLabel ("    "
-                                   + tr (ve_color_names.at (i).toStdString ().data ()));
+          + tr (ve_color_names.at (i).toStdString ().data ()));
       description[i]->setAlignment (Qt::AlignRight);
 
-      QColor setting_color = settings->color_value (ve_colors[i], mode);
+      QColor setting_color = settings.color_value (ve_colors[i], mode);
       color[i] = new color_picker (setting_color);
-      color[i]->setObjectName (ve_colors[i].key);
+      color[i]->setObjectName (ve_colors[i].settings_key ());
       color[i]->setMinimumSize (30, 10);
       style_grid->addWidget (description[i], row, 2*column);
       style_grid->addWidget (color[i], row, 2*column+1);
@@ -1563,57 +1700,170 @@
 void settings_dialog::update_varedit_colors (int def)
 {
   QCheckBox *cb_color_mode
-    = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.key);
+    = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.settings_key ());
 
   int m = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     m = 1;
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   color_picker *c_picker;
 
   for (unsigned int i = 0; i < ve_colors_count; i++)
     {
-      c_picker = varedit_colors_box->findChild <color_picker *> (ve_colors[i].key);
+      c_picker = varedit_colors_box->findChild <color_picker *> (ve_colors[i].settings_key ());
       if (c_picker)
         {
           if (def != settings_reload_default_colors_flag)
             {
               // Get current value from settings or the default
-              c_picker->set_color (settings->color_value (ve_colors[i], m));
+              c_picker->set_color (settings.color_value (ve_colors[i], m));
             }
           else
             {
               // Get the default value
-              c_picker->set_color (settings->get_color_value (ve_colors[i].def, m));
+              c_picker->set_color (settings.get_color_value (ve_colors[i].def (), m));
             }
         }
     }
 }
 
-void settings_dialog::write_varedit_colors (gui_settings *settings)
+void settings_dialog::write_varedit_colors ()
 {
   QCheckBox *cb_color_mode
-    = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.key);
+    = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.settings_key ());
 
   int mode = 0;
   if (cb_color_mode && cb_color_mode->isChecked ())
     mode = 1;
 
+  gui_settings settings;
+
   color_picker *color;
 
   for (int i = 0; i < ve_colors_count; i++)
     {
-      color = varedit_colors_box->findChild <color_picker *> (ve_colors[i].key);
+      color = varedit_colors_box->findChild <color_picker *> (ve_colors[i].settings_key ());
       if (color)
-        settings->set_color_value (ve_colors[i], color->color (), mode);
+        settings.set_color_value (ve_colors[i], color->color (), mode);
     }
 
-  settings->setValue (ve_color_mode.key, mode);
+  settings.setValue (ve_color_mode.settings_key (), mode);
+
+  settings.sync ();
+}
+
+QString settings_dialog::get_shortcuts_file_name (import_export_action action)
+{
+  QString file;
+
+  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
+  int opts = 0;  // No options by default.
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
+    opts = QFileDialog::DontUseNativeDialog;
+
+  if (action == OSC_IMPORT)
+    file = QFileDialog::getOpenFileName
+      (this, tr ("Import shortcuts from file..."), QString (),
+       tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
+       nullptr, QFileDialog::Option (opts));
+
+  else
+    file = QFileDialog::getSaveFileName
+      (this, tr ("Export shortcuts to file..."), QString (),
+       tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
+       nullptr, QFileDialog::Option (opts));
+
+  return file;
+}
+
+// Ask whether to overwrite current shortcuts with settings from an
+// imported file.  Optionally allow current shortcuts to be saved to a
+// file.
+
+// FIXME: If the tree view contains changes that have not yet been
+//        saved to the application settings object, should we
+//
+//   * allow the user to choose whether to
+//     - cancel the operation (X)
+//     - save the modified settings (X)
+//     - save the current application settings (XX)
+//
+//   * unconditionally display an error dialog and cancel the
+//     export operation
+//
+//   (X) - already an option, but not based on whether the tree view
+//         contains unsaved changes
+//   (XX) - already possible (cancel operation, cancel settings
+//          dialog, re-open settings dialog and export changes).
+
+bool settings_dialog::overwrite_all_shortcuts ()
+{
+  QMessageBox msg_box;
 
-  settings->sync ();
+  msg_box.setWindowTitle (tr ("Overwriting Shortcuts"));
+  msg_box.setIcon (QMessageBox::Warning);
+  msg_box.setText (tr ("You are about to overwrite all shortcuts.\n"
+                       "Would you like to save the current shortcut set or cancel the action?"));
+  msg_box.setStandardButtons (QMessageBox::Save | QMessageBox::Cancel);
+
+  QPushButton *discard
+    = msg_box.addButton (tr ("Don't save"), QMessageBox::DestructiveRole);
+
+  msg_box.setDefaultButton (QMessageBox::Save);
+
+  int ret = msg_box.exec ();
+
+  if (msg_box.clickedButton () == discard)
+    return true;
+
+  if (ret == QMessageBox::Save)
+    {
+      QString file = get_shortcuts_file_name (OSC_EXPORT);
+
+      gui_settings osc_settings (file, QSettings::IniFormat);
+
+      if (osc_settings.status () ==  QSettings::NoError)
+        {
+          shortcuts_treewidget->export_shortcuts (osc_settings);
+          return true;
+        }
+      else
+        qWarning () << (tr ("Failed to open %1 as Octave shortcut file")
+                        .arg (file));
+    }
+
+  return false;
+}
+
+QMessageBox* settings_dialog::wait_message_box (const QString& text, QWidget *p)
+{
+  QMessageBox *info = new QMessageBox (p);
+
+  info->setIcon (QMessageBox::Information);
+  info->setWindowTitle (tr ("Octave GUI preferences"));
+  info->setText (text);
+  info->setStandardButtons (QMessageBox::Ok);
+  info->setAttribute (Qt::WA_DeleteOnClose);
+  info->setWindowModality (Qt::NonModal);
+
+  info->show ();
+  QThread::msleep (100);
+  QCoreApplication::processEvents ();
+
+  QApplication::setOverrideCursor (Qt::WaitCursor);
+
+  return info;
+}
+
+void settings_dialog::close_wait_message_box (QMessageBox *mbox)
+{
+  QApplication::restoreOverrideCursor ();
+  mbox->close ();
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/settings-dialog.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/settings-dialog.h	Fri Jun 23 20:51:51 2023 +0200
@@ -29,43 +29,43 @@
 #include <QCheckBox>
 #include <QDialog>
 #include <QLineEdit>
+#include <QMessageBox>
 #include <QRadioButton>
 
 #include "color-picker.h"
 #include "gui-preferences-ed.h"
-#include "gui-settings.h"
 #include "ui-settings-dialog.h"
 
 class QsciLexer;
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 // Ui::settings_dialog is a generated class.
 
 class settings_dialog : public QDialog, private Ui::settings_dialog
 {
-  Q_OBJECT public:
+  Q_OBJECT
 
-  explicit settings_dialog (QWidget *parent, base_qobject& octave_qobj,
+public:
+
+  explicit settings_dialog (QWidget *parent,
                             const QString& desired_tab = QString ());
 
-  ~settings_dialog (void) = default;
+  ~settings_dialog () = default;
 
   void show_tab (const QString&);
 
 signals:
 
-  void apply_new_settings (void);
+  void apply_new_settings ();
 
 private slots:
 
-  void get_octave_dir (void);
-  void get_file_browser_dir (void);
+  void get_octave_dir ();
+  void get_file_browser_dir ();
   void get_dir (QLineEdit *, const QString&);
   void set_disabled_pref_file_browser_dir (bool disable);
-  void proxy_items_update (void);
+  void proxy_items_update ();
 
   // slots updating colors depending on theme
   void update_terminal_colors (int def = 0);
@@ -77,30 +77,43 @@
   void button_clicked (QAbstractButton *button);
 
   // slots for import/export-buttons of shortcut sets
-  void import_shortcut_set (void);
-  void export_shortcut_set (void);
-  void default_shortcut_set (void);
+  void import_shortcut_set ();
+  void export_shortcut_set ();
+  void default_shortcut_set ();
 
 private:
 
+  enum import_export_action
+  {
+    OSC_IMPORT,
+    OSC_EXPORT
+  };
+
 #if defined (HAVE_QSCINTILLA)
-  void update_lexer (QsciLexer *lexer, gui_settings *settings, int mode, int def = 0);
-  void get_lexer_settings (QsciLexer *lexer, gui_settings *settings);
-  void write_lexer_settings (QsciLexer *lexer, gui_settings *settings);
+  void update_lexer (QsciLexer *lexer, int mode, int def = 0);
+  void get_lexer_settings (QsciLexer *lexer);
+  void write_lexer_settings (QsciLexer *lexer);
 #endif
 
-  void write_changed_settings (bool closing);
+  void read_settings (bool first);
+
+  void write_changed_settings ();
 
-  void read_workspace_colors (gui_settings *settings);
-  void write_workspace_colors (gui_settings *settings);
+  void read_workspace_colors ();
+  void write_workspace_colors ();
+
+  void read_terminal_colors ();
+  void write_terminal_colors ();
 
-  void read_terminal_colors (gui_settings *settings);
-  void write_terminal_colors (gui_settings *settings);
+  void read_varedit_colors ();
+  void write_varedit_colors ();
+
+  QString get_shortcuts_file_name (import_export_action action);
 
-  void read_varedit_colors (gui_settings *settings);
-  void write_varedit_colors (gui_settings *settings);
+  QMessageBox* wait_message_box (const QString& test, QWidget *p);
+  void close_wait_message_box (QMessageBox *mbox);
 
-  base_qobject& m_octave_qobj;
+  bool overwrite_all_shortcuts ();
 
   color_picker *m_widget_title_bg_color;
   color_picker *m_widget_title_bg_color_active;
--- a/libgui/src/settings-dialog.ui	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/settings-dialog.ui	Fri Jun 23 20:51:51 2023 +0200
@@ -55,8 +55,8 @@
            <rect>
             <x>0</x>
             <y>0</y>
-            <width>1021</width>
-            <height>584</height>
+            <width>1035</width>
+            <height>573</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_17">
@@ -869,7 +869,7 @@
             <x>0</x>
             <y>0</y>
             <width>1021</width>
-            <height>1427</height>
+            <height>1404</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -2681,7 +2681,7 @@
                 <number>0</number>
                </property>
                <item>
-                <widget class="QTreeWidget" name="shortcuts_treewidget">
+                <widget class="octave::shortcuts_tree_widget" name="shortcuts_treewidget">
                  <property name="sizePolicy">
                   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
                    <horstretch>0</horstretch>
@@ -2951,14 +2951,47 @@
     </widget>
    </item>
    <item>
-    <widget class="QDialogButtonBox" name="button_box">
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
+    <layout class="QHBoxLayout" name="horizontalLayout_20">
+     <item>
+      <spacer name="horizontalSpacer_4">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QDialogButtonBox" name="button_box">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="toolTip">
+        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ok&lt;/span&gt; - close dialog and apply settings&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Apply - &lt;/span&gt;apply settings but leave dialog open&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cancel - &lt;/span&gt;close dialog and discard changes not yet applied&lt;br&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Reset -&lt;/span&gt; reload settings discarding changes not yet applied&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+       <property name="standardButtons">
+        <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>octave::shortcuts_tree_widget</class>
+   <extends>QTreeWidget</extends>
+   <header>shortcuts-tree-widget.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections>
   <connection>
--- a/libgui/src/shortcut-manager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,798 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2014-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// 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 <QApplication>
-#include <QCheckBox>
-#include <QDebug>
-#include <QDialogButtonBox>
-#include <QFileDialog>
-#include <QGridLayout>
-#include <QHeaderView>
-#include <QKeySequence>
-#include <QLineEdit>
-#include <QMessageBox>
-#include <QPushButton>
-#include <QVBoxLayout>
-#include <QtCore>
-
-#include "octave-qobject.h"
-#include "shortcut-manager.h"
-#include "gui-preferences-global.h"
-#include "gui-preferences-sc.h"
-#include "error.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-// enter_shortcut:
-// class derived from QLineEdit for directly entering key sequences which
-
-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
-void enter_shortcut::keyPressEvent (QKeyEvent *e)
-{
-  if (! m_direct_shortcut)
-    {
-      QLineEdit::keyPressEvent (e);
-      return;
-    }
-
-  if (e->type () == QEvent::KeyPress)
-    {
-      int key = e->key ();
-
-      if (key == Qt::Key_unknown || key == 0)
-        return;
-
-      Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();
-
-      if (m_shift_modifier || (modifiers & Qt::ShiftModifier))
-        key += Qt::SHIFT;
-      if (modifiers & Qt::ControlModifier)
-        key += Qt::CTRL;
-      if (modifiers & Qt::AltModifier)
-        key += Qt::ALT;
-      if (modifiers & Qt::MetaModifier)
-        key += Qt::META;
-
-      setText (QKeySequence (key).toString ());
-    }
-}
-
-// slot for checkbox whether the shortcut is directly entered or not
-void enter_shortcut::handle_direct_shortcut (int state)
-{
-  if (state)
-    m_direct_shortcut = true;  // the shortcut is directly entered
-  else
-    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 (base_qobject& oct_qobj)
-  : m_octave_qobj (oct_qobj)
-{
-  setObjectName ("Shortcut_Manager");
-
-  // Mac: don't let Qt interpret CMD key ("Meta" in Qt terminology) as Ctrl
-#if defined (Q_OS_MAC)
-  QCoreApplication::setAttribute (Qt::AA_MacDontSwapCtrlAndMeta, true);
-#endif
-}
-
-void shortcut_manager::init_data (void)
-{
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  settings->setValue (sc_main_ctrld.key, false); // reset use fo ctrl-d
-
-  // actions not related to specific menus or widgets
-
-  // dock widgets
-  init (tr ("Undock/Dock Widget"), sc_dock_widget_dock);
-  init (tr ("Close Widget"), sc_dock_widget_close);
-
-  // actions of the main window
-
-  // file
-  init (tr ("New File"), sc_main_file_new_file);
-  init (tr ("New Function"), sc_main_file_new_function);
-  init (tr ("New Figure"), sc_main_file_new_figure);
-  init (tr ("Open File"), sc_main_file_open_file);
-  init (tr ("Load Workspace"), sc_main_file_load_workspace);
-  init (tr ("Save Workspace As"), sc_main_file_save_workspace);
-  init (tr ("Exit Octave"), sc_main_file_exit);
-
-  // edit
-  init (tr ("Copy"), sc_main_edit_copy);
-  init (tr ("Paste"), sc_main_edit_paste);
-  init (tr ("Undo"), sc_main_edit_undo);
-  init (tr ("Select All"), sc_main_edit_select_all);
-  init (tr ("Clear Clipboard"), sc_main_edit_clear_clipboard);
-  init (tr ("Find in Files"), sc_main_edit_find_in_files);
-  init (tr ("Clear Command Window"), sc_main_edit_clear_command_window);
-  init (tr ("Clear Command History"), sc_main_edit_clear_history);
-  init (tr ("Clear Workspace"), sc_main_edit_clear_workspace);
-  init (tr ("Set Path"), sc_main_edit_set_path);
-  init (tr ("Preferences"), sc_main_edit_preferences);
-
-  // debug
-  init (tr ("Step"), sc_main_debug_step_over);
-  init (tr ("Step Into"), sc_main_debug_step_into);
-  init (tr ("Step Out"), sc_main_debug_step_out);
-  init (tr ("Continue"), sc_main_debug_continue);
-  init (tr ("Quit Debug Mode"), sc_main_debug_quit);
-
-  // tools
-  init (tr ("Start/Stop Profiler Session"), sc_main_tools_start_profiler);
-  init (tr ("Resume Profiler Session"), sc_main_tools_resume_profiler);
-  init (tr ("Show Profile Data"), sc_main_tools_show_profiler);
-
-  // window
-  init (tr ("Show Command Window"), sc_main_window_show_command);
-  init (tr ("Show Command History"), sc_main_window_show_history);
-  init (tr ("Show File Browser"), sc_main_window_show_file_browser);
-  init (tr ("Show Workspace"), sc_main_window_show_workspace);
-  init (tr ("Show Editor"), sc_main_window_show_editor);
-  init (tr ("Show Documentation"), sc_main_window_show_doc);
-  init (tr ("Show Variable Editor"), sc_main_window_show_variable_editor);
-  init (tr ("Command Window"), sc_main_window_command);
-  init (tr ("Command History"), sc_main_window_history);
-  init (tr ("File Browser"), sc_main_window_file_browser);
-  init (tr ("Workspace"), sc_main_window_workspace);
-  init (tr ("Editor"), sc_main_window_editor);
-  init (tr ("Documentation"), sc_main_window_doc);
-  init (tr ("Variable Editor"), sc_main_window_variable_editor);
-  init (tr ("Previous Widget"), sc_main_window_previous_dock);
-  init (tr ("Reset Default Window Layout"), sc_main_window_reset);
-
-  // help
-  init (tr ("Show On-disk Documentation"), sc_main_help_ondisk_doc);
-  init (tr ("Show Online Documentation"), sc_main_help_online_doc);
-  init (tr ("Report Bug"), sc_main_help_report_bug);
-  init (tr ("Octave Packages"), sc_main_help_packages);
-  init (tr ("Contribute to Octave"), sc_main_help_contribute);
-  init (tr ("Octave Developer Resources"), sc_main_help_developer);
-  init (tr ("About Octave"), sc_main_help_about);
-
-  // news
-  init (tr ("Release Notes"), sc_main_news_release_notes);
-  init (tr ("Community News"), sc_main_news_community_news);
-
-  // Tab handling
-  // The following shortcuts are moved into a separate tab.  The key names
-  // are not changed, to preserve compatibility with older versions.
-  init (tr ("Close Tab"), sc_edit_file_close);
-  init (tr ("Close All Tabs"), sc_edit_file_close_all);
-  init (tr ("Close Other Tabs"), sc_edit_file_close_other);
-  init (tr ("Switch to Left Tab"), sc_edit_tabs_switch_left_tab);
-  init (tr ("Switch to Right Tab"), sc_edit_tabs_switch_right_tab);
-  init (tr ("Move Tab Left"), sc_edit_tabs_move_tab_left);
-  init (tr ("Move Tab Right"), sc_edit_tabs_move_tab_right);
-
-  // Zooming
-  init (tr ("Zoom In"), sc_edit_view_zoom_in);
-  init (tr ("Zoom Out"), sc_edit_view_zoom_out);
-#if defined (Q_OS_MAC)
-  init (tr ("Zoom Normal"), sc_edit_view_zoom_normal);
-#else
-  init (tr ("Zoom Normal"), sc_edit_view_zoom_normal);
-#endif
-
-  // actions of the editor
-
-  // file
-  init (tr ("Edit Function"), sc_edit_file_edit_function);
-  init (tr ("Save File"), sc_edit_file_save);
-  init (tr ("Save File As"), sc_edit_file_save_as);
-  init (tr ("Print"), sc_edit_file_print);
-
-  // edit
-  init (tr ("Redo"), sc_edit_edit_redo);
-  init (tr ("Cut"), sc_edit_edit_cut);
-  init (tr ("Find and Replace"), sc_edit_edit_find_replace);
-  init (tr ("Find Next"), sc_edit_edit_find_next);
-  init (tr ("Find Previous"), sc_edit_edit_find_previous);
-  init (tr ("Delete to Start of Word"), sc_edit_edit_delete_start_word);
-  init (tr ("Delete to End of Word"), sc_edit_edit_delete_end_word);
-  init (tr ("Delete to Start of Line"), sc_edit_edit_delete_start_line);
-  init (tr ("Delete to End of Line"), sc_edit_edit_delete_end_line);
-  init (tr ("Delete Line"), sc_edit_edit_delete_line);
-  init (tr ("Copy Line"), sc_edit_edit_copy_line);
-  init (tr ("Cut Line"), sc_edit_edit_cut_line);
-  init (tr ("Duplicate Selection/Line"), sc_edit_edit_duplicate_selection);
-  init (tr ("Transpose Line"), sc_edit_edit_transpose_line);
-  init (tr ("Show Completion List"), sc_edit_edit_completion_list);
-
-  init (tr ("Comment Selection"), sc_edit_edit_comment_selection);
-  init (tr ("Uncomment Selection"), sc_edit_edit_uncomment_selection);
-  init (tr ("Comment Selection (Choosing String)"), sc_edit_edit_comment_var_selection);
-  init (tr ("Uppercase Selection"), sc_edit_edit_upper_case);
-  init (tr ("Lowercase Selection"), sc_edit_edit_lower_case);
-
-#if defined (Q_OS_MAC)
-  init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection);
-  init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection);
-#else
-  init (tr ("Indent Selection Rigidly"), sc_edit_edit_indent_selection);
-  init (tr ("Unindent Selection Rigidly"), sc_edit_edit_unindent_selection);
-#endif
-  init (tr ("Indent Code"), sc_edit_edit_smart_indent_line_or_selection);
-
-  init (tr ("Convert Line Endings to Windows"), sc_edit_edit_conv_eol_winows);
-  init (tr ("Convert Line Endings to Unix"), sc_edit_edit_conv_eol_unix);
-  init (tr ("Convert Line Endings to Mac"), sc_edit_edit_conv_eol_mac);
-
-  init (tr ("Goto Line"), sc_edit_edit_goto_line);
-  init (tr ("Move to Matching Brace"), sc_edit_edit_move_to_brace);
-  init (tr ("Select to Matching Brace"), sc_edit_edit_select_to_brace);
-  init (tr ("Toggle Bookmark"), sc_edit_edit_toggle_bookmark);
-  init (tr ("Next Bookmark"), sc_edit_edit_next_bookmark);
-  init (tr ("Previous Bookmark"), sc_edit_edit_previous_bookmark);
-  init (tr ("Remove All Bookmark"), sc_edit_edit_remove_bookmark);
-
-  init (tr ("Preferences"), sc_edit_edit_preferences);
-  init (tr ("Styles Preferences"), sc_edit_edit_styles_preferences);
-
-  // view
-  init (tr ("Show Line Numbers"), sc_edit_view_show_line_numbers);
-  init (tr ("Show Whitespace Characters"), sc_edit_view_show_white_spaces);
-  init (tr ("Show Line Endings"), sc_edit_view_show_eol_chars);
-  init (tr ("Show Indentation Guides"), sc_edit_view_show_ind_guides);
-  init (tr ("Show Long Line Marker"), sc_edit_view_show_long_line);
-  init (tr ("Show Toolbar"), sc_edit_view_show_toolbar);
-  init (tr ("Show Statusbar"), sc_edit_view_show_statusbar);
-  init (tr ("Show Horizontal Scrollbar"), sc_edit_view_show_hscrollbar);
-  init (tr ("Sort Tabs Alphabetically"), sc_edit_view_sort_tabs);
-
-  // debug
-  init (tr ("Toggle Breakpoint"), sc_edit_debug_toggle_breakpoint);
-  init (tr ("Next Breakpoint"), sc_edit_debug_next_breakpoint);
-  init (tr ("Previous Breakpoint"), sc_edit_debug_previous_breakpoint);
-  init (tr ("Remove All Breakpoints"), sc_edit_debug_remove_breakpoints);
-
-  // run
-  init (tr ("Run File"), sc_edit_run_run_file);
-  init (tr ("Run Selection"), sc_edit_run_run_selection);
-
-  // help
-  init (tr ("Help on Keyword"), sc_edit_help_help_keyword);
-  init (tr ("Document on Keyword"), sc_edit_help_doc_keyword);
-
-  // Documentation browser
-  init (tr ("Go to Homepage"), sc_doc_go_home);
-  init (tr ("Go Back one Page"), sc_doc_go_back);
-  init (tr ("Go Forward one Page"), sc_doc_go_next);
-  init (tr ("Bookmark this Page"), sc_doc_bookmark);
-}
-
-// write one or all actual shortcut set(s) into a settings file
-void shortcut_manager::write_shortcuts (gui_settings *settings,
-                                        bool closing)
-{
-  bool sc_ctrld = false;
-
-  QString sc_main = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1);
-
-  for (int i = 0; i < m_sc.count (); i++)  // loop over all shortcuts
-    {
-      settings->setValue (sc_group + "/" + m_sc.at (i).m_settings_key,
-                          m_sc.at (i).m_actual_sc.toString ());
-      // special: check main-window for Ctrl-D (Terminal)
-      if (m_sc.at (i).m_settings_key.startsWith (sc_main)
-          && m_sc.at (i).m_actual_sc == QKeySequence (Qt::ControlModifier+Qt::Key_D))
-        sc_ctrld = true;
-    }
-
-  settings->setValue (sc_main_ctrld.key, sc_ctrld);
-
-  if (closing)
-    {
-      delete m_dialog;     // the dialog for key sequences can be removed now
-      m_dialog = nullptr;  // make sure it is zero again
-    }
-
-  settings->sync ();      // sync the settings file
-}
-
-void shortcut_manager::set_shortcut (QAction *action, const sc_pref& scpref,
-                                     bool enable)
-{
-  if (! enable)
-    {
-      // Disable => remove existing shortcut from the action
-      action->setShortcut (QKeySequence ());
-      return;
-    }
-
-  // Enable: Is the given key known? If yes, get the value from the
-  //         settings file and set it to the action
-  int index;
-
-  index = m_action_hash[scpref.key] - 1;
-
-  if (index > -1 && index < m_sc.count ())
-    {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
-      action->setShortcut (QKeySequence (settings->sc_value (scpref)));
-    }
-  else
-    qDebug () << "Key: " << scpref.key << " not found in m_action_hash";
-}
-
-void shortcut_manager::shortcut (QShortcut *sc, const sc_pref& scpref)
-{
-  int index;
-
-  index = m_action_hash[scpref.key] - 1;
-
-  if (index > -1 && index < m_sc.count ())
-    {
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
-      sc->setKey (QKeySequence (settings->sc_value (scpref)));
-    }
-  else
-    qDebug () << "Key: " << scpref.key << " not found in m_action_hash";
-}
-
-void shortcut_manager::fill_treewidget (QTreeWidget *tree_view)
-{
-  m_dialog = nullptr;
-  m_level_hash.clear ();
-
-  tree_view->header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
-
-  QTreeWidgetItem *main = new QTreeWidgetItem (tree_view);
-  main->setText (0, tr ("Global"));
-  main->setExpanded (true);
-  QTreeWidgetItem *main_file = new QTreeWidgetItem (main);
-  main_file->setText (0, tr ("File Menu"));
-  QTreeWidgetItem *main_edit = new QTreeWidgetItem (main);
-  main_edit->setText (0, tr ("Edit Menu"));
-  QTreeWidgetItem *main_debug = new QTreeWidgetItem (main);
-  main_debug->setText (0, tr ("Debug Menu"));
-  QTreeWidgetItem *main_tools = new QTreeWidgetItem (main);
-  main_tools->setText (0, tr ("Tools Menu"));
-  QTreeWidgetItem *main_window = new QTreeWidgetItem (main);
-  main_window->setText (0, tr ("Window Menu"));
-  QTreeWidgetItem *main_help = new QTreeWidgetItem (main);
-  main_help->setText (0, tr ("Help Menu"));
-  QTreeWidgetItem *main_news = new QTreeWidgetItem (main);
-  main_news->setText (0, tr ("News Menu"));
-  QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main);
-  main_dock_widgets->setText (0, tr ("Handling of Dock Widgets"));
-  QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main);
-  main_tabs->setText (0, tr ("Tab Handling in Dock Widgets"));
-  QTreeWidgetItem *main_find = new QTreeWidgetItem (main);
-  main_find->setText (0, tr ("Find & Replace in Dock Widgets"));
-  QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main);
-  main_zoom->setText (0, tr ("Zooming in Editor and Documentation"));
-
-  m_level_hash[sc_main_file]   = main_file;
-  m_level_hash[sc_main_edit]   = main_edit;
-  m_level_hash[sc_main_debug]   = main_debug;
-  m_level_hash[sc_main_tools]   = main_tools;
-  m_level_hash[sc_main_window]   = main_window;
-  m_level_hash[sc_main_help]   = main_help;
-  m_level_hash[sc_main_news]   = main_news;
-  m_level_hash[sc_dock_widget] = main_dock_widgets;
-  m_level_hash[sc_edit_tabs]   = main_tabs;
-  m_level_hash[sc_edit_find]   = main_find;
-  m_level_hash[sc_edit_zoom]   = main_zoom;
-
-  QTreeWidgetItem *editor = new QTreeWidgetItem (tree_view);
-  editor->setText (0, tr ("Editor"));
-  editor->setExpanded (true);
-  QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor);
-  editor_file->setText (0, tr ("File Menu"));
-  QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor);
-  editor_edit->setText (0, tr ("Edit Menu"));
-  QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor);
-  editor_view->setText (0, tr ("View Menu"));
-  QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor);
-  editor_debug->setText (0, tr ("Debug Menu"));
-  QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor);
-  editor_run->setText (0, tr ("Run Menu"));
-  QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor);
-  editor_help->setText (0, tr ("Help Menu"));
-
-  m_level_hash[sc_edit_file] = editor_file;
-  m_level_hash[sc_edit_edit] = editor_edit;
-  m_level_hash[sc_edit_view] = editor_view;
-  m_level_hash[sc_edit_debug] = editor_debug;
-  m_level_hash[sc_edit_run] = editor_run;
-  m_level_hash[sc_edit_help] = editor_help;
-
-  QTreeWidgetItem *doc = new QTreeWidgetItem (tree_view);
-  doc->setText (0, tr ("Documentation Viewer"));
-  doc->setExpanded (true);
-
-  QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc);
-  doc_browser->setText (0, tr ("Browser"));
-
-  m_level_hash[sc_doc] = doc_browser;
-
-  connect (tree_view, &QTreeWidget::itemDoubleClicked,
-           this, &shortcut_manager::handle_double_clicked);
-
-  for (int i = 0; i < m_sc.count (); i++)
-    {
-      shortcut_t sc = m_sc.at (i);
-
-      QTreeWidgetItem *section = m_level_hash[sc.m_settings_key.section (':', 0, 0)];
-
-      // handle sections which have changed and do not correspond to the
-      // previously defined keyname
-      if (section == editor_file)
-        {
-          // Closing tabs now in global tab handling section
-          if (sc.m_settings_key.contains (sc_edit_file_cl))
-            section = main_tabs;
-        }
-      if (section == editor_edit)
-        {
-          // Find & replace now in global file & replace handling section
-          if (sc.m_settings_key.contains (sc_edit_edit_find))
-            section = main_find;
-        }
-      if (section == editor_view)
-        {
-          // Zooming now in global zoom handling section
-          if (sc.m_settings_key.contains (sc_edit_view_zoom))
-            section = main_zoom;
-        }
-
-      QTreeWidgetItem *tree_item = new QTreeWidgetItem (section);
-
-      // set a slightly transparent foreground for default columns
-      QColor fg = QColor (tree_item->foreground (1).color ());
-      fg.setAlpha (128);
-      tree_item->setForeground (1, QBrush (fg));
-
-      // write the shortcuts
-      tree_item->setText (0, sc.m_description);
-      tree_item->setText (1, sc.m_default_sc.toString ());
-      tree_item->setText (2, sc.m_actual_sc.toString ());
-
-      m_item_index_hash[tree_item] = i + 1; // index+1 to avoid 0
-      m_index_item_hash[i] = tree_item;
-    }
-}
-
-// import or export of shortcut sets,
-// called from settings dialog when related buttons are clicked;
-// returns true on success, false otherwise
-bool
-shortcut_manager::import_export (int action)
-{
-  // ask to save the current shortcuts, maybe abort import
-  if (action == OSC_DEFAULT || action == OSC_IMPORT)
-    {
-      if (! overwrite_all_shortcuts ())
-        return false;
-    }
-
-  // get the filename to read or write the shortcuts,
-  // the default extension is .osc (octave shortcuts)
-  if (action != OSC_DEFAULT)
-    {
-      QString file;
-
-      // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-      int opts = 0;  // No options by default.
-      resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-      gui_settings *settings = rmgr.get_settings ();
-      if (! settings->value (global_use_native_dialogs).toBool ())
-        opts = QFileDialog::DontUseNativeDialog;
-
-      if (action == OSC_IMPORT)
-        file = QFileDialog::getOpenFileName (this,
-                                             tr ("Import shortcuts from file..."), QString (),
-                                             tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
-                                             nullptr, QFileDialog::Option (opts));
-      else if (action == OSC_EXPORT)
-        file = QFileDialog::getSaveFileName (this,
-                                             tr ("Export shortcuts to file..."), QString (),
-                                             tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
-                                             nullptr, QFileDialog::Option (opts));
-
-      if (file.isEmpty ())
-        return false;
-
-      gui_settings osc_settings (file, QSettings::IniFormat);
-
-      if (osc_settings.status () !=  QSettings::NoError)
-        {
-          qWarning () << tr ("Failed to open %1 as Octave shortcut file")
-            .arg (file);
-          return false;
-        }
-      else
-        {
-          if (action == OSC_IMPORT)
-            import_shortcuts (&osc_settings);   // import (special action)
-          else if (action == OSC_EXPORT)
-            write_shortcuts (&osc_settings, false); // export, (save settings)
-        }
-    }
-  else
-    {
-      import_shortcuts (nullptr);
-    }
-
-  return true;
-}
-
-void shortcut_manager::handle_double_clicked (QTreeWidgetItem *item, int col)
-{
-  if (col != 2)
-    return;
-
-  int i = m_item_index_hash[item];
-  if (i == 0)
-    return;  // top-level-item clicked
-
-  shortcut_dialog (i-1); // correct to index starting at 0
-}
-
-void shortcut_manager::shortcut_dialog_finished (int result)
-{
-  if (result == QDialog::Rejected)
-    return;
-
-  // check for duplicate
-  int double_index = m_shortcut_hash[m_edit_actual->text ()] - 1;
-
-  if (double_index >= 0 && double_index != m_handled_index)
-    {
-      int ret = QMessageBox::warning (this, tr ("Double Shortcut"),
-                                      tr ("The chosen shortcut\n  \"%1\"\n"
-                                          "is already used for the action\n  \"%2\".\n"
-                                          "Do you want to use the shortcut anyhow removing it "
-                                          "from the previous action?")
-                                      .arg (m_edit_actual->text ())
-                                      .arg (m_sc.at (double_index).m_description),
-                                      QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
-
-      if (ret == QMessageBox::Yes)
-        {
-          shortcut_t double_shortcut = m_sc.at (double_index);
-          double_shortcut.m_actual_sc = QKeySequence ();
-          m_sc.replace (double_index, double_shortcut);
-          m_index_item_hash[double_index]->setText (2, QString ());
-        }
-      else
-        return;
-    }
-
-  shortcut_t shortcut = m_sc.at (m_handled_index);
-  if (! shortcut.m_actual_sc.isEmpty ())
-    m_shortcut_hash.remove (shortcut.m_actual_sc.toString ());
-  shortcut.m_actual_sc = m_edit_actual->text ();
-  m_sc.replace (m_handled_index, shortcut);
-
-  m_index_item_hash[m_handled_index]->setText (2, shortcut.m_actual_sc.toString ());
-
-  if (! shortcut.m_actual_sc.isEmpty ())
-    m_shortcut_hash[shortcut.m_actual_sc.toString ()] = m_handled_index + 1;
-}
-
-void shortcut_manager::shortcut_dialog_set_default (void)
-{
-  m_edit_actual->setText (m_label_default->text ());
-}
-
-void shortcut_manager::init (const QString& description, const sc_pref& sc)
-{
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-
-  QKeySequence actual = QKeySequence (settings->sc_value (sc));
-
-  // append the new shortcut to the list
-  shortcut_t shortcut_info;
-  shortcut_info.m_description = description;
-  shortcut_info.m_settings_key = sc.key;
-  shortcut_info.m_actual_sc = actual;
-  shortcut_info.m_default_sc = settings->sc_def_value (sc);
-  m_sc << shortcut_info;
-
-  // insert shortcut in order to check for duplicates later
-  if (! actual.isEmpty ())
-    m_shortcut_hash[actual.toString ()] = m_sc.count ();
-  m_action_hash[sc.key] = m_sc.count ();
-
-  // check whether ctrl+d is used from main window, i.e. is a global shortcut
-  QString main_group_prefix
-    = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1);
-  if (sc.key.startsWith (main_group_prefix)
-      && actual == QKeySequence (Qt::ControlModifier+Qt::Key_D))
-    settings->setValue (sc_main_ctrld.key, true);
-}
-
-void shortcut_manager::shortcut_dialog (int index)
-{
-  if (! m_dialog)
-    {
-      m_dialog = new QDialog (this);
-
-      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 "
-                                     "shortcut to its default."));
-      help->setWordWrap (true);
-      box->addWidget (help);
-
-      QCheckBox *direct
-        = new QCheckBox (tr ("Enter shortcut directly by performing it"));
-
-      QCheckBox *shift
-        = new QCheckBox (tr ("Add Shift modifier\n"
-                             "(allows one to enter number keys)"));
-
-      shift->setStyleSheet
-        ("QCheckBox::indicator { subcontrol-position: left top; }");
-
-      connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled);
-
-      direct->setCheckState (Qt::Checked);
-
-      box->addWidget (direct);
-      box->addWidget (shift);
-
-      box->addSpacing (15);
-
-      QGridLayout *grid = new QGridLayout ();
-
-      QLabel *actual = new QLabel (tr ("Actual shortcut"));
-      m_edit_actual = new enter_shortcut (m_dialog);
-      m_edit_actual->setAlignment (Qt::AlignHCenter);
-      grid->addWidget (actual, 0, 0);
-      grid->addWidget (m_edit_actual, 0, 1);
-
-      QLabel *def = new QLabel (tr ("Default shortcut"));
-      m_label_default = new QLabel (m_dialog);
-      m_label_default->setAlignment (Qt::AlignHCenter);
-      grid->addWidget (def, 1, 0);
-      grid->addWidget (m_label_default, 1, 1);
-
-      QPushButton *set_default = new QPushButton (tr ("Set to default"));
-      grid->addWidget (set_default, 0, 2);
-      connect (set_default, &QPushButton::clicked,
-               this, &shortcut_manager::shortcut_dialog_set_default);
-
-      box->addLayout (grid);
-
-      box->addSpacing (18);
-
-      QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok
-                                                           | QDialogButtonBox::Cancel);
-      QList<QAbstractButton *> buttons = button_box->buttons ();
-      for (int i = 0; i < buttons.count (); i++)
-        buttons.at (i)->setShortcut (QKeySequence ());
-      connect (button_box, &QDialogButtonBox::accepted,
-               m_dialog, &QDialog::accept);
-      connect (button_box, &QDialogButtonBox::rejected,
-               m_dialog, &QDialog::reject);
-      box->addWidget (button_box);
-
-      m_dialog->setLayout (box);
-
-      connect (direct, &QCheckBox::stateChanged,
-               m_edit_actual, &enter_shortcut::handle_direct_shortcut);
-      connect (shift, &QCheckBox::stateChanged,
-               m_edit_actual, &enter_shortcut::handle_shift_modifier);
-      connect (m_dialog, &QDialog::finished,
-               this, &shortcut_manager::shortcut_dialog_finished);
-
-    }
-
-  m_edit_actual->setText (m_sc.at (index).m_actual_sc.toString ());
-  m_label_default->setText (m_sc.at (index).m_default_sc.toString ());
-  m_handled_index = index;
-
-  m_edit_actual->setFocus ();
-  m_dialog->setFocusProxy (m_edit_actual);
-  m_dialog->exec ();
-}
-
-// import a shortcut set from a given settings file or reset to
-// the defaults (settings = 0) and refresh the tree view
-void shortcut_manager::import_shortcuts (gui_settings *settings)
-{
-  for (int i = 0; i < m_sc.count (); i++)
-    {
-      // update the list of all shortcuts
-      shortcut_t sc = m_sc.at (i);           // make a copy
-
-      if (settings)
-        sc.m_actual_sc = QKeySequence (         // get new shortcut from settings
-                                       settings->value (sc_group + sc.m_settings_key,sc.m_actual_sc).
-                                       toString ());       // and use the old one as default
-      else
-        sc.m_actual_sc = QKeySequence (sc.m_default_sc); // get default shortcut
-
-      m_sc.replace (i, sc);                  // replace the old with the new one
-
-      // update the tree view
-      QTreeWidgetItem *tree_item = m_index_item_hash[i]; // get related tree item
-      tree_item->setText (2, sc.m_actual_sc.toString ()); // display new shortcut
-    }
-}
-
-// ask the user whether to save the current shortcut set;
-// returns true to proceed with import action, false to abort it
-bool shortcut_manager::overwrite_all_shortcuts (void)
-{
-  QMessageBox msg_box;
-  msg_box.setWindowTitle (tr ("Overwriting Shortcuts"));
-  msg_box.setIcon (QMessageBox::Warning);
-  msg_box.setText (tr ("You are about to overwrite all shortcuts.\n"
-                       "Would you like to save the current shortcut set or cancel the action?"));
-  msg_box.setStandardButtons (QMessageBox::Save | QMessageBox::Cancel);
-  QPushButton *discard = msg_box.addButton (tr ("Don't save"),
-                                            QMessageBox::DestructiveRole);
-  msg_box.setDefaultButton (QMessageBox::Save);
-
-  int ret = msg_box.exec ();
-
-  if (msg_box.clickedButton () == discard)
-    return true;  // do not save and go ahead
-
-  if (ret == QMessageBox::Save)
-    {
-      if (import_export (OSC_EXPORT))
-        return true;  // go ahead
-    }
-
-  return false; // abort the import
-}
-
-OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/shortcut-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2014-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// 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_shortcut_manager_h)
-#define octave_shortcut_manager_h 1
-
-#include <QKeyEvent>
-#include <QLabel>
-#include <QLineEdit>
-#include <QShortcut>
-#include <QTreeWidget>
-#include <QWidget>
-
-#include "gui-settings.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-class enter_shortcut : public QLineEdit
-{
-  Q_OBJECT
-
-public:
-
-  enter_shortcut (QWidget *p = nullptr);
-
-  ~enter_shortcut (void) = default;
-
-  virtual void keyPressEvent (QKeyEvent *e);
-
-public slots:
-
-  void handle_direct_shortcut (int);
-  void handle_shift_modifier (int);
-
-private:
-
-  bool m_direct_shortcut;
-  bool m_shift_modifier;
-
-};
-
-class base_qobject;
-
-class shortcut_manager : public QWidget
-{
-  Q_OBJECT
-
-public:
-
-  enum
-    {
-      OSC_IMPORT  = 0,
-      OSC_EXPORT  = 1,
-      OSC_DEFAULT = 2
-    };
-
-  shortcut_manager (base_qobject& oct_qobj);
-
-  // No copying!
-
-  shortcut_manager (const shortcut_manager&) = delete;
-
-  shortcut_manager& operator = (const shortcut_manager&) = delete;
-
-  ~shortcut_manager (void) = default;
-
-  void init_data (void);
-
-  void write_shortcuts (gui_settings *settings, bool closing);
-
-  void set_shortcut (QAction *action, const sc_pref& scpref, bool enable = true);
-
-  void shortcut (QShortcut *sc, const sc_pref& scpref);
-
-  void fill_treewidget (QTreeWidget *tree_view);
-
-  bool import_export (int action);
-
-protected slots:
-
-  void handle_double_clicked (QTreeWidgetItem *, int);
-  void shortcut_dialog_finished (int);
-  void shortcut_dialog_set_default ();
-
-private:
-
-  void init (const QString&, const sc_pref& scpref);
-  void shortcut_dialog (int);
-  void import_shortcuts (gui_settings *settings);
-  bool overwrite_all_shortcuts (void);
-
-  class shortcut_t
-  {
-  public:
-
-    shortcut_t (void)
-      : m_tree_item (nullptr), m_description (), m_settings_key (),
-        m_actual_sc (QKeySequence ()), m_default_sc (QKeySequence ())
-    { }
-
-    shortcut_t (const shortcut_t& x)
-      : m_tree_item (x.m_tree_item), m_description (x.m_description),
-        m_settings_key (x.m_settings_key)
-    {
-      m_actual_sc = x.m_actual_sc;
-      m_default_sc = x.m_default_sc;
-    }
-
-    shortcut_t& operator = (const shortcut_t& x)
-    {
-      if (&x != this)
-        {
-          m_tree_item = x.m_tree_item;
-          m_description = x.m_description;
-          m_settings_key = x.m_settings_key;
-
-          m_actual_sc = QKeySequence ();
-          m_default_sc = QKeySequence ();
-
-          m_actual_sc = x.m_actual_sc;
-          m_default_sc = x.m_default_sc;
-        }
-
-      return *this;
-    }
-
-    ~shortcut_t (void) = default;
-
-    QTreeWidgetItem *m_tree_item;
-    QString m_description;
-    QString m_settings_key;
-    QKeySequence m_actual_sc;
-    QKeySequence m_default_sc;
-  };
-
-  base_qobject& m_octave_qobj;
-
-  QList<shortcut_t> m_sc;
-  QHash<QString, int> m_shortcut_hash;
-  QHash<QString, int> m_action_hash;
-  QHash <QString, QTreeWidgetItem *> m_level_hash;
-  QHash<int, QTreeWidgetItem *> m_index_item_hash;
-  QHash<QTreeWidgetItem *, int> m_item_index_hash;
-
-  QDialog *m_dialog;
-  enter_shortcut *m_edit_actual;
-  QLabel *m_label_default;
-  int m_handled_index;
-};
-
-OCTAVE_END_NAMESPACE(octave)
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/shortcuts-tree-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,712 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2014-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <QApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QHeaderView>
+#include <QKeyEvent>
+#include <QLabel>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+#include "gui-preferences-sc.h"
+#include "gui-settings.h"
+#include "shortcuts-tree-widget.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+// enter_shortcut:
+// class derived from QLineEdit for directly entering key sequences which
+
+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
+void enter_shortcut::keyPressEvent (QKeyEvent *e)
+{
+  if (! m_direct_shortcut)
+    {
+      QLineEdit::keyPressEvent (e);
+      return;
+    }
+
+  if (e->type () == QEvent::KeyPress)
+    {
+      int key = e->key ();
+
+      if (key == Qt::Key_unknown || key == 0)
+        return;
+
+      Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();
+
+      if (m_shift_modifier || (modifiers & Qt::ShiftModifier))
+        key |= Qt::SHIFT;
+      if (modifiers & Qt::ControlModifier)
+        key |= Qt::CTRL;
+      if (modifiers & Qt::AltModifier)
+        key |= Qt::ALT;
+      if (modifiers & Qt::MetaModifier)
+        key |= Qt::META;
+
+      setText (QKeySequence (key).toString ());
+    }
+}
+
+// slot for checkbox whether the shortcut is directly entered or not
+void enter_shortcut::handle_direct_shortcut (int state)
+{
+  if (state)
+    m_direct_shortcut = true;  // the shortcut is directly entered
+  else
+    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
+}
+
+tree_widget_shortcut_item::tree_widget_shortcut_item
+(QTreeWidgetItem *parent, const sc_pref& scpref, const QString& actual_text)
+  : QTreeWidgetItem (parent), m_settings_key (scpref.settings_key ())
+{
+  // set a slightly transparent foreground for default columns
+  QColor fg = QColor (foreground (DEFAULT_COLUMN).color ());
+  fg.setAlpha (128);
+  setForeground (DEFAULT_COLUMN, QBrush (fg));
+
+  // write the shortcuts
+  set_description (scpref.description ());
+  set_default_text (scpref.def_text ());
+  set_actual_text (actual_text);
+}
+
+QString tree_widget_shortcut_item::settings_key () const
+{
+  return m_settings_key;
+}
+
+QString tree_widget_shortcut_item::description () const
+{
+  return text (DESCRIPTION_COLUMN);
+}
+
+void tree_widget_shortcut_item::set_description (const QString& text)
+{
+  setText (DESCRIPTION_COLUMN, text);
+}
+
+QString tree_widget_shortcut_item::default_text () const
+{
+  return text (DEFAULT_COLUMN);
+}
+
+void tree_widget_shortcut_item::set_default_text (const QString& text)
+{
+  setText (DEFAULT_COLUMN, text);
+}
+
+QString tree_widget_shortcut_item::actual_text () const
+{
+  return text (ACTUAL_COLUMN);
+}
+
+void tree_widget_shortcut_item::set_actual_text (const QString& text)
+{
+  setText (ACTUAL_COLUMN, text);
+}
+
+shortcut_edit_dialog::shortcut_edit_dialog
+  (tree_widget_shortcut_item *shortcut_item, QWidget *parent)
+  : QDialog (parent), m_shortcut_item (shortcut_item),
+    m_settings_key (shortcut_item->settings_key ())
+{
+  setAttribute (Qt::WA_DeleteOnClose);
+
+  setWindowTitle (tr ("Enter new Shortcut"));
+
+  QVBoxLayout *box = new QVBoxLayout (this);
+
+  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 "
+                                 "shortcut to its default. (%1)")
+                             .arg (m_settings_key));
+
+  help->setWordWrap (true);
+
+  box->addWidget (help);
+
+  QCheckBox *direct
+    = new QCheckBox (tr ("Enter shortcut directly by performing it"));
+
+  QCheckBox *shift
+    = new QCheckBox (tr ("Add Shift modifier\n"
+                         "(allows one to enter number keys)"));
+
+  shift->setStyleSheet
+    ("QCheckBox::indicator { subcontrol-position: left top; }");
+
+  connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled);
+
+  direct->setCheckState (Qt::Checked);
+
+  box->addWidget (direct);
+  box->addWidget (shift);
+
+  box->addSpacing (15);
+
+  QGridLayout *grid = new QGridLayout ();
+
+  QLabel *actual = new QLabel (tr ("Actual shortcut"));
+
+  m_edit_actual = new enter_shortcut (this);
+  m_edit_actual->setAlignment (Qt::AlignHCenter);
+
+  grid->addWidget (actual, 0, 0);
+  grid->addWidget (m_edit_actual, 0, 1);
+
+  QLabel *def = new QLabel (tr ("Default shortcut"));
+
+  QLabel *label_default = new QLabel (this);
+  label_default->setAlignment (Qt::AlignHCenter);
+
+  grid->addWidget (def, 1, 0);
+  grid->addWidget (label_default, 1, 1);
+
+  QPushButton *set_default = new QPushButton (tr ("Set to default"));
+
+  connect (set_default, &QPushButton::clicked,
+           this, &shortcut_edit_dialog::set_default_shortcut);
+
+  grid->addWidget (set_default, 0, 2);
+
+  box->addLayout (grid);
+  box->addSpacing (18);
+
+  QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok
+                                                       | QDialogButtonBox::Cancel);
+  QList<QAbstractButton *> buttons = button_box->buttons ();
+  for (int i = 0; i < buttons.count (); i++)
+    buttons.at (i)->setShortcut (QKeySequence ());
+
+  connect (button_box, &QDialogButtonBox::accepted,
+           this, &QDialog::accept);
+
+  connect (button_box, &QDialogButtonBox::rejected,
+           this, &QDialog::reject);
+
+  box->addWidget (button_box);
+
+  setLayout (box);
+
+  connect (direct, &QCheckBox::stateChanged,
+           m_edit_actual, &enter_shortcut::handle_direct_shortcut);
+
+  connect (shift, &QCheckBox::stateChanged,
+           m_edit_actual, &enter_shortcut::handle_shift_modifier);
+
+  connect (this, &QDialog::finished,
+           this, &shortcut_edit_dialog::finished);
+
+  gui_settings settings;
+
+  const sc_pref scpref = all_shortcut_preferences::value (m_settings_key);
+
+  QString actual_text = settings.sc_value (scpref);
+
+  m_default_text = scpref.def_text ();
+
+  m_edit_actual->setText (actual_text);
+  label_default->setText (m_default_text);
+
+  m_edit_actual->setFocus ();
+
+  setFocusProxy (m_edit_actual);
+}
+
+void shortcut_edit_dialog::finished (int result)
+{
+  if (result == QDialog::Rejected)
+    return;
+
+  // Check whether the chosen shortcut is already in use either in the
+  // current context (section of the shortcut settings) or as a global
+  // (main_) shortcut.  This job might have been easier if we had
+  // organized the sections as child groups instead of using a colon in
+  // the settings key to separate the section from the shortcut name.
+
+ // Note that m_settings_key doesn't begin with the sc_group prefix.
+
+  QString my_section = get_shortcut_section (m_settings_key);
+  QString actual_text = m_edit_actual->text ();
+
+  bool conflict = false;
+  QString other_settings_key;
+
+  gui_settings settings;
+
+  settings.beginGroup (sc_group);
+  const QStringList shortcut_settings_keys = settings.allKeys ();
+  settings.endGroup ();
+
+  for (const auto& settings_key : shortcut_settings_keys)
+    {
+      if (settings_key == m_settings_key)
+        continue;
+
+      QString section = get_shortcut_section (settings_key);
+
+      if (section == my_section || section.startsWith ("main_"))
+        {
+          QString shortcut_text
+            = settings.value (sc_group + "/" + settings_key).toString ();
+
+          if (shortcut_text == actual_text)
+            {
+              other_settings_key = settings_key;
+              conflict = true;
+            }
+        }
+    }
+
+  if (conflict)
+    {
+      // We only need the description of the other shortcut, not the
+      // complete sc_pref info.
+
+      const sc_pref other_scpref
+        = all_shortcut_preferences::value (other_settings_key);
+
+      int ret = QMessageBox::warning (this, tr ("Double Shortcut"),
+                                      tr ("The chosen shortcut\n  \"%1\"\n"
+                                          "is already used for the action\n  \"%2\".\n"
+                                          "Do you want to use the shortcut and remove it "
+                                          "from the previous action?")
+                                      .arg (actual_text)
+                                      .arg (other_scpref.description ()),
+                                      QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+      if (ret == QMessageBox::Yes)
+        emit set_shortcut (other_settings_key, "");
+      else
+        return;
+    }
+
+  m_shortcut_item->set_actual_text (actual_text);
+}
+
+void shortcut_edit_dialog::set_default_shortcut ()
+{
+  // Just remove user-set value so that the default will be used.
+  m_edit_actual->setText ("");
+}
+
+shortcuts_tree_widget::shortcuts_tree_widget (QWidget *parent)
+  : QTreeWidget (parent)
+{
+  QHash <QString, QTreeWidgetItem *> level_hash;
+
+  header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
+
+  int dsc_col = tree_widget_shortcut_item::DESCRIPTION_COLUMN;
+
+  QTreeWidgetItem *main = new QTreeWidgetItem (this);
+  main->setText (dsc_col, tr ("Global"));
+  main->setExpanded (true);
+
+  QTreeWidgetItem *main_file = new QTreeWidgetItem (main);
+  main_file->setText (dsc_col, tr ("File Menu"));
+
+  QTreeWidgetItem *main_edit = new QTreeWidgetItem (main);
+  main_edit->setText (dsc_col, tr ("Edit Menu"));
+
+  QTreeWidgetItem *main_debug = new QTreeWidgetItem (main);
+  main_debug->setText (dsc_col, tr ("Debug Menu"));
+
+  QTreeWidgetItem *main_tools = new QTreeWidgetItem (main);
+  main_tools->setText (dsc_col, tr ("Tools Menu"));
+
+  QTreeWidgetItem *main_window = new QTreeWidgetItem (main);
+  main_window->setText (dsc_col, tr ("Window Menu"));
+
+  QTreeWidgetItem *main_help = new QTreeWidgetItem (main);
+  main_help->setText (dsc_col, tr ("Help Menu"));
+
+  QTreeWidgetItem *main_news = new QTreeWidgetItem (main);
+  main_news->setText (dsc_col, tr ("News Menu"));
+
+  QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main);
+  main_dock_widgets->setText (dsc_col, tr ("Handling of Dock Widgets"));
+
+  QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main);
+  main_tabs->setText (dsc_col, tr ("Tab Handling in Dock Widgets"));
+
+  QTreeWidgetItem *main_find = new QTreeWidgetItem (main);
+  main_find->setText (dsc_col, tr ("Find & Replace in Dock Widgets"));
+
+  QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main);
+  main_zoom->setText (dsc_col, tr ("Zooming in Editor and Documentation"));
+
+  level_hash[sc_main_file] = main_file;
+  level_hash[sc_main_edit] = main_edit;
+  level_hash[sc_main_debug] = main_debug;
+  level_hash[sc_main_tools] = main_tools;
+  level_hash[sc_main_window] = main_window;
+  level_hash[sc_main_help] = main_help;
+  level_hash[sc_main_news] = main_news;
+  level_hash[sc_dock_widget] = main_dock_widgets;
+  level_hash[sc_edit_tabs] = main_tabs;
+  level_hash[sc_edit_find] = main_find;
+  level_hash[sc_edit_zoom] = main_zoom;
+
+  QTreeWidgetItem *editor = new QTreeWidgetItem (this);
+  editor->setText (dsc_col, tr ("Editor"));
+  editor->setExpanded (true);
+
+  QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor);
+  editor_file->setText (dsc_col, tr ("File Menu"));
+
+  QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor);
+  editor_edit->setText (dsc_col, tr ("Edit Menu"));
+
+  QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor);
+  editor_view->setText (dsc_col, tr ("View Menu"));
+
+  QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor);
+  editor_debug->setText (dsc_col, tr ("Debug Menu"));
+
+  QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor);
+  editor_run->setText (dsc_col, tr ("Run Menu"));
+
+  QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor);
+  editor_help->setText (dsc_col, tr ("Help Menu"));
+
+  level_hash[sc_edit_file] = editor_file;
+  level_hash[sc_edit_edit] = editor_edit;
+  level_hash[sc_edit_view] = editor_view;
+  level_hash[sc_edit_debug] = editor_debug;
+  level_hash[sc_edit_run] = editor_run;
+  level_hash[sc_edit_help] = editor_help;
+
+  QTreeWidgetItem *doc = new QTreeWidgetItem (this);
+  doc->setText (dsc_col, tr ("Documentation Viewer"));
+  doc->setExpanded (true);
+
+  QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc);
+  doc_browser->setText (dsc_col, tr ("Browser"));
+
+  level_hash[sc_doc] = doc_browser;
+
+  connect (this, &QTreeWidget::itemDoubleClicked,
+           this, &shortcuts_tree_widget::edit_selection);
+
+  const QList<QString> shortcut_settings_keys
+    = all_shortcut_preferences::keys ();
+
+  gui_settings settings;
+
+  settings.beginGroup (sc_group);
+
+  for (const auto& settings_key : shortcut_settings_keys)
+    {
+      QTreeWidgetItem *section = level_hash[settings_key.section (':', 0, 0)];
+
+      // handle sections which have changed and do not correspond to the
+      // previously defined keyname
+      if (section == editor_file)
+        {
+          // Closing tabs now in global tab handling section
+          if (settings_key.contains (sc_edit_file_cl))
+            section = main_tabs;
+        }
+      else if (section == editor_edit)
+        {
+          // Find & replace now in global file & replace handling section
+          if (settings_key.contains (sc_edit_edit_find))
+            section = main_find;
+        }
+      else if (section == editor_view)
+        {
+          // Zooming now in global zoom handling section
+          if (settings_key.contains (sc_edit_view_zoom))
+            section = main_zoom;
+        }
+
+      // We don't want to apply default value here.
+      QString actual_text = settings.value (settings_key).toString ();
+
+      const sc_pref scpref = all_shortcut_preferences::value (settings_key);
+
+      // Inserts itself in the tree widget in SECTION.  The parent
+      // object will delete it.
+      new tree_widget_shortcut_item (section, scpref, actual_text);
+    }
+
+  settings.endGroup ();
+}
+
+void
+shortcuts_tree_widget::edit_selection (QTreeWidgetItem *item, int col)
+{
+  if (col != 2)
+    return;
+
+  tree_widget_shortcut_item *shortcut_item
+    = dynamic_cast<tree_widget_shortcut_item *> (item);
+
+  if (! shortcut_item)
+    return;  // top-level-item clicked
+
+  shortcut_edit_dialog *dialog
+    = new shortcut_edit_dialog (shortcut_item);
+
+  connect (dialog, &shortcut_edit_dialog::set_shortcut,
+           this, &shortcuts_tree_widget::update_widget_value);
+
+  dialog->show ();
+}
+
+void shortcuts_tree_widget::update_widget_value (const QString& settings_key,
+                                                 const QString& sc_text)
+{
+  tree_widget_shortcut_item *item = get_item (settings_key);
+
+  if (item)
+    item->set_actual_text (sc_text);
+}
+
+tree_widget_shortcut_item *
+shortcuts_tree_widget::get_item (const QString& settings_key)
+{
+  // There aren't many shortcuts so iterating over all of them to find
+  // an individual item isn't a big performance issue.  If we had many
+  // more items we could use a QHash <settings_key, sc_pref> data member.
+
+  tree_widget_shortcut_item *item = nullptr;
+
+  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
+  while (*it)
+    {
+      tree_widget_shortcut_item *shortcut_item
+        = dynamic_cast<tree_widget_shortcut_item *> (*it);
+
+      if (settings_key == shortcut_item->settings_key ())
+        {
+          item = shortcut_item;
+          break;
+        }
+
+      it++;
+    }
+
+  // FIXME: Should it be an error to not find a match?
+
+  if (! item)
+    qWarning () << (tr ("item %1 not found in shortcut settings dialog")
+                    .arg (settings_key));
+
+  return item;
+}
+
+void shortcuts_tree_widget::update_settings_value (gui_settings& settings,
+                                                   const QString& settings_key)
+{
+  tree_widget_shortcut_item *item = get_item (settings_key);
+
+  if (item)
+    settings.setValue (settings_key, item->actual_text ());
+}
+
+// Refresh the tree view with values from the settings object.
+
+void shortcuts_tree_widget::import_shortcuts (gui_settings& settings)
+{
+  settings.beginGroup (sc_group);
+
+  const QStringList shortcut_settings_keys = settings.allKeys ();
+
+  for (const auto& settings_key : shortcut_settings_keys)
+    {
+      // We don't want to apply default value here.
+      QString sc_text = settings.value (settings_key).toString ();
+
+      update_widget_value (settings_key, sc_text);
+    }
+
+  settings.endGroup ();
+
+  bool sc_ctrld = false;
+
+  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
+  while (*it)
+    {
+      tree_widget_shortcut_item *shortcut_item
+        = dynamic_cast<tree_widget_shortcut_item *> (*it);
+
+      if (! shortcut_item)
+        continue;
+
+      QString settings_key = shortcut_item->settings_key ();
+      QString sc_text = shortcut_item->actual_text ();
+
+      if (sc_text.isEmpty ())
+        sc_text = shortcut_item->default_text ();
+
+      QString section = get_shortcut_section (settings_key);
+
+      // special: check main-window for Ctrl-D (Terminal)
+      if (section.startsWith ("main_")
+          && QKeySequence (sc_text)
+             == QKeySequence (Qt::ControlModifier | Qt::Key_D))
+
+        sc_ctrld = true;
+
+      it++;
+    }
+
+  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);
+
+  settings.sync ();
+}
+
+// Export all shortcuts from the tree view to the settings object.
+
+void shortcuts_tree_widget::export_shortcuts (gui_settings& settings)
+{
+  settings.beginGroup (sc_group);
+
+  bool sc_ctrld = false;
+
+  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
+  while (*it)
+    {
+      tree_widget_shortcut_item *shortcut_item
+        = dynamic_cast<tree_widget_shortcut_item *> (*it);
+
+      if (! shortcut_item)
+        continue;
+
+      QString settings_key = shortcut_item->settings_key ();
+      QString sc_text = shortcut_item->actual_text ();
+
+      if (sc_text.isEmpty ())
+        sc_text = shortcut_item->default_text ();
+      else
+        settings.setValue (settings_key, sc_text);
+
+      QString section = get_shortcut_section (settings_key);
+
+      // special: check main-window for Ctrl-D (Terminal)
+      if (section.startsWith ("main_")
+          && QKeySequence (sc_text)
+             == QKeySequence (Qt::ControlModifier | Qt::Key_D))
+
+        sc_ctrld = true;
+
+      it++;
+    }
+
+  settings.endGroup ();
+
+  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);
+
+  settings.sync ();
+}
+
+// Clear all user-defined settings from the tree widget and the
+// application settings.
+
+void shortcuts_tree_widget::set_default_shortcuts ()
+{
+  gui_settings settings;
+
+  settings.beginGroup (sc_group);
+
+  settings.remove ("");
+
+  settings.endGroup ();
+
+  bool sc_ctrld = false;
+
+  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
+  while (*it)
+    {
+      tree_widget_shortcut_item *shortcut_item
+        = dynamic_cast<tree_widget_shortcut_item *> (*it);
+
+      if (! shortcut_item)
+        continue;
+
+      QString settings_key = shortcut_item->settings_key ();
+
+      shortcut_item->set_actual_text ("");
+
+      QString sc_text = shortcut_item->default_text ();
+
+      QString section = get_shortcut_section (settings_key);
+
+      // special: check main-window for Ctrl-D (Terminal)
+      if (section.startsWith ("main_")
+          && QKeySequence (sc_text)
+             == QKeySequence (Qt::ControlModifier | Qt::Key_D))
+
+        sc_ctrld = true;
+
+      it++;
+    }
+
+  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);
+
+  settings.sync ();
+}
+
+// For each key found in application settings object, transfer
+// corresponding setting to the application settings object.
+
+void shortcuts_tree_widget::write_settings ()
+{
+  gui_settings settings;
+
+  export_shortcuts (settings);
+}
+
+OCTAVE_END_NAMESPACE(octave)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/shortcuts-tree-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,158 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2014-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_shortcuts_tree_widget_h)
+#define octave_shortcuts_tree_widget_h 1
+
+#include <QCheckBox>
+#include <QDialog>
+#include <QKeyEvent>
+#include <QLineEdit>
+#include <QString>
+#include <QTreeWidget>
+#include <QtCore>
+
+#include "gui-preferences.h"
+#include "gui-settings.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+class enter_shortcut : public QLineEdit
+{
+  Q_OBJECT
+
+public:
+
+  enter_shortcut (QWidget *p = nullptr);
+
+  ~enter_shortcut () = default;
+
+  virtual void keyPressEvent (QKeyEvent *e);
+
+public slots:
+
+  void handle_direct_shortcut (int);
+  void handle_shift_modifier (int);
+
+private:
+
+  bool m_direct_shortcut;
+  bool m_shift_modifier;
+};
+
+class tree_widget_shortcut_item : public QTreeWidgetItem
+{
+public:
+
+  enum
+  {
+    DESCRIPTION_COLUMN = 0,
+    DEFAULT_COLUMN,
+    ACTUAL_COLUMN
+  };
+
+  tree_widget_shortcut_item (QTreeWidgetItem *parent, const sc_pref& scpref,
+                             const QString& actual_text);
+
+  QString settings_key () const;
+
+  QString description () const;
+  void set_description (const QString& text);
+
+  QString default_text () const;
+  void set_default_text (const QString& text);
+
+  QString actual_text () const;
+  void set_actual_text (const QString& text);
+
+private:
+
+  QString m_settings_key;
+};
+
+class shortcut_edit_dialog : public QDialog
+{
+  Q_OBJECT
+
+public:
+
+  shortcut_edit_dialog (tree_widget_shortcut_item *shortcut_item,
+                        QWidget *parent = nullptr);
+
+public slots:
+
+  void finished (int result);
+
+  void set_default_shortcut ();
+
+signals:
+
+  void set_shortcut (const QString& settings_key,
+                     const QString& settings_value);
+
+private:
+
+  tree_widget_shortcut_item *m_shortcut_item;
+
+  enter_shortcut *m_edit_actual;
+
+  QString m_settings_key;
+  QString m_default_text;
+};
+
+class shortcuts_tree_widget : public QTreeWidget
+{
+  Q_OBJECT
+
+public:
+
+  shortcuts_tree_widget (QWidget *parent);
+
+  void import_shortcuts (gui_settings& settings);
+
+  void export_shortcuts (gui_settings& settings);
+
+  void set_default_shortcuts ();
+
+  void write_settings ();
+
+public slots:
+
+  void edit_selection (QTreeWidgetItem *item, int col);
+
+  void update_widget_value (const QString& settings_key,
+                            const QString& sc_text);
+
+private:
+
+  tree_widget_shortcut_item * get_item (const QString& settings_key);
+
+  void update_settings_value (gui_settings& settings,
+                              const QString& settings_key);
+};
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- a/libgui/src/tab-bar.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/tab-bar.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,22 +48,22 @@
 }
 
 // slots for tab navigation
-void tab_bar::switch_left_tab (void)
+void tab_bar::switch_left_tab ()
 {
   switch_tab (-1);
 }
 
-void tab_bar::switch_right_tab (void)
+void tab_bar::switch_right_tab ()
 {
   switch_tab (1);
 }
 
-void tab_bar::move_tab_left (void)
+void tab_bar::move_tab_left ()
 {
   switch_tab (-1, true);
 }
 
-void tab_bar::move_tab_right (void)
+void tab_bar::move_tab_right ()
 {
   switch_tab (1, true);
 }
@@ -91,7 +91,7 @@
     setCurrentIndex (new_pos);
 }
 
-void tab_bar::sort_tabs_alph (void)
+void tab_bar::sort_tabs_alph ()
 {
   QString current_title = tabText (currentIndex ());
   int tab_with_focus = 0;
--- a/libgui/src/tab-bar.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/tab-bar.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,10 +49,10 @@
 
   tab_bar (QWidget *p);
 
-  ~tab_bar (void) = default;
+  ~tab_bar () = default;
 
   void set_rotated (int rotated);
-  QMenu * get_context_menu (void) { return m_context_menu; };
+  QMenu * get_context_menu () { return m_context_menu; };
   QSize tabSizeHint (int idx) const;
 
 signals:
@@ -61,11 +61,11 @@
 
 public slots:
 
-  void switch_left_tab (void);
-  void switch_right_tab (void);
-  void move_tab_left (void);
-  void move_tab_right (void);
-  void sort_tabs_alph (void);
+  void switch_left_tab ();
+  void switch_right_tab ();
+  void move_tab_left ();
+  void move_tab_right ();
+  void sort_tabs_alph ();
 
 private slots:
 
--- a/libgui/src/terminal-dock-widget.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/terminal-dock-widget.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include <QGuiApplication>
 #include <QScreen>
 
 // This header is only needed for the new terminal widget.
@@ -39,23 +40,26 @@
 
 #include "gui-preferences-cs.h"
 #include "gui-preferences-global.h"
+#include "gui-preferences-sc.h"
+#include "gui-settings.h"
 
-#include "octave-qobject.h"
 #include "terminal-dock-widget.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 terminal_dock_widget::terminal_dock_widget (QWidget *p,
-                                            base_qobject& oct_qobj)
-: octave_dock_widget ("TerminalDockWidget", p, oct_qobj),
-  m_experimental_terminal_widget (oct_qobj.experimental_terminal_widget ())
+                                            bool experimental_terminal_widget)
+  : octave_dock_widget ("TerminalDockWidget", p),
+    m_experimental_terminal_widget (experimental_terminal_widget)
 {
+  init_control_d_shortcut_behavior ();
+
   // FIXME: we could do this in a better way, but improving it doesn't
   // matter much if we will eventually be removing the old terminal.
   if (m_experimental_terminal_widget)
     {
 #if defined (HAVE_QSCINTILLA)
-      command_widget *widget = new command_widget (oct_qobj, this);
+      command_widget *widget = new command_widget (this);
       console *con = widget->get_console ();
 
       connect (this, &terminal_dock_widget::settings_changed,
@@ -68,17 +72,17 @@
                widget, &command_widget::insert_interpreter_output);
 
       connect (this, &terminal_dock_widget::execute_command_signal,
-               con, &console::execute_command);
+              con, &console::execute_command);
 
       connect (this, &terminal_dock_widget::new_command_line_signal,
-               con, &console::new_command_line);
+              con, &console::new_command_line);
 
       m_terminal = widget;
 #endif
     }
   else
     {
-      QTerminal *widget = QTerminal::create (oct_qobj, this);
+      QTerminal *widget = QTerminal::create (this);
 
       connect (this, &terminal_dock_widget::settings_changed,
                widget, &QTerminal::notice_settings);
@@ -88,6 +92,12 @@
       connect (this, &terminal_dock_widget::visibilityChanged,
                widget, &QTerminal::handle_visibility_changed);
 
+      connect (widget, QOverload<const fcn_callback&>::of (&QTerminal::interpreter_event),
+               this, QOverload<const fcn_callback&>::of (&terminal_dock_widget::interpreter_event));
+
+      connect (widget, QOverload<const meth_callback&>::of (&QTerminal::interpreter_event),
+               this, QOverload<const meth_callback&>::of (&terminal_dock_widget::interpreter_event));
+
       m_terminal = widget;
     }
 
@@ -101,16 +111,16 @@
 
   // Chose a reasonable size at startup in order to avoid truncated
   // startup messages
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+
+  gui_settings settings;
 
   QFont font = QFont ();
   font.setStyleHint (QFont::TypeWriter);
-  QString default_font = settings->value (global_mono_font).toString ();
+  QString default_font = settings.string_value (global_mono_font);
   font.setFamily
-    (settings->value (cs_font.key, default_font).toString ());
+    (settings.value (cs_font.settings_key (), default_font).toString ());
   font.setPointSize
-    (settings->value (cs_font_size).toInt ());
+    (settings.int_value (cs_font_size));
 
   QFontMetrics metrics(font);
 
@@ -131,29 +141,29 @@
     make_window ();
 }
 
-bool terminal_dock_widget::has_focus (void) const
+bool terminal_dock_widget::has_focus () const
 {
   QWidget *w = widget ();
   return w->hasFocus ();
 }
 
-QTerminal * terminal_dock_widget::get_qterminal (void)
+QTerminal * terminal_dock_widget::get_qterminal ()
 {
   return (m_experimental_terminal_widget
           ? nullptr : dynamic_cast<QTerminal *> (m_terminal));
 }
 
 #if defined (HAVE_QSCINTILLA)
-command_widget * terminal_dock_widget::get_command_widget (void)
+command_widget * terminal_dock_widget::get_command_widget ()
 {
   return (m_experimental_terminal_widget
           ? dynamic_cast<command_widget *> (m_terminal) : nullptr);
 }
 #endif
 
-void terminal_dock_widget::notice_settings (const gui_settings *settings)
+void terminal_dock_widget::notice_settings ()
 {
-  emit settings_changed (settings);
+  emit settings_changed ();
 }
 
 void terminal_dock_widget::init_command_prompt ()
@@ -168,4 +178,39 @@
     }
 }
 
+void terminal_dock_widget::init_control_d_shortcut_behavior ()
+{
+  gui_settings settings;
+
+  // Reset use of Ctrl-D.  Do this before the call to beginGroup
+  // because sc_main_ctrld.key already begins with the sc_group
+  // prefix.
+  settings.setValue (sc_main_ctrld.settings_key (), false);
+
+  settings.beginGroup (sc_group);
+  const QStringList shortcut_settings_keys = settings.allKeys ();
+  settings.endGroup ();
+
+  for (const auto& settings_key : shortcut_settings_keys)
+    {
+      // Check whether Ctrl+D is used from main window, i.e. is a
+      // global shortcut.
+
+      QString section = get_shortcut_section (settings_key);
+
+      if (section.startsWith ("main_"))
+        {
+          sc_pref scpref = all_shortcut_preferences::value (settings_key);
+
+          QKeySequence actual = QKeySequence (settings.sc_value (scpref));
+
+          if (actual == QKeySequence (Qt::ControlModifier | Qt::Key_D))
+            {
+              settings.setValue (sc_main_ctrld.settings_key (), true);
+              break;
+            }
+        }
+   }
+}
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/terminal-dock-widget.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/terminal-dock-widget.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,6 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 class command_widget;
-class base_qobject;
 
 class terminal_dock_widget : public octave_dock_widget
 {
@@ -43,29 +42,32 @@
 
 public:
 
-  terminal_dock_widget (QWidget *parent, base_qobject& oct_qobj);
+  terminal_dock_widget (QWidget *parent,
+                        bool experimental_terminal_widget = false);
 
-  ~terminal_dock_widget (void) = default;
+  ~terminal_dock_widget () = default;
 
-  bool has_focus (void) const;
+  bool has_focus () const;
 
   void init_command_prompt ();
 
+  void init_control_d_shortcut_behavior ();
+
   // FIXME: The next two functions could be eliminated (or combined)
   // if we had a common interface for the old and new terminal
   // widgets.
 
   // Only valid if using the old terminal widget.
-  QTerminal * get_qterminal (void);
+  QTerminal * get_qterminal ();
 
 #if defined (HAVE_QSCINTILLA)
   // Only valid if using the new terminal widget.
-  command_widget * get_command_widget (void);
+  command_widget * get_command_widget ();
 #endif
 
 signals:
 
-  void settings_changed (const gui_settings *settings);
+  void settings_changed ();
 
   // Note: the following four signals are
   // currently only used by the new experimental terminal widget.
@@ -78,9 +80,12 @@
 
   void execute_command_signal (const QString&);
 
+  void interpreter_event (const fcn_callback& fcn);
+  void interpreter_event (const meth_callback& meth);
+
 public slots:
 
-  void notice_settings (const gui_settings *settings);
+  void notice_settings ();
 
 private:
 
--- a/libgui/src/variable-editor-model.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/variable-editor-model.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -104,7 +104,7 @@
 { }
 
 std::string
-base_ve_model::name (void) const
+base_ve_model::name () const
 {
   return m_name;
 }
@@ -125,7 +125,7 @@
 }
 
 int
-base_ve_model::column_width (void) const
+base_ve_model::column_width () const
 {
   int width = 0;
 
@@ -257,7 +257,7 @@
 }
 
 void
-base_ve_model::clear_update_pending (void)
+base_ve_model::clear_update_pending ()
 {
   return m_update_pending.clear ();
 }
@@ -285,7 +285,7 @@
 }
 
 QString
-base_ve_model::make_description_text (void) const
+base_ve_model::make_description_text () const
 {
   QString lbl_txt = QString::fromStdString (m_name);
 
@@ -330,13 +330,9 @@
     maybe_resize_columns (m_data_cols + 16);
   }
 
-  ~numeric_model (void) = default;
-
-  // No copying!
+  ~numeric_model () = default;
 
-  numeric_model (const numeric_model&) = delete;
-
-  numeric_model& operator = (const numeric_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (numeric_model)
 
   void maybe_resize_rows (int rows)
   {
@@ -394,13 +390,9 @@
     m_display_cols = 1;
   }
 
-  ~string_model (void) = default;
-
-  // No copying!
+  ~string_model () = default;
 
-  string_model (const string_model&) = delete;
-
-  string_model& operator = (const string_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (string_model)
 
   QVariant edit_display (const QModelIndex&, int) const
   {
@@ -431,13 +423,9 @@
     maybe_resize_columns (m_data_cols + 16);
   }
 
-  ~cell_model (void) = default;
-
-  // No copying!
+  ~cell_model () = default;
 
-  cell_model (const cell_model&) = delete;
-
-  cell_model& operator = (const cell_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (cell_model)
 
   void maybe_resize_rows (int rows)
   {
@@ -532,13 +520,9 @@
     m_display_cols = 1;
   }
 
-  ~scalar_struct_model (void) = default;
-
-  // No copying!
+  ~scalar_struct_model () = default;
 
-  scalar_struct_model (const scalar_struct_model&) = delete;
-
-  scalar_struct_model& operator = (const scalar_struct_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (scalar_struct_model)
 
   QVariant edit_display (const QModelIndex& idx, int role) const
   {
@@ -655,15 +639,11 @@
     m_display_cols = m_data_cols;
   }
 
-  ~display_only_model (void) = default;
-
-  // No copying!
+  ~display_only_model () = default;
 
-  display_only_model (const display_only_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (display_only_model)
 
-  display_only_model& operator = (const display_only_model&) = delete;
-
-  bool is_editable (void) const { return false; }
+  bool is_editable () const { return false; }
 
   QVariant edit_display (const QModelIndex&, int) const
   {
@@ -679,7 +659,7 @@
     return QString::fromStdString (buf.str ());
   }
 
-  QString make_description_text (void) const
+  QString make_description_text () const
   {
     return (QString ("unable to edit %1")
             .arg (base_ve_model::make_description_text ()));
@@ -706,13 +686,9 @@
     m_display_cols = m_data_cols;
   }
 
-  ~vector_struct_model (void) = default;
-
-  // No copying!
+  ~vector_struct_model () = default;
 
-  vector_struct_model (const vector_struct_model&) = delete;
-
-  vector_struct_model& operator = (const vector_struct_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (vector_struct_model)
 
   void maybe_resize_rows (int rows)
   {
@@ -839,13 +815,9 @@
     maybe_resize_columns (m_data_cols + 16);
   }
 
-  ~struct_model (void) = default;
-
-  // No copying!
+  ~struct_model () = default;
 
-  struct_model (const struct_model&) = delete;
-
-  struct_model& operator = (const struct_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (struct_model)
 
   void maybe_resize_rows (int rows)
   {
@@ -951,7 +923,7 @@
 variable_editor_model::variable_editor_model (const QString& expr,
                                               const octave_value& val,
                                               QObject *parent)
-  : QAbstractTableModel (parent), rep (create (expr, val))
+  : QAbstractTableModel (parent), m_rep (create (expr, val))
 {
   update_description ();
 
@@ -1255,7 +1227,7 @@
 }
 
 void
-variable_editor_model::update_data_cache (void)
+variable_editor_model::update_data_cache ()
 {
   emit interpreter_event
     ([=] (interpreter& interp)
@@ -1336,7 +1308,7 @@
   int old_rows = display_rows ();
   int old_cols = display_columns ();
 
-  rep->maybe_resize_rows (rows);
+  m_rep->maybe_resize_rows (rows);
 
   int new_rows = display_rows ();
   int new_cols = display_columns ();
@@ -1351,7 +1323,7 @@
   int old_rows = display_rows ();
   int old_cols = display_columns ();
 
-  rep->maybe_resize_columns (cols);
+  m_rep->maybe_resize_columns (cols);
 
   int new_rows = display_rows ();
   int new_cols = display_columns ();
@@ -1371,9 +1343,9 @@
 void
 variable_editor_model::reset (const octave_value& val)
 {
-  base_ve_model *old_rep = rep;
+  base_ve_model *old_rep = m_rep;
 
-  rep = create (QString::fromStdString (name ()), val);
+  m_rep = create (QString::fromStdString (name ()), val);
 
   delete old_rep;
 
@@ -1383,7 +1355,7 @@
 }
 
 void
-variable_editor_model::invalidate (void)
+variable_editor_model::invalidate ()
 {
   beginResetModel ();
 
@@ -1404,7 +1376,7 @@
 {
   if (requires_sub_editor (idx))
     {
-      QString name = QString::fromStdString(rep->name ());
+      QString name = QString::fromStdString(m_rep->name ());
       emit edit_variable_signal (name + subscript_expression (idx),
                                  value_at (idx));
     }
--- a/libgui/src/variable-editor-model.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/variable-editor-model.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,6 +26,8 @@
 #if ! defined (octave_variable_editor_model_h)
 #define octave_variable_editor_model_h 1
 
+#include "octave-config.h"
+
 #include <QAbstractTableModel>
 #include <QMap>
 #include <QString>
@@ -45,27 +47,23 @@
 
   base_ve_model (const QString& expr, const octave_value& val);
 
-  virtual ~base_ve_model (void) = default;
-
-  // No copying!
+  virtual ~base_ve_model () = default;
 
-  base_ve_model (const base_ve_model&) = delete;
-
-  base_ve_model& operator = (const base_ve_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_ve_model)
 
   virtual void maybe_resize_rows (int) { }
 
   virtual void maybe_resize_columns (int) { }
 
-  std::string name (void) const;
+  std::string name () const;
 
   bool index_ok (const QModelIndex& idx, int& row, int& col) const;
 
-  virtual bool is_editable (void) const { return true; }
+  virtual bool is_editable () const { return true; }
 
   virtual octave_value value_at (const QModelIndex& idx) const;
 
-  int column_width (void) const;
+  int column_width () const;
 
   int rowCount (const QModelIndex& = QModelIndex ()) const;
 
@@ -85,7 +83,7 @@
 
   QString update_pending_data (const QModelIndex& idx) const;
 
-  void clear_update_pending (void);
+  void clear_update_pending ();
 
   virtual char quote_char (const QModelIndex& idx) const;
 
@@ -98,17 +96,17 @@
 
   virtual QString subscript_expression (const QModelIndex& idx) const;
 
-  bool is_valid (void) const { return m_valid; }
+  bool is_valid () const { return m_valid; }
 
-  octave_idx_type data_rows (void) const { return m_data_rows; }
+  octave_idx_type data_rows () const { return m_data_rows; }
 
-  octave_idx_type data_columns (void) const { return m_data_cols; }
+  octave_idx_type data_columns () const { return m_data_cols; }
 
-  int display_rows (void) const { return m_display_rows; }
+  int display_rows () const { return m_display_rows; }
 
-  int display_columns (void) const { return m_display_cols; }
+  int display_columns () const { return m_display_cols; }
 
-  virtual QString make_description_text (void) const;
+  virtual QString make_description_text () const;
 
   void reset (const octave_value& val);
 
@@ -145,51 +143,47 @@
   variable_editor_model (const QString& expr, const octave_value& val,
                          QObject *parent = nullptr);
 
-  ~variable_editor_model (void)
+  ~variable_editor_model ()
   {
-    delete rep;
+    delete m_rep;
   }
 
-  // No copying!
-
-  variable_editor_model (const variable_editor_model&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (variable_editor_model)
 
-  variable_editor_model& operator = (const variable_editor_model&) = delete;
-
-  std::string name (void) const
+  std::string name () const
   {
-    return rep->name ();
+    return m_rep->name ();
   }
 
-  bool is_editable (void) const
+  bool is_editable () const
   {
-    return rep->is_editable ();
+    return m_rep->is_editable ();
   }
 
   octave_value value_at (const QModelIndex& idx) const
   {
-    return rep->value_at (idx);
+    return m_rep->value_at (idx);
   }
 
-  int column_width (void) const
+  int column_width () const
   {
-    return rep->column_width ();
+    return m_rep->column_width ();
   }
 
   int rowCount (const QModelIndex& idx = QModelIndex ()) const
   {
-    return rep->rowCount (idx);
+    return m_rep->rowCount (idx);
   }
 
   int columnCount (const QModelIndex& idx = QModelIndex ()) const
   {
-    return rep->columnCount (idx);
+    return m_rep->columnCount (idx);
   }
 
   QVariant data (const QModelIndex& idx = QModelIndex (),
                  int role = Qt::DisplayRole) const
   {
-    return rep->data (idx, role);
+    return m_rep->data (idx, role);
   }
 
   bool setData (const QModelIndex& idx, const QVariant& v,
@@ -215,38 +209,38 @@
 
   bool requires_sub_editor (const QModelIndex& idx) const
   {
-    return rep->requires_sub_editor (idx);
+    return m_rep->requires_sub_editor (idx);
   }
 
   void set_update_pending (const QModelIndex& idx, const QString& str)
   {
-    rep->set_update_pending (idx, str);
+    m_rep->set_update_pending (idx, str);
   }
 
   bool update_pending (const QModelIndex& idx) const
   {
-    return rep->update_pending (idx);
+    return m_rep->update_pending (idx);
   }
 
   QString update_pending_data (const QModelIndex& idx) const
   {
-    return rep->update_pending_data (idx);
+    return m_rep->update_pending_data (idx);
   }
 
-  void clear_update_pending (void)
+  void clear_update_pending ()
   {
-    rep->clear_update_pending ();
+    m_rep->clear_update_pending ();
   }
 
   char quote_char (const QModelIndex& idx) const
   {
-    return rep->quote_char (idx);
+    return m_rep->quote_char (idx);
   }
 
   QVariant
   headerData (int section, Qt::Orientation orientation, int role) const
   {
-    return rep->header_data (section, orientation, role);
+    return m_rep->header_data (section, orientation, role);
   }
 
   // Return a subscript expression as a string that can be used to
@@ -255,27 +249,27 @@
 
   QString subscript_expression (const QModelIndex& idx) const
   {
-    return rep->subscript_expression (idx);
+    return m_rep->subscript_expression (idx);
   }
 
-  int display_rows (void) const
+  int display_rows () const
   {
-    return rep->display_rows ();
+    return m_rep->display_rows ();
   }
 
-  octave_idx_type data_rows (void) const
+  octave_idx_type data_rows () const
   {
-    return rep->data_rows ();
+    return m_rep->data_rows ();
   }
 
-  int display_columns (void) const
+  int display_columns () const
   {
-    return rep->display_columns ();
+    return m_rep->display_columns ();
   }
 
-  octave_idx_type data_columns (void) const
+  octave_idx_type data_columns () const
   {
-    return rep->data_columns ();
+    return m_rep->data_columns ();
   }
 
   void maybe_resize_rows (int rows);
@@ -303,7 +297,7 @@
 
   void update_data (const octave_value& val);
 
-  void update_data_cache (void);
+  void update_data_cache ();
 
   void double_click (const QModelIndex& idx);
 
@@ -315,7 +309,7 @@
 
 private:
 
-  base_ve_model *rep;
+  base_ve_model *m_rep;
 
   void init_from_oct (interpreter& interp);
 
@@ -323,22 +317,22 @@
 
   octave_value retrieve_variable (interpreter&, const std::string& name);
 
-  bool is_valid (void) const
+  bool is_valid () const
   {
-    return rep->is_valid ();
+    return m_rep->is_valid ();
   }
 
   void change_display_size (int old_rows, int old_cols,
                             int new_rows, int new_cols);
 
-  QString make_description_text (void) const
+  QString make_description_text () const
   {
-    return rep->make_description_text ();
+    return m_rep->make_description_text ();
   }
 
   void reset (const octave_value& val);
 
-  void invalidate (void);
+  void invalidate ();
 
   void update_description (const QString& description = QString ());
 
--- a/libgui/src/variable-editor.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/variable-editor.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,6 +38,8 @@
 #include <QMdiArea>
 #include <QMenu>
 #include <QPalette>
+#include <QPointer>
+#include <QRegularExpression>
 #include <QScreen>
 #include <QScrollBar>
 #include <QStackedWidget>
@@ -55,11 +57,9 @@
 #include "gui-preferences-global.h"
 #include "gui-preferences-sc.h"
 #include "gui-preferences-ve.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
+#include "gui-settings.h"
 #include "ovl.h"
 #include "qt-utils.h"
-#include "shortcut-manager.h"
 #include "variable-editor-model.h"
 #include "variable-editor.h"
 
@@ -84,13 +84,12 @@
 
 // Variable dock widget
 
-variable_dock_widget::variable_dock_widget (QWidget *p,
-                                            base_qobject& oct_qobj)
-  : label_dock_widget (p, oct_qobj)
-    // See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+variable_dock_widget::variable_dock_widget (QWidget *p)
+  : label_dock_widget (p)
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
-  , m_waiting_for_mouse_move (false)
-  , m_waiting_for_mouse_button_release (false)
+    , m_waiting_for_mouse_move (false)
+    , m_waiting_for_mouse_button_release (false)
 #endif
 {
   setFocusPolicy (Qt::StrongFocus);
@@ -113,9 +112,10 @@
   m_prev_geom = QRect (0, 0, 0, 0);
 
   QHBoxLayout *h_layout = m_title_widget->findChild<QHBoxLayout *> ();
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+
+  gui_settings settings;
   m_fullscreen_action
-    = new QAction (rmgr.icon ("view-fullscreen", false), "", this);
+    = new QAction (settings.icon ("view-fullscreen", false), "", this);
   m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));
   QToolButton *fullscreen_button = new QToolButton (m_title_widget);
   fullscreen_button->setDefaultAction (m_fullscreen_action);
@@ -148,8 +148,8 @@
       if (m_full_screen)
         {
           setGeometry (m_prev_geom);
-          resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-          m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false));
+          gui_settings settings;
+          m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false));
           m_full_screen = false;
         }
       m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));
@@ -183,7 +183,7 @@
       activateWindow ();
       setFocus ();
 
-      // See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
       m_waiting_for_mouse_move = true;
 #endif
@@ -196,7 +196,7 @@
 
       setFocus ();
 
-      // See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
       m_waiting_for_mouse_move = false;
       m_waiting_for_mouse_button_release = false;
@@ -205,14 +205,14 @@
 }
 
 void
-variable_dock_widget::change_fullscreen (void)
+variable_dock_widget::change_fullscreen ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
   if (! m_full_screen)
     {
       m_prev_floating = isFloating ();
-      m_fullscreen_action->setIcon (rmgr.icon ("view-restore", false));
+      m_fullscreen_action->setIcon (settings.icon ("view-restore", false));
       if (m_prev_floating)
         m_fullscreen_action->setToolTip (tr ("Restore geometry"));
       else
@@ -232,7 +232,7 @@
     }
   else
     {
-      m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false));
+      m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false));
       setGeometry (m_prev_geom);
       if (m_prev_floating)
         m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP));
@@ -329,7 +329,7 @@
 }
 
 void
-variable_dock_widget::unfloat_float (void)
+variable_dock_widget::unfloat_float ()
 {
   hide ();
   setFloating (false);
@@ -340,7 +340,7 @@
 }
 
 void
-variable_dock_widget::refloat (void)
+variable_dock_widget::refloat ()
 {
   setFloating (true);
   m_waiting_for_mouse_move = false;
@@ -353,21 +353,19 @@
 #else
 
 void
-variable_dock_widget::unfloat_float (void)
+variable_dock_widget::unfloat_float ()
 { }
 
 void
-variable_dock_widget::refloat (void)
+variable_dock_widget::refloat ()
 { }
 
 #endif
 
 // Variable editor stack
 
-variable_editor_stack::variable_editor_stack (QWidget *p,
-                                              base_qobject& oct_qobj)
-  : QStackedWidget (p), m_octave_qobj (oct_qobj),
-    m_edit_view (new variable_editor_view (this, m_octave_qobj))
+variable_editor_stack::variable_editor_stack (QWidget *p)
+  : QStackedWidget (p), m_edit_view (new variable_editor_view (this))
 {
   setFocusPolicy (Qt::StrongFocus);
 
@@ -426,7 +424,7 @@
 }
 
 void
-variable_editor_stack::levelUp (void)
+variable_editor_stack::levelUp ()
 {
   if (! hasFocus ())
     return;
@@ -437,7 +435,7 @@
 
   if (name.endsWith (')') || name.endsWith ('}'))
     {
-      name.remove ( QRegExp ("[({][^({]*[)}]$)") );
+      name.remove (QRegularExpression {"[({][^({]*[)}]$)"});
       emit edit_variable_signal (name, octave_value ());
     }
 }
@@ -467,24 +465,24 @@
   // No format given, test save default options
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
+      {
+        // INTERPRETER THREAD
 
-      // We can skip the entire callback function because it does not
-      // make any changes to the interpreter state.
+        // We can skip the entire callback function because it does
+        // not make any changes to the interpreter state.
 
-      if (this_ves.isNull ())
-        return;
+        if (this_ves.isNull ())
+          return;
 
-      octave_value_list argout
-        = Fsave_default_options (interp, octave_value_list (), 1);
-      QString save_opts = QString::fromStdString (argout(0).string_value ());
+        octave_value_list argout
+          = Fsave_default_options (interp, octave_value_list (), 1);
+        QString save_opts = QString::fromStdString (argout(0).string_value ());
 
-      connect (this, &variable_editor_stack::do_save_signal,
-               this, &variable_editor_stack::do_save);
+        connect (this, &variable_editor_stack::do_save_signal,
+                 this, &variable_editor_stack::do_save);
 
-      emit (do_save_signal (format_string, save_opts));
-    });
+        emit do_save_signal (format_string, save_opts);
+      });
 }
 
 // Perform saving the variable after desired format is determined
@@ -503,9 +501,10 @@
 
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = 0;  // No options by default.
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  if (! settings->value (global_use_native_dialogs).toBool ())
+
+  gui_settings settings;
+
+  if (! settings.bool_value (global_use_native_dialogs))
     opts = QFileDialog::DontUseNativeDialog;
 
   QString name = objectName ();
@@ -521,25 +520,24 @@
   // Let the interpreter thread do the saving
   emit interpreter_event
     ([=] (interpreter& interp)
-    {
-      // INTERPRETER THREAD
+      {
+        // INTERPRETER THREAD
 
-      octave_value_list ovl;
-      std::list<octave_value> str_list
-        = {octave_value (file.toStdString ()),
-        octave_value (name.toStdString ())};
-      if (! format.isEmpty ())
-        str_list.push_front (octave_value (format.toStdString ()));
+        octave_value_list ovl;
+        std::list<octave_value> str_list
+                            = {octave_value (file.toStdString ()),
+                               octave_value (name.toStdString ())};
+        if (! format.isEmpty ())
+          str_list.push_front (octave_value (format.toStdString ()));
 
-      Fsave (interp, octave_value_list (str_list));
-    });
+        Fsave (interp, octave_value_list (str_list));
+      });
 }
 
 // Custom editable variable table view
 
-variable_editor_view::variable_editor_view (QWidget *p,
-                                            base_qobject& oct_qobj)
-  : QTableView (p), m_octave_qobj (oct_qobj), m_var_model (nullptr)
+variable_editor_view::variable_editor_view (QWidget *p)
+  : QTableView (p), m_var_model (nullptr)
 {
   setWordWrap (false);
   setContextMenuPolicy (Qt::CustomContextMenu);
@@ -576,7 +574,7 @@
 }
 
 QList<int>
-variable_editor_view::range_selected (void)
+variable_editor_view::range_selected ()
 {
   QItemSelectionModel *sel = selectionModel ();
 
@@ -632,9 +630,9 @@
 
   // Variable with desired range as string
   QString variable = QString ("%1(%2:%3,%4:%5)")
-    .arg (objectName ())
-    .arg (range.at (0)).arg (s1)
-    .arg (range.at (2)).arg (s2);
+                              .arg (objectName ())
+                              .arg (range.at (0)).arg (s1)
+                              .arg (range.at (2)).arg (s2);
 
   // Desired command as string
   QString command;
@@ -642,7 +640,7 @@
     command = QString ("unnamed = %1;").arg (variable);
   else
     command = QString ("figure (); %1 (%2); title ('%2');")
-      .arg (cmd).arg (variable);
+                        .arg (cmd).arg (variable);
 
   emit command_signal (command);
 }
@@ -651,31 +649,31 @@
 variable_editor_view::add_edit_actions (QMenu *menu,
                                         const QString& qualifier_string)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
-  menu->addAction (rmgr.icon ("edit-cut"),
+  menu->addAction (settings.icon ("edit-cut"),
                    tr ("Cut") + qualifier_string,
                    this, &variable_editor_view::cutClipboard);
 
-  menu->addAction (rmgr.icon ("edit-copy"),
+  menu->addAction (settings.icon ("edit-copy"),
                    tr ("Copy") + qualifier_string,
                    this, &variable_editor_view::copyClipboard);
 
-  menu->addAction (rmgr.icon ("edit-paste"),
+  menu->addAction (settings.icon ("edit-paste"),
                    tr ("Paste"),
                    this, &variable_editor_view::pasteClipboard);
 
   menu->addSeparator ();
 
-  menu->addAction (rmgr.icon ("edit-delete"),
+  menu->addAction (settings.icon ("edit-delete"),
                    tr ("Clear") + qualifier_string,
                    this, &variable_editor_view::clearContent);
 
-  menu->addAction (rmgr.icon ("edit-delete"),
+  menu->addAction (settings.icon ("edit-delete"),
                    tr ("Delete") + qualifier_string,
                    this, &variable_editor_view::delete_selected);
 
-  menu->addAction (rmgr.icon ("document-new"),
+  menu->addAction (settings.icon ("document-new"),
                    tr ("Variable from Selection"),
                    this, &variable_editor_view::createVariable);
 }
@@ -816,7 +814,7 @@
 }
 
 void
-variable_editor_view::createVariable (void)
+variable_editor_view::createVariable ()
 {
   // FIXME: Create unnamed1..n if exist ('unnamed', 'var') is true.
 
@@ -824,7 +822,7 @@
 }
 
 void
-variable_editor_view::transposeContent (void)
+variable_editor_view::transposeContent ()
 {
   if (! hasFocus ())
     return;
@@ -833,7 +831,7 @@
 }
 
 void
-variable_editor_view::delete_selected (void)
+variable_editor_view::delete_selected ()
 {
   if (! hasFocus ())
     return;
@@ -863,7 +861,7 @@
 }
 
 void
-variable_editor_view::clearContent (void)
+variable_editor_view::clearContent ()
 {
   if (! hasFocus ())
     return;
@@ -881,7 +879,7 @@
 }
 
 void
-variable_editor_view::cutClipboard (void)
+variable_editor_view::cutClipboard ()
 {
   copyClipboard ();
 
@@ -889,7 +887,7 @@
 }
 
 void
-variable_editor_view::copyClipboard (void)
+variable_editor_view::copyClipboard ()
 {
   if (! hasFocus ())
     return;
@@ -920,7 +918,7 @@
 }
 
 void
-variable_editor_view::pasteClipboard (void)
+variable_editor_view::pasteClipboard ()
 {
   if (! hasFocus ())
     return;
@@ -1103,9 +1101,9 @@
 
 // Variable editor.
 
-variable_editor::variable_editor (QWidget *p, base_qobject& oct_qobj)
-  : octave_dock_widget ("VariableEditor", p, oct_qobj),
-    m_main (new dw_main_window (oct_qobj)),
+variable_editor::variable_editor (QWidget *p)
+  : octave_dock_widget ("VariableEditor", p),
+    m_main (new dw_main_window ()),
     m_tool_bar (new QToolBar (m_main)),
     m_default_width (30),
     m_default_height (100),
@@ -1127,7 +1125,7 @@
   setAttribute (Qt::WA_AlwaysShowToolTips);
 
   m_main->setParent (this);
-  // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357
+// See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357
 #if (QT_VERSION < 0x050601) || (QT_VERSION >= 0x050701)
   m_main->setDockOptions (QMainWindow::AnimatedDocks |
                           QMainWindow::AllowNestedDocks |
@@ -1196,7 +1194,7 @@
     }
 }
 
-variable_editor::~variable_editor (void)
+variable_editor::~variable_editor ()
 {
   // FIXME: Maybe toolbar actions could be handled with signals and
   // slots so that deleting the toolbar here would disconnect all
@@ -1211,13 +1209,8 @@
 void
 variable_editor::edit_variable (const QString& name, const octave_value& val)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-
   if (m_stylesheet.isEmpty ())
-    {
-      gui_settings *settings = rmgr.get_settings ();
-      notice_settings (settings);
-    }
+    notice_settings ();
 
   QDockWidget *existing_qdw = m_main->findChild<QDockWidget *> (name);
   if (existing_qdw)
@@ -1242,8 +1235,7 @@
       return;
     }
 
-  variable_dock_widget *page
-    = new variable_dock_widget (this, m_octave_qobj);
+  variable_dock_widget *page = new variable_dock_widget (this);
 
   page->setObjectName (name);
   m_main->addDockWidget (Qt::LeftDockWidgetArea, page);
@@ -1270,8 +1262,7 @@
            page, SLOT (refloat ()), Qt::QueuedConnection);
 #endif
 
-  variable_editor_stack *stack
-    = new variable_editor_stack (page, m_octave_qobj);
+  variable_editor_stack *stack = new variable_editor_stack (page);
 
   stack->setObjectName (name);
   page->setWidget (stack);
@@ -1388,7 +1379,7 @@
 }
 
 void
-variable_editor::tab_to_front (void)
+variable_editor::tab_to_front ()
 {
   QWidget *parent = parentWidget ();
 
@@ -1413,7 +1404,7 @@
 }
 
 void
-variable_editor::refresh (void)
+variable_editor::refresh ()
 {
   emit refresh_signal ();
 }
@@ -1425,31 +1416,33 @@
 }
 
 void
-variable_editor::notice_settings (const gui_settings *settings)
+variable_editor::notice_settings ()
 {
-  m_main->notice_settings (settings); // update settings in parent main win
+  gui_settings settings;
 
-  m_default_width = settings->value (ve_column_width).toInt ();
+  m_main->notice_settings (); // update settings in parent main win
 
-  m_default_height = settings->value (ve_row_height).toInt ();
+  m_default_width = settings.int_value (ve_column_width);
+
+  m_default_height = settings.int_value (ve_row_height);
 
-  m_alternate_rows = settings->value (ve_alternate_rows).toBool ();
+  m_alternate_rows = settings.bool_value (ve_alternate_rows);
 
-  m_use_terminal_font = settings->value (ve_use_terminal_font).toBool ();
+  m_use_terminal_font = settings.bool_value (ve_use_terminal_font);
 
   QString font_name;
   int font_size;
-  QString default_font = settings->value (global_mono_font).toString ();
+  QString default_font = settings.string_value (global_mono_font);
 
   if (m_use_terminal_font)
     {
-      font_name = settings->value (cs_font.key, default_font).toString ();
-      font_size = settings->value (cs_font_size).toInt ();
+      font_name = settings.value (cs_font.settings_key (), default_font).toString ();
+      font_size = settings.int_value (cs_font_size);
     }
   else
     {
-      font_name = settings->value (ve_font_name.key, default_font).toString ();
-      font_size = settings->value (ve_font_size).toInt ();
+      font_name = settings.value (ve_font_name.settings_key (), default_font).toString ();
+      font_size = settings.int_value (ve_font_size);
     }
 
   m_font = QFont (font_name, font_size);
@@ -1458,11 +1451,11 @@
 
   m_add_font_height = fm.height ();
 
-  int mode = settings->value (ve_color_mode).toInt ();
+  int mode = settings.int_value (ve_color_mode);
 
   for (int i = 0; i < ve_colors_count; i++)
     {
-      QColor setting_color = settings->color_value (ve_colors[i], mode);
+      QColor setting_color = settings.color_value (ve_colors[i], mode);
       m_table_colors.replace (i, setting_color);
     }
 
@@ -1472,7 +1465,7 @@
 
   if (m_tool_bar)
     {
-      int size_idx = settings->value (global_icon_size).toInt ();
+      int size_idx = settings.int_value (global_icon_size);
       size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
       QStyle *st = style ();
@@ -1481,8 +1474,7 @@
     }
 
   // Shortcuts (same as file editor)
-  shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
-  scmgr.set_shortcut (m_save_action, sc_edit_file_save);
+  settings.set_shortcut (m_save_action, sc_edit_file_save);
 }
 
 void
@@ -1543,13 +1535,13 @@
 }
 
 void
-variable_editor::record_hovered_focus_variable (void)
+variable_editor::record_hovered_focus_variable ()
 {
   m_hovered_focus_vname = m_current_focus_vname;
 }
 
 void
-variable_editor::restore_hovered_focus_variable (void)
+variable_editor::restore_hovered_focus_variable ()
 {
   variable_dock_widget *tofocus = findChild<variable_dock_widget *> (m_hovered_focus_vname);
   if (tofocus != nullptr)
@@ -1566,13 +1558,13 @@
 }
 
 void
-variable_editor::save (void)
+variable_editor::save ()
 {
   emit save_signal ();
 }
 
 void
-variable_editor::cutClipboard (void)
+variable_editor::cutClipboard ()
 {
   copyClipboard ();
 
@@ -1580,13 +1572,13 @@
 }
 
 void
-variable_editor::copyClipboard (void)
+variable_editor::copyClipboard ()
 {
   emit copy_clipboard_signal ();
 }
 
 void
-variable_editor::pasteClipboard (void)
+variable_editor::pasteClipboard ()
 {
   emit paste_clipboard_signal ();
 
@@ -1594,40 +1586,40 @@
 }
 
 void
-variable_editor::levelUp (void)
+variable_editor::levelUp ()
 {
   emit level_up_signal ();
 }
 
 // Also updates the font.
 
-void variable_editor::update_colors (void)
+void variable_editor::update_colors ()
 {
   m_stylesheet = "";
 
   if (m_table_colors.length () > 0)
     m_stylesheet += "QTableView::item{ color: "
-      + m_table_colors[0].name () +" }";
+                    + m_table_colors[0].name () +" }";
 
   if (m_table_colors.length () > 1)
     m_stylesheet += "QTableView::item{ background-color: "
-      + m_table_colors[1].name () +" }";
+                    + m_table_colors[1].name () +" }";
 
   if (m_table_colors.length () > 2)
     m_stylesheet += "QTableView::item{ selection-color: "
-      + m_table_colors[2].name () +" }";
+                    + m_table_colors[2].name () +" }";
 
   if (m_table_colors.length () > 3)
     m_stylesheet += "QTableView::item:selected{ background-color: "
-      + m_table_colors[3].name () +" }";
+                    + m_table_colors[3].name () +" }";
 
   if (m_table_colors.length () > 4 && m_alternate_rows)
     {
       m_stylesheet += "QTableView::item:alternate{ background-color: "
-        + m_table_colors[4].name () +" }";
+                      + m_table_colors[4].name () +" }";
 
       m_stylesheet += "QTableView::item:alternate:selected{ background-color: "
-        + m_table_colors[3].name () +" }";
+                      + m_table_colors[3].name () +" }";
     }
 
   QList<QTableView *> viewlist = findChildren<QTableView *> ();
@@ -1664,7 +1656,7 @@
 }
 
 void
-variable_editor::construct_tool_bar (void)
+variable_editor::construct_tool_bar ()
 {
   m_tool_bar->setAllowedAreas (Qt::TopToolBarArea);
 
@@ -1672,22 +1664,23 @@
 
   m_tool_bar->setWindowTitle (tr ("Variable Editor Toolbar"));
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
+  gui_settings settings;
 
-  m_save_action = add_tool_bar_button (rmgr.icon ("document-save"), tr ("Save"),
-                                       this, SLOT (save ()));
+  m_save_action = add_tool_bar_button (settings.icon ("document-save"),
+                                       tr ("Save"), this, SLOT (save ()));
   addAction (m_save_action);
   m_save_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   m_save_action->setStatusTip(tr("Save variable to a file"));
 
-  QAction *action = new QAction (rmgr.icon ("document-save-as"), tr ("Save in format ..."), m_tool_bar);
+  QAction *action = new QAction (settings.icon ("document-save-as"),
+                                 tr ("Save in format ..."), m_tool_bar);
 
   QToolButton *save_tool_button = new HoverToolButton (m_tool_bar);
   save_tool_button->setDefaultAction (action);
 
   save_tool_button->setText (tr ("Save in format ..."));
   save_tool_button->setToolTip (tr("Save variable to a file in different format"));
-  save_tool_button->setIcon (rmgr.icon ("document-save-as"));
+  save_tool_button->setIcon (settings.icon ("document-save-as"));
   save_tool_button->setPopupMode (QToolButton::InstantPopup);
 
   QMenu *save_menu = new ReturnFocusMenu (save_tool_button);
@@ -1699,22 +1692,22 @@
     m_save_mapper->setMapping
       (save_menu->addAction (ve_save_formats.at (i),
                              m_save_mapper, SLOT (map ())),
-       ve_save_formats.at (i));
+                             ve_save_formats.at (i));
 
   save_tool_button->setMenu (save_menu);
   m_tool_bar->addWidget (save_tool_button);
 
   m_tool_bar->addSeparator ();
 
-  action = add_tool_bar_button (rmgr.icon ("edit-cut"), tr ("Cut"),
+  action = add_tool_bar_button (settings.icon ("edit-cut"), tr ("Cut"),
                                 this, SLOT (cutClipboard ()));
   action->setStatusTip(tr("Cut data to clipboard"));
 
-  action = add_tool_bar_button (rmgr.icon ("edit-copy"), tr ("Copy"),
+  action = add_tool_bar_button (settings.icon ("edit-copy"), tr ("Copy"),
                                 this, SLOT (copyClipboard ()));
   action->setStatusTip(tr("Copy data to clipboard"));
 
-  action = add_tool_bar_button (rmgr.icon ("edit-paste"), tr ("Paste"),
+  action = add_tool_bar_button (settings.icon ("edit-paste"), tr ("Paste"),
                                 this, SLOT (pasteClipboard ()));
   action->setStatusTip(tr("Paste clipboard into variable data"));
 
@@ -1724,14 +1717,15 @@
   // QAction *print_action; /icons/fileprint.png
   // m_tool_bar->addSeparator ();
 
-  action = new QAction (rmgr.icon ("plot-xy-curve"), tr ("Plot"), m_tool_bar);
+  action = new QAction (settings.icon ("plot-xy-curve"), tr ("Plot"),
+                        m_tool_bar);
   action->setToolTip (tr ("Plot Selected Data"));
   QToolButton *plot_tool_button = new HoverToolButton (m_tool_bar);
   plot_tool_button->setDefaultAction (action);
 
   plot_tool_button->setText (tr ("Plot"));
   plot_tool_button->setToolTip (tr ("Plot selected data"));
-  plot_tool_button->setIcon (rmgr.icon ("plot-xy-curve"));
+  plot_tool_button->setIcon (settings.icon ("plot-xy-curve"));
 
   plot_tool_button->setPopupMode (QToolButton::InstantPopup);
 
@@ -1747,7 +1741,7 @@
 
   m_tool_bar->addSeparator ();
 
-  action = add_tool_bar_button (rmgr.icon ("go-up"), tr ("Up"), this,
+  action = add_tool_bar_button (settings.icon ("go-up"), tr ("Up"), this,
                                 SLOT (levelUp ()));
   action->setStatusTip(tr("Go one level up in variable hierarchy"));
 
@@ -1757,7 +1751,7 @@
   QList<HoverToolButton *> hbuttonlist
     = m_tool_bar->findChildren<HoverToolButton *> (""
                                                    , Qt::FindDirectChildrenOnly
-                                                   );
+                                                  );
   for (int i = 0; i < hbuttonlist.size (); i++)
     {
       connect (hbuttonlist.at (i), &HoverToolButton::hovered_signal,
@@ -1769,7 +1763,7 @@
   QList<ReturnFocusToolButton *> rfbuttonlist
     = m_tool_bar->findChildren<ReturnFocusToolButton *> (""
                                                          , Qt::FindDirectChildrenOnly
-                                                         );
+                                                        );
   for (int i = 0; i < rfbuttonlist.size (); i++)
     {
       connect (rfbuttonlist.at (i), &ReturnFocusToolButton::about_to_activate,
--- a/libgui/src/variable-editor.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/variable-editor.h	Fri Jun 23 20:51:51 2023 +0200
@@ -26,13 +26,14 @@
 #if ! defined (octave_variable_editor_h)
 #define octave_variable_editor_h 1
 
+#include "octave-config.h"
+
 #include <QHeaderView>
 #include <QSignalMapper>
 #include <QStackedWidget>
 #include <QTableView>
 
 #include "dw-main-window.h"
-#include "gui-settings.h"
 #include "octave-dock-widget.h"
 #include "qt-interpreter-events.h"
 #include "tab-bar.h"
@@ -45,8 +46,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class variable_editor_model;
 class variable_editor_view;
 
@@ -58,9 +57,9 @@
 
 public:
 
-  variable_dock_widget (QWidget *p, base_qobject& oct_qobj);
+  variable_dock_widget (QWidget *p);
 
-  ~variable_dock_widget (void) = default;
+  ~variable_dock_widget () = default;
 
 signals:
 
@@ -84,7 +83,7 @@
 
   void toplevel_change (bool);
 
-  void change_fullscreen (void);
+  void change_fullscreen ();
 
 protected:
 
@@ -98,19 +97,19 @@
 
   QRect m_prev_geom;
 
-  // See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #define QTBUG_44813_FIX_VERSION 0x999999
 signals:
 
-  void queue_unfloat_float (void);
+  void queue_unfloat_float ();
 
-  void queue_float (void);
+  void queue_float ();
 
 protected slots:
 
-  void unfloat_float (void);
+  void unfloat_float ();
 
-  void refloat (void);
+  void refloat ();
 
 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
 protected:
@@ -131,13 +130,13 @@
 
 public:
 
-  variable_editor_stack (QWidget *p, base_qobject& oct_qobj);
+  variable_editor_stack (QWidget *p);
 
-  ~variable_editor_stack (void) = default;
+  ~variable_editor_stack () = default;
 
-  variable_editor_view * edit_view (void) {return m_edit_view;};
+  variable_editor_view * edit_view () {return m_edit_view;};
 
-  QTextEdit * disp_view (void) {return m_disp_view;};
+  QTextEdit * disp_view () {return m_disp_view;};
 
 signals:
 
@@ -152,7 +151,7 @@
 
   void set_editable (bool editable);
 
-  void levelUp (void);
+  void levelUp ();
 
   void save (const QString& format = QString ());
 
@@ -162,8 +161,6 @@
 
   QTextEdit * make_disp_view (QWidget *parent);
 
-  base_qobject& m_octave_qobj;
-
   variable_editor_view *m_edit_view;
 
   QTextEdit *m_disp_view;
@@ -175,9 +172,9 @@
 
 public:
 
-  variable_editor_view (QWidget *p, base_qobject& oct_qobj);
+  variable_editor_view (QWidget *p);
 
-  ~variable_editor_view (void) = default;
+  ~variable_editor_view () = default;
 
   void setModel (QAbstractItemModel *model);
 
@@ -189,21 +186,21 @@
 
 public slots:
 
-  void createVariable (void);
+  void createVariable ();
 
-  void transposeContent (void);
+  void transposeContent ();
 
-  QList<int> range_selected (void);
+  QList<int> range_selected ();
 
-  void delete_selected (void);
+  void delete_selected ();
 
-  void clearContent (void);
+  void clearContent ();
 
-  void cutClipboard (void);
+  void cutClipboard ();
 
-  void copyClipboard (void);
+  void copyClipboard ();
 
-  void pasteClipboard (void);
+  void pasteClipboard ();
 
   void handle_horizontal_scroll_action (int action);
 
@@ -221,8 +218,6 @@
 
   void add_edit_actions (QMenu *menu, const QString& qualifier_string);
 
-  base_qobject& m_octave_qobj;
-
   variable_editor_model *m_var_model;
 };
 
@@ -237,13 +232,13 @@
 
   HoverToolButton (QWidget *parent = nullptr);
 
-  ~HoverToolButton (void) = default;
+  ~HoverToolButton () = default;
 
 signals:
 
-  void hovered_signal (void);
+  void hovered_signal ();
 
-  void popup_shown_signal (void);
+  void popup_shown_signal ();
 
 protected:
 
@@ -258,11 +253,11 @@
 
   ReturnFocusToolButton (QWidget *parent = nullptr);
 
-  ~ReturnFocusToolButton (void) = default;
+  ~ReturnFocusToolButton () = default;
 
 signals:
 
-  void about_to_activate (void);
+  void about_to_activate ();
 
 protected:
 
@@ -277,11 +272,11 @@
 
   ReturnFocusMenu (QWidget *parent = nullptr);
 
-  ~ReturnFocusMenu (void) = default;
+  ~ReturnFocusMenu () = default;
 
 signals:
 
-  void about_to_activate (void);
+  void about_to_activate ();
 
 protected:
 
@@ -296,41 +291,37 @@
 
 public:
 
-  variable_editor (QWidget *parent, base_qobject& oct_qobj);
+  variable_editor (QWidget *parent);
 
-  ~variable_editor (void);
-
-  // No copying!
+  ~variable_editor ();
 
-  variable_editor (const variable_editor&) = delete;
-
-  variable_editor& operator = (const variable_editor&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (variable_editor)
 
-  void refresh (void);
+  void refresh ();
 
-  void tab_to_front (void);
+  void tab_to_front ();
 
 signals:
 
-  void updated (void);
+  void updated ();
 
-  void finished (void);
+  void finished ();
 
   void command_signal (const QString& cmd);
 
-  void refresh_signal (void);
+  void refresh_signal ();
 
-  void clear_content_signal (void);
+  void clear_content_signal ();
 
-  void copy_clipboard_signal (void);
+  void copy_clipboard_signal ();
 
-  void paste_clipboard_signal (void);
+  void paste_clipboard_signal ();
 
-  void level_up_signal (void);
+  void level_up_signal ();
 
-  void save_signal (void);
+  void save_signal ();
 
-  void delete_selected_signal (void);
+  void delete_selected_signal ();
 
   void interpreter_event (const fcn_callback& fcn);
   void interpreter_event (const meth_callback& meth);
@@ -339,7 +330,7 @@
 
   void callUpdate (const QModelIndex&, const QModelIndex&);
 
-  void notice_settings (const gui_settings *);
+  void notice_settings ();
 
   void edit_variable (const QString& name, const octave_value& val);
 
@@ -347,23 +338,23 @@
 
   void variable_focused (const QString& name);
 
-  void record_hovered_focus_variable (void);
+  void record_hovered_focus_variable ();
 
-  void restore_hovered_focus_variable (void);
+  void restore_hovered_focus_variable ();
 
 protected slots:
 
   void closeEvent (QCloseEvent *);
 
-  void save (void);
+  void save ();
 
-  void cutClipboard (void);
+  void cutClipboard ();
 
-  void copyClipboard (void);
+  void copyClipboard ();
 
-  void pasteClipboard (void);
+  void pasteClipboard ();
 
-  void levelUp (void);
+  void levelUp ();
 
 protected:
 
@@ -396,12 +387,12 @@
 
   QList<QColor> m_table_colors;
 
-  void update_colors (void);
+  void update_colors ();
 
   QAction * add_tool_bar_button (const QIcon& icon, const QString& text,
                                  const QObject *receiver, const char *member);
 
-  void construct_tool_bar (void);
+  void construct_tool_bar ();
 
   QString m_current_focus_vname;
 
--- a/libgui/src/welcome-wizard.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/welcome-wizard.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 
 #include "gui-preferences-dw.h"
 #include "gui-preferences-nr.h"
-#include "octave-qobject.h"
+#include "gui-settings.h"
 #include "welcome-wizard.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -53,10 +53,9 @@
   return logo;
 };
 
-welcome_wizard::welcome_wizard (base_qobject& oct_qobj, QWidget *p)
-  : QDialog (p), m_octave_qobj (oct_qobj), m_page_ctor_list (),
-    m_page_list_iterator (),
-    m_current_page (initial_page::create (oct_qobj, this)),
+welcome_wizard::welcome_wizard (QWidget *p)
+  : QDialog (p), m_page_ctor_list (), m_page_list_iterator (),
+    m_current_page (initial_page::create (this)),
     m_allow_web_connect_state (false),
     m_max_height (0), m_max_width (0)
 {
@@ -92,7 +91,7 @@
 #endif
 }
 
-void welcome_wizard::adjust_size (void)
+void welcome_wizard::adjust_size ()
 {
   // Get adjusted size for the current page
   adjustSize ();
@@ -112,12 +111,12 @@
   m_allow_web_connect_state = state == Qt::Checked;
 }
 
-void welcome_wizard::show_page (void)
+void welcome_wizard::show_page ()
 {
   delete m_current_page;
   delete layout ();
 
-  m_current_page = (*m_page_list_iterator) (m_octave_qobj, this);
+  m_current_page = (*m_page_list_iterator) (this);
 
   QVBoxLayout *new_layout = new QVBoxLayout ();
   setLayout (new_layout);
@@ -125,41 +124,34 @@
   new_layout->addWidget (m_current_page);
 }
 
-void welcome_wizard::previous_page (void)
+void welcome_wizard::previous_page ()
 {
   --m_page_list_iterator;
 
   show_page ();
 }
 
-void welcome_wizard::next_page (void)
+void welcome_wizard::next_page ()
 {
   ++m_page_list_iterator;
 
   show_page ();
 }
 
-void welcome_wizard::accept (void)
+void welcome_wizard::accept ()
 {
   // Create default settings file.
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  rmgr.reload_settings ();
-
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  if (settings)
-    {
-      settings->setValue (nr_allow_connection.key,
-                          m_allow_web_connect_state);
+  settings.setValue (nr_allow_connection.settings_key (), m_allow_web_connect_state);
 
-      settings->sync ();
-    }
+  settings.sync ();
 
   QDialog::accept ();
 }
 
-initial_page::initial_page (base_qobject& oct_qobj, welcome_wizard *wizard)
+initial_page::initial_page (welcome_wizard *wizard)
   : QWidget (wizard),
     m_title (new QLabel (tr ("Welcome to Octave!"), this)),
     m_message (new QLabel (this)),
@@ -171,7 +163,7 @@
   ft.setPointSize (20);
   m_title->setFont (ft);
 
-  resource_manager& rmgr = oct_qobj.get_resource_manager ();
+  gui_settings settings;
 
   m_message->setText
     (tr ("<html><body>\n"
@@ -179,7 +171,7 @@
          "Click 'Next' to create a configuration file and launch Octave.</p>\n"
          "<p>The configuration file is stored in<br>%1.</p>\n"
          "</body></html>").
-     arg (rmgr.get_settings_file ()));
+     arg (settings.file_name ()));
   m_message->setWordWrap (true);
   m_message->setMinimumWidth (400);
 
@@ -217,8 +209,7 @@
   connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject);
 }
 
-setup_community_news::setup_community_news (base_qobject&,
-                                            welcome_wizard *wizard)
+setup_community_news::setup_community_news (welcome_wizard *wizard)
   : QWidget (wizard),
     m_title (new QLabel (tr ("Community News"), this)),
     m_message (new QLabel (this)),
@@ -257,7 +248,7 @@
 
   QHBoxLayout *checkbox_layout = new QHBoxLayout;
 
-  bool allow_connection = nr_allow_connection.def.toBool ();
+  bool allow_connection = nr_allow_connection.def ().toBool ();
   if (allow_connection)
     m_checkbox->setCheckState (Qt::Checked);
   else
@@ -311,7 +302,7 @@
   connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject);
 }
 
-final_page::final_page (base_qobject&, welcome_wizard *wizard)
+final_page::final_page (welcome_wizard *wizard)
   : QWidget (wizard),
     m_title (new QLabel (tr ("Enjoy!"), this)),
     m_message (new QLabel (this)),
--- a/libgui/src/welcome-wizard.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/welcome-wizard.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,26 +32,22 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class welcome_wizard : public QDialog
 {
   Q_OBJECT
 
 public:
 
-  typedef QWidget *(*page_creator_fptr) (base_qobject&, welcome_wizard *);
+  typedef QWidget *(*page_creator_fptr) (welcome_wizard *);
 
-  welcome_wizard (base_qobject& oct_qobj, QWidget *parent = nullptr);
+  welcome_wizard (QWidget *parent = nullptr);
 
-  ~welcome_wizard (void) = default;
+  ~welcome_wizard () = default;
 
-  void adjust_size (void);
+  void adjust_size ();
 
 private:
 
-  base_qobject& m_octave_qobj;
-
   QList<page_creator_fptr> m_page_ctor_list;
   QList<page_creator_fptr>::iterator m_page_list_iterator;
   QWidget *m_current_page;
@@ -63,11 +59,11 @@
 
   void handle_web_connect_option (int state);
 
-  void show_page (void);
-  void previous_page (void);
-  void next_page (void);
+  void show_page ();
+  void previous_page ();
+  void next_page ();
 
-  void accept (void);
+  void accept ();
 };
 
 class initial_page : public QWidget
@@ -76,14 +72,14 @@
 
 public:
 
-  initial_page (base_qobject& oct_qobj, welcome_wizard *wizard);
+  initial_page (welcome_wizard *wizard);
 
-  ~initial_page (void) = default;
+  ~initial_page () = default;
 
   static QWidget *
-  create (base_qobject& oct_qobj, welcome_wizard *wizard)
+  create (welcome_wizard *wizard)
   {
-    return new initial_page (oct_qobj, wizard);
+    return new initial_page (wizard);
   }
 
 private:
@@ -101,14 +97,14 @@
 
 public:
 
-  setup_community_news (base_qobject& oct_qobj, welcome_wizard *wizard);
+  setup_community_news (welcome_wizard *wizard);
 
-  ~setup_community_news (void) = default;
+  ~setup_community_news () = default;
 
   static QWidget *
-  create (base_qobject& oct_qobj, welcome_wizard *wizard)
+  create (welcome_wizard *wizard)
   {
-    return new setup_community_news (oct_qobj, wizard);
+    return new setup_community_news (wizard);
   }
 
 private:
@@ -129,14 +125,14 @@
 
 public:
 
-  final_page (base_qobject& oct_qobj, welcome_wizard *wizard);
+  final_page (welcome_wizard *wizard);
 
-  ~final_page (void) = default;
+  ~final_page () = default;
 
   static QWidget *
-  create (base_qobject& oct_qobj, welcome_wizard *wizard)
+  create (welcome_wizard *wizard)
   {
-    return new final_page (oct_qobj, wizard);
+    return new final_page (wizard);
   }
 
 private:
--- a/libgui/src/workspace-model.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/workspace-model.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,13 +27,13 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <sstream>
 
 #include <QTreeWidget>
+#include <QToolTip>
 
 #include "gui-preferences-ws.h"
 #include "gui-settings.h"
-#include "octave-qobject.h"
 #include "workspace-model.h"
 
 #include "syminfo.h"
@@ -42,7 +42,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 workspace_model::workspace_model (QObject *p)
-: QAbstractTableModel (p)
+  : QAbstractTableModel (p)
 {
   // The header names. Use tr () again when accessing them since
   // the translator si not yet initialized when this ctor is called
@@ -191,22 +191,24 @@
 }
 
 void
-workspace_model::clear_workspace (void)
+workspace_model::clear_workspace ()
 {
   clear_data ();
   update_table ();
 }
 
 void
-workspace_model::notice_settings (const gui_settings *settings)
+workspace_model::notice_settings ()
 {
-  m_enable_colors = settings->value (ws_enable_colors).toBool ();
+  gui_settings settings;
 
-  int mode = settings->value (ws_color_mode).toInt ();
+  m_enable_colors = settings.bool_value (ws_enable_colors);
+
+  int mode = settings.int_value (ws_color_mode);
 
   for (int i = 0; i < ws_colors_count; i++)
     {
-      QColor setting_color = settings->color_value (ws_colors[i], mode);
+      QColor setting_color = settings.color_value (ws_colors[i], mode);
 
       QPalette p (setting_color);
       m_storage_class_colors.replace (i, setting_color);
@@ -218,7 +220,19 @@
 }
 
 void
-workspace_model::clear_data (void)
+workspace_model::show_symbol_tooltip (const QPoint& pos,
+                                      const QString& symbol)
+{
+  int symbol_idx = m_symbols.indexOf (symbol);
+
+  if (symbol_idx > -1)
+    QToolTip::showText (pos, symbol + " = " + m_values.at (symbol_idx));
+  else
+    QToolTip::hideText ();
+}
+
+void
+workspace_model::clear_data ()
 {
   m_top_level = false;
   m_syminfo_list = symbol_info_list ();
@@ -231,7 +245,7 @@
 }
 
 void
-workspace_model::update_table (void)
+workspace_model::update_table ()
 {
   beginResetModel ();
 
--- a/libgui/src/workspace-model.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/workspace-model.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,8 +34,6 @@
 #include <QStringList>
 #include <QVector>
 
-#include "gui-settings.h"
-
 #include "syminfo.h"
 
 // Defined for purposes of sending QList<int> as part of signal.
@@ -51,7 +49,7 @@
 
   workspace_model (QObject *parent = nullptr);
 
-  ~workspace_model (void) = default;
+  ~workspace_model () = default;
 
   int rowCount (const QModelIndex& parent = QModelIndex ()) const;
 
@@ -64,36 +62,38 @@
 
   QVariant data (const QModelIndex& index, int role) const;
 
-  bool is_top_level (void) const { return m_top_level; }
+  bool is_top_level () const { return m_top_level; }
 
   QColor storage_class_color (int s_class)
   {
     return m_storage_class_colors.at (s_class);
   }
 
-  symbol_info_list get_symbol_info (void) const { return m_syminfo_list; }
+  symbol_info_list get_symbol_info () const { return m_syminfo_list; }
 
-  QStringList get_symbol_names (void) const { return m_symbols; }
-  QStringList get_symbol_values (void) const { return m_values; }
+  QStringList get_symbol_names () const { return m_symbols; }
+  QStringList get_symbol_values () const { return m_values; }
 
 signals:
 
-  void model_changed (void);
-  void prompt_variable_editor(void);
+  void model_changed ();
+  void prompt_variable_editor();
 
 public slots:
 
   void set_workspace (bool top_level, bool debug,
                       const symbol_info_list& syminfo);
 
-  void clear_workspace (void);
+  void clear_workspace ();
 
-  void notice_settings (const gui_settings *);
+  void notice_settings ();
+
+  void show_symbol_tooltip (const QPoint& pos, const QString& symbol);
 
 private:
 
-  void clear_data (void);
-  void update_table (void);
+  void clear_data ();
+  void update_table ();
 
   bool m_top_level;
   symbol_info_list m_syminfo_list;
--- a/libgui/src/workspace-view.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/workspace-view.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,25 +42,24 @@
 #include <QVBoxLayout>
 
 #include "gui-preferences-ws.h"
-#include "octave-qobject.h"
-#include "octave-qtutils.h"
+#include "gui-settings.h"
 #include "workspace-view.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-workspace_view::workspace_view (QWidget *p, base_qobject& oct_qobj)
-: octave_dock_widget ("WorkspaceView", p, oct_qobj),
-  m_view (new QTableView (this)),
-  m_filter_checkbox (new QCheckBox ()),
-  m_filter (new QComboBox (this)),
-  m_filter_widget (new QWidget (this))
+workspace_view::workspace_view (QWidget *p)
+  : octave_dock_widget ("WorkspaceView", p),
+    m_view (new QTableView (this)),
+    m_filter_checkbox (new QCheckBox ()),
+    m_filter (new QComboBox (this)),
+    m_filter_widget (new QWidget (this))
 {
   set_title (tr ("Workspace"));
   setStatusTip (tr ("View the variables in the active workspace."));
 
   m_filter->setToolTip (tr ("Enter text to filter the workspace"));
   m_filter->setEditable (true);
-  m_filter->setMaxCount (ws_max_filter_history.def.toInt ());
+  m_filter->setMaxCount (ws_max_filter_history.def ().toInt ());
   m_filter->setInsertPolicy (QComboBox::NoInsert);
   m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
   QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
@@ -85,7 +84,7 @@
   filter_layout->addWidget (filter_label);
   filter_layout->addWidget (m_filter_checkbox);
   filter_layout->addWidget (m_filter);
-  filter_layout->setMargin (0);
+  filter_layout->setContentsMargins (0, 0, 0, 0);
 
   m_filter_widget->setLayout (filter_layout);
 
@@ -94,51 +93,46 @@
   ws_layout->addWidget (m_view);
   ws_layout->setSpacing (0);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  if (settings)
-    {
-      m_filter_shown = settings->value (ws_filter_shown).toBool ();
-      m_filter_widget->setVisible (m_filter_shown);
+  m_filter_shown = settings.bool_value (ws_filter_shown);
+  m_filter_widget->setVisible (m_filter_shown);
 
-      ws_layout->setMargin (2);
+  ws_layout->setContentsMargins (2, 2, 2, 2);
 
-      // Set the empty widget to have our layout.
-      widget ()->setLayout (ws_layout);
+  // Set the empty widget to have our layout.
+  widget ()->setLayout (ws_layout);
 
-      // Initialize collapse/expand state of the workspace subcategories.
+  // Initialize collapse/expand state of the workspace subcategories.
 
-      //enable sorting (setting column and order after model was set)
-      m_view->setSortingEnabled (true);
-      // Initialize column order and width of the workspace
-      m_view->horizontalHeader ()->restoreState
-        (settings->value (ws_column_state.key).toByteArray ());
+  //enable sorting (setting column and order after model was set)
+  m_view->setSortingEnabled (true);
+  // Initialize column order and width of the workspace
+  m_view->horizontalHeader ()->restoreState
+    (settings.value (ws_column_state.settings_key ()).toByteArray ());
 
-      // Set header properties for sorting
-      m_view->horizontalHeader ()->setSectionsClickable (true);
-      m_view->horizontalHeader ()->setSectionsMovable (true);
-      m_view->horizontalHeader ()->setSortIndicator (
-                                                     settings->value (ws_sort_column).toInt (),
-                                                     static_cast<Qt::SortOrder> (settings->value (ws_sort_order).toUInt ()));
-      // FIXME: use value<Qt::SortOrder> instead of static cast after
-      //        dropping support of Qt 5.4
+  // Set header properties for sorting
+  m_view->horizontalHeader ()->setSectionsClickable (true);
+  m_view->horizontalHeader ()->setSectionsMovable (true);
+  m_view->horizontalHeader ()->setSortIndicator
+    (settings.int_value (ws_sort_column),
+     static_cast<Qt::SortOrder> (settings.uint_value (ws_sort_order)));
+  // FIXME: use value<Qt::SortOrder> instead of static cast after
+  //        dropping support of Qt 5.4
 
-      m_view->horizontalHeader ()->setSortIndicatorShown (true);
+  m_view->horizontalHeader ()->setSortIndicatorShown (true);
 
-      m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);
-      connect (m_view->horizontalHeader (),
-               &QTableView::customContextMenuRequested,
-               this, &workspace_view::header_contextmenu_requested);
+  m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);
+  connect (m_view->horizontalHeader (),
+           &QTableView::customContextMenuRequested,
+           this, &workspace_view::header_contextmenu_requested);
 
-      // Init state of the filter
-      m_filter->addItems (settings->value (ws_mru_list.key).toStringList ());
+  // Init state of the filter
+  m_filter->addItems (settings.value (ws_mru_list.settings_key ()).toStringList ());
 
-      bool filter_state =
-        settings->value (ws_filter_active).toBool ();
-      m_filter_checkbox->setChecked (filter_state);
-      filter_activate (filter_state);
-    }
+  bool filter_state = settings.bool_value (ws_filter_active);
+  m_filter_checkbox->setChecked (filter_state);
+  filter_activate (filter_state);
 
   // Connect signals and slots.
 
@@ -167,29 +161,32 @@
   m_view->setModel (&m_filter_model);
 
   // set the sorting after the model is set, it would be ignored otherwise
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
-  m_view->sortByColumn (
-                        settings->value (ws_sort_column).toInt (),
-                        static_cast<Qt::SortOrder> (settings->value (ws_sort_order).toUInt ()));
-  // FIXME: use value<Qt::SortOrder> instead of static cast after
-  //        dropping support of Qt 5.4
+
+  gui_settings settings;
+
+  m_view->sortByColumn
+    (settings.int_value (ws_sort_column),
+     static_cast<Qt::SortOrder> (settings.uint_value (ws_sort_order)));
+    // FIXME: use value<Qt::SortOrder> instead of static cast after
+    //        dropping support of Qt 5.4
 
   m_model = model;
 }
 
 void
-workspace_view::notice_settings (const gui_settings *settings)
+workspace_view::notice_settings ()
 {
-  m_model->notice_settings (settings); // update colors of model first
+  gui_settings settings;
+
+  m_model->notice_settings (); // update colors of model first
 
   for (int i = 0; i < ws_columns_shown.length (); i++)
-    m_view->setColumnHidden (i + 1, ! settings->value (ws_columns_shown_keys.at (i), true).toBool ());
+    m_view->setColumnHidden (i + 1, ! settings.value (ws_columns_shown_keys.at (i), true).toBool ());
 
   QString tool_tip;
 
-  if (settings->value (ws_enable_colors).toBool ()
-      && ! settings->value (ws_hide_tool_tips).toBool ())
+  if (settings.bool_value (ws_enable_colors)
+      && ! settings.bool_value (ws_hide_tool_tips))
     {
       tool_tip  = QString (tr ("View the variables in the active workspace.<br>"));
       tool_tip += QString (tr ("Colors for variable attributes:"));
@@ -209,31 +206,27 @@
 }
 
 void
-workspace_view::save_settings (void)
+workspace_view::save_settings ()
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
-  if (! settings)
-    return;
-
-  settings->setValue (ws_column_state.key,
-                      m_view->horizontalHeader ()->saveState ());
+  settings.setValue (ws_column_state.settings_key (),
+                     m_view->horizontalHeader ()->saveState ());
 
   int sort_column = m_view->horizontalHeader ()->sortIndicatorSection ();
   Qt::SortOrder sort_order = m_view->horizontalHeader ()->sortIndicatorOrder ();
-  settings->setValue (ws_sort_column.key, sort_column);
-  settings->setValue (ws_sort_order.key, sort_order);
+  settings.setValue (ws_sort_column.settings_key (), sort_column);
+  settings.setValue (ws_sort_order.settings_key (), sort_order);
 
-  settings->setValue (ws_filter_active.key, m_filter_checkbox->isChecked ());
-  settings->setValue (ws_filter_shown.key, m_filter_shown);
+  settings.setValue (ws_filter_active.settings_key (), m_filter_checkbox->isChecked ());
+  settings.setValue (ws_filter_shown.settings_key (), m_filter_shown);
 
   QStringList mru;
   for (int i = 0; i < m_filter->count (); i++)
     mru.append (m_filter->itemText (i));
-  settings->setValue (ws_mru_list.key, mru);
+  settings.setValue (ws_mru_list.settings_key (), mru);
 
-  settings->sync ();
+  settings.sync ();
 
   octave_dock_widget::save_settings ();
 }
@@ -274,7 +267,7 @@
 }
 
 void
-workspace_view::update_filter_history (void)
+workspace_view::update_filter_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -292,8 +285,7 @@
   QMenu menu (this);
   QSignalMapper sig_mapper (this);
 
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   for (int i = 0; i < ws_columns_shown.length (); i++)
     {
@@ -302,7 +294,7 @@
                           &sig_mapper, SLOT (map ()));
       sig_mapper.setMapping (action, i);
       action->setCheckable (true);
-      action->setChecked (settings->value (ws_columns_shown_keys.at (i), true).toBool ());
+      action->setChecked (settings.value (ws_columns_shown_keys.at (i), true).toBool ());
     }
 
   // FIXME: We could use
@@ -328,16 +320,15 @@
 void
 workspace_view::toggle_header (int col)
 {
-  resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
-  gui_settings *settings = rmgr.get_settings ();
+  gui_settings settings;
 
   QString key = ws_columns_shown_keys.at (col);
-  bool shown = settings->value (key, true).toBool ();
+  bool shown = settings.value (key, true).toBool ();
 
   m_view->setColumnHidden (col + 1, shown);
 
-  settings->setValue (key, ! shown);
-  settings->sync ();
+  settings.setValue (key, ! shown);
+  settings.sync ();
 
   octave_dock_widget::save_settings ();
 }
@@ -404,7 +395,7 @@
 }
 
 void
-workspace_view::handle_contextmenu_copy (void)
+workspace_view::handle_contextmenu_copy ()
 {
   QModelIndex index = m_view->currentIndex ();
 
@@ -419,7 +410,7 @@
 }
 
 void
-workspace_view::handle_contextmenu_copy_value (void)
+workspace_view::handle_contextmenu_copy_value ()
 {
   QModelIndex index = m_view->currentIndex ();
 
@@ -428,7 +419,7 @@
 }
 
 void
-workspace_view::handle_contextmenu_rename (void)
+workspace_view::handle_contextmenu_rename ()
 {
   QModelIndex index = m_view->currentIndex ();
 
@@ -452,7 +443,7 @@
 }
 
 void
-workspace_view::handle_contextmenu_edit (void)
+workspace_view::handle_contextmenu_edit ()
 {
   QModelIndex index = m_view->currentIndex ();
 
@@ -461,31 +452,31 @@
 }
 
 void
-workspace_view::handle_contextmenu_clear (void)
+workspace_view::handle_contextmenu_clear ()
 {
   relay_contextmenu_command ("clear", true);
 }
 
 void
-workspace_view::handle_contextmenu_disp (void)
+workspace_view::handle_contextmenu_disp ()
 {
   relay_contextmenu_command ("disp");
 }
 
 void
-workspace_view::handle_contextmenu_plot (void)
+workspace_view::handle_contextmenu_plot ()
 {
   relay_contextmenu_command ("figure (); plot");
 }
 
 void
-workspace_view::handle_contextmenu_stem (void)
+workspace_view::handle_contextmenu_stem ()
 {
   relay_contextmenu_command ("figure (); stem");
 }
 
 void
-workspace_view::handle_contextmenu_filter (void)
+workspace_view::handle_contextmenu_filter ()
 {
   m_filter_shown = ! m_filter_shown;
   m_filter_widget->setVisible (m_filter_shown);
@@ -494,7 +485,7 @@
 }
 
 void
-workspace_view::handle_model_changed (void)
+workspace_view::handle_model_changed ()
 {
   // m_view->resizeRowsToContents ();
   // Just modify those rows that have been added rather than go through
--- a/libgui/src/workspace-view.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libgui/src/workspace-view.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,17 +39,15 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class base_qobject;
-
 class workspace_view : public octave_dock_widget
 {
   Q_OBJECT
 
 public:
 
-  workspace_view (QWidget *parent, base_qobject& oct_qobj);
+  workspace_view (QWidget *parent);
 
-  ~workspace_view (void) = default;
+  ~workspace_view () = default;
 
 signals:
 
@@ -74,15 +72,15 @@
 
   void setModel (workspace_model *model);
 
-  void notice_settings (const gui_settings *);
+  void notice_settings ();
 
-  void save_settings (void);
+  void save_settings ();
 
 protected slots:
 
   void filter_update (const QString& expression);
   void filter_activate (bool enable);
-  void update_filter_history (void);
+  void update_filter_history ();
 
   void header_contextmenu_requested (const QPoint& mpos);
 
@@ -90,22 +88,22 @@
 
   void contextmenu_requested (const QPoint& pos);
 
-  void handle_contextmenu_copy (void);
-  void handle_contextmenu_copy_value (void);
-  void handle_contextmenu_rename (void);
-  void handle_contextmenu_edit (void);
-  void handle_contextmenu_clear (void);
-  void handle_contextmenu_disp (void);
-  void handle_contextmenu_plot (void);
-  void handle_contextmenu_stem (void);
-  void handle_contextmenu_filter (void);
+  void handle_contextmenu_copy ();
+  void handle_contextmenu_copy_value ();
+  void handle_contextmenu_rename ();
+  void handle_contextmenu_edit ();
+  void handle_contextmenu_clear ();
+  void handle_contextmenu_disp ();
+  void handle_contextmenu_plot ();
+  void handle_contextmenu_stem ();
+  void handle_contextmenu_filter ();
 
 public slots:
 
-  void handle_model_changed (void);
+  void handle_model_changed ();
 
-  void copyClipboard (void);
-  void selectAll (void);
+  void copyClipboard ();
+  void selectAll ();
 
 private:
 
--- a/libinterp/build-env.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/build-env.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(build_env)
 
-extern OCTINTERP_API octave_scalar_map features (void);
+extern OCTINTERP_API octave_scalar_map features ();
 
 extern OCTINTERP_API const char *AMD_CPPFLAGS;
 extern OCTINTERP_API const char *AMD_LDFLAGS;
@@ -144,7 +144,6 @@
 extern OCTINTERP_API const char *QT_CPPFLAGS;
 extern OCTINTERP_API const char *QT_LDFLAGS;
 extern OCTINTERP_API const char *QT_LIBS;
-extern OCTINTERP_API const char *QT_OPENGL_LIBS;
 extern OCTINTERP_API const char *RANLIB;
 extern OCTINTERP_API const char *RDYNAMIC_FLAG;
 extern OCTINTERP_API const char *READLINE_LIBS;
--- a/libinterp/build-env.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/build-env.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -251,8 +251,6 @@
 
 const char *QT_LIBS = %OCTAVE_CONF_QT_LIBS%;
 
-const char *QT_OPENGL_LIBS = %OCTAVE_CONF_QT_OPENGL_LIBS%;
-
 const char *RANLIB = %OCTAVE_CONF_RANLIB%;
 
 const char *RDYNAMIC_FLAG = %OCTAVE_CONF_RDYNAMIC_FLAG%;
--- a/libinterp/corefcn/Cell.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/Cell.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -123,7 +123,7 @@
 }
 
 bool
-Cell::iscellstr (void) const
+Cell::iscellstr () const
 {
   bool retval = true;
 
@@ -142,7 +142,7 @@
 }
 
 Array<std::string>
-Cell::cellstr_value (void) const
+Cell::cellstr_value () const
 {
   Array<std::string> retval (dims ());
 
@@ -155,7 +155,7 @@
 }
 
 string_vector
-Cell::string_vector_value (void) const
+Cell::string_vector_value () const
 {
   octave_idx_type n = numel ();
 
@@ -288,7 +288,7 @@
 }
 
 octave_idx_type
-Cell::nnz (void) const
+Cell::nnz () const
 {
   err_wrong_type_arg ("nnz", "cell array");
 }
@@ -355,7 +355,7 @@
 }
 
 octave_value
-Cell::resize_fill_value (void) const
+Cell::resize_fill_value () const
 {
   static octave_value rfv = octave_value (Matrix ());
   return rfv;
--- a/libinterp/corefcn/Cell.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/Cell.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,13 +43,13 @@
 {
 public:
 
-  Cell (void) = default;
+  Cell () = default;
 
   Cell (const Cell& c) = default;
 
   Cell& operator = (const Cell& c) = default;
 
-  ~Cell (void) = default;
+  ~Cell () = default;
 
   Cell (const octave_value& val)
     : Array<octave_value> (dim_vector (1, 1), val) { }
@@ -97,11 +97,11 @@
 
   Cell (const dim_vector& dv, const string_vector& sv, bool trim = false);
 
-  bool iscellstr (void) const;
+  bool iscellstr () const;
 
-  Array<std::string> cellstr_value (void) const;
+  Array<std::string> cellstr_value () const;
 
-  string_vector string_vector_value (void) const;
+  string_vector string_vector_value () const;
 
   using Array<octave_value>::index;
 
@@ -119,7 +119,7 @@
   Cell reshape (const dim_vector& new_dims) const
   { return Array<octave_value>::reshape (new_dims); }
 
-  octave_idx_type nnz (void) const;
+  octave_idx_type nnz () const;
 
   Cell column (octave_idx_type i) const;
 
@@ -135,33 +135,33 @@
   Cell& insert (const Cell& a, const Array<octave_idx_type>& ra_idx);
 
   // FIXME
-  bool any_element_is_nan (void) const { return false; }
-  bool is_true (void) const { return false; }
+  bool any_element_is_nan () const { return false; }
+  bool is_true () const { return false; }
 
-  octave_value resize_fill_value (void) const;
+  octave_value resize_fill_value () const;
 
   Cell diag (octave_idx_type k = 0) const;
 
   Cell diag (octave_idx_type m, octave_idx_type n) const;
 
-  Cell xisalnum (void) const { return map (&octave_value::xisalnum); }
-  Cell xisalpha (void) const { return map (&octave_value::xisalpha); }
-  Cell xisascii (void) const { return map (&octave_value::xisascii); }
-  Cell xiscntrl (void) const { return map (&octave_value::xiscntrl); }
-  Cell xisdigit (void) const { return map (&octave_value::xisdigit); }
-  Cell xisgraph (void) const { return map (&octave_value::xisgraph); }
-  Cell xislower (void) const { return map (&octave_value::xislower); }
-  Cell xisprint (void) const { return map (&octave_value::xisprint); }
-  Cell xispunct (void) const { return map (&octave_value::xispunct); }
-  Cell xisspace (void) const { return map (&octave_value::xisspace); }
-  Cell xisupper (void) const { return map (&octave_value::xisupper); }
-  Cell xisxdigit (void) const { return map (&octave_value::xisxdigit); }
-  Cell xtolower (void) const { return map (&octave_value::xtolower); }
-  Cell xtoupper (void) const { return map (&octave_value::xtoupper); }
+  Cell xisalnum () const { return map (&octave_value::xisalnum); }
+  Cell xisalpha () const { return map (&octave_value::xisalpha); }
+  Cell xisascii () const { return map (&octave_value::xisascii); }
+  Cell xiscntrl () const { return map (&octave_value::xiscntrl); }
+  Cell xisdigit () const { return map (&octave_value::xisdigit); }
+  Cell xisgraph () const { return map (&octave_value::xisgraph); }
+  Cell xislower () const { return map (&octave_value::xislower); }
+  Cell xisprint () const { return map (&octave_value::xisprint); }
+  Cell xispunct () const { return map (&octave_value::xispunct); }
+  Cell xisspace () const { return map (&octave_value::xisspace); }
+  Cell xisupper () const { return map (&octave_value::xisupper); }
+  Cell xisxdigit () const { return map (&octave_value::xisxdigit); }
+  Cell xtolower () const { return map (&octave_value::xtolower); }
+  Cell xtoupper () const { return map (&octave_value::xtoupper); }
 
 private:
 
-  typedef octave_value (octave_value::*ctype_mapper) (void) const;
+  typedef octave_value (octave_value::*ctype_mapper) () const;
 
   Cell map (ctype_mapper) const;
 };
--- a/libinterp/corefcn/__contourc__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/__contourc__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -71,7 +71,7 @@
 // Add contents of current contour to contourc.
 // this_contour.cols () - 1;
 static void
-end_contour (void)
+end_contour ()
 {
   if (elem > 2)
     {
--- a/libinterp/corefcn/__eigs__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/__eigs__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,6 +53,10 @@
 {
 public:
 
+  eigs_callback (octave::interpreter& interp)
+    : m_interpreter (interp)
+  { }
+
   ColumnVector
   eigs_func (const ColumnVector& x, int& eigs_error);
 
@@ -61,6 +65,8 @@
 
   //--------
 
+  octave::interpreter& m_interpreter;
+
   // Pointer for user defined function.
   octave_value m_eigs_fcn;
 
@@ -84,7 +90,7 @@
 
       try
         {
-          tmp = octave::feval (m_eigs_fcn, args, 1);
+          tmp = m_interpreter.feval (m_eigs_fcn, args, 1);
         }
       catch (octave::execution_exception& ee)
         {
@@ -125,7 +131,7 @@
 
       try
         {
-          tmp = octave::feval (m_eigs_fcn, args, 1);
+          tmp = m_interpreter.feval (m_eigs_fcn, args, 1);
         }
       catch (octave::execution_exception& ee)
         {
@@ -213,7 +219,7 @@
   ComplexColumnVector cresid;
   octave_idx_type info = 1;
 
-  eigs_callback callback;
+  eigs_callback callback (interp);
 
   unwind_protect_var<int> restore_var (call_depth);
   call_depth++;
--- a/libinterp/corefcn/__ftp__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/__ftp__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -367,12 +367,10 @@
     {
       std::string file = files(i);
 
-      sys::file_stat fs (file);
-
-      if (! fs.exists ())
+      if (! sys::file_exists (file))
         error ("__ftp__mput: file does not exist");
 
-      if (fs.is_dir ())
+      if (sys::dir_exists (file))
         {
           file_list.append (url_xfer.mput_directory ("", file));
 
--- a/libinterp/corefcn/__ichol__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/__ichol__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -117,7 +117,7 @@
         iw[ridx[j]] = j;
 
       jrow = Llist[k];
-      // Iterate over each non-zero element in the actual row.
+      // Iterate over each nonzero element in the actual row.
       while (jrow != -1)
         {
           jjrow = Lfirst[jrow];
@@ -201,7 +201,7 @@
   // matrix is used to build the output matrix due to that fact.
   if (! args(0).iscomplex ())
     {
-      SparseMatrix sm = Ftril (args(0))(0).sparse_matrix_value ();
+      SparseMatrix sm = Ftril (ovl (args(0)))(0).sparse_matrix_value ();
       ichol_0 <SparseMatrix, double, ichol_mult_real,
               ichol_checkpivot_real> (sm, michol);
       return ovl (sm);
@@ -209,7 +209,7 @@
   else
     {
       SparseComplexMatrix sm
-        = Ftril (args(0))(0).sparse_complex_matrix_value ();
+        = Ftril (ovl (args(0)))(0).sparse_complex_matrix_value ();
       ichol_0 <SparseComplexMatrix, Complex, ichol_mult_complex,
               ichol_checkpivot_complex> (sm, michol);
       return ovl (sm);
@@ -296,8 +296,8 @@
             {
               j = ridx_l[jj];
               // If the element in the j position of the row is zero,
-              // then it will become non-zero, so we add it to the
-              // vector that tracks non-zero elements in the working row.
+              // then it will become nonzero, so we add it to the
+              // vector that tracks nonzero elements in the working row.
               if (! mark[j])
                 {
                   mark[j] = true;
@@ -330,7 +330,7 @@
           ridx_l = ridx_out_l.fortran_vec ();
         }
 
-      // The sorting of the non-zero elements of the working column can be
+      // The sorting of the nonzero elements of the working column can be
       // handled in a couple of ways.  The most efficient two I found, are
       // keeping the elements in an ordered binary search tree dynamically or
       // keep them unsorted in a vector and at the end of the outer iteration
@@ -341,7 +341,7 @@
       ridx_l[total_len] = k;
       w_len = 1;
 
-      // Extract the non-zero elements of working column and
+      // Extract the nonzero elements of working column and
       // drop the elements that are lower than droptol * cols_norm[k].
       for (i = 0; i < ind ; i++)
         {
@@ -434,7 +434,7 @@
   if (! args(0).iscomplex ())
     {
       SparseMatrix L;
-      SparseMatrix sm_l = Ftril (args(0))(0).sparse_matrix_value ();
+      SparseMatrix sm_l = Ftril (ovl (args(0)))(0).sparse_matrix_value ();
       RowVector sm_col_norms = xcolnorms (sm_l, 1);
       ichol_t <SparseMatrix,
               double, ichol_mult_real, ichol_checkpivot_real>
@@ -446,7 +446,7 @@
     {
       SparseComplexMatrix L;
       SparseComplexMatrix sm_l
-        = Ftril (args(0))(0).sparse_complex_matrix_value ();
+        = Ftril (ovl (args(0)))(0).sparse_complex_matrix_value ();
       Array <Complex> cols_norm = xcolnorms (sm_l, 1);
       ichol_t <SparseComplexMatrix,
               Complex, ichol_mult_complex, ichol_checkpivot_complex>
--- a/libinterp/corefcn/__magick_read__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/__magick_read__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -181,6 +181,8 @@
 {
 public:
 
+  image_region () = delete;
+
   image_region (const octave_scalar_map& options)
   {
     // FIXME: should we have better checking on the input map and values
@@ -208,36 +210,28 @@
     m_col_out = cols.numel ();
   }
 
-  // Default copy, move, and delete methods are all OK for this class.
-
-  image_region (const image_region&) = default;
-  image_region (image_region&&) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (image_region)
 
-  image_region& operator = (const image_region&) = default;
-  image_region& operator = (image_region&&) = default;
-
-  ~image_region (void) = default;
-
-  octave_idx_type row_start (void) const { return m_row_start; }
-  octave_idx_type col_start (void) const { return m_col_start; }
-  octave_idx_type row_end (void) const { return m_row_end; }
-  octave_idx_type col_end (void) const { return m_col_end; }
+  octave_idx_type row_start () const { return m_row_start; }
+  octave_idx_type col_start () const { return m_col_start; }
+  octave_idx_type row_end () const { return m_row_end; }
+  octave_idx_type col_end () const { return m_col_end; }
 
   // Length of the area to load into the Image Pixel Cache.  We use max and
   // min to account for cases where last element of range is the range limit.
 
-  octave_idx_type row_cache (void) const { return m_row_cache; }
-  octave_idx_type col_cache (void) const { return m_col_cache; }
+  octave_idx_type row_cache () const { return m_row_cache; }
+  octave_idx_type col_cache () const { return m_col_cache; }
 
   // How much we have to shift in the memory when doing the loops.
 
-  octave_idx_type row_shift (void) const { return m_row_shift; }
-  octave_idx_type col_shift (void) const { return m_col_shift; }
+  octave_idx_type row_shift () const { return m_row_shift; }
+  octave_idx_type col_shift () const { return m_col_shift; }
 
   // The actual height and width of the output image
 
-  octave_idx_type row_out (void) const { return m_row_out; }
-  octave_idx_type col_out (void) const { return m_col_out; }
+  octave_idx_type row_out () const { return m_row_out; }
+  octave_idx_type col_out () const { return m_col_out; }
 
 private:
 
@@ -343,7 +337,7 @@
   retval(0) = octave_value (img);
 
   // Only bother reading the colormap if it was requested as output.
-  if (nargout > 1)
+  if (nargout >= 2)
     {
       // In theory, it should be possible for each frame of an image to
       // have different colormaps but for Matlab compatibility, we only
@@ -355,22 +349,31 @@
 
       retval(1) = maps(0);
 
-      // only interpret alpha channel if it exists and was requested as output
-      if (imvec[def_elem].matte () && nargout >= 3)
+      // only interpret alpha channel if it was requested as output
+      if (nargout >= 3)
         {
-          const Matrix amap = maps(1).matrix_value ();
-          const double *amap_fvec = amap.data ();
+          if (imvec[def_elem].matte ())
+            {
+              // Alpha channel exists.
+              const Matrix amap = maps(1).matrix_value ();
+              const double *amap_fvec = amap.data ();
+
+              NDArray alpha (dim_vector (nRows, nCols, 1, nFrames));
+              double *alpha_fvec = alpha.fortran_vec ();
 
-          NDArray alpha (dim_vector (nRows, nCols, 1, nFrames));
-          double *alpha_fvec = alpha.fortran_vec ();
+              // GraphicsMagick stores the alpha values inverted, i.e.,
+              // 1 for transparent and 0 for opaque so we fix that here.
+              const octave_idx_type nPixels = alpha.numel ();
+              for (octave_idx_type pix = 0; pix < nPixels; pix++)
+                alpha_fvec[pix] = 1 - amap_fvec[static_cast<int> (img_fvec[3])];
 
-          // GraphicsMagick stores the alpha values inverted, i.e.,
-          // 1 for transparent and 0 for opaque so we fix that here.
-          const octave_idx_type nPixels = alpha.numel ();
-          for (octave_idx_type pix = 0; pix < nPixels; pix++)
-            alpha_fvec[pix] = 1 - amap_fvec[static_cast<int> (img_fvec[3])];
-
-          retval(2) = alpha;
+              retval(2) = alpha;
+            }
+          else
+            {
+              // No alpha channel.  Return empty matrix.
+              retval(2) = Matrix ();
+            }
         }
     }
 
@@ -785,7 +788,7 @@
 }
 
 static void
-maybe_initialize_magick (void)
+maybe_initialize_magick ()
 {
   static bool initialized = false;
 
@@ -1589,7 +1592,7 @@
   // If writemode is set to append, read the image and append to it.  Even
   // if set to append, make sure that something was read at all.
   const std::string writemode = options.getfield ("writemode").string_value ();
-  if (writemode == "append" && sys::file_stat (filename).exists ())
+  if (writemode == "append" && sys::file_exists (filename))
     {
       std::vector<Magick::Image> ini_imvec;
       read_file (filename, ini_imvec);
--- a/libinterp/corefcn/amd.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/amd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -132,8 +132,7 @@
   AMD_NAME (_defaults) (Control);
   if (nargin > 1)
     {
-      octave_scalar_map arg1 = args(
-                                 1).xscalar_map_value ("amd: OPTS argument must be a scalar structure");
+      octave_scalar_map arg1 = args(1).xscalar_map_value ("amd: OPTS argument must be a scalar structure");
 
       octave_value tmp;
 
--- a/libinterp/corefcn/auto-shlib.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/auto-shlib.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-auto_shlib::auto_shlib (void)
+auto_shlib::auto_shlib ()
   : dynamic_library (get_current_shlib ())
 { }
 
--- a/libinterp/corefcn/auto-shlib.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/auto-shlib.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,9 +43,9 @@
 {
 public:
 
-  auto_shlib (void);
+  auto_shlib ();
 
-  ~auto_shlib (void) = default;
+  ~auto_shlib () = default;
 
   auto_shlib (const auto_shlib&) = default;
 
--- a/libinterp/corefcn/base-text-renderer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/base-text-renderer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,15 +53,11 @@
     ROTATION_270 = 3
   };
 
-  base_text_renderer (void) : text_processor () { }
-
-  // No copying!
+  base_text_renderer () : text_processor () { }
 
-  base_text_renderer (const base_text_renderer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_text_renderer)
 
-  base_text_renderer& operator = (const base_text_renderer&) = delete;
-
-  virtual ~base_text_renderer (void) = default;
+  virtual ~base_text_renderer () = default;
 
   virtual void
   set_anti_aliasing (bool val) = 0;
@@ -78,10 +74,10 @@
             const std::string& angle, double size) = 0;
 
   virtual bool
-  ok (void) { return true; };
+  ok () { return true; };
 
   virtual octave_map
-  get_system_fonts (void) = 0;
+  get_system_fonts () = 0;
 
   virtual void set_color (const Matrix& c) = 0;
 
--- a/libinterp/corefcn/bsxfun.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/bsxfun.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,6 @@
 #include "oct-map.h"
 #include "ov-colon.h"
 #include "ov-fcn-handle.h"
-#include "parse.h"
 #include "unwind-prot.h"
 #include "variables.h"
 
@@ -131,7 +130,7 @@
     return octave_value (bsxfun_pow (xa, ya));
 }
 
-static void maybe_fill_table (void)
+static void maybe_fill_table ()
 {
   static bool filled = false;
   if (filled)
@@ -283,30 +282,6 @@
     }
 }
 
-#if 0
-// FIXME: this function is not used; is it OK to delete it?
-static void
-update_index (octave_value_list& idx, const dim_vector& dv, octave_idx_type i)
-{
-  octave_idx_type nd = dv.ndims ();
-
-  if (i == 0)
-    {
-      for (octave_idx_type j = nd - 1; j > 0; j--)
-        idx(j) = octave_value (1.0);
-      idx(0) = octave_value (':');
-    }
-  else
-    {
-      for (octave_idx_type j = 1; j < nd; j++)
-        {
-          idx (j) = octave_value (i % dv(j) + 1);
-          i /= dv(j);
-        }
-    }
-}
-#endif
-
 static void
 update_index (Array<int>& idx, const dim_vector& dv, octave_idx_type i)
 {
@@ -414,14 +389,14 @@
           octave_value_list inputs (2);
           inputs(0) = A;
           inputs(1) = B;
-          retval = feval (fcn, inputs, 1);
+          retval = interp.feval (fcn, inputs, 1);
         }
       else if (dvc.numel () < 1)
         {
           octave_value_list inputs (2);
           inputs(0) = A.resize (dvc);
           inputs(1) = B.resize (dvc);
-          retval = feval (fcn, inputs, 1);
+          retval = interp.feval (fcn, inputs, 1);
         }
       else
         {
@@ -463,7 +438,7 @@
               if (maybe_update_column (Bc, B, dvb, dvc, i, idxB))
                 inputs(1) = Bc;
 
-              octave_value_list tmp = feval (fcn, inputs, 1);
+              octave_value_list tmp = interp.feval (fcn, inputs, 1);
 
 #define BSXINIT(T, CLS, EXTRACTOR)                                      \
               (result_type == CLS)                                      \
--- a/libinterp/corefcn/c-file-ptr-stream.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 #  define SEEK_END 2
 #endif
 
-c_file_ptr_buf::~c_file_ptr_buf (void)
+c_file_ptr_buf::~c_file_ptr_buf ()
 {
   buf_close ();
 }
@@ -142,7 +142,7 @@
 }
 
 int
-c_file_ptr_buf::sync (void)
+c_file_ptr_buf::sync ()
 {
   flush ();
 
@@ -150,13 +150,13 @@
 }
 
 int
-c_file_ptr_buf::flush (void)
+c_file_ptr_buf::flush ()
 {
   return m_f ? std::fflush (m_f) : traits_type::eof ();
 }
 
 int
-c_file_ptr_buf::buf_close (void)
+c_file_ptr_buf::buf_close ()
 {
   int retval = -1;
 
@@ -178,7 +178,7 @@
 }
 
 off_t
-c_file_ptr_buf::tell (void)
+c_file_ptr_buf::tell ()
 {
   return m_f ? octave_ftello_wrapper (m_f) : -1;
 }
@@ -191,7 +191,7 @@
 
 #if defined (HAVE_ZLIB)
 
-c_zfile_ptr_buf::~c_zfile_ptr_buf (void)
+c_zfile_ptr_buf::~c_zfile_ptr_buf ()
 {
   buf_close ();
 }
@@ -253,39 +253,17 @@
                           std::ios::seekdir /* dir */,
                           std::ios::openmode)
 {
-  // FIXME
-#if 0
-  if (m_f)
-    {
-      gzseek (m_f, offset, seekdir_to_whence (dir));
-
-      return gztell (m_f);
-    }
-  else
-    return 0;
-#endif
   return -1;
 }
 
 std::streampos
 c_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
 {
-  // FIXME
-#if 0
-  if (m_f)
-    {
-      gzseek (m_f, offset, SEEK_SET);
-
-      return gztell (m_f);
-    }
-  else
-    return 0;
-#endif
   return -1;
 }
 
 int
-c_zfile_ptr_buf::sync (void)
+c_zfile_ptr_buf::sync ()
 {
   flush ();
 
@@ -293,7 +271,7 @@
 }
 
 int
-c_zfile_ptr_buf::flush (void)
+c_zfile_ptr_buf::flush ()
 {
   // FIXME: do we need something more complex here, passing
   // something other than 0 for the second argument to gzflush and
@@ -303,7 +281,7 @@
 }
 
 int
-c_zfile_ptr_buf::buf_close (void)
+c_zfile_ptr_buf::buf_close ()
 {
   int retval = -1;
 
--- a/libinterp/corefcn/c-file-ptr-stream.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,25 +46,23 @@
 
   typedef int (*close_fcn) (FILE *);
 
-  FILE * stdiofile (void) { return m_f; }
+  FILE * stdiofile () { return m_f; }
+
+  c_file_ptr_buf () = delete;
 
   c_file_ptr_buf (FILE *f, close_fcn cf = file_close)
     : std::streambuf (), m_f (f), m_cf (cf)
   { }
 
-  // No copying!
-
-  c_file_ptr_buf (const c_file_ptr_buf&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (c_file_ptr_buf)
 
-  c_file_ptr_buf& operator = (const c_file_ptr_buf&) = delete;
-
-  ~c_file_ptr_buf (void);
+  ~c_file_ptr_buf ();
 
   int_type overflow (int_type);
 
-  int_type underflow (void) { return underflow_common (false); }
+  int_type underflow () { return underflow_common (false); }
 
-  int_type uflow (void) { return underflow_common (true); }
+  int_type uflow () { return underflow_common (true); }
 
   int_type pbackfail (int_type);
 
@@ -78,19 +76,19 @@
   std::streampos seekpos (std::streampos,
                           std::ios::openmode = std::ios::in | std::ios::out);
 
-  int sync (void);
+  int sync ();
 
-  int flush (void);
+  int flush ();
 
-  int buf_close (void);
+  int buf_close ();
 
   int file_number () const { return m_f ? fileno (m_f) : -1; }
 
   int seek (off_t offset, int origin);
 
-  off_t tell (void);
+  off_t tell ();
 
-  void clear (void) { if (m_f) clearerr (m_f); }
+  void clear () { if (m_f) clearerr (m_f); }
 
   static int file_close (FILE *m_f);
 
@@ -113,29 +111,27 @@
 {
 public:
 
+  c_file_ptr_stream () = delete;
+
   c_file_ptr_stream (FILE_T m_f,
                      typename BUF_T::close_fcn m_cf = BUF_T::file_close)
     : STREAM_T (nullptr), m_buf (new BUF_T (m_f, m_cf))
   { STREAM_T::init (m_buf); }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (c_file_ptr_stream)
 
-  c_file_ptr_stream (const c_file_ptr_stream&) = delete;
-
-  c_file_ptr_stream& operator = (const c_file_ptr_stream&) = delete;
+  ~c_file_ptr_stream () { delete m_buf; m_buf = nullptr; }
 
-  ~c_file_ptr_stream (void) { delete m_buf; m_buf = nullptr; }
+  BUF_T * rdbuf () { return m_buf; }
 
-  BUF_T * rdbuf (void) { return m_buf; }
-
-  void stream_close (void) { if (m_buf) m_buf->buf_close (); }
+  void stream_close () { if (m_buf) m_buf->buf_close (); }
 
   int seek (off_t offset, int origin)
   { return m_buf ? m_buf->seek (offset, origin) : -1; }
 
-  off_t tell (void) { return m_buf ? m_buf->tell () : -1; }
+  off_t tell () { return m_buf ? m_buf->tell () : -1; }
 
-  void clear (void) { if (m_buf) m_buf->clear (); STREAM_T::clear (); }
+  void clear () { if (m_buf) m_buf->clear (); STREAM_T::clear (); }
 
 private:
 
@@ -161,25 +157,23 @@
 
   typedef int (*close_fcn) (gzFile);
 
-  gzFile stdiofile (void) { return m_f; }
+  gzFile stdiofile () { return m_f; }
+
+  c_zfile_ptr_buf () = delete;
 
   c_zfile_ptr_buf (gzFile f, close_fcn cf = file_close)
     : std::streambuf (), m_f (f), m_cf (cf)
   { }
 
-  // No copying!
-
-  c_zfile_ptr_buf (const c_zfile_ptr_buf&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (c_zfile_ptr_buf)
 
-  c_zfile_ptr_buf& operator = (const c_zfile_ptr_buf&) = delete;
-
-  ~c_zfile_ptr_buf (void);
+  ~c_zfile_ptr_buf ();
 
   int_type overflow (int_type);
 
-  int_type underflow (void) { return underflow_common (false); }
+  int_type underflow () { return underflow_common (false); }
 
-  int_type uflow (void) { return underflow_common (true); }
+  int_type uflow () { return underflow_common (true); }
 
   int_type pbackfail (int_type);
 
@@ -193,20 +187,20 @@
   std::streampos seekpos (std::streampos,
                           std::ios::openmode = std::ios::in | std::ios::out);
 
-  int sync (void);
+  int sync ();
 
-  int flush (void);
+  int flush ();
 
-  int buf_close (void);
+  int buf_close ();
 
   int file_number () const { return -1; }
 
   int seek (off_t offset, int origin)
   { return m_f ? gzseek (m_f, offset, origin) >= 0 : -1; }
 
-  off_t tell (void) { return m_f ? gztell (m_f) : -1; }
+  off_t tell () { return m_f ? gztell (m_f) : -1; }
 
-  void clear (void) { if (m_f) gzclearerr (m_f); }
+  void clear () { if (m_f) gzclearerr (m_f); }
 
   static int file_close (gzFile m_f) { return ::gzclose (m_f); }
 
@@ -232,39 +226,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::i_c_file_ptr_stream' instead")
-typedef octave::i_c_file_ptr_stream i_c_file_ptr_stream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::o_c_file_ptr_stream' instead")
-typedef octave::o_c_file_ptr_stream o_c_file_ptr_stream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::io_c_file_ptr_stream' instead")
-typedef octave::io_c_file_ptr_stream io_c_file_ptr_stream;
-
-// FIXME: HAVE_ZLIB is not defined here because we do not (and should
-// not) include config.h in this header file.  We need to find a way to
-// define this interface without exposing gzFile.  Should this be a
-// private header that can only be used if included after config.h in an
-// Octave source file and not inside another header file?
-
-#  if defined (HAVE_ZLIB)
-
-OCTAVE_DEPRECATED (7, "use 'octave::i_c_zfile_ptr_stream' instead")
-typedef octave::c_file_ptr_stream<std::istream, gzFile, octave::c_zfile_ptr_buf>
-  i_c_zfile_ptr_stream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::o_c_zfile_ptr_stream' instead")
-typedef octave::c_file_ptr_stream<std::ostream, gzFile, octave::c_zfile_ptr_buf>
-  o_c_zfile_ptr_stream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::io_c_zfile_ptr_stream' instead")
-typedef octave::c_file_ptr_stream<std::iostream, gzFile, octave::c_zfile_ptr_buf>
-  io_c_zfile_ptr_stream;
-
-#  endif
-
 #endif
-
-#endif
--- a/libinterp/corefcn/call-stack.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/call-stack.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -30,17 +30,18 @@
 #include "lo-regexp.h"
 #include "str-vec.h"
 
+#include "pt-bytecode-vm.h"
+#include "builtin-defun-decls.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-handle.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 "syminfo.h"
 #include "symrec.h"
@@ -88,7 +89,7 @@
   return fcn;
 }
 
-int call_stack::current_line (void) const
+int call_stack::current_line () const
 {
   int retval = -1;
 
@@ -101,7 +102,7 @@
   return retval;
 }
 
-int call_stack::current_column (void) const
+int call_stack::current_column () const
 {
   int retval = -1;
 
@@ -114,7 +115,7 @@
   return retval;
 }
 
-octave_user_code *call_stack::current_user_code (void) const
+octave_user_code *call_stack::current_user_code () const
 {
   // Start at current frame.
 
@@ -133,7 +134,7 @@
   return nullptr;
 }
 
-int call_stack::current_user_code_line (void) const
+int call_stack::current_user_code_line () const
 {
   // Start at current frame.
 
@@ -157,7 +158,7 @@
   return -1;
 }
 
-int call_stack::current_user_code_column (void) const
+int call_stack::current_user_code_column () const
 {
   // Start at current frame.
 
@@ -181,7 +182,7 @@
   return -1;
 }
 
-unwind_protect *call_stack::curr_fcn_unwind_protect_frame (void)
+unwind_protect *call_stack::curr_fcn_unwind_protect_frame ()
 {
   // Start at current frame.
 
@@ -200,7 +201,7 @@
   return nullptr;
 }
 
-octave_user_code *call_stack::debug_user_code (void) const
+octave_user_code *call_stack::debug_user_code () const
 {
   octave_user_code *retval = nullptr;
 
@@ -226,7 +227,7 @@
   return retval;
 }
 
-int call_stack::debug_user_code_line (void) const
+int call_stack::debug_user_code_line () const
 {
   int retval = -1;
 
@@ -255,7 +256,7 @@
   return retval;
 }
 
-int call_stack::debug_user_code_column (void) const
+int call_stack::debug_user_code_column () const
 {
   int retval = -1;
 
@@ -285,7 +286,7 @@
   return retval;
 }
 
-std::string call_stack::get_dispatch_class (void) const
+std::string call_stack::get_dispatch_class () const
 {
   return m_cs[m_curr_frame]->get_dispatch_class ();
 }
@@ -323,7 +324,7 @@
   return retval;
 }
 
-bool call_stack::all_scripts (void) const
+bool call_stack::all_scripts () const
 {
   bool retval = true;
 
@@ -448,6 +449,25 @@
   m_curr_frame = new_frame_idx;
 }
 
+void call_stack::push (vm &vm, octave_user_function *fcn, int nargout, int nargin)
+{
+  std::size_t new_frame_idx;
+  std::shared_ptr<stack_frame> parent_link;
+  std::shared_ptr<stack_frame> static_link;
+
+  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
+
+  std::shared_ptr<stack_frame> new_frame
+    = stack_frame::create_bytecode (m_evaluator, fcn, vm,
+                                    new_frame_idx, // ??? index
+                                    parent_link, static_link,
+                                    nargout, nargin);
+
+  m_cs.push_back (new_frame);
+
+  m_curr_frame = new_frame_idx;
+}
+
 void call_stack::push (octave_function *fcn)
 {
   std::size_t new_frame_idx;
@@ -486,14 +506,14 @@
   return retval;
 }
 
-std::size_t call_stack::find_current_user_frame (void) const
+std::size_t call_stack::find_current_user_frame () const
 {
   std::size_t user_frame = m_curr_frame;
 
   std::shared_ptr<stack_frame> frm = m_cs[user_frame];
 
   if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
-         || frm->is_scope_frame ()))
+         || frm->is_scope_frame () || frm->is_bytecode_fcn_frame()))
     {
       frm = frm->static_link ();
 
@@ -503,7 +523,7 @@
   return user_frame;
 }
 
-std::shared_ptr<stack_frame> call_stack::current_user_frame (void) const
+std::shared_ptr<stack_frame> call_stack::current_user_frame () const
 {
   std::size_t frame = find_current_user_frame ();
 
@@ -533,7 +553,8 @@
 
   if (! (frm && (frm->is_user_fcn_frame ()
                  || frm->is_user_script_frame ()
-                 || frm->is_scope_frame ())))
+                 || frm->is_scope_frame ()
+                 || frm->is_bytecode_fcn_frame ())))
     error ("call_stack::dbupdown: invalid initial frame in call stack!");
 
   // Use index into the call stack to begin the search.  At this point
@@ -569,7 +590,7 @@
       frm = m_cs[xframe];
 
       if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
-          || frm->is_scope_frame ())
+          || frm->is_scope_frame () || frm->is_bytecode_fcn_frame ())
         {
           last_good_frame = xframe;
 
@@ -616,7 +637,7 @@
 // value of m_curr_frame would be wiped out when dbup returns and the
 // stack frame for dbup is popped.
 
-void call_stack::goto_caller_frame (void)
+void call_stack::goto_caller_frame ()
 {
   std::size_t start = find_current_user_frame ();
 
@@ -628,7 +649,7 @@
   m_curr_frame = caller_frame ? caller_frame->index () : 0;
 }
 
-void call_stack::goto_base_frame (void)
+void call_stack::goto_base_frame ()
 {
   if (m_curr_frame > 0)
     m_curr_frame = 0;
@@ -653,7 +674,7 @@
       std::shared_ptr<stack_frame> frm = m_cs[n];
 
       if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
-          || frm->is_scope_frame ())
+          || frm->is_scope_frame () || frm->is_bytecode_fcn_frame())
         {
           if (frm->index () == curr_frame)
             curr_user_frame = frames.size ();
@@ -669,7 +690,7 @@
 }
 
 std::list<std::shared_ptr<stack_frame>>
-                                     call_stack::backtrace_frames (void) const
+                                     call_stack::backtrace_frames () const
 {
   octave_idx_type curr_user_frame = -1;
 
@@ -688,7 +709,7 @@
   for (const auto& frm : frames)
     {
       if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
-          || frm->is_scope_frame ())
+          || frm->is_scope_frame () || frm->is_bytecode_fcn_frame())
         {
           retval.push_back (frame_info (frm->fcn_file_name (),
                                         frm->fcn_name (print_subfn),
@@ -699,7 +720,7 @@
   return retval;
 }
 
-std::list<frame_info> call_stack::backtrace_info (void) const
+std::list<frame_info> call_stack::backtrace_info () const
 {
   octave_idx_type curr_user_frame = -1;
 
@@ -726,7 +747,7 @@
   for (const auto& frm : frames)
     {
       if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
-          || frm->is_scope_frame ())
+          || frm->is_scope_frame () || frm->is_bytecode_fcn_frame())
         {
           file(k) = frm->fcn_file_name ();
           name(k) = frm->fcn_name (print_subfn);
@@ -740,19 +761,19 @@
   return retval;
 }
 
-octave_map call_stack::backtrace (void) const
+octave_map call_stack::backtrace () const
 {
   octave_idx_type curr_user_frame = -1;
 
   return backtrace (curr_user_frame, true);
 }
 
-octave_map call_stack::empty_backtrace (void) const
+octave_map call_stack::empty_backtrace () const
 {
   return octave_map (dim_vector (0, 1), bt_fields);
 }
 
-void call_stack::pop (void)
+void call_stack::pop ()
 {
   // Never pop top scope.
   // FIXME: is it possible for this case to happen?
@@ -772,18 +793,36 @@
     }
 }
 
-void call_stack::clear (void)
+std::shared_ptr<stack_frame> call_stack::pop_return ()
+{
+  if (!m_cs.empty ())
+    {
+      std::shared_ptr<stack_frame> elt = std::move (m_cs.back ());
+      m_cs.pop_back ();
+
+      m_curr_frame = elt->parent_frame_index ();
+
+      if (elt->is_closure_context ())
+        elt->break_closure_cycles (elt);
+
+      return elt;
+    }
+
+  return nullptr;
+}
+
+void call_stack::clear ()
 {
   while (! m_cs.empty ())
     pop ();
 }
 
-symbol_info_list call_stack::all_variables (void)
+symbol_info_list call_stack::all_variables ()
 {
   return m_cs[m_curr_frame]->all_variables ();
 }
 
-std::list<std::string> call_stack::global_variable_names (void) const
+std::list<std::string> call_stack::global_variable_names () const
 {
   std::list<std::string> retval;
 
@@ -798,12 +837,12 @@
   return retval;
 }
 
-std::list<std::string> call_stack::top_level_variable_names (void) const
+std::list<std::string> call_stack::top_level_variable_names () const
 {
   return m_cs[0]->variable_names ();
 }
 
-std::list<std::string> call_stack::variable_names (void) const
+std::list<std::string> call_stack::variable_names () const
 {
   return m_cs[m_curr_frame]->variable_names ();
 }
@@ -838,7 +877,7 @@
     }
 }
 
-void call_stack::clear_global_variables (void)
+void call_stack::clear_global_variables ()
 {
   for (auto& nm_ov : m_global_values)
     nm_ov.second = octave_value ();
@@ -856,12 +895,12 @@
   return m_cs[m_curr_frame]->regexp_symbol_info (pattern);
 }
 
-symbol_info_list call_stack::get_symbol_info (void)
+symbol_info_list call_stack::get_symbol_info ()
 {
   return m_cs[m_curr_frame]->get_symbol_info ();
 }
 
-symbol_info_list call_stack::top_scope_symbol_info (void) const
+symbol_info_list call_stack::top_scope_symbol_info () const
 {
   return m_cs[0]->get_symbol_info ();
 }
@@ -976,15 +1015,17 @@
 
       // Set up temporary scope.
 
-      symbol_scope tmp_scope ("$dummy_scope$");
+      symbol_scope tmp_scope (file_name);
 
       push (tmp_scope);
 
-      unwind_action restore_scope ([=] (void) { pop (); });
+      unwind_action restore_scope ([=] () { pop (); });
+
+      interpreter& interp = m_evaluator.get_interpreter ();
 
-      feval ("load", octave_value (file_name), 0);
+      Fload (interp, ovl (file_name));
 
-      std::string newmsg = "Variables in the file " + file_name + ":\n\n";
+      std::string newmsg = "Variables in the file " + file_name + ":\n";
 
       if (global_only)
         return do_global_who_two (patterns, have_regexp, return_list,
@@ -1109,7 +1150,7 @@
   return octave_value ();
 }
 
-void call_stack::display (void) const
+void call_stack::display () const
 {
   std::ostream& os = octave_stdout;
 
@@ -1129,6 +1170,24 @@
   m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);
 }
 
+void
+call_stack::set_nargin (int nargin)
+{
+  m_cs[m_curr_frame]->set_nargin (nargin);
+}
+
+void
+call_stack::set_nargout (int nargout)
+{
+  m_cs[m_curr_frame]->set_nargout (nargout);
+}
+
+void
+call_stack::set_active_bytecode_ip (int ip)
+{
+  m_cs[m_curr_frame]->set_active_bytecode_ip (ip);
+}
+
 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);
--- a/libinterp/corefcn/call-stack.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/call-stack.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,6 +49,7 @@
 class tree_evaluator;
 class symbol_info_list;
 class unwind_protect;
+class vm;
 
 class
 OCTINTERP_API
@@ -73,39 +74,39 @@
 
   octave_function * current_function (bool skip_first = false) const;
 
-  octave_function * caller_function (void) const
+  octave_function * caller_function () const
   {
     return current_function (true);
   }
 
   // Current line in current function.
-  int current_line (void) const;
+  int current_line () const;
 
   // Current column in current function.
-  int current_column (void) const;
+  int current_column () const;
 
-  std::size_t current_frame (void) const { return m_curr_frame; }
+  std::size_t current_frame () const { return m_curr_frame; }
 
-  std::size_t size (void) const { return m_cs.size (); }
+  std::size_t size () const { return m_cs.size (); }
 
-  std::shared_ptr<stack_frame> get_current_stack_frame (void) const
+  std::shared_ptr<stack_frame> get_current_stack_frame () const
   {
     return m_cs[m_curr_frame];
   }
 
-  symbol_scope top_scope (void) const
+  symbol_scope top_scope () const
   {
     return m_cs[0]->get_scope ();
   }
 
-  symbol_scope current_scope (void) const
+  symbol_scope current_scope () const
   {
     // FIXME: Can m_curr_frame ever be invalid?
     return (m_curr_frame < m_cs.size ()
             ? m_cs[m_curr_frame]->get_scope () : symbol_scope ());
   }
 
-  bool at_top_level (void) const
+  bool at_top_level () const
   {
     return current_scope () == top_scope ();
   }
@@ -123,26 +124,26 @@
   }
 
   // User code caller.
-  octave_user_code * current_user_code (void) const;
+  octave_user_code * current_user_code () const;
 
-  unwind_protect * curr_fcn_unwind_protect_frame (void);
+  unwind_protect * curr_fcn_unwind_protect_frame ();
 
   // Line in user code caller.
-  int current_user_code_line (void) const;
+  int current_user_code_line () const;
 
   // Column in user code caller.
-  int current_user_code_column (void) const;
+  int current_user_code_column () const;
 
   // Current function that we are debugging.
-  octave_user_code * debug_user_code (void) const;
+  octave_user_code * debug_user_code () const;
 
   // Line number in current function that we are debugging.
-  int debug_user_code_line (void) const;
+  int debug_user_code_line () const;
 
   // Column number in current function that we are debugging.
-  int debug_user_code_column (void) const;
+  int debug_user_code_column () const;
 
-  std::string get_dispatch_class (void) const;
+  std::string get_dispatch_class () const;
 
   void set_dispatch_class (const std::string& class_name);
 
@@ -151,7 +152,7 @@
   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;
+  bool all_scripts () const;
 
   void push (const symbol_scope& scope);
 
@@ -166,6 +167,8 @@
 
   void push (octave_function *fcn);
 
+  void push (vm &vm, octave_user_function *fcn, int nargout, int nargin);
+
   void set_location (int l, int c)
   {
     if (! m_cs.empty ())
@@ -204,23 +207,23 @@
     goto_frame (n);
   }
 
-  std::size_t find_current_user_frame (void) const;
+  std::size_t find_current_user_frame () const;
 
-  std::shared_ptr<stack_frame> current_user_frame (void) const;
+  std::shared_ptr<stack_frame> current_user_frame () const;
 
   std::size_t dbupdown (std::size_t start, int n, bool verbose);
   std::size_t dbupdown (int n = -1, bool verbose = false);
 
-  void goto_caller_frame (void);
+  void goto_caller_frame ();
 
-  void goto_base_frame (void);
+  void goto_base_frame ();
 
   std::list<std::shared_ptr<stack_frame>>
                                        backtrace_frames (octave_idx_type& curr_user_frame) const;
 
   // List of raw stack frames.
 
-  std::list<std::shared_ptr<stack_frame>> backtrace_frames (void) const;
+  std::list<std::shared_ptr<stack_frame>> backtrace_frames () const;
 
   // List of stack_info objects that can be used in liboctave and
   // stored in the execution_exception object.
@@ -228,7 +231,7 @@
   std::list<frame_info> backtrace_info (octave_idx_type& curr_user_frame,
                                         bool print_subfn = true) const;
 
-  std::list<frame_info> backtrace_info (void) const;
+  std::list<frame_info> backtrace_info () const;
 
   // The same as backtrace_info but in the form of a struct array
   // object that may be used in the interpreter.
@@ -236,21 +239,23 @@
   octave_map backtrace (octave_idx_type& curr_user_frame,
                         bool print_subfn = true) const;
 
-  octave_map backtrace (void) const;
+  octave_map backtrace () const;
 
-  octave_map empty_backtrace (void) const;
+  octave_map empty_backtrace () const;
 
-  void pop (void);
+  void pop ();
 
-  void clear (void);
+  std::shared_ptr<stack_frame> pop_return ();
 
-  symbol_info_list all_variables (void);
+  void clear ();
 
-  std::list<std::string> global_variable_names (void) const;
+  symbol_info_list all_variables ();
 
-  std::list<std::string> top_level_variable_names (void) const;
+  std::list<std::string> global_variable_names () const;
 
-  std::list<std::string> variable_names (void) const;
+  std::list<std::string> top_level_variable_names () const;
+
+  std::list<std::string> variable_names () const;
 
   void clear_global_variable (const std::string& name);
 
@@ -258,15 +263,15 @@
 
   void clear_global_variable_regexp(const std::string& pattern);
 
-  void clear_global_variables (void);
+  void clear_global_variables ();
 
   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 get_symbol_info ();
 
-  symbol_info_list top_scope_symbol_info (void) const;
+  symbol_info_list top_scope_symbol_info () const;
 
   octave_value max_stack_depth (const octave_value_list& args, int nargout);
 
@@ -294,13 +299,18 @@
                                   bool have_regexp, bool return_list,
                                   bool verbose, const std::string& msg = "");
 
-  void display (void) const;
+  void display () const;
 
   void set_auto_fcn_var (stack_frame::auto_var_type avt,
                          const octave_value& val);
 
+  void set_nargin (int nargin);
+  void set_nargout (int nargout);
+
   octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;
 
+  void set_active_bytecode_ip (int ip);
+
 private:
 
   void get_new_frame_index_and_links
--- a/libinterp/corefcn/cellfun.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/cellfun.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,6 @@
 #include "defun.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
-#include "parse.h"
 #include "variables.h"
 #include "unwind-prot.h"
 #include "errwarn.h"
@@ -68,11 +67,9 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static octave_value_list
-get_output_list (error_system& es,
-                 octave_idx_type count, octave_idx_type nargout,
-                 const octave_value_list& inputlist,
-                 octave_value& fcn,
-                 octave_value& error_handler)
+get_output_list (interpreter& interp, octave_idx_type count,
+                 octave_idx_type nargout, const octave_value_list& inputlist,
+                 octave_value& fcn, octave_value& error_handler)
 {
   octave_value_list tmp;
 
@@ -80,13 +77,13 @@
 
   try
     {
-      tmp = feval (fcn, inputlist, nargout);
+      tmp = interp.feval (fcn, inputlist, nargout);
     }
   catch (const execution_exception& ee)
     {
       if (error_handler.is_defined ())
         {
-          interpreter& interp = __get_interpreter__ ();
+          error_system& es = interp.get_error_system ();
 
           es.save_exception (ee);
           interp.recover_from_exception ();
@@ -101,6 +98,8 @@
     {
       if (error_handler.is_defined ())
         {
+          error_system& es = interp.get_error_system ();
+
           octave_scalar_map msg;
           msg.assign ("identifier", es.last_error_id ());
           msg.assign ("message", es.last_error_message ());
@@ -111,7 +110,7 @@
           octave_value_list errlist = inputlist;
           errlist.prepend (msg);
 
-          tmp = feval (error_handler, errlist, nargout);
+          tmp = interp.feval (error_handler, errlist, nargout);
         }
       else
         tmp.clear ();
@@ -359,7 +358,7 @@
 
 @example
 @group
-cellfun ("tolower", @{"Foo", "Bar", "FooBar"@},
+cellfun ("lower", @{"Foo", "Bar", "FooBar"@},
          "UniformOutput", false)
 @result{} @{"foo", "bar", "foobar"@}
 @end group
@@ -537,8 +536,6 @@
         }
     }
 
-  error_system& es = interp.get_error_system ();
-
   // Apply functions.
 
   if (uniform_output)
@@ -559,7 +556,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (es, count, nargout, inputlist, fcn,
+            = get_output_list (interp, count, nargout, inputlist, fcn,
                                error_handler);
 
           int tmp_numel = tmp.length ();
@@ -645,7 +642,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (es, count, nargout, inputlist, fcn,
+            = get_output_list (interp, count, nargout, inputlist, fcn,
                                error_handler);
 
           if (nargout > 0 && tmp.length () < nargout)
@@ -1277,8 +1274,6 @@
             }
         }
 
-      error_system& es = interp.get_error_system ();
-
       // Apply functions.
 
       if (uniform_output)
@@ -1300,7 +1295,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (es, count, nargout, inputlist, fcn,
+                = get_output_list (interp, count, nargout, inputlist, fcn,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
@@ -1392,7 +1387,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (es, count, nargout, inputlist, fcn,
+                = get_output_list (interp, count, nargout, inputlist, fcn,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
@@ -2057,20 +2052,29 @@
   if (mat2cell_mismatch (a.dims (), d, nd))
     return retval;
 
-  dim_vector rdv = dim_vector::alloc (nd);
+  // For each dimension, count the number of partitions specified.
+  // For example, "mat2cell (A, [1 1 1], [2 2])" has 3 partitions on dim1
+  // and 2 partitions on dim2.  Number of dimension (nd) is 2 for this example.
+  dim_vector retdv = dim_vector::alloc (nd);
   OCTAVE_LOCAL_BUFFER (octave_idx_type, nidx, nd);
-  octave_idx_type idxtot = 0;
+  octave_idx_type idxtot = 0;   // Number of idx operations.  5 in example.
   for (int i = 0; i < nd; i++)
     {
-      rdv(i) = nidx[i] = d[i].numel ();
+      retdv(i) = nidx[i] = d[i].numel ();
       idxtot += nidx[i];
     }
 
-  retval.clear (rdv);
+  if (nd == 1)
+    retdv(1) = 1;        // All Octave arrays have at least two dimensions.
+  retval.clear (retdv);  // Resize retval based on calculated partitions.
 
   OCTAVE_LOCAL_BUFFER (idx_vector, xidx, idxtot);
   OCTAVE_LOCAL_BUFFER (idx_vector *, idx, nd);
 
+  // Loop over all dimensions (specified partitions) and prepare an idx_vector
+  // to retrieve the requested elements.  The partitions are specified in
+  // input parameter 'd' which is an Array of octave_idx_type.  In the example,
+  // d[0] = [1 1 1].
   idxtot = 0;
   for (int i = 0; i < nd; i++)
     {
@@ -2080,19 +2084,28 @@
     }
 
   OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0);
-  Array<idx_vector> ra_idx
-  (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon);
+  // Declare array of index vectors which will perform indexing.
+  // Initialize to magic colon (':') so that dimensions that are not actually
+  // specified will be collapsed.
+  Array<idx_vector> ra_idx (dim_vector (1, std::max (nd, a.ndims ())),
+                                        idx_vector::colon);
 
-  for (octave_idx_type j = 0; j < retval.numel (); j++)
+  const octave_idx_type retnumel = retval.numel ();
+  for (octave_idx_type j = 0; j < retnumel; j++)
     {
       octave_quit ();
 
+      // Copy prepared indices for this iteration to ra_idx.
       for (int i = 0; i < nd; i++)
         ra_idx.xelem (i) = idx[i][ridx[i]];
 
+      // Perform indexing operation and store in output retval.
       retval.xelem (j) = a.index (ra_idx);
 
-      rdv.increment_index (ridx);
+      // DO NOT increment on last loop because it will overflow past
+      // declared size of ridx (bug #63682).
+      if (j < (retnumel - 1))
+        retdv.increment_index (ridx);
     }
 
   return retval;
@@ -2166,7 +2179,7 @@
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{C} =} mat2cell (@var{A}, @var{dim1}, @var{dim2}, @dots{}, @var{dimi}, @dots{}, @var{dimn})
 @deftypefnx {} {@var{C} =} mat2cell (@var{A}, @var{rowdim})
-Convert the matrix @var{A} to a cell array.
+Convert the matrix @var{A} to a cell array @var{C}.
 
 Each dimension argument (@var{dim1}, @var{dim2}, etc.@:) is a vector of
 integers which specifies how to divide that dimension's elements amongst the
@@ -2337,6 +2350,15 @@
 %! c = mat2cell (x, 1, [0,4,2,0,4,0]);
 %! empty1by0str = resize ("", 1, 0);
 %! assert (c, {empty1by0str,"abcd","ef",empty1by0str,"ghij",empty1by0str});
+
+## Omitted input for trailing dimensions means not splitting on them.
+%!test <*63682>
+%! x = reshape (1:16, 4, 2, 2);
+%! c1 = mat2cell (x, [2, 2], 2, 2);
+%! c2 = mat2cell (x, [2, 2]);
+%! assert (c1, c2);
+%! assert (c1, {cat(3, [1,5;2,6], [9,13;10,14]); ...
+%!              cat(3, [3,7;4,8], [11,15;12,16])});
 */
 
 // FIXME: it would be nice to allow ranges being handled without a conversion.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/compile.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,453 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "ovl.h"
+#include "ov.h"
+#include "defun.h"
+#include "variables.h"
+#include "interpreter.h"
+
+#include "pt-bytecode-vm.h"
+#include "pt-bytecode-walk.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+// Cleverly hidden in pt-bytecode-vm.cc to prevent inlining here
+extern "C" void dummy_mark_1 (void);
+extern "C" void dummy_mark_2 (void);
+
+DEFUN (__dummy_mark_1, , ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {} __dummy_mark_1 ()
+
+Dummy function that calls the c-function void dummy_mark_1 (void)
+that does nothing.
+
+Usefull for e.g. marking start and end for Callgrind analyzis
+or as an entry point for gdb.
+
+@end deftypefn */)
+{
+  dummy_mark_1 ();
+
+  return {};
+}
+
+DEFUN (__dummy_mark_2, , ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {} __dummy_mark_2 ()
+
+Dummy function that calls the c-function void dummy_mark_2 (void)
+that does nothing.
+
+Usefull for e.g. marking start and end for Callgrind analyzis
+or as an entry point for gdb.
+
+@end deftypefn */)
+{
+  dummy_mark_2 ();
+
+  return {};
+}
+
+DEFUN (__vm_clear_cache__, , ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{val} =} __vm_clear_cache__ ()
+
+Internal function.
+
+@end deftypefn */)
+{
+  octave::load_path::signal_clear_fcn_cache ();
+
+  return octave_value {true};
+}
+
+DEFUN (__vm_print_trace, , ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{prints_trace} =} __vm_print_trace ())
+
+Internal function.
+
+Print a debug trace from the VM. Toggles on or off each call.
+
+There has to be a breakpoint set in some file for the trace
+to actually print anything.
+
+Returns true if a trace will be printed from now on, false otherwise.
+
+@end deftypefn */)
+{
+  vm::m_trace_enabled = !vm::m_trace_enabled;
+
+  return octave_value {vm::m_trace_enabled};
+}
+
+DEFUN (__ref_count, args, ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{count} =} __ref_count (@var{obj}))
+
+Internal function.
+
+Returns reference count for an object.
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+
+  octave_value ov = args (0);
+
+  return octave_value {ov.get_count ()};
+}
+
+DEFMETHOD (__vm_is_executing, interp, , ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{is_executing} =} __vm_is_executing ())
+
+Internal function.
+
+Returns true if the VM is executing the function calling __vm_is_executing ().
+
+False otherwise.
+
+@end deftypefn */)
+{
+  bool bytecode_running = interp.get_evaluator ().get_current_stack_frame ()->is_bytecode_fcn_frame ();
+
+  return octave_value {bytecode_running};
+}
+
+DEFMETHOD (__vm_profile, interp, args, ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {} __vm_profile on
+@deftypefnx {} {} __vm_profile off
+@deftypefnx {} {} __vm_profile resume
+@deftypefnx {} {} __vm_profile clear
+@deftypefnx {} {@var{T} =} __vm_profile ("info")
+@deftypefnx {} {} __vm_profile
+
+Internal function.
+
+Profile code running in the VM.
+
+@table @code
+@item profile on
+Start the profiler, clearing all previously collected data if there is any.
+
+@item profile off
+Stop profiling.  The collected data can later be retrieved and examined
+with @code{T = profile ("info")}.
+
+@item profile clear
+Clear all collected profiler data.
+
+@item profile resume
+Restart profiling without clearing the old data.  All newly collected
+statistics are added to the existing ones.
+
+@item profile
+Toggles between profiling and printing the result of the profiler.
+Clears the profiler on each print.
+
+@item info
+Prints the profiler data.
+
+Not that output to a variable is not implemented yet.
+
+@end table
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  // Unless a "profiler enabled" flag is added to the evaluator
+  // the vm profiler need the debugger to be active for it to actually
+  // be able to profile.
+  if (!interp.get_evaluator ().debug_mode ())
+    warning ("As a workaround atleast one breakpoint has to be set"
+    " in any file (preferably not being profiled) for the profiler to actually profile anything.");
+
+  std::string arg0;
+
+  if (nargin >= 1)
+   arg0 = args (0).string_value ();
+
+  if (!arg0.size ())
+    {
+      if (!vm::m_vm_profiler)
+        {
+          vm::m_vm_profiler = std::make_shared<vm_profiler> ();
+
+          vm::m_profiler_enabled = true;
+        }
+      else
+        {
+          vm::m_profiler_enabled = false;
+          auto p = vm::m_vm_profiler;
+          vm::m_vm_profiler = nullptr;
+
+          auto cpy = *p;
+          cpy.print_to_stdout ();
+        }
+    }
+  else if (arg0 == "on")
+    {
+      vm::m_profiler_enabled = false;
+      vm::m_vm_profiler = std::make_shared<vm_profiler> ();
+      vm::m_profiler_enabled = true;
+    }
+  else if (arg0 == "resume")
+    {
+      if (!vm::m_vm_profiler)
+        vm::m_vm_profiler = std::make_shared<vm_profiler> ();
+
+      vm::m_profiler_enabled = true;
+    }
+  else if (arg0 == "off")
+    {
+      vm::m_profiler_enabled = false;
+    }
+  else if (arg0 == "clear")
+    {
+      vm::m_profiler_enabled = false;
+      vm::m_vm_profiler = nullptr;
+    }
+  else if (arg0 == "info")
+    {
+      auto p_vm_profiler = vm::m_vm_profiler;
+      if (p_vm_profiler)
+        {
+          auto cpy = *p_vm_profiler;
+          cpy.print_to_stdout ();
+        }
+      else
+        warning ("Nothing recorded.");
+    }
+  else
+    print_usage ();
+
+  return octave_value {true};
+}
+
+DEFMETHOD (__print_bytecode, interp, args, ,
+  doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{success} =} __print_bytecode (@var{fn_name}))
+
+Internal function.
+
+Prints the bytecode of a function, if any.
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+
+  std::string fn_name = args(0).string_value ();
+  symbol_table& symtab = interp.get_symbol_table ();
+
+  octave_value ov = symtab.find_function (fn_name);
+
+  if (!ov.is_defined ())
+    {
+      error ("Function not defined: %s", fn_name.c_str ());
+    }
+
+  octave_user_function *ufn = ov.user_function_value ();
+
+  if (!ufn || !ufn->is_user_function ())
+    {
+      error ("Function not a user function: %s", fn_name.c_str ());
+    }
+
+  if (!ufn->is_compiled () && V__enable_vm_eval__)
+    compile_user_function (*ufn, 0);
+  else if (!ufn->is_compiled ())
+    error ("Function not compiled: %s", fn_name.c_str ());
+
+  if (!ufn->is_compiled ())
+    error ("Function can't be compiled: %s", fn_name.c_str ());
+
+  auto bc = ufn->get_bytecode ();
+
+  print_bytecode (bc);
+
+  return octave_value {true};
+}
+
+DEFMETHOD (__compile, interp, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{success} =} __compile (@var{fn_name})
+@deftypefnx  {} {@var{success} =} __compile (@var{fn_name}, "clear")
+@deftypefnx  {} {@var{success} =} __compile (@var{fn_name}, "print")
+
+Compile the specified function to bytecode.
+
+The compiled function and its subfunctions will be executed
+by the VM when called.
+
+Returns true on success, otherwise false.
+
+The @qcode{"print"} option prints the bytecode after compilation.
+
+The @qcode{"clear"} option removes the bytecode from the function instead.
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (! nargin)
+    print_usage ();
+
+  std::string fcn_to_compile;
+  bool do_clear = false;
+  bool do_print = false;
+
+  for (int i = 0; i < nargin; i++)
+    {
+      auto arg = args(i);
+
+      if (! arg.is_string())
+        error ("Non string argument");
+
+      std::string arg_s = arg.string_value ();
+
+      if (i == 0)
+        {
+          fcn_to_compile = arg_s;
+          continue;
+        }
+
+      if (arg_s == "clear")
+        do_clear = true;
+
+      if (arg_s == "print")
+        do_print = true;
+    }
+
+  if (do_clear)
+    {
+      std::string name = fcn_to_compile;
+      symbol_table& symtab = interp.get_symbol_table ();
+      octave_value ov = symtab.find_function (name);
+
+      if (!ov.is_defined ())
+        {
+          error ("Function not defined: %s", name.c_str ());
+        }
+
+      octave_user_function *ufn = ov.user_function_value ();
+
+      if (!ufn || !ufn->is_user_function ())
+        {
+          error ("Function not a user function: %s", name.c_str ());
+        }
+
+      ufn->clear_bytecode ();
+
+      return octave_value {true};
+    }
+
+
+  {
+    std::string name = fcn_to_compile;
+    symbol_table& symtab = interp.get_symbol_table ();
+    octave_value ov = symtab.find_function (name);
+
+    if (!ov.is_defined ())
+      {
+        error ("Function not defined: %s", name.c_str ());
+      }
+
+    if (! ov.is_user_function ())
+      {
+        error ("Function is not a user function: %s", name.c_str ());
+      }
+
+    octave_user_function *ufn = ov.user_function_value ();
+
+    if (!ufn || !ufn->is_user_function ())
+      {
+        error ("Function is not really a user function: %s", name.c_str ());
+      }
+
+    // Throws on errors
+    compile_user_function (*ufn, do_print);
+  }
+
+  return octave_value {true};
+}
+
+// If TRUE, use VM evaluator rather than tree walker.
+// FIXME: Use OCTAVE_ENABLE_VM_EVALUATOR define to set it to true when
+// the VM has been tested properly.
+bool V__enable_vm_eval__ = false;
+
+DEFUN (__enable_vm_eval__, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{val} =} __enable_vm_eval__ ()
+@deftypefnx {} {@var{old_val} =} __enable_vm_eval__ (@var{new_val})
+@deftypefnx {} {@var{old_val} =} __enable_vm_eval__ (@var{new_val}, "local")
+Query or set whether Octave automatically compiles functions to bytecode
+and executes them in a virtual machine (VM).
+
+Note that the virtual machine feature is experimental.
+
+The default value is currently false, while the VM is still experimental.
+Users need to explicitly call @code{__enable_vm_eval__ (1)} to enable it.
+In future, this will be set to the value of  the OCTAVE_ENABLE_VM_EVALUATOR
+flag that was set when building Octave.
+
+When false, Octave uses a traditional tree walker
+to evaluate statements parsed from m-code.  When true, Octave translates parsed
+statements to an intermediate representation that is then evaluated by a
+virtual machine.
+
+When called from inside a function with the @qcode{"local"} option, the setting
+is changed locally for the function and any subroutines it calls.  The original
+setting is restored when exiting the function.
+
+Once compiled to bytecode, the function will always be evaluated by the
+VM no matter the state of @qcode{"__enable_vm_eval__"}, until the bytecode is
+cleared, by e.g. @qcode{"clear all"} or an modification to the
+function's m-file.
+
+@seealso{__compile}
+
+@end deftypefn */)
+{
+  return set_internal_variable (V__enable_vm_eval__, args, nargout,
+                                "__enable_vm_eval__");
+}
+
+OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/daspk.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/daspk.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,11 +36,11 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "parse.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -82,7 +82,9 @@
 
       try
         {
-          tmp = feval (daspk_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (daspk_fcn, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -132,7 +134,9 @@
 
       try
         {
-          tmp = feval (daspk_jac, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (daspk_jac, args, 1);
         }
       catch (execution_exception& ee)
         {
--- a/libinterp/corefcn/dasrt.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dasrt.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,11 +37,11 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "parse.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -83,7 +83,9 @@
 
       try
         {
-          tmp = feval (dasrt_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (dasrt_fcn, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -124,7 +126,9 @@
 
       try
         {
-          tmp = feval (dasrt_cf, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (dasrt_cf, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -170,7 +174,9 @@
 
       try
         {
-          tmp = feval (dasrt_jac, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (dasrt_jac, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -466,11 +472,9 @@
 
   ColumnVector state = args(argp++).xvector_value ("dasrt: initial state X_0 must be a vector");
 
-  ColumnVector stateprime = args(
-                              argp++).xvector_value ("dasrt: initial derivatives XDOT_0 must be a vector");
+  ColumnVector stateprime = args(argp++).xvector_value ("dasrt: initial derivatives XDOT_0 must be a vector");
 
-  ColumnVector out_times = args(
-                             argp++).xvector_value ("dasrt: output time variable T must be a vector");
+  ColumnVector out_times = args(argp++).xvector_value ("dasrt: output time variable T must be a vector");
 
   double tzero = out_times (0);
 
--- a/libinterp/corefcn/dassl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dassl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,11 +35,11 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "parse.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -81,7 +81,9 @@
 
       try
         {
-          tmp = feval (dassl_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (dassl_fcn, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -131,7 +133,9 @@
 
       try
         {
-          tmp = feval (dassl_jac, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (dassl_jac, args, 1);
         }
       catch (execution_exception& ee)
         {
--- a/libinterp/corefcn/data.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/data.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,6 +49,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "oct-map.h"
 #include "ov-class.h"
 #include "ov-complex.h"
@@ -60,7 +61,6 @@
 #include "ov.h"
 #include "ovl.h"
 #include "pager.h"
-#include "parse.h"
 #include "pt-mat.h"
 #include "utils.h"
 #include "variables.h"
@@ -1680,7 +1680,9 @@
 
   std::string cname = ov.class_name ();
 
-  symbol_table& symtab = __get_symbol_table__ ();
+  interpreter& interp = __get_interpreter__ ();
+
+  symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value fcn = symtab.find_method (dtype, cname);
 
@@ -1690,7 +1692,7 @@
 
       try
         {
-          result = feval (fcn, ovl (ov), 1);
+          result = interp.feval (fcn, ovl (ov), 1);
         }
       catch (execution_exception& ee)
         {
@@ -1718,7 +1720,7 @@
 
       try
         {
-          result = feval (fcn, ovl (ov), 1);
+          result = interp.feval (fcn, ovl (ov), 1);
         }
       catch (execution_exception& ee)
         {
@@ -1746,7 +1748,9 @@
 
   std::string dtype = get_dispatch_type (ovl);
 
-  symbol_table& symtab = __get_symbol_table__ ();
+  interpreter& interp = __get_interpreter__ ();
+
+  symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value fcn = symtab.find_method (cattype, dtype);
 
@@ -1758,7 +1762,7 @@
 
       try
         {
-          tmp2 = feval (fcn, ovl, 1);
+          tmp2 = interp.feval (fcn, ovl, 1);
         }
       catch (execution_exception& ee)
         {
@@ -4635,6 +4639,7 @@
 %!assert (ones (2, "like", speye (2)), sparse ([1, 1; 1, 1]))
 %!assert (ones (2, "like", sparse (1i)), sparse (complex ([1, 1; 1, 1])))
 
+## Note: Matlab compatibility requires using 0 for negative dimensions.
 %!assert (size (ones (1, -2, 2)), [1, 0, 2])
 
 ## Test input validation
@@ -4790,6 +4795,9 @@
 %!assert (Inf (3, 2, "single"), single ([Inf, Inf; Inf, Inf; Inf, Inf]))
 %!assert (size (inf (3, 4, 5, "single")), [3, 4, 5])
 
+## Note: Matlab compatibility requires using 0 for negative dimensions.
+%!assert (size (Inf (2, -3, 2)), [2, 0, 2])
+
 %!assert (Inf (2, 2, "like", speye (2)), sparse ([Inf, Inf; Inf, Inf]))
 %!assert (Inf (2, 2, "like", complex (ones (2, 2))), [Inf, Inf; Inf, Inf])
 %!assert (Inf (2, 2, "like", double (1)), double ([Inf, Inf; Inf, Inf]))
@@ -5045,6 +5053,10 @@
 %!assert (eps (single (NaN)), single (NaN))
 %!assert (eps (single ([1/2 1 2 realmax("single") 0 realmin("single")/2 realmin("single")/16 Inf NaN])),
 %!        single ([2^-24 2^-23 2^-22 2^104 2^-149 2^-149 2^-149 NaN NaN]))
+
+## Note: Matlab compatibility requires using 0 for negative dimensions.
+%!assert (size (eps (2, -3, 2)), [2, 0, 2])
+
 %!error <X must be of a floating point type> eps (uint8 ([0 1 2]))
 %!error <must be scalar> eps (1:3, 1)
 %!error <must be scalar> eps (1, 1:3)
@@ -5534,12 +5546,15 @@
 %!assert (full (eye (3)), [1, 0, 0; 0, 1, 0; 0, 0, 1])
 %!assert (full (eye (2, 3)), [1, 0, 0; 0, 1, 0])
 
-%!assert (full (eye (3,"single")), single ([1, 0, 0; 0, 1, 0; 0, 0, 1]))
-%!assert (full (eye (2, 3,"single")), single ([1, 0, 0; 0, 1, 0]))
+%!assert (full (eye (3, "single")), single ([1, 0, 0; 0, 1, 0; 0, 0, 1]))
+%!assert (full (eye (2, 3, "single")), single ([1, 0, 0; 0, 1, 0]))
 
 %!assert (eye (3, "int8"), int8 ([1, 0, 0; 0, 1, 0; 0, 0, 1]))
 %!assert (eye (2, 3, "int8"), int8 ([1, 0, 0; 0, 1, 0]))
 
+## Note: Matlab compatibility requires using 0 for negative dimensions.
+%!assert (size (eye (2, -3)), [2, 0])
+
 ## Test input validation
 %!error eye (1, 2, 3)
 %!error <conversion of 1.1 .*failed> eye (1.1)
@@ -5741,27 +5756,41 @@
 %!assert (numel (linspace (0, 1, 2-eps)), 1)
 %!assert (linspace (10, 20, 2.1), [10 20])
 %!assert (linspace (10, 20, 2.9), [10 20])
-%!assert (1 ./ linspace (-0, 0, 4), [-Inf, Inf, Inf, Inf])
 %!assert (linspace (Inf, Inf, 3), [Inf, Inf, Inf])
 %!assert (linspace (-Inf, -Inf, 3), [-Inf, -Inf, -Inf])
 %!assert (linspace (-Inf, Inf, 3), [-Inf, 0, Inf])
+## Octave prefers to return NaN which indicates failure of algorithm.
+%!assert (linspace (-Inf, Inf, 4), [-Inf, NaN, NaN, Inf])
+%!assert (linspace (-Inf, 0, 3), [-Inf, NaN, 0])
+%!assert (linspace (-Inf, 0, 4), [-Inf, NaN, NaN, 0])
 %!assert (linspace (Inf + 1i, Inf + 1i, 3), [Inf + 1i, Inf + 1i, Inf + 1i])
-%!assert (linspace (-Inf + 1i, Inf + 1i, 3), [-Inf + 1i, NaN + 1i, Inf + 1i])
+%!assert (linspace (-Inf - 1i, Inf + 1i, 3), [-Inf - 1i, 0 + 0i, Inf + 1i])
+%!assert (linspace (-Inf - 1i, Inf + 2i, 3), [-Inf - 1i, NaN + 0.5i, Inf + 2i])
+%!assert (linspace (-Inf - 3i, Inf + 0i, 4),
+%!        [-Inf - 3i, NaN - 2i, NaN - 1i, Inf + 0i])
+%!assert (linspace (complex (-1, -Inf), complex (1, Inf), 3),
+%!          [complex(-1, -Inf), 0 + 0i, complex(1, Inf)])
+%!assert (linspace (complex (-1, -Inf), complex (2, Inf), 3),
+%!          [complex(-1, -Inf), complex(0.5, NaN), complex(2, Inf)])
+%!assert (linspace (complex (-3, -Inf), complex (0, Inf), 4),
+%!        [complex(-3, -Inf), complex(-2, NaN), complex(-1, NaN), complex(0, Inf)])
 
 ## FIXME: Octave is not fully Matlab-compatible for some combinations of
 ##        Inf/-Inf endpoints.  See bug #56933.  This was dubbed "Won't Fix"
-##        so these tests have been removed from the test suite by commenting
-##        them out.  If the behavior in the future is made compatible these
-##        tests can be re-instated.
+##        as Octave prefers to return NaN for some of these conditions to
+##        better reflect that the algorithm has failed.  If the behavior in
+##        the future is made compatible these tests can be re-instated.
 ##%!assert <56933> (linspace (-Inf, Inf, 4), [-Inf, -Inf, Inf, Inf])
 ##%!assert <56933> (linspace (-Inf, Inf, 5), [-Inf, -Inf, 0, Inf, Inf])
 ##%!assert <56933> (linspace (0, Inf, 4), [0, Inf, Inf, Inf])
 ##%!assert <56933> (linspace (0, -Inf, 4), [0, -Inf, -Inf, -Inf])
 ##%!assert <56933> (linspace (-Inf, 0, 4), [-Inf, NaN, NaN, 0])
 ##%!assert <56933> (linspace (Inf, 0, 4), [Inf, NaN, NaN, 0])
-
-%!error linspace ()
-%!error linspace (1, 2, 3, 4)
+##%!assert (1 ./ linspace (-0, 0, 4), [-Inf, Inf, Inf, Inf])
+
+## Test input validation
+%!error <Invalid call> linspace ()
+%!error <Invalid call> linspace (1, 2, 3, 4)
 %!error <N must be a scalar> linspace (1, 2, [3, 4])
 %!error <START, END must be scalars or vectors> linspace (ones (2,2), 2, 3)
 %!error <START, END must be scalars or vectors> linspace (2, ones (2,2), 3)
@@ -6528,7 +6557,7 @@
 (@dots{}((@var{A1} * @var{A2}) * @var{A3}) * @dots{})
 @end example
 
-@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower}
+@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower, tensorprod}
 @end deftypefn */)
 {
   return binary_assoc_op_defun_body (octave_value::op_mul,
--- a/libinterp/corefcn/data.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/data.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,14 +41,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::do_class_concat' instead")
-inline OCTINTERP_API octave_value
-do_class_concat (const octave_value_list& ovl, const std::string& cattype,
-                 int dim)
-{
-  return octave::do_class_concat (ovl, cattype, dim);
-}
 #endif
-
-#endif
--- a/libinterp/corefcn/debug.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/debug.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -939,7 +939,7 @@
 // for example.
 
 void
-show_octave_dbstack (void)
+show_octave_dbstack ()
 {
   do_dbstack (octave::__get_interpreter__ (),
               octave_value_list (), 0, std::cerr);
--- a/libinterp/corefcn/defaults.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/defaults.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -74,7 +74,7 @@
   return retval;
 }
 
-static std::string get_octave_home (void)
+static std::string get_octave_home ()
 {
   std::string op = OCTAVE_PREFIX;
 
@@ -86,7 +86,7 @@
   return oh.empty () ? op : oh;
 }
 
-static std::string get_octave_exec_home (void)
+static std::string get_octave_exec_home ()
 {
   std::string op = OCTAVE_PREFIX;
   std::string oep = OCTAVE_EXEC_PREFIX;
@@ -108,14 +108,14 @@
   return oep;
 }
 
-static std::string get_local_site_defaults_file (void)
+static std::string get_local_site_defaults_file ()
 {
   std::string lsf = sys::env::getenv ("OCTAVE_SITE_INITFILE");
 
   return lsf.empty () ? local_startupfile_dir () + "/octaverc" : lsf;
 }
 
-static std::string get_site_defaults_file (void)
+static std::string get_site_defaults_file ()
 {
   std::string sf = sys::env::getenv ("OCTAVE_VERSION_INITFILE");
 
@@ -132,7 +132,7 @@
   return prepend_home_dir (octave_exec_home (), s);
 }
 
-std::string canonical_host_type (void)
+std::string canonical_host_type ()
 {
   static const std::string s_canonical_host_type
     = OCTAVE_CANONICAL_HOST_TYPE;
@@ -140,35 +140,35 @@
   return s_canonical_host_type;
 }
 
-std::string release (void)
+std::string release ()
 {
   static const std::string s_octave_release = OCTAVE_RELEASE;
 
   return s_octave_release;
 }
 
-std::string default_pager (void)
+std::string default_pager ()
 {
   static const std::string s_default_pager = OCTAVE_DEFAULT_PAGER;
 
   return s_default_pager;
 }
 
-std::string octave_home (void)
+std::string octave_home ()
 {
   static const std::string s_octave_home = get_octave_home ();
 
   return s_octave_home;
 }
 
-std::string octave_exec_home (void)
+std::string octave_exec_home ()
 {
   static const std::string s_octave_exec_home = get_octave_exec_home ();
 
   return s_octave_exec_home;
 }
 
-std::string bin_dir (void)
+std::string bin_dir ()
 {
   static const std::string s_bin_dir
     = prepend_octave_exec_home (OCTAVE_BINDIR);
@@ -176,7 +176,7 @@
   return s_bin_dir;
 }
 
-std::string data_dir (void)
+std::string data_dir ()
 {
   static const std::string s_data_dir
     = prepend_octave_home (OCTAVE_DATADIR);
@@ -184,7 +184,7 @@
   return s_data_dir;
 }
 
-std::string dataroot_dir (void)
+std::string dataroot_dir ()
 {
   static const std::string s_dataroot_dir
     = prepend_octave_home (OCTAVE_DATAROOTDIR);
@@ -192,7 +192,7 @@
   return s_dataroot_dir;
 }
 
-std::string include_dir (void)
+std::string include_dir ()
 {
   static const std::string s_include_dir
     = prepend_octave_home (OCTAVE_INCLUDEDIR);
@@ -200,7 +200,7 @@
   return s_include_dir;
 }
 
-std::string lib_dir (void)
+std::string lib_dir ()
 {
   static const std::string s_lib_dir
     = prepend_octave_exec_home (OCTAVE_LIBDIR);
@@ -208,7 +208,7 @@
   return s_lib_dir;
 }
 
-std::string libexec_dir (void)
+std::string libexec_dir ()
 {
   static const std::string s_libexec_dir
     = prepend_octave_exec_home (OCTAVE_LIBEXECDIR);
@@ -216,7 +216,7 @@
   return s_libexec_dir;
 }
 
-std::string arch_lib_dir (void)
+std::string arch_lib_dir ()
 {
   static const std::string s_arch_lib_dir
     = prepend_octave_exec_home (OCTAVE_ARCHLIBDIR);
@@ -224,7 +224,7 @@
   return s_arch_lib_dir;
 }
 
-std::string info_dir (void)
+std::string info_dir ()
 {
   static const std::string s_info_dir
     = prepend_octave_exec_home (OCTAVE_INFODIR);
@@ -232,7 +232,7 @@
   return s_info_dir;
 }
 
-std::string local_ver_arch_lib_dir (void)
+std::string local_ver_arch_lib_dir ()
 {
   static const std::string s_local_ver_arch_lib_dir
     = prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR);
@@ -240,7 +240,7 @@
   return s_local_ver_arch_lib_dir;
 }
 
-std::string local_api_arch_lib_dir (void)
+std::string local_api_arch_lib_dir ()
 {
   static const std::string s_local_api_arch_lib_dir
     = prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR);
@@ -248,7 +248,7 @@
   return s_local_api_arch_lib_dir;
 }
 
-std::string local_arch_lib_dir (void)
+std::string local_arch_lib_dir ()
 {
   static const std::string s_local_arch_lib_dir
     = prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR);
@@ -256,7 +256,7 @@
   return s_local_arch_lib_dir;
 }
 
-std::string local_ver_oct_file_dir (void)
+std::string local_ver_oct_file_dir ()
 {
   static const std::string s_local_ver_oct_file_dir
     = prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR);
@@ -264,7 +264,7 @@
   return s_local_ver_oct_file_dir;
 }
 
-std::string local_api_oct_file_dir (void)
+std::string local_api_oct_file_dir ()
 {
   static const std::string s_local_api_oct_file_dir
     = prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR);
@@ -272,7 +272,7 @@
   return s_local_api_oct_file_dir;
 }
 
-std::string local_oct_file_dir (void)
+std::string local_oct_file_dir ()
 {
   static const std::string s_local_oct_file_dir
     = prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR);
@@ -280,7 +280,7 @@
   return s_local_oct_file_dir;
 }
 
-std::string oct_file_dir (void)
+std::string oct_file_dir ()
 {
   static const std::string s_oct_file_dir
     = prepend_octave_exec_home (OCTAVE_OCTFILEDIR);
@@ -288,7 +288,7 @@
   return s_oct_file_dir;
 }
 
-std::string local_ver_fcn_file_dir (void)
+std::string local_ver_fcn_file_dir ()
 {
   static const std::string s_local_ver_fcn_file_dir
     = prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR);
@@ -296,7 +296,7 @@
   return s_local_ver_fcn_file_dir;
 }
 
-std::string local_api_fcn_file_dir (void)
+std::string local_api_fcn_file_dir ()
 {
   static const std::string s_local_api_fcn_file_dir
     = prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR);
@@ -304,7 +304,7 @@
   return s_local_api_fcn_file_dir;
 }
 
-std::string local_fcn_file_dir (void)
+std::string local_fcn_file_dir ()
 {
   static const std::string s_local_fcn_file_dir
     = prepend_octave_home (OCTAVE_LOCALFCNFILEDIR);
@@ -312,7 +312,7 @@
   return s_local_fcn_file_dir;
 }
 
-std::string fcn_file_dir (void)
+std::string fcn_file_dir ()
 {
   static const std::string s_fcn_file_dir
     = prepend_octave_home (OCTAVE_FCNFILEDIR);
@@ -320,7 +320,7 @@
   return s_fcn_file_dir;
 }
 
-std::string oct_data_dir (void)
+std::string oct_data_dir ()
 {
   static const std::string s_oct_data_dir
     = prepend_octave_home (OCTAVE_OCTDATADIR);
@@ -328,7 +328,7 @@
   return s_oct_data_dir;
 }
 
-std::string oct_doc_dir (void)
+std::string oct_doc_dir ()
 {
   static const std::string s_oct_doc_dir
     = prepend_octave_home (OCTAVE_OCTDOCDIR);
@@ -336,7 +336,7 @@
   return s_oct_doc_dir;
 }
 
-std::string oct_etc_dir (void)
+std::string oct_etc_dir ()
 {
   static const std::string s_oct_etc_dir
     = prepend_octave_home (OCTAVE_OCTETCDIR);
@@ -344,7 +344,7 @@
   return s_oct_etc_dir;
 }
 
-std::string oct_fonts_dir (void)
+std::string oct_fonts_dir ()
 {
   static const std::string s_oct_fonts_dir
     = prepend_octave_home (OCTAVE_OCTFONTSDIR);
@@ -352,7 +352,7 @@
   return s_oct_fonts_dir;
 }
 
-std::string oct_include_dir (void)
+std::string oct_include_dir ()
 {
   static const std::string s_oct_include_dir
     = prepend_octave_home (OCTAVE_OCTINCLUDEDIR);
@@ -360,7 +360,7 @@
   return s_oct_include_dir;
 }
 
-std::string oct_lib_dir (void)
+std::string oct_lib_dir ()
 {
   static const std::string s_oct_lib_dir
     = prepend_octave_exec_home (OCTAVE_OCTLIBDIR);
@@ -368,7 +368,7 @@
   return s_oct_lib_dir;
 }
 
-std::string oct_locale_dir (void)
+std::string oct_locale_dir ()
 {
   static const std::string s_oct_locale_dir
     = prepend_octave_home (OCTAVE_OCTLOCALEDIR);
@@ -376,7 +376,7 @@
   return s_oct_locale_dir;
 }
 
-std::string oct_tests_dir (void)
+std::string oct_tests_dir ()
 {
   static const std::string s_oct_tests_dir
     = prepend_octave_home (OCTAVE_OCTTESTSDIR);
@@ -384,7 +384,7 @@
   return s_oct_tests_dir;
 }
 
-std::string man_dir (void)
+std::string man_dir ()
 {
   static const std::string s_man_dir
     = prepend_octave_home (OCTAVE_MANDIR);
@@ -392,7 +392,7 @@
   return s_man_dir;
 }
 
-std::string man1_dir (void)
+std::string man1_dir ()
 {
   static const std::string s_man1_dir
     = prepend_octave_home (OCTAVE_MAN1DIR);
@@ -400,14 +400,14 @@
   return s_man1_dir;
 }
 
-std::string man1_ext (void)
+std::string man1_ext ()
 {
   static const std::string s_man1_ext = OCTAVE_MAN1EXT;
 
   return s_man1_ext;
 }
 
-std::string image_dir (void)
+std::string image_dir ()
 {
   static const std::string s_image_dir
     = prepend_octave_home (OCTAVE_IMAGEDIR);
@@ -415,7 +415,7 @@
   return s_image_dir;
 }
 
-std::string local_startupfile_dir (void)
+std::string local_startupfile_dir ()
 {
   static const std::string s_local_startupfile_dir
     = prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR);
@@ -423,7 +423,7 @@
   return s_local_startupfile_dir;
 }
 
-std::string startupfile_dir (void)
+std::string startupfile_dir ()
 {
   static const std::string s_startupfile_dir
     = prepend_octave_home (OCTAVE_STARTUPFILEDIR);
@@ -431,7 +431,7 @@
   return s_startupfile_dir;
 }
 
-std::string local_site_defaults_file (void)
+std::string local_site_defaults_file ()
 {
   static const std::string s_local_site_defaults_file
     = get_local_site_defaults_file ();
@@ -439,7 +439,7 @@
   return s_local_site_defaults_file;
 }
 
-std::string site_defaults_file (void)
+std::string site_defaults_file ()
 {
   static const std::string s_site_defaults_file
     = get_site_defaults_file ();
--- a/libinterp/corefcn/defaults.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/defaults.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,61 +46,61 @@
 // functions to be consistent with the values that require
 // initialization.
 
-extern OCTINTERP_API std::string canonical_host_type (void);
-extern OCTINTERP_API std::string release (void);
-extern OCTINTERP_API std::string default_pager (void);
+extern OCTINTERP_API std::string canonical_host_type ();
+extern OCTINTERP_API std::string release ();
+extern OCTINTERP_API std::string default_pager ();
 
 // These require initialization, so can't be defined as pure
 // constants.  We use functions to access these values so that
 // they can't be modified by users.
 
-extern OCTINTERP_API std::string octave_home (void);
-extern OCTINTERP_API std::string octave_exec_home (void);
+extern OCTINTERP_API std::string octave_home ();
+extern OCTINTERP_API std::string octave_exec_home ();
 
-extern OCTINTERP_API std::string bin_dir (void);
-extern OCTINTERP_API std::string data_dir (void);
-extern OCTINTERP_API std::string dataroot_dir (void);
-extern OCTINTERP_API std::string include_dir (void);
-extern OCTINTERP_API std::string lib_dir (void);
-extern OCTINTERP_API std::string libexec_dir (void);
+extern OCTINTERP_API std::string bin_dir ();
+extern OCTINTERP_API std::string data_dir ();
+extern OCTINTERP_API std::string dataroot_dir ();
+extern OCTINTERP_API std::string include_dir ();
+extern OCTINTERP_API std::string lib_dir ();
+extern OCTINTERP_API std::string libexec_dir ();
 
-extern OCTINTERP_API std::string local_ver_arch_lib_dir (void);
-extern OCTINTERP_API std::string local_api_arch_lib_dir (void);
-extern OCTINTERP_API std::string local_arch_lib_dir (void);
-extern OCTINTERP_API std::string arch_lib_dir (void);
+extern OCTINTERP_API std::string local_ver_arch_lib_dir ();
+extern OCTINTERP_API std::string local_api_arch_lib_dir ();
+extern OCTINTERP_API std::string local_arch_lib_dir ();
+extern OCTINTERP_API std::string arch_lib_dir ();
 
-extern OCTINTERP_API std::string local_ver_oct_file_dir (void);
-extern OCTINTERP_API std::string local_api_oct_file_dir (void);
-extern OCTINTERP_API std::string local_oct_file_dir (void);
-extern OCTINTERP_API std::string oct_file_dir (void);
+extern OCTINTERP_API std::string local_ver_oct_file_dir ();
+extern OCTINTERP_API std::string local_api_oct_file_dir ();
+extern OCTINTERP_API std::string local_oct_file_dir ();
+extern OCTINTERP_API std::string oct_file_dir ();
 
-extern OCTINTERP_API std::string local_ver_fcn_file_dir (void);
-extern OCTINTERP_API std::string local_api_fcn_file_dir (void);
-extern OCTINTERP_API std::string local_fcn_file_dir (void);
-extern OCTINTERP_API std::string fcn_file_dir (void);
+extern OCTINTERP_API std::string local_ver_fcn_file_dir ();
+extern OCTINTERP_API std::string local_api_fcn_file_dir ();
+extern OCTINTERP_API std::string local_fcn_file_dir ();
+extern OCTINTERP_API std::string fcn_file_dir ();
 
-extern OCTINTERP_API std::string oct_data_dir (void);
-extern OCTINTERP_API std::string oct_doc_dir (void);
-extern OCTINTERP_API std::string oct_etc_dir (void);
-extern OCTINTERP_API std::string oct_fonts_dir (void);
-extern OCTINTERP_API std::string oct_include_dir (void);
-extern OCTINTERP_API std::string oct_lib_dir (void);
-extern OCTINTERP_API std::string oct_locale_dir (void);
-extern OCTINTERP_API std::string oct_tests_dir (void);
+extern OCTINTERP_API std::string oct_data_dir ();
+extern OCTINTERP_API std::string oct_doc_dir ();
+extern OCTINTERP_API std::string oct_etc_dir ();
+extern OCTINTERP_API std::string oct_fonts_dir ();
+extern OCTINTERP_API std::string oct_include_dir ();
+extern OCTINTERP_API std::string oct_lib_dir ();
+extern OCTINTERP_API std::string oct_locale_dir ();
+extern OCTINTERP_API std::string oct_tests_dir ();
 
-extern OCTINTERP_API std::string info_dir (void);
+extern OCTINTERP_API std::string info_dir ();
 
-extern OCTINTERP_API std::string man_dir (void);
-extern OCTINTERP_API std::string man1_dir (void);
-extern OCTINTERP_API std::string man1_ext (void);
+extern OCTINTERP_API std::string man_dir ();
+extern OCTINTERP_API std::string man1_dir ();
+extern OCTINTERP_API std::string man1_ext ();
 
-extern OCTINTERP_API std::string image_dir (void);
+extern OCTINTERP_API std::string image_dir ();
 
-extern OCTINTERP_API std::string local_startupfile_dir (void);
-extern OCTINTERP_API std::string startupfile_dir (void);
+extern OCTINTERP_API std::string local_startupfile_dir ();
+extern OCTINTERP_API std::string startupfile_dir ();
 
-extern OCTINTERP_API std::string local_site_defaults_file (void);
-extern OCTINTERP_API std::string site_defaults_file (void);
+extern OCTINTERP_API std::string local_site_defaults_file ();
+extern OCTINTERP_API std::string site_defaults_file ();
 
 OCTAVE_END_NAMESPACE(config)
 
--- a/libinterp/corefcn/defun.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/defun.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,13 +46,12 @@
 #include "interpreter.h"
 #include "symtab.h"
 #include "variables.h"
-#include "parse.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 // Print the usage part of the doc string of FCN (user-defined or DEFUN).
 void
-print_usage (void)
+print_usage ()
 {
   tree_evaluator& tw = __get_evaluator__ ();
 
@@ -67,7 +66,9 @@
 void
 print_usage (const std::string& name)
 {
-  feval ("print_usage", octave_value (name), 0);
+  interpreter& interp = __get_interpreter__ ();
+
+  interp.feval ("print_usage", octave_value (name), 0);
 }
 
 void
@@ -136,7 +137,7 @@
 }
 
 dynamic_library
-get_current_shlib (void)
+get_current_shlib ()
 {
   dynamic_library retval;
 
--- a/libinterp/corefcn/dirfns.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dirfns.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,6 +39,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "glob-match.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-glob.h"
 #include "pathsearch.h"
@@ -207,9 +208,7 @@
 
   dirname = sys::file_ops::tilde_expand (dirname);
 
-  sys::file_stat fs (dirname);
-
-  if (fs && fs.is_dir ())
+  if (sys::dir_exists (dirname))
     {
       // For Matlab compatibility, return true when directory already exists.
       return ovl (true, "directory exists", "mkdir");
--- a/libinterp/corefcn/display.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/display.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-void display_info::initialize (void)
+void display_info::initialize ()
 {
   int avail = 0;
 
--- a/libinterp/corefcn/display.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/display.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,32 +42,32 @@
   // initialize to find the actual system parameters for the given
   // display.
 
-  display_info (void)
+  display_info ()
     : m_rx (72), m_ry (72), m_ht (1), m_wd (1), m_dp (0),
       m_dpy_avail (false), m_msg ()
   { }
 
-  ~display_info (void) = default;
+  ~display_info () = default;
 
   display_info (const display_info&) = default;
 
   display_info& operator = (const display_info&) = default;
 
-  void initialize (void);
+  void initialize ();
 
-  double x_dpi (void) const { return m_rx; }
+  double x_dpi () const { return m_rx; }
 
-  double y_dpi (void) const { return m_ry; }
+  double y_dpi () const { return m_ry; }
 
-  int height (void) const { return m_ht; }
+  int height () const { return m_ht; }
 
-  int width (void) const { return m_wd; }
+  int width () const { return m_wd; }
 
-  int depth (void) const { return m_dp; }
+  int depth () const { return m_dp; }
 
-  bool display_available (void) const { return m_dpy_avail; }
+  bool display_available () const { return m_dpy_avail; }
 
-  std::string message (void) const { return m_msg; }
+  std::string message () const { return m_msg; }
 
 private:
 
--- a/libinterp/corefcn/dot.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dot.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -91,7 +91,7 @@
 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}
+@seealso{cross, divergence, tensorprod}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -193,9 +193,9 @@
       // of calculating possibly garbage results.
       // Think of the dot product of two int8 vectors where the multiplications
       // exceed intmax.
-      octave_value_list tmp;
+      octave_value_list tmp (2);
+      tmp(0) = binary_op (octave_value::op_el_mul, argx, argy);
       tmp(1) = dim + 1;
-      tmp(0) = binary_op (octave_value::op_el_mul, argx, argy);
 
       tmp = Fsum (tmp, 1);
       if (! tmp.empty ())
--- a/libinterp/corefcn/dynamic-ld.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dynamic-ld.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -95,7 +95,7 @@
 }
 
 void
-dynamic_loader::shlibs_list::display (void) const
+dynamic_loader::shlibs_list::display () const
 {
   std::cerr << "current shared libraries:" << std::endl;
   for (const auto& lib : m_lib_list)
--- a/libinterp/corefcn/dynamic-ld.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/dynamic-ld.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,15 +52,11 @@
     typedef std::list<dynamic_library>::iterator iterator;
     typedef std::list<dynamic_library>::const_iterator const_iterator;
 
-    shlibs_list (void) : m_lib_list () { }
-
-    // No copying!
+    shlibs_list () : m_lib_list () { }
 
-    shlibs_list (const shlibs_list&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (shlibs_list)
 
-    shlibs_list& operator = (const shlibs_list&) = delete;
-
-    ~shlibs_list (void) = default;
+    ~shlibs_list () = default;
 
     void append (const dynamic_library& shl);
 
@@ -68,7 +64,7 @@
 
     dynamic_library find_file (const std::string& file_name) const;
 
-    void display (void) const;
+    void display () const;
 
   private:
 
@@ -79,17 +75,15 @@
 
 public:
 
+  dynamic_loader () = delete;
+
   dynamic_loader (interpreter& interp)
     : m_interpreter (interp), m_loaded_shlibs (), m_doing_load (false)
   { }
 
-  // No copying!
-
-  dynamic_loader (const dynamic_loader&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (dynamic_loader)
 
-  dynamic_loader& operator = (const dynamic_loader&) = delete;
-
-  virtual ~dynamic_loader (void) = default;
+  virtual ~dynamic_loader () = default;
 
   octave_function *
   load_oct (const std::string& fcn_name,
--- a/libinterp/corefcn/environment.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/environment.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -104,7 +104,7 @@
                                 false);
 }
 
-std::string environment::init_editor (void)
+std::string environment::init_editor ()
 {
   std::string retval = "emacs";
 
@@ -116,7 +116,7 @@
   return retval;
 }
 
-std::string environment::init_exec_path (void)
+std::string environment::init_exec_path ()
 {
   std::string exec_path = sys::env::getenv ("OCTAVE_EXEC_PATH");
 
@@ -134,7 +134,7 @@
   return exec_path;
 }
 
-std::string environment::init_image_path (void)
+std::string environment::init_image_path ()
 {
   std::string image_path = ".";
 
--- a/libinterp/corefcn/environment.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/environment.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,15 +39,17 @@
 {
 public:
 
-  environment (void)
+  environment ()
     : m_editor (init_editor ()),
       m_exec_path (init_exec_path ()),
       m_image_path (init_image_path ())
   { }
 
+  OCTAVE_DEFAULT_COPY_DELETE (environment)
+
   octave_value editor (const octave_value_list& args, int nargout);
 
-  std::string editor (void) const { return m_editor; }
+  std::string editor () const { return m_editor; }
 
   std::string editor (const std::string& ed)
   {
@@ -56,13 +58,13 @@
 
   octave_value exec_path (const octave_value_list& args, int nargout);
 
-  std::string exec_path (void) const { return m_exec_path; }
+  std::string exec_path () const { return m_exec_path; }
 
   std::string exec_path (const std::string& path);
 
   octave_value image_path (const octave_value_list& args, int nargout);
 
-  std::string image_path (void) const { return m_image_path; }
+  std::string image_path () const { return m_image_path; }
 
   std::string image_path (const std::string& path)
   {
@@ -77,11 +79,11 @@
 
   std::string m_image_path;
 
-  static std::string init_editor (void);
+  static std::string init_editor ();
 
-  static std::string init_exec_path (void);
+  static std::string init_exec_path ();
 
-  static std::string init_image_path (void);
+  static std::string init_image_path ();
 
   std::string set (std::string& var, const std::string& new_val)
   {
--- a/libinterp/corefcn/error.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/error.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -697,7 +697,7 @@
   return retval;
 }
 
-std::string error_system::default_warning_state (void)
+std::string error_system::default_warning_state ()
 {
   std::string retval = "on";
 
@@ -829,7 +829,7 @@
   set_warning_option ("off", id);
 }
 
-void error_system::initialize_default_warning_state (void)
+void error_system::initialize_default_warning_state ()
 {
   warning_options (init_warning_options ("on"));
 
@@ -901,17 +901,6 @@
   last_error_stack (make_stack_map (ee.stack_info ()));
 }
 
-// DEPRECATED in Octave 7.
-void error_system::display_exception (const execution_exception& ee,
-                                      std::ostream& os) const
-{
-  if (m_beep_on_error)
-    os << "\a";
-
-  ee.display (octave_diary);
-  ee.display (os);
-}
-
 void error_system::display_exception (const execution_exception& ee) const
 {
   // FIXME: How should we handle beep_on_error?
@@ -1813,10 +1802,10 @@
 octave_value_list
 set_warning_state (const std::string& id, const std::string& state)
 {
-  octave_value_list args;
+  octave_value_list args (2);
 
+  args(0) = state;
   args(1) = id;
-  args(0) = state;
 
   interpreter& interp = __get_interpreter__ ();
 
--- a/libinterp/corefcn/error.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/error.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,18 +48,16 @@
 
   OCTINTERP_API error_system (interpreter& interp);
 
-  error_system (const error_system&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (error_system)
 
-  error_system& operator = (const error_system&) = delete;
-
-  ~error_system (void) = default;
+  ~error_system () = default;
 
   OCTINTERP_API octave_value
   debug_on_error (const octave_value_list& args, int nargout);
 
   void set_debug_on_error (bool flag) { m_debug_on_error = flag; }
 
-  bool debug_on_error (void) const { return m_debug_on_error; }
+  bool debug_on_error () const { return m_debug_on_error; }
 
   bool debug_on_error (bool flag)
   {
@@ -73,7 +71,7 @@
 
   void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; }
 
-  bool debug_on_caught (void) const { return m_debug_on_caught; }
+  bool debug_on_caught () const { return m_debug_on_caught; }
 
   bool debug_on_caught (bool flag)
   {
@@ -87,7 +85,7 @@
 
   void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; }
 
-  bool debug_on_warning (void) const { return m_debug_on_warning; }
+  bool debug_on_warning () const { return m_debug_on_warning; }
 
   bool debug_on_warning (bool flag)
   {
@@ -104,7 +102,7 @@
     m_discard_warning_messages = flag;
   }
 
-  bool discard_warning_messages (void) const
+  bool discard_warning_messages () const
   {
     return m_discard_warning_messages;
   }
@@ -121,7 +119,7 @@
 
   void set_beep_on_error (bool flag) { m_beep_on_error = flag; }
 
-  bool beep_on_error (void) const { return m_beep_on_error; }
+  bool beep_on_error () const { return m_beep_on_error; }
 
   bool beep_on_error (bool flag)
   {
@@ -135,7 +133,7 @@
 
   void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; }
 
-  bool backtrace_on_warning (void) const { return m_backtrace_on_warning; }
+  bool backtrace_on_warning () const { return m_backtrace_on_warning; }
 
   bool backtrace_on_warning (bool flag)
   {
@@ -149,7 +147,7 @@
 
   void set_verbose_warning (bool flag) { m_verbose_warning = flag; }
 
-  bool verbose_warning (void) const { return m_verbose_warning; }
+  bool verbose_warning () const { return m_verbose_warning; }
 
   bool verbose_warning (bool flag)
   {
@@ -163,7 +161,7 @@
 
   void set_quiet_warning (bool flag) { m_quiet_warning = flag; }
 
-  bool quiet_warning (void) const { return m_quiet_warning; }
+  bool quiet_warning () const { return m_quiet_warning; }
 
   bool quiet_warning (bool flag)
   {
@@ -172,7 +170,7 @@
     return val;
   }
 
-  octave_map warning_options (void) const { return m_warning_options; }
+  octave_map warning_options () const { return m_warning_options; }
 
   void set_warning_options (const octave_map& val)
   { m_warning_options = val; }
@@ -190,7 +188,7 @@
   void set_last_error_message (const std::string& val)
   { m_last_error_message = val; }
 
-  std::string last_error_message (void) const { return m_last_error_message; }
+  std::string last_error_message () const { return m_last_error_message; }
 
   std::string last_error_message (const std::string& s)
   {
@@ -205,7 +203,7 @@
   void set_last_warning_message (const std::string& val)
   { m_last_warning_message = val; }
 
-  std::string last_warning_message (void) const
+  std::string last_warning_message () const
   { return m_last_warning_message; }
 
   std::string last_warning_message (const std::string& s)
@@ -221,7 +219,7 @@
   void set_last_warning_id (const std::string& val)
   { m_last_warning_id = val; }
 
-  std::string last_warning_id (void) const { return m_last_warning_id; }
+  std::string last_warning_id () const { return m_last_warning_id; }
 
   std::string last_warning_id (const std::string& s)
   {
@@ -235,7 +233,7 @@
 
   void set_last_error_id (const std::string& val) { m_last_error_id = val; }
 
-  std::string last_error_id (void) const { return m_last_error_id; }
+  std::string last_error_id () const { return m_last_error_id; }
 
   std::string last_error_id (const std::string& s)
   {
@@ -249,7 +247,7 @@
     m_last_error_stack = val;
   }
 
-  octave_map last_error_stack (void) const { return m_last_error_stack; }
+  octave_map last_error_stack () const { return m_last_error_stack; }
 
   octave_map last_error_stack (const octave_map& new_val)
   {
@@ -305,7 +303,7 @@
 
   OCTINTERP_API octave_scalar_map warning_query (const std::string& id_arg);
 
-  OCTINTERP_API std::string default_warning_state (void);
+  OCTINTERP_API std::string default_warning_state ();
 
   OCTINTERP_API void display_warning_options (std::ostream& os);
 
@@ -314,7 +312,7 @@
 
   OCTINTERP_API void disable_warning (const std::string& id);
 
-  OCTINTERP_API void initialize_default_warning_state (void);
+  OCTINTERP_API void initialize_default_warning_state ();
 
   OCTINTERP_API void interpreter_try (unwind_protect& frame);
 
@@ -334,13 +332,6 @@
 
   OCTINTERP_API void save_exception (const execution_exception& ee);
 
-  // FIXME
-  //#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "second argument is no longer accepted")
-  OCTINTERP_API void display_exception (const execution_exception& ee,
-                                        std::ostream& os) const;
-  //#endif
-
   OCTINTERP_API void display_exception (const execution_exception& ee) const;
 
 private:
@@ -573,44 +564,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::defun_usage_message' instead")
-inline void defun_usage_message (const std::string& msg)
-{
-  octave::defun_usage_message (msg);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead")
-inline octave_value_list
-set_warning_state (const std::string& id, const std::string& state)
-{
-  return octave::set_warning_state (id, state);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead")
-inline octave_value_list set_warning_state (const octave_value_list& args)
-{
-  return octave::set_warning_state (args);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::warning_enabled' instead")
-inline int warning_enabled (const std::string& id)
-{
-  return octave::warning_enabled (id);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::disable_warning' instead")
-inline void disable_warning (const std::string& id)
-{
-  octave::disable_warning (id);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::interpreter_try' instead")
-inline void interpreter_try (octave::unwind_protect& uwp)
-{
-  octave::interpreter_try (uwp);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/errwarn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/errwarn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void
-err_2_or_3_dim_plot (void)
+err_2_or_3_dim_plot ()
 {
   error ("plot: can only plot in 2 or 3 dimensions");
 }
@@ -62,7 +62,7 @@
 }
 
 void
-err_indexed_cs_list (void)
+err_indexed_cs_list ()
 {
   error ("a cs-list cannot be further indexed");
 }
@@ -74,25 +74,25 @@
 }
 
 void
-err_invalid_inquiry_subscript (void)
+err_invalid_inquiry_subscript ()
 {
   error ("invalid dimension inquiry of a non-existent value");
 }
 
 void
-err_invalid_structure_assignment (void)
+err_invalid_structure_assignment ()
 {
   error ("invalid dot name structure assignment because the structure array is empty.  Specify a subscript on the structure array to resolve.");
 }
 
 void
-err_nonbraced_cs_list_assignment (void)
+err_nonbraced_cs_list_assignment ()
 {
   error ("invalid assignment to cs-list outside multiple assignment");
 }
 
 void
-err_nonconformant (void)
+err_nonconformant ()
 {
   error ("nonconformant matrices");
 }
@@ -113,7 +113,7 @@
 }
 
 void
-err_range_invalid (void)
+err_range_invalid ()
 {
   error ("range constant used in invalid context");
 }
@@ -125,7 +125,7 @@
 }
 
 void
-err_string_invalid (void)
+err_string_invalid ()
 {
   error ("std::string constant used in invalid context");
 }
@@ -137,7 +137,7 @@
 }
 
 void
-err_unrecognized_float_fmt (void)
+err_unrecognized_float_fmt ()
 {
   error ("unrecognized floating point format requested");
 }
@@ -300,7 +300,7 @@
 */
 
 void
-warn_complex_cmp (void)
+warn_complex_cmp ()
 {
   warning_with_id ("Octave:language-extension",
                    "comparing complex numbers is not supported in Matlab");
@@ -362,7 +362,7 @@
 }
 
 void
-warn_logical_conversion (void)
+warn_logical_conversion ()
 {
   warning_with_id ("Octave:logical-conversion",
                    "value not equal to 1 or 0 converted to logical 1");
--- a/libinterp/corefcn/errwarn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/errwarn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_2_or_3_dim_plot (void);
+err_2_or_3_dim_plot ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_data_conversion (const char *from, const char *to);
@@ -54,22 +54,22 @@
                       const std::string& pkg = "Octave");
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_indexed_cs_list (void);
+err_indexed_cs_list ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_invalid_conversion (const std::string& from, const std::string& to);
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_invalid_inquiry_subscript (void);
+err_invalid_inquiry_subscript ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_invalid_structure_assignment (void);
+err_invalid_structure_assignment ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_nonbraced_cs_list_assignment (void);
+err_nonbraced_cs_list_assignment ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_nonconformant (void);
+err_nonconformant ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_nonconformant (octave_idx_type r1, octave_idx_type c1,
@@ -79,19 +79,19 @@
 err_not_implemented (const char *);
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_range_invalid (void);
+err_range_invalid ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_square_matrix_required (const char *fcn, const char *name);
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_string_invalid (void);
+err_string_invalid ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_unrecognized_data_fmt (const char *name);
 
 OCTAVE_NORETURN extern OCTINTERP_API void
-err_unrecognized_float_fmt (void);
+err_unrecognized_float_fmt ();
 
 OCTAVE_NORETURN extern OCTINTERP_API void
 err_user_returned_invalid (const char *name);
@@ -158,7 +158,7 @@
 warn_array_as_logical (const dim_vector& dv);
 
 extern OCTINTERP_API void
-warn_complex_cmp (void);
+warn_complex_cmp ();
 
 extern OCTINTERP_API void
 warn_data_file_in_path (const std::string& fcn, const std::string& file);
@@ -184,7 +184,7 @@
 warn_invalid_value_specified (const char *name);
 
 extern OCTINTERP_API void
-warn_logical_conversion (void);
+warn_logical_conversion ();
 
 extern OCTINTERP_API void
 warn_wrong_type_arg (const char *name, const octave_value& tc);
--- a/libinterp/corefcn/event-manager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/event-manager.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-static int readline_event_hook (void)
+static int readline_event_hook ()
 {
   event_manager& evmgr = __get_event_manager__ ();
 
@@ -74,7 +74,7 @@
   command_editor::add_event_hook (readline_event_hook);
 }
 
-event_manager::~event_manager (void)
+event_manager::~event_manager ()
 {
   delete m_event_queue_mutex;
 }
@@ -94,7 +94,7 @@
   m_instance = obj;
 }
 
-bool event_manager::enable (void)
+bool event_manager::enable ()
 {
   bool retval = m_link_enabled;
 
@@ -121,7 +121,7 @@
     }
 }
 
-void event_manager::discard_events (void)
+void event_manager::discard_events ()
 {
   if (enabled ())
     {
@@ -133,13 +133,13 @@
     }
 }
 
-void event_manager::push_event_queue (void)
+void event_manager::push_event_queue ()
 {
   std::shared_ptr<event_queue> evq (new event_queue ());
   m_gui_event_queue.push (evq);
 }
 
-void event_manager::pop_event_queue (void)
+void event_manager::pop_event_queue ()
 {
   // FIXME: Should we worry about the possibility of events remaining
   // in the queue when we pop back to the previous queue?  If so, then
@@ -172,7 +172,7 @@
     }
 }
 
-void event_manager::set_workspace (void)
+void event_manager::set_workspace ()
 {
   if (enabled ())
     {
@@ -183,7 +183,7 @@
     }
 }
 
-void event_manager::set_history (void)
+void event_manager::set_history ()
 {
   if (enabled ())
     m_instance->set_history (command_history::list ());
--- a/libinterp/corefcn/event-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/event-manager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-typedef std::function<void (void)> fcn_callback;
+typedef std::function<void ()> fcn_callback;
 typedef std::function<void (interpreter&)> meth_callback;
 
 class execution_exception;
@@ -79,13 +79,13 @@
 {
 public:
 
-  interpreter_events (void) = default;
+  interpreter_events () = default;
 
   interpreter_events (const interpreter_events&) = default;
 
   interpreter_events& operator = (const interpreter_events&) = default;
 
-  virtual ~interpreter_events (void) = default;
+  virtual ~interpreter_events () = default;
 
   // Note: START_GUI and CLOSE_GUI currently only work with the new
   // experimental terminal widget.
@@ -96,11 +96,11 @@
   // command line application.
 
   virtual void start_gui (bool /*gui_app*/ = false) { }
-  virtual void close_gui (void) { }
+  virtual void close_gui () { }
 
   // Dialogs.
 
-  virtual bool have_dialogs (void) const { return false; }
+  virtual bool have_dialogs () const { return false; }
 
   typedef std::list<std::pair<std::string, std::string>> filter_list;
 
@@ -144,27 +144,27 @@
     return "";
   }
 
-  virtual void update_path_dialog (void) {  }
+  virtual void update_path_dialog () {  }
 
-  virtual void show_preferences (void) { }
+  virtual void show_preferences () { }
 
-  virtual void apply_preferences (void) { }
+  virtual void apply_preferences () { }
 
-  virtual void show_terminal_window (void) { }
+  virtual void show_terminal_window () { }
 
   virtual bool show_documentation (const std::string& /*file*/)
   {
     return false;
   }
 
-  virtual void show_file_browser (void) { }
+  virtual void show_file_browser () { }
 
-  virtual void show_command_history (void) { }
+  virtual void show_command_history () { }
 
-  virtual void show_workspace (void) { }
+  virtual void show_workspace () { }
 
   virtual void show_community_news (int /*serial*/) { }
-  virtual void show_release_notes (void) { }
+  virtual void show_release_notes () { }
 
   virtual bool edit_file (const std::string& /*file*/) { return false; }
 
@@ -176,7 +176,7 @@
   // confirmation before another action.  Could these be reformulated
   // using the question_dialog action?
 
-  virtual bool confirm_shutdown (void) { return true; }
+  virtual bool confirm_shutdown () { return true; }
 
   virtual bool prompt_new_edit_file (const std::string& /*file*/)
   {
@@ -231,7 +231,7 @@
   virtual void gui_status_update (const std::string& /*feature*/,
                                   const std::string& /*status*/) { }
 
-  virtual void update_gui_lexer (void) { }
+  virtual void update_gui_lexer () { }
 
   // Notifications of events in the interpreter that a GUI will
   // normally wish to respond to.
@@ -250,7 +250,7 @@
                  bool /*update_variable_editor*/)
   { }
 
-  virtual void clear_workspace (void) { }
+  virtual void clear_workspace () { }
 
   virtual void update_prompt (const std::string& /*prompt*/) { }
 
@@ -258,11 +258,11 @@
 
   virtual void append_history (const std::string& /*hist_entry*/) { }
 
-  virtual void clear_history (void) { }
+  virtual void clear_history () { }
 
-  virtual void pre_input_event (void) { }
+  virtual void pre_input_event () { }
 
-  virtual void post_input_event (void) { }
+  virtual void post_input_event () { }
 
   virtual void
   enter_debugger_event (const std::string& /*fcn_name*/,
@@ -273,14 +273,14 @@
   virtual void
   execute_in_debugger_event (const std::string& /*file*/, int /*line*/) { }
 
-  virtual void exit_debugger_event (void) { }
+  virtual void exit_debugger_event () { }
 
   virtual void
   update_breakpoint (bool /*insert*/, const std::string& /*file*/,
                      int /*line*/, const std::string& /*cond*/)
   { }
 
-  virtual void interpreter_interrupted (void) { }
+  virtual void interpreter_interrupted () { }
 };
 
 //! Provides threadsafe access to octave.
@@ -296,14 +296,9 @@
 
   OCTINTERP_API event_manager (interpreter& interp);
 
-  // No copying!
-
-  event_manager (const event_manager&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (event_manager)
 
-  event_manager&
-  operator = (const event_manager&) = delete;
-
-  virtual ~event_manager (void);
+  virtual ~event_manager ();
 
   // OBJ should be an object of a class that is derived from the base
   // class interpreter_events, or nullptr to disconnect and delete the
@@ -312,16 +307,16 @@
   OCTINTERP_API void
   connect_link (const std::shared_ptr<interpreter_events>& obj);
 
-  OCTINTERP_API bool enable (void);
+  OCTINTERP_API bool enable ();
 
-  bool disable (void)
+  bool disable ()
   {
     bool retval = m_link_enabled;
     m_link_enabled = false;
     return retval;
   }
 
-  bool enabled (void) const
+  bool enabled () const
   {
     return m_link_enabled;
   }
@@ -337,22 +332,22 @@
   }
 
   std::shared_ptr<interpreter_events>
-  qt_event_handlers (void) const { return m_qt_event_handlers; }
+  qt_event_handlers () const { return m_qt_event_handlers; }
 
   // If disable is TRUE, then no additional events will be processed
   // other than exit.
 
   OCTINTERP_API void process_events (bool disable = false);
 
-  OCTINTERP_API void discard_events (void);
+  OCTINTERP_API void discard_events ();
 
   // The post_event and post_exception functions provide a thread-safe
   // way for the GUI to queue interpreter functions for execution.
   // The queued functions are executed when the interpreter is
   // otherwise idle.
 
-  void push_event_queue (void);
-  void pop_event_queue (void);
+  void push_event_queue ();
+  void pop_event_queue ();
 
   OCTINTERP_API void post_event (const fcn_callback& fcn);
   OCTINTERP_API void post_event (const meth_callback& meth);
@@ -376,7 +371,7 @@
       m_instance->start_gui (gui_app);
   }
 
-  void close_gui (void)
+  void close_gui ()
   {
     if (enabled ())
       m_instance->close_gui ();
@@ -384,7 +379,7 @@
 
   // Dialogs
 
-  bool have_dialogs (void) const
+  bool have_dialogs () const
   {
     return m_qt_event_handlers && m_qt_event_handlers->have_dialogs ();
   }
@@ -442,13 +437,13 @@
             : "");
   }
 
-  void update_path_dialog (void)
+  void update_path_dialog ()
   {
     if (application::is_gui_running () && enabled ())
       m_instance->update_path_dialog ();
   }
 
-  bool show_preferences (void)
+  bool show_preferences ()
   {
     if (enabled ())
       {
@@ -459,7 +454,7 @@
       return false;
   }
 
-  bool apply_preferences (void)
+  bool apply_preferences ()
   {
     if (enabled ())
       {
@@ -470,7 +465,7 @@
       return false;
   }
 
-  void show_terminal_window (void)
+  void show_terminal_window ()
   {
     if (enabled ())
       m_instance->show_terminal_window ();
@@ -481,19 +476,19 @@
     return enabled () ? m_instance->show_documentation (file) : false;
   }
 
-  void show_file_browser (void)
+  void show_file_browser ()
   {
     if (enabled ())
       m_instance->show_file_browser ();
   }
 
-  void show_command_history (void)
+  void show_command_history ()
   {
     if (enabled ())
       m_instance->show_command_history ();
   }
 
-  void show_workspace (void)
+  void show_workspace ()
   {
     if (enabled ())
       m_instance->show_workspace ();
@@ -505,7 +500,7 @@
       m_instance->show_community_news (serial);
   }
 
-  void show_release_notes (void)
+  void show_release_notes ()
   {
     if (enabled ())
       m_instance->show_release_notes ();
@@ -527,7 +522,7 @@
       return false;
   }
 
-  bool confirm_shutdown (void)
+  bool confirm_shutdown ()
   {
     bool retval = true;
 
@@ -637,7 +632,7 @@
       return false;
   }
 
-  bool update_gui_lexer (void)
+  bool update_gui_lexer ()
   {
     if (enabled ())
       {
@@ -667,7 +662,7 @@
       m_instance->file_renamed (load_new);
   }
 
-  OCTINTERP_API void set_workspace (void);
+  OCTINTERP_API void set_workspace ();
 
   void set_workspace (bool top_level, const symbol_info_list& syminfo,
                       bool update_variable_editor = true)
@@ -677,7 +672,7 @@
                                  update_variable_editor);
   }
 
-  void clear_workspace (void)
+  void clear_workspace ()
   {
     if (enabled ())
       m_instance->clear_workspace ();
@@ -689,7 +684,7 @@
       m_instance->update_prompt (prompt);
   }
 
-  OCTINTERP_API void set_history (void);
+  OCTINTERP_API void set_history ();
 
   void set_history (const string_vector& hist)
   {
@@ -703,19 +698,19 @@
       m_instance->append_history (hist_entry);
   }
 
-  void clear_history (void)
+  void clear_history ()
   {
     if (enabled ())
       m_instance->clear_history ();
   }
 
-  void pre_input_event (void)
+  void pre_input_event ()
   {
     if (enabled ())
       m_instance->pre_input_event ();
   }
 
-  void post_input_event (void)
+  void post_input_event ()
   {
     if (enabled ())
       m_instance->post_input_event ();
@@ -738,7 +733,7 @@
       m_instance->execute_in_debugger_event (file, line);
   }
 
-  void exit_debugger_event (void)
+  void exit_debugger_event ()
   {
     if (enabled () && m_debugging)
       {
@@ -755,7 +750,7 @@
       m_instance->update_breakpoint (insert, file, line, cond);
   }
 
-  void interpreter_interrupted (void)
+  void interpreter_interrupted ()
   {
     if (enabled ())
       m_instance->interpreter_interrupted ();
--- a/libinterp/corefcn/event-queue.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/event-queue.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 void
-event_queue_safe::warn_unhandled_exception (void) const
+event_queue_safe::warn_unhandled_exception () const
 {
   warning ("unhandled exception in event_queue_safe handler.  "
            "It is a bug in Octave for this to happen.  "
--- a/libinterp/corefcn/event-queue.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/event-queue.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,20 +40,16 @@
 {
 public:
 
-  event_queue (void) : m_fifo () { }
-
-  // No copying!
+  event_queue () : m_fifo () { }
 
-  event_queue (const event_queue&) = delete;
-
-  event_queue& operator = (const event_queue&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (event_queue)
 
   // Destructor should not raise an exception, so all actions registered
   // should be exception-safe.  If you're not sure, see event_queue_safe.
 
-  ~event_queue (void) { run (); }
+  ~event_queue () { run (); }
 
-  void run_first (void)
+  void run_first ()
   {
     if (! empty ())
       {
@@ -64,7 +60,7 @@
       }
   }
 
-  void discard_first (void)
+  void discard_first ()
   {
     if (! empty ())
       {
@@ -74,7 +70,7 @@
       }
   }
 
-  std::size_t size (void) const { return m_fifo.size (); }
+  std::size_t size () const { return m_fifo.size (); }
 
 protected:
 
@@ -97,15 +93,11 @@
 {
 public:
 
-  event_queue_safe (void) : event_queue () { }
-
-  // No copying!
+  event_queue_safe () : event_queue () { }
 
-  event_queue_safe (const event_queue_safe&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (event_queue_safe)
 
-  event_queue_safe& operator = (const event_queue_safe&) = delete;
-
-  ~event_queue_safe (void)
+  ~event_queue_safe ()
   {
     while (! empty ())
       {
@@ -122,7 +114,7 @@
 
 private:
 
-  void warn_unhandled_exception (void) const;
+  void warn_unhandled_exception () const;
 
 };
 
--- a/libinterp/corefcn/fcn-info.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/fcn-info.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -29,6 +29,7 @@
 
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 
 #include "defun.h"
@@ -91,7 +92,7 @@
 }
 
 octave_value
-fcn_info::fcn_info_rep::load_class_constructor (void)
+fcn_info::fcn_info_rep::load_class_constructor ()
 {
   octave_value retval;
 
@@ -241,7 +242,7 @@
 // to btyp_num_types (static constant).  Only the leftmost dimension can be
 // variable in C/C++.  Typedefs are boring.
 
-static builtin_type_t (* build_sup_table (void))[btyp_num_types]
+static builtin_type_t (* build_sup_table ())[btyp_num_types]
 {
   static builtin_type_t sup_table[btyp_num_types][btyp_num_types];
   for (int i = 0; i < btyp_num_types; i++)
@@ -573,7 +574,7 @@
                         }
 
                       if (! file.empty ())
-                        is_same_file = same_file (file, ff);
+                        is_same_file = sys::same_file (file, ff);
                     }
                   else
                     {
@@ -999,7 +1000,7 @@
 }
 
 octave_value
-fcn_info::fcn_info_rep::find_autoload (void)
+fcn_info::fcn_info_rep::find_autoload ()
 {
   // Autoloaded function.
 
@@ -1030,7 +1031,7 @@
 }
 
 octave_value
-fcn_info::fcn_info_rep::find_user_function (void)
+fcn_info::fcn_info_rep::find_user_function ()
 {
   // Function on the path.
 
@@ -1060,7 +1061,7 @@
 }
 
 octave_value
-fcn_info::fcn_info_rep::find_package (void)
+fcn_info::fcn_info_rep::find_package ()
 {
   // FIXME: implement correct way to check out of date package
   //if (package.is_defined ())
@@ -1098,7 +1099,7 @@
 }
 
 octave_value
-fcn_info::fcn_info_rep::dump (void) const
+fcn_info::fcn_info_rep::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "name", full_name () },
@@ -1183,8 +1184,7 @@
 
   if (nargin == 1)
     {
-      std::string sval = args(
-                           0).xstring_value ("ignore_function_time_stamp: first argument must be a string");
+      std::string sval = args(0).xstring_value ("ignore_function_time_stamp: first argument must be a string");
 
       if (sval == "all")
         Vignore_function_time_stamp = 2;
--- a/libinterp/corefcn/fcn-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/fcn-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -68,19 +68,15 @@
         }
     }
 
-    // No copying!
-
-    fcn_info_rep (const fcn_info_rep&) = delete;
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fcn_info_rep)
 
-    fcn_info_rep& operator = (const fcn_info_rep&) = delete;
-
-    ~fcn_info_rep (void) = default;
+    ~fcn_info_rep () = 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_constructor ();
 
     octave_value load_class_method (const std::string& dispatch_type);
 
@@ -97,13 +93,13 @@
 
     octave_value find_method (const octave_value_list& args);
 
-    octave_value find_autoload (void);
+    octave_value find_autoload ();
 
-    octave_value find_package (void);
+    octave_value find_package ();
 
-    octave_value find_user_function (void);
+    octave_value find_user_function ();
 
-    bool is_user_function_defined (void) const
+    bool is_user_function_defined () const
     {
       return function_on_path.is_defined ();
     }
@@ -171,13 +167,13 @@
         cmdline_function = octave_value ();
     }
 
-    void clear_mex_function (void)
+    void clear_mex_function ()
     {
       if (function_on_path.is_mex_function ())
         clear_user_function ();
     }
 
-    void clear_package (void)
+    void clear_package ()
     {
       package = octave_value ();
     }
@@ -194,9 +190,9 @@
       clear_package ();
     }
 
-    octave_value dump (void) const;
+    octave_value dump () const;
 
-    std::string full_name (void) const
+    std::string full_name () const
     {
       if (package_name.empty ())
         return name;
@@ -247,7 +243,7 @@
 
   fcn_info& operator = (const fcn_info&) = default;
 
-  ~fcn_info (void) = default;
+  ~fcn_info () = default;
 
   octave_value find (const symbol_scope& search_scope,
                      const octave_value_list& args = octave_value_list ())
@@ -276,28 +272,28 @@
     return m_rep->find_method (dispatch_type);
   }
 
-  octave_value find_built_in_function (void) const
+  octave_value find_built_in_function () const
   {
     return m_rep->built_in_function;
   }
 
-  octave_value find_cmdline_function (void) const
+  octave_value find_cmdline_function () const
   {
     return m_rep->cmdline_function;
   }
 
-  octave_value find_autoload (void)
+  octave_value find_autoload ()
   {
     return m_rep->find_autoload ();
   }
 
   // FIXME: find_function_on_path might be a better name?
-  octave_value find_user_function (void)
+  octave_value find_user_function ()
   {
     return m_rep->find_user_function ();
   }
 
-  bool is_user_function_defined (void) const
+  bool is_user_function_defined () const
   {
     return m_rep->is_user_function_defined ();
   }
@@ -347,9 +343,9 @@
     m_rep->clear_autoload_function (force);
   }
 
-  void clear_mex_function (void) { m_rep->clear_mex_function (); }
+  void clear_mex_function () { m_rep->clear_mex_function (); }
 
-  octave_value dump (void) const { return m_rep->dump (); }
+  octave_value dump () const { return m_rep->dump (); }
 
 private:
 
--- a/libinterp/corefcn/file-io.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/file-io.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -418,12 +418,12 @@
 
   std::string fname = sys::file_ops::tilde_expand (name);
 
-  sys::file_stat fs (fname);
+  bool is_dir = sys::dir_exists (fname);
 
   if (! (md & std::ios::out))
     fname = find_data_file_in_load_path ("fopen", fname);
 
-  if (! fs.is_dir ())
+  if (! is_dir)
     {
 #if defined (HAVE_ZLIB)
       if (use_zlib)
--- a/libinterp/corefcn/ft-text-renderer.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ft-text-renderer.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -102,7 +102,7 @@
 {
 private:
 
-  ft_manager (void)
+  ft_manager ()
     : m_library (), m_freetype_initialized (false),
       m_fontconfig_initialized (false)
   {
@@ -121,15 +121,11 @@
 
 public:
 
-  // No copying!
-
-  ft_manager (const ft_manager&) = delete;
-
-  ft_manager& operator = (const ft_manager&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (ft_manager)
 
 private:
 
-  ~ft_manager (void)
+  ~ft_manager ()
   {
     if (m_freetype_initialized)
       FT_Done_FreeType (m_library);
@@ -146,42 +142,42 @@
 
 public:
 
-  static bool instance_ok (void)
+  static bool instance_ok ()
   {
     bool retval = true;
 
-    if (! m_instance)
+    if (! s_instance)
       {
-        m_instance = new ft_manager ();
+        s_instance = new ft_manager ();
         singleton_cleanup_list::add (cleanup_instance);
       }
 
     return retval;
   }
 
-  static void cleanup_instance (void)
-  { delete m_instance; m_instance = nullptr; }
+  static void cleanup_instance ()
+  { delete s_instance; s_instance = nullptr; }
 
   static FT_Face get_font (const std::string& name, const std::string& weight,
                            const std::string& angle, double size,
                            FT_ULong c = 0)
   {
     return (instance_ok ()
-            ? m_instance->do_get_font (name, weight, angle, size, c)
+            ? s_instance->do_get_font (name, weight, angle, size, c)
             : nullptr);
   }
 
-  static octave_map get_system_fonts (void)
+  static octave_map get_system_fonts ()
   {
     return (instance_ok ()
-            ? m_instance->do_get_system_fonts ()
+            ? s_instance->do_get_system_fonts ()
             : octave_map ());
   }
 
   static void font_destroyed (FT_Face face)
   {
     if (instance_ok ())
-      m_instance->do_font_destroyed (face);
+      s_instance->do_font_destroyed (face);
   }
 
 private:
@@ -189,7 +185,7 @@
   typedef std::pair<std::string, double> ft_key;
   typedef std::map<ft_key, FT_Face> ft_cache;
 
-  static octave_map do_get_system_fonts (void)
+  static octave_map do_get_system_fonts ()
   {
     static octave_map font_map;
 
@@ -434,7 +430,7 @@
 
   //--------
 
-  static ft_manager *m_instance;
+  static ft_manager *s_instance;
 
   // Cache the fonts loaded by FreeType.  This cache only contains
   // weak references to the fonts, strong references are only present
@@ -446,7 +442,7 @@
   bool m_fontconfig_initialized;
 };
 
-ft_manager *ft_manager::m_instance = nullptr;
+ft_manager *ft_manager::s_instance = nullptr;
 
 static void
 ft_face_destroyed (void *object)
@@ -468,7 +464,7 @@
 
 public:
 
-  ft_text_renderer (void)
+  ft_text_renderer ()
     : base_text_renderer (), m_font (), m_bbox (1, 4, 0.0), m_halign (0),
       m_xoffset (0), m_line_yoffset (0), m_yoffset (0), m_mode (MODE_BBOX),
       m_color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (),
@@ -476,13 +472,9 @@
       m_max_fontsize (0), m_antialias (true)
   { }
 
-  // No copying!
-
-  ft_text_renderer (const ft_text_renderer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (ft_text_renderer)
 
-  ft_text_renderer& operator = (const ft_text_renderer&) = delete;
-
-  ~ft_text_renderer (void) = default;
+  ~ft_text_renderer () = default;
 
   void visit (text_element_string& e);
 
@@ -504,11 +496,11 @@
 
   void visit (text_element_combined& e);
 
-  void reset (void);
+  void reset ();
 
-  uint8NDArray get_pixels (void) const { return m_pixels; }
+  uint8NDArray get_pixels () const { return m_pixels; }
 
-  Matrix get_boundingbox (void) const { return m_bbox; }
+  Matrix get_boundingbox () const { return m_bbox; }
 
   uint8NDArray render (text_element *elt, Matrix& box,
                        int rotation = ROTATION_0);
@@ -522,7 +514,7 @@
   void set_font (const std::string& name, const std::string& weight,
                  const std::string& angle, double size);
 
-  octave_map get_system_fonts (void);
+  octave_map get_system_fonts ();
 
   void set_color (const Matrix& c);
 
@@ -543,7 +535,7 @@
   {
   public:
 
-    ft_font (void)
+    ft_font ()
       : text_renderer::font (), m_face (nullptr) { }
 
     ft_font (const std::string& nm, const std::string& wt,
@@ -553,7 +545,7 @@
 
     ft_font (const ft_font& ft);
 
-    ~ft_font (void)
+    ~ft_font ()
     {
       if (m_face)
         FT_Done_Face (m_face);
@@ -561,20 +553,20 @@
 
     ft_font& operator = (const ft_font& ft);
 
-    bool is_valid (void) const { return get_face (); }
+    bool is_valid () const { return get_face (); }
 
-    FT_Face get_face (void) const;
+    FT_Face get_face () const;
 
   private:
 
     mutable FT_Face m_face;
   };
 
-  void push_new_line (void);
+  void push_new_line ();
 
-  void update_line_bbox (void);
+  void update_line_bbox ();
 
-  void compute_bbox (void);
+  void compute_bbox ();
 
   int compute_line_xoffset (const Matrix& lb) const;
 
@@ -660,13 +652,13 @@
 }
 
 octave_map
-ft_text_renderer::get_system_fonts (void)
+ft_text_renderer::get_system_fonts ()
 {
   return ft_manager::get_system_fonts ();
 }
 
 void
-ft_text_renderer::push_new_line (void)
+ft_text_renderer::push_new_line ()
 {
   switch (m_mode)
     {
@@ -727,7 +719,7 @@
 }
 
 void
-ft_text_renderer::compute_bbox (void)
+ft_text_renderer::compute_bbox ()
 {
   // Stack the various line bbox together and compute the final
   // bounding box for the entire text string.
@@ -761,7 +753,7 @@
 }
 
 void
-ft_text_renderer::update_line_bbox (void)
+ft_text_renderer::update_line_bbox ()
 {
   // Called after a font change, when in MODE_BBOX mode, to update the
   // current line bbox with the new font metrics.  This also includes the
@@ -1368,7 +1360,7 @@
 }
 
 void
-ft_text_renderer::reset (void)
+ft_text_renderer::reset ()
 {
   set_mode (MODE_BBOX);
   set_color (Matrix (1, 3, 0.0));
@@ -1509,7 +1501,7 @@
 }
 
 FT_Face
-ft_text_renderer::ft_font::get_face (void) const
+ft_text_renderer::ft_font::get_face () const
 {
   if (! m_face && ! m_name.empty ())
     {
@@ -1534,7 +1526,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 base_text_renderer *
-make_ft_text_renderer (void)
+make_ft_text_renderer ()
 {
 #if defined (HAVE_FREETYPE)
   return new ft_text_renderer ();
--- a/libinterp/corefcn/ft-text-renderer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ft-text-renderer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 
 class base_text_renderer;
 
-extern base_text_renderer * make_ft_text_renderer (void);
+extern base_text_renderer * make_ft_text_renderer ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/libinterp/corefcn/genprops.awk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/genprops.awk	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 ## in the class declaration:
 ##
 ##   TYPE
-##   get_NAME (void) const
+##   get_NAME () const
 ##   {
 ##     return NAME;
 ##   }
@@ -151,7 +151,7 @@
 
 function emit_get_accessor (i, rtype, faccess)
 {
-  printf ("  %s get_%s (void) const", rtype, name[i]);
+  printf ("  %s get_%s () const", rtype, name[i]);
 
   if (emit_get[i] == "definition" && deprecated[i])
     printf ("\n  {\n    warning_with_id (\"Octave:deprecated-property\",\"'%s' is deprecated and will be removed from a future version of Octave\");\n    return m_%s.%s ();\n  }\n", name[i], name[i], faccess);
@@ -165,7 +165,7 @@
 
 function emit_get_bool (i)
 {
-  printf ("  bool is_%s (void) const", name[i]);
+  printf ("  bool is_%s () const", name[i]);
 
   if (emit_get[i] == "definition")
     printf (" { return m_%s.is_on (); }\n", name[i]);
@@ -193,7 +193,7 @@
 
 function emit_get_color (i)
 {
-  printf ("  bool %s_is_rgb (void) const { return m_%s.is_rgb (); }\n", name[i], name[i]);
+  printf ("  bool %s_is_rgb () const { return m_%s.is_rgb (); }\n", name[i], name[i]);
 
   printf ("  bool %s_is (const std::string& v) const", name[i]);
 
@@ -202,7 +202,7 @@
   else
     printf (";\n");
 
-  printf ("  Matrix get_%s_rgb (void) const", name[i]);
+  printf ("  Matrix get_%s_rgb () const", name[i]);
 
   if (emit_get[i] == "definition")
     printf (" { return (m_%s.is_rgb () ? m_%s.rgb () : Matrix ()); }\n", name[i], name[i]);
@@ -216,7 +216,7 @@
 
 function emit_get_double_radio (i)
 {
-  printf ("  bool %s_is_double (void) const { return m_%s.is_double (); }\n", name[i], name[i]);
+  printf ("  bool %s_is_double () const { return m_%s.is_double (); }\n", name[i], name[i]);
 
   printf ("  bool %s_is (const std::string& v) const", name[i]);
 
@@ -225,7 +225,7 @@
   else
     printf (";\n");
 
-  printf ("  double get_%s_double (void) const", name[i]);
+  printf ("  double get_%s_double () const", name[i]);
 
   if (emit_get[i] == "definition")
     printf (" { return (m_%s.is_double () ? m_%s.double_value () : 0); }\n", name[i], name[i]);
@@ -260,14 +260,14 @@
 
 function emit_get_string_array (i)
 {
-  printf ("  std::string get_%s_string (void) const", name[i]);
+  printf ("  std::string get_%s_string () const", name[i]);
 
   if (emit_get[i] == "definition")
     printf (" { return m_%s.string_value (); }\n", name[i]);
   else
     printf (";\n");
 
-  printf ("  string_vector get_%s_vector (void) const", name[i]);
+  printf ("  string_vector get_%s_vector () const", name[i]);
 
   if (emit_get[i] == "definition")
     printf (" { return m_%s.string_vector_value (); }\n", name[i]);
@@ -283,15 +283,17 @@
 {
   printf ("public:\n");
   printf ("  properties (const graphics_handle& mh, const graphics_handle& p);\n\n");
-  printf ("  ~properties (void) { }\n\n");
+  printf ("  properties () = delete;\n\n");
+  printf ("  OCTAVE_DISABLE_COPY_MOVE (properties)\n\n");
+  printf ("  ~properties () = default;\n\n");
   printf ("  void set (const caseless_str& pname, const octave_value& val);\n\n");
   printf ("  octave_value get (bool all = false) const;\n\n");
   printf ("  octave_value get (const caseless_str& pname) const;\n\n");
   printf ("  octave_value get (const std::string& pname) const\n  {\n    return get (caseless_str (pname));\n  }\n\n");
   printf ("  octave_value get (const char *pname) const\n  {\n    return get (caseless_str (pname));\n  }\n\n");
   printf ("  property get_property (const caseless_str& pname);\n\n");
-  printf ("  std::string graphics_object_name (void) const { return s_go_name; }\n\n");
-  printf ("  static property_list::pval_map_type factory_defaults (void);\n\n");
+  printf ("  std::string graphics_object_name () const { return s_go_name; }\n\n");
+  printf ("  static property_list::pval_map_type factory_defaults ();\n\n");
   printf ("private:\n  static std::string s_go_name;\n\n");
 }
 
@@ -300,7 +302,7 @@
   if (class_name && ! base)
     emit_common_declarations();
 
-  printf ("public:\n\n\n  static std::set<std::string> core_property_names (void);\n\n  static std::set<std::string> readonly_property_names (void);\n\n  static bool has_core_property (const caseless_str& pname);\n\n  static bool has_readonly_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names (void) const;\n\n");
+  printf ("public:\n\n\n  static std::set<std::string> core_property_names ();\n\n  static std::set<std::string> readonly_property_names ();\n\n  static bool has_core_property (const caseless_str& pname);\n\n  static bool has_readonly_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names () const;\n\n");
 
   if (! base)
     printf ("  bool has_property (const caseless_str& pname) const;\n\n");
@@ -357,7 +359,7 @@
         emit_get_string_array(i);
       else
       {
-        printf ("  %s get_%s (void) const", type[i], name[i]);
+        printf ("  %s get_%s () const", type[i], name[i]);
 
         if (emit_get[i] == "definition")
           printf (" { return m_%s; }\n", name[i]);
@@ -418,7 +420,7 @@
 
     if (updater[i] == "extern")
     {
-      printf ("  void update_%s (void);\n\n", name[i]);
+      printf ("  void update_%s ();\n\n", name[i]);
     }
 
 ##    if (emit_ov_set[i])
@@ -593,12 +595,12 @@
 
     if (base)
     {
-      printf ("property_list::pval_map_type\nbase_properties::factory_defaults (void)\n{\n");
+      printf ("property_list::pval_map_type\nbase_properties::factory_defaults ()\n{\n");
       printf ("  property_list::pval_map_type m;\n\n");
     }
     else
     {
-      printf ("property_list::pval_map_type\n%s::properties::factory_defaults (void)\n{\n",
+      printf ("property_list::pval_map_type\n%s::properties::factory_defaults ()\n{\n",
               class_name);
       printf ("  property_list::pval_map_type m = base_properties::factory_defaults ();\n\n");
     }
@@ -638,7 +640,7 @@
       printf ("base_properties");
     else
       printf ("%s::properties", class_name);
-    printf ("::core_property_names (void)\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
+    printf ("::core_property_names ()\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
     for (i = 1; i <= idx; i++)
       printf ("      all_pnames.insert (\"%s\");\n", name[i]);
     if (! base)
@@ -658,7 +660,7 @@
       printf ("base_properties");
     else
       printf ("%s::properties", class_name);
-    printf ("::readonly_property_names (void)\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
+    printf ("::readonly_property_names ()\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
     for (i = 1; i <= idx; i++)
         if (readonly[i])
         {
@@ -681,7 +683,7 @@
         printf ("base_properties");
     else
       printf ("%s::properties", class_name);
-    printf ("::all_property_names (void) const\n{\n  static std::set<std::string> all_pnames = core_property_names ();\n\n");
+    printf ("::all_property_names () const\n{\n  static std::set<std::string> all_pnames = core_property_names ();\n\n");
     if (base)
       printf ("  std::set<std::string> retval = all_pnames;\n  std::set<std::string> dyn_props = dynamic_property_names ();\n  retval.insert (dyn_props.begin (), dyn_props.end ());\n  for (std::map<caseless_str, property, cmp_caseless_str>::const_iterator p = m_all_props.begin ();\n       p != m_all_props.end (); p++)\n    retval.insert (p->first);\n\n  return retval;\n}\n\n");
     else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/gh-manager.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,705 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "cmd-edit.h"
+
+#include "builtin-defun-decls.h"
+#include "gh-manager.h"
+#include "graphics-utils.h"
+#include "input.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+static double
+make_handle_fraction ()
+{
+  static double maxrand = RAND_MAX + 2.0;
+
+  return (rand () + 1.0) / maxrand;
+}
+
+graphics_handle
+gh_manager::get_handle (bool integer_figure_handle)
+{
+  graphics_handle retval;
+
+  if (integer_figure_handle)
+    {
+      // Figure handles are positive integers corresponding
+      // to the figure number.
+
+      // We always want the lowest unused figure number.
+
+      retval = 1;
+
+      while (m_handle_map.find (retval) != m_handle_map.end ())
+        retval++;
+    }
+  else
+    {
+      // Other graphics handles are negative integers plus some random
+      // fractional part.  To avoid running out of integers, we recycle the
+      // integer part but tack on a new random part each time.
+
+      auto p = m_handle_free_list.begin ();
+
+      if (p != m_handle_free_list.end ())
+        {
+          retval = *p;
+          m_handle_free_list.erase (p);
+        }
+      else
+        {
+          retval = graphics_handle (m_next_handle);
+
+          m_next_handle = std::ceil (m_next_handle) - 1.0 - make_handle_fraction ();
+        }
+    }
+
+  return retval;
+}
+
+void
+gh_manager::free (const graphics_handle& h, bool from_root)
+{
+  if (h.ok ())
+    {
+      if (h.value () == 0)
+        error ("graphics_handle::free: can't delete root object");
+
+      auto p = m_handle_map.find (h);
+
+      if (p == m_handle_map.end ())
+        error ("graphics_handle::free: invalid object %g", h.value ());
+
+      base_properties& bp = p->second.get_properties ();
+
+      if (! p->second.valid_object () || bp.is_beingdeleted ())
+        return;
+
+      graphics_handle parent_h = p->second.get_parent ();
+      graphics_object parent_go = nullptr;
+      if (! from_root || isfigure (h.value ()))
+        parent_go = get_object (parent_h);
+
+      bp.set_beingdeleted (true);
+
+      // delete listeners before invalidating object
+      p->second.remove_all_listeners ();
+
+      bp.delete_children (true, from_root);
+
+      // NOTE: Call the delete function while the object's state is still valid.
+      octave_value val = bp.get_deletefcn ();
+
+      bp.execute_deletefcn ();
+
+      // Notify graphics toolkit.
+      p->second.finalize ();
+
+
+      // 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 ((! from_root || isfigure (h.value ())) && parent_go.valid_object ()
+          && h.ok ())
+        parent_go.remove_child (h);
+
+      // Note: this will be valid only for first explicitly deleted
+      // object.  All its children will then have an
+      // unknown graphics toolkit.
+
+      // Graphics handles for non-figure objects are negative
+      // integers plus some random fractional part.  To avoid
+      // running out of integers, we recycle the integer part
+      // but tack on a new random part each time.
+
+      m_handle_map.erase (p);
+
+      if (h.value () < 0)
+        m_handle_free_list.insert
+        (std::ceil (h.value ()) - make_handle_fraction ());
+    }
+}
+
+void
+gh_manager::renumber_figure (const graphics_handle& old_gh,
+                             const graphics_handle& new_gh)
+{
+  auto p = m_handle_map.find (old_gh);
+
+  if (p == m_handle_map.end ())
+    error ("graphics_handle::free: invalid object %g", old_gh.value ());
+
+  graphics_object go = p->second;
+
+  m_handle_map.erase (p);
+
+  m_handle_map[new_gh] = go;
+
+  if (old_gh.value () < 0)
+    m_handle_free_list.insert (std::ceil (old_gh.value ())
+                               - make_handle_fraction ());
+
+  for (auto& hfig : m_figure_list)
+    {
+      if (hfig == old_gh)
+        {
+          hfig = new_gh;
+          break;
+        }
+    }
+}
+
+void
+gh_manager::close_all_figures ()
+{
+  // FIXME: should we process or discard pending events?
+
+  m_event_queue.clear ();
+
+  // Don't use m_figure_list_iterator because we'll be removing elements
+  // from the list elsewhere.
+
+  Matrix hlist = figure_handle_list (true);
+
+  for (octave_idx_type i = 0; i < hlist.numel (); i++)
+    {
+      graphics_handle h = lookup (hlist(i));
+
+      if (h.ok ())
+        close_figure (h);
+    }
+
+  // They should all be closed now.  If not, force them to close.
+
+  hlist = figure_handle_list (true);
+
+  for (octave_idx_type i = 0; i < hlist.numel (); i++)
+    {
+      graphics_handle h = lookup (hlist(i));
+
+      if (h.ok ())
+        force_close_figure (h);
+    }
+
+  // None left now, right?
+
+  hlist = figure_handle_list (true);
+
+  if (hlist.numel () != 0)
+    warning ("gh_manager::close_all_figures: some graphics elements failed to close");
+
+  // Clear all callback objects from our list.
+
+  m_callback_objects.clear ();
+}
+
+// We use a random value for the handle to avoid issues with plots and
+// scalar values for the first argument.
+gh_manager::gh_manager (octave::interpreter& interp)
+  : m_interpreter (interp), m_handle_map (), m_handle_free_list (),
+    m_next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)),
+    m_figure_list (), m_graphics_lock (),  m_event_queue (),
+    m_callback_objects (), m_event_processing (0)
+{
+  m_handle_map[0] = graphics_object (new root_figure ());
+
+  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();
+
+  // Make sure the default graphics toolkit is registered.
+  gtk_mgr.default_toolkit ();
+}
+
+graphics_handle
+gh_manager::make_graphics_handle (const std::string& go_name,
+                                  const graphics_handle& p,
+                                  bool integer_figure_handle,
+                                  bool call_createfcn, bool notify_toolkit)
+{
+  graphics_handle h = get_handle (integer_figure_handle);
+
+  base_graphics_object *bgo = make_graphics_object_from_type (go_name, h, p);
+
+  if (! bgo)
+    error ("gh_manager::make_graphics_handle: invalid object type '%s'",
+           go_name.c_str ());
+
+  graphics_object go (bgo);
+
+  m_handle_map[h] = go;
+
+  if (go_name == "axes")
+    {
+      // Handle defaults for labels since overriding defaults for
+      // them can't work before the axes object is fully
+      // constructed.
+
+      axes::properties& props
+        = dynamic_cast<axes::properties&> (go.get_properties ());
+
+      graphics_object tgo;
+
+      tgo = get_object (props.get_xlabel ());
+      tgo.override_defaults ();
+
+      tgo = get_object (props.get_ylabel ());
+      tgo.override_defaults ();
+
+      tgo = get_object (props.get_zlabel ());
+      tgo.override_defaults ();
+
+      tgo = get_object (props.get_title ());
+      tgo.override_defaults ();
+    }
+
+  // Overriding defaults will work now because the handle is valid
+  // and we can find parent objects (not just handles).
+  go.override_defaults ();
+
+  if (call_createfcn)
+    bgo->get_properties ().execute_createfcn ();
+
+  // Notify graphics toolkit.
+  if (notify_toolkit)
+    go.initialize ();
+
+  return h;
+}
+
+graphics_handle
+gh_manager::make_figure_handle (double val, bool notify_toolkit)
+{
+  graphics_handle h = val;
+
+  base_graphics_object *bgo = new figure (h, 0);
+  graphics_object go (bgo);
+
+  m_handle_map[h] = go;
+
+  // Notify graphics toolkit.
+  if (notify_toolkit)
+    go.initialize ();
+
+  go.override_defaults ();
+
+  return h;
+}
+
+void
+gh_manager::push_figure (const graphics_handle& h)
+{
+  pop_figure (h);
+
+  m_figure_list.push_front (h);
+}
+
+void
+gh_manager::pop_figure (const graphics_handle& h)
+{
+  for (auto it = m_figure_list.begin (); it != m_figure_list.end (); it++)
+    {
+      if (*it == h)
+        {
+          m_figure_list.erase (it);
+          break;
+        }
+    }
+}
+
+static void
+xset_gcbo (const graphics_handle& h)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  graphics_object go = gh_mgr.get_object (0);
+
+  root_figure::properties& props
+    = dynamic_cast<root_figure::properties&> (go.get_properties ());
+
+  props.set_callbackobject (h.as_octave_value ());
+}
+
+void
+gh_manager::restore_gcbo ()
+{
+  octave::autolock guard (m_graphics_lock);
+
+  m_callback_objects.pop_front ();
+
+  xset_gcbo (m_callback_objects.empty ()
+             ? graphics_handle () : m_callback_objects.front ().get_handle ());
+}
+
+void
+gh_manager::execute_listener (const graphics_handle& h, const octave_value& l)
+{
+  if (octave::thread::is_thread ())
+    execute_callback (h, l, octave_value ());
+  else
+    {
+      octave::autolock guard (m_graphics_lock);
+
+      post_event (graphics_event::create_callback_event (h, l));
+    }
+}
+
+void
+gh_manager::execute_callback (const graphics_handle& h,
+                              const octave_value& cb_arg,
+                              const octave_value& data)
+{
+  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 ();
+      if (data.is_defined ())
+        args(1) = data;
+      else
+        args(1) = Matrix ();
+
+      octave::unwind_action_safe restore_gcbo_action
+      (&gh_manager::restore_gcbo, this);
+
+      graphics_object go (get_object (h));
+      if (go)
+        {
+          // FIXME: Is the lock necessary when we're only calling a
+          //        const "get" method?
+          octave::autolock guard (m_graphics_lock);
+          m_callback_objects.push_front (go);
+          xset_gcbo (h);
+        }
+
+      // Copy CB because "function_value" method is non-const.
+      octave_value cb = cb_arg;
+
+      if (cb.is_function ())
+        fcn = cb.function_value ();
+      else if (cb.is_function_handle ())
+        ov_fcn = cb;
+      else if (cb.is_string ())
+        {
+          int status;
+          std::string s = cb.string_value ();
+
+          try
+            {
+              m_interpreter.eval_string (s, false, status, 0);
+            }
+          catch (const octave::execution_exception& ee)
+            {
+              m_interpreter.handle_exception (ee);
+            }
+        }
+      else if (cb.iscell () && cb.length () > 0
+               && (cb.rows () == 1 || cb.columns () == 1)
+               && (cb.cell_value ()(0).is_function ()
+                   || cb.cell_value ()(0).is_function_handle ()))
+        {
+          Cell c = cb.cell_value ();
+
+          ov_fcn = c(0);
+
+          for (int i = 1; i < c.numel () ; i++)
+            args(1+i) = c(i);
+        }
+      else
+        {
+          std::string nm = cb.class_name ();
+          error ("trying to execute non-executable object (class = %s)",
+                 nm.c_str ());
+        }
+
+      if (fcn || ov_fcn.is_defined ())
+        try
+          {
+            if (ov_fcn.is_defined ())
+              m_interpreter.feval (ov_fcn, args);
+            else
+              m_interpreter.feval (fcn, args);
+          }
+        catch (const octave::execution_exception& ee)
+          {
+            m_interpreter.handle_exception (ee);
+          }
+
+      // Redraw after interacting with a user-interface (ui*) object.
+      if (Vdrawnow_requested)
+        {
+          if (go)
+            {
+              std::string go_name
+                = go.get_properties ().graphics_object_name ();
+
+              if (go_name.length () > 1
+                  && go_name[0] == 'u' && go_name[1] == 'i')
+                {
+                  Fdrawnow (m_interpreter);
+                  Vdrawnow_requested = false;
+                }
+            }
+        }
+    }
+}
+
+static int
+process_graphics_events ()
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  return gh_mgr.process_events ();
+}
+
+void
+gh_manager::post_event (const graphics_event& e)
+{
+  m_event_queue.push_back (e);
+
+  octave::command_editor::add_event_hook (process_graphics_events);
+}
+
+void
+gh_manager::post_callback (const graphics_handle& h, const std::string& name,
+                           const octave_value& data)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  graphics_object go = get_object (h);
+
+  if (go.valid_object ())
+    {
+      caseless_str cname (name);
+      int busyaction = base_graphics_event::QUEUE;
+
+      if (cname == "deletefcn" || cname == "createfcn"
+          || cname == "closerequestfcn"
+          || ((go.isa ("figure") || go.isa ("uipanel")
+               || go.isa ("uibuttongroup"))
+              && (cname == "resizefcn" || cname == "sizechangedfcn")))
+        busyaction = base_graphics_event::INTERRUPT;
+      else if (go.get_properties ().get_busyaction () == "cancel")
+        busyaction = base_graphics_event::CANCEL;
+
+      // The "closerequestfcn" callback must be executed once the figure has
+      // been made current.  Let "close" do the job.
+      if (cname == "closerequestfcn")
+        {
+          std::string cmd ("close (gcbf ());");
+          post_event (graphics_event::create_mcode_event (h, cmd, busyaction));
+        }
+      else
+        post_event (graphics_event::create_callback_event (h, name, data,
+                    busyaction));
+    }
+}
+
+void
+gh_manager::post_function (graphics_event::event_fcn fcn, void *fcn_data)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  post_event (graphics_event::create_function_event (fcn, fcn_data));
+}
+
+void
+gh_manager::post_set (const graphics_handle& h, const std::string& name,
+                      const octave_value& value, bool notify_toolkit,
+                      bool redraw_figure)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  post_event (graphics_event::create_set_event (h, name, value, notify_toolkit,
+              redraw_figure));
+}
+
+int
+gh_manager::process_events (bool force)
+{
+  graphics_event e;
+  bool old_Vdrawnow_requested = Vdrawnow_requested;
+  bool events_executed = false;
+
+  do
+    {
+      e = graphics_event ();
+
+      {
+        octave::autolock guard (m_graphics_lock);
+
+        if (! m_event_queue.empty ())
+          {
+            if (m_callback_objects.empty () || force)
+              {
+                e = m_event_queue.front ();
+
+                m_event_queue.pop_front ();
+              }
+            else
+              {
+                const graphics_object& go = m_callback_objects.front ();
+
+                if (go.get_properties ().is_interruptible ())
+                  {
+                    e = m_event_queue.front ();
+
+                    m_event_queue.pop_front ();
+                  }
+                else
+                  {
+                    std::list<graphics_event>::iterator p = m_event_queue.begin ();
+
+                    while (p != m_event_queue.end ())
+                      if (p->get_busyaction () == base_graphics_event::CANCEL)
+                        {
+                          p = m_event_queue.erase (p);
+                        }
+                      else if (p->get_busyaction ()
+                               == base_graphics_event::INTERRUPT)
+                        {
+                          e = (*p);
+                          m_event_queue.erase (p);
+                          break;
+                        }
+                      else
+                        p++;
+                  }
+              }
+          }
+      }
+
+      if (e.ok ())
+        {
+          e.execute ();
+          events_executed = true;
+        }
+    }
+  while (e.ok ());
+
+  {
+    octave::autolock guard (m_graphics_lock);
+
+    if (m_event_queue.empty () && m_event_processing == 0)
+      octave::command_editor::remove_event_hook (process_graphics_events);
+  }
+
+  if (events_executed)
+    octave::flush_stdout ();
+
+  if (Vdrawnow_requested && ! old_Vdrawnow_requested)
+    {
+      Fdrawnow (m_interpreter);
+
+      Vdrawnow_requested = false;
+    }
+
+  return 0;
+}
+
+
+/*
+## Test interruptible/busyaction properties
+%!function cb (h, ~)
+%! setappdata (gcbf (), "cb_exec", [getappdata(gcbf (), "cb_exec") h]);
+%! drawnow ();
+%! setappdata (gcbf (), "cb_exec", [getappdata(gcbf (), "cb_exec") h]);
+%!endfunction
+%!
+%!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);
+%!   hui2 = uicontrol ("parent", hf, "busyaction", "queue", "callback", @cb);
+%!   hui3 = uicontrol ("parent", hf, "busyaction", "queue", "callback", @cb);
+%!   __go_post_callback__ (hui1, "callback");
+%!   __go_post_callback__ (hui2, "callback");
+%!   __go_post_callback__ (hui3, "callback");
+%!
+%!   assert (getappdata (hf, "cb_exec"), []);
+%!   drawnow ();
+%!   assert (getappdata (hf, "cb_exec"), [hui1 hui2 hui3 hui3 hui2 hui1]);
+%!
+%!   ## Interruptible off
+%!   setappdata (hf, "cb_exec", []);
+%!   set (hui1, "interruptible", "off");
+%!   __go_post_callback__ (hui1, "callback");
+%!   __go_post_callback__ (hui2, "callback");
+%!   __go_post_callback__ (hui3, "callback");
+%!   drawnow ();
+%!   assert (getappdata (hf, "cb_exec"), [hui1 hui1 hui2 hui3 hui3 hui2]);
+%!
+%!   ## "resizefcn" callback interrupts regardless of interruptible property
+%!   setappdata (hf, "cb_exec", []);
+%!   __go_post_callback__ (hui1, "callback");
+%!   __go_post_callback__ (hf, "resizefcn");
+%!   drawnow ();
+%!   assert (getappdata (hf, "cb_exec"), [hui1 hf hf hui1]);
+%!
+%!   ## test "busyaction" "cancel"
+%!   setappdata (hf, "cb_exec", []);
+%!   set (hui2, "busyaction", "cancel");
+%!   __go_post_callback__ (hui1, "callback");
+%!   __go_post_callback__ (hui2, "callback");
+%!   __go_post_callback__ (hui3, "callback");
+%!   __go_post_callback__ (hf, "resizefcn");
+%!   drawnow ();
+%!   assert (getappdata (hf, "cb_exec"), [hui1 hf hui3 hui3 hf hui1]);
+%! unwind_protect_cleanup
+%!   close (hf)
+%! end_unwind_protect
+*/
+
+void
+gh_manager::enable_event_processing (bool enable)
+{
+  octave::autolock guard (m_graphics_lock);
+
+  if (enable)
+    {
+      m_event_processing++;
+
+      octave::command_editor::add_event_hook (process_graphics_events);
+    }
+  else
+    {
+      m_event_processing--;
+
+      if (m_event_queue.empty () && m_event_processing == 0)
+        octave::command_editor::remove_event_hook (process_graphics_events);
+    }
+}
+
+OCTAVE_END_NAMESPACE(octave)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/gh-manager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,288 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_gh_manager_h)
+#define octave_gh_manager_h 1
+
+#include "octave-config.h"
+
+#include "graphics.h"
+#include "gtk-manager.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+class OCTINTERP_API gh_manager
+{
+public:
+
+  typedef std::pair<uint8NDArray /*pixels*/, std::string /*svg*/> latex_data;
+
+  OCTINTERP_API gh_manager (octave::interpreter& interp);
+
+  // FIXME: eventually eliminate these static functions and access
+  // gh_manager object through the interpreter.
+
+  OCTINTERP_API graphics_handle get_handle (bool integer_figure_handle);
+
+  OCTINTERP_API void free (const graphics_handle& h, bool from_root = false);
+
+  OCTINTERP_API void renumber_figure (const graphics_handle& old_gh,
+                                      const graphics_handle& new_gh);
+
+  graphics_handle lookup (double val) const
+  {
+    const_iterator p = (octave::math::isnan (val)
+                        ? m_handle_map.end () : m_handle_map.find (val));
+
+    return (p != m_handle_map.end ()) ? p->first : graphics_handle ();
+  }
+
+  graphics_handle lookup (const octave_value& val) const
+  {
+    return (val.is_real_scalar ()
+            ? lookup (val.double_value ()) : graphics_handle ());
+  }
+
+  graphics_object get_object (double val) const
+  {
+    return get_object (lookup (val));
+  }
+
+  graphics_object get_object (const graphics_handle& h) const
+  {
+    const_iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());
+
+    return (p != m_handle_map.end ()) ? p->second : graphics_object ();
+  }
+
+  OCTINTERP_API graphics_handle
+  make_graphics_handle (const std::string& go_name,
+                        const graphics_handle& p,
+                        bool integer_figure_handle = false,
+                        bool call_createfcn = true,
+                        bool notify_toolkit = true);
+
+  OCTINTERP_API graphics_handle
+  make_figure_handle (double val, bool notify_toolkit = true);
+
+  OCTINTERP_API void push_figure (const graphics_handle& h);
+
+  OCTINTERP_API void pop_figure (const graphics_handle& h);
+
+  graphics_handle current_figure () const
+  {
+    graphics_handle retval;
+
+    for (const auto& hfig : m_figure_list)
+      {
+        if (is_handle_visible (hfig))
+          retval = hfig;
+      }
+
+    return retval;
+  }
+
+  Matrix handle_list (bool show_hidden = false)
+  {
+    Matrix retval (1, m_handle_map.size ());
+
+    octave_idx_type i = 0;
+    for (const auto& h_iter : m_handle_map)
+      {
+        graphics_handle h = h_iter.first;
+
+        if (show_hidden || is_handle_visible (h))
+          retval(i++) = h.value ();
+      }
+
+    retval.resize (1, i);
+
+    return retval;
+  }
+
+  void lock () { m_graphics_lock.lock (); }
+
+  bool try_lock () { return m_graphics_lock.try_lock (); }
+
+  void unlock () { m_graphics_lock.unlock (); }
+
+  Matrix figure_handle_list (bool show_hidden = false)
+  {
+    Matrix retval (1, m_figure_list.size ());
+
+    octave_idx_type i = 0;
+    for (const auto& hfig : m_figure_list)
+      {
+        if (show_hidden || is_handle_visible (hfig))
+          retval(i++) = hfig.value ();
+      }
+
+    retval.resize (1, i);
+
+    return retval;
+  }
+
+  OCTINTERP_API void
+  execute_listener (const graphics_handle& h, const octave_value& l);
+
+  void execute_callback (const graphics_handle& h,
+                         const std::string& name,
+                         const octave_value& data = Matrix ())
+  {
+    octave_value cb;
+
+    if (true)
+      {
+        octave::autolock guard (graphics_lock ());
+
+        graphics_object go = get_object (h);
+
+        if (go.valid_object ())
+          cb = go.get (name);
+      }
+
+    execute_callback (h, cb, data);
+  }
+
+  OCTINTERP_API void
+  execute_callback (const graphics_handle& h, const octave_value& cb,
+                    const octave_value& data = Matrix ());
+
+  OCTINTERP_API void
+  post_callback (const graphics_handle& h, const std::string& name,
+                 const octave_value& data = Matrix ());
+
+  OCTINTERP_API void
+  post_function (graphics_event::event_fcn fcn, void *fcn_data = nullptr);
+
+  OCTINTERP_API void
+  post_set (const graphics_handle& h, const std::string& name,
+            const octave_value& value, bool notify_toolkit = true,
+            bool redraw_figure = false);
+
+  OCTINTERP_API int process_events (bool force = false);
+
+  OCTINTERP_API void enable_event_processing (bool enable = true);
+
+  bool is_handle_visible (const graphics_handle& h) const
+  {
+    bool retval = false;
+
+    graphics_object go = get_object (h);
+
+    if (go.valid_object ())
+      retval = go.is_handle_visible ();
+
+    return retval;
+  }
+
+  OCTINTERP_API void close_all_figures ();
+
+  OCTINTERP_API void restore_gcbo ();
+
+  OCTINTERP_API void post_event (const graphics_event& e);
+
+  octave::mutex graphics_lock ()
+  {
+    return m_graphics_lock;
+  }
+
+  latex_data get_latex_data (const std::string& key) const
+  {
+    latex_data retval;
+
+    const auto it = m_latex_cache.find (key);
+
+    if (it != m_latex_cache.end ())
+      retval = it->second;
+
+    return retval;
+  }
+
+  void set_latex_data (const std::string& key, latex_data val)
+  {
+    // Limit the number of cache entries to 500
+    if (m_latex_keys.size () >= 500)
+      {
+        auto it = m_latex_cache.find (m_latex_keys.front ());
+
+        if (it != m_latex_cache.end ())
+          m_latex_cache.erase (it);
+
+        m_latex_keys.pop_front ();
+      }
+
+    m_latex_cache[key] = val;
+    m_latex_keys.push_back (key);
+  }
+
+private:
+
+  typedef std::map<graphics_handle, graphics_object>::iterator iterator;
+  typedef std::map<graphics_handle, graphics_object>::const_iterator
+    const_iterator;
+
+  typedef std::set<graphics_handle>::iterator free_list_iterator;
+  typedef std::set<graphics_handle>::const_iterator const_free_list_iterator;
+
+  typedef std::list<graphics_handle>::iterator figure_list_iterator;
+  typedef std::list<graphics_handle>::const_iterator const_figure_list_iterator;
+
+  octave::interpreter& m_interpreter;
+
+  // A map of handles to graphics objects.
+  std::map<graphics_handle, graphics_object> m_handle_map;
+
+  // The available graphics handles.
+  std::set<graphics_handle> m_handle_free_list;
+
+  // The next handle available if m_handle_free_list is empty.
+  double m_next_handle;
+
+  // The allocated figure handles.  Top of the stack is most recently
+  // created.
+  std::list<graphics_handle> m_figure_list;
+
+  // The lock for accessing the graphics sytsem.
+  octave::mutex m_graphics_lock;
+
+  // The list of events queued by graphics toolkits.
+  std::list<graphics_event> m_event_queue;
+
+  // The stack of callback objects.
+  std::list<graphics_object> m_callback_objects;
+
+  // A flag telling whether event processing must be constantly on.
+  int m_event_processing;
+
+  // Cache of already parsed latex strings. Store a separate list of keys
+  // to allow for erasing oldest entries if cache size becomes too large.
+  std::unordered_map<std::string, latex_data> m_latex_cache;
+  std::list<std::string> m_latex_keys;
+};
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- a/libinterp/corefcn/gl-render.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gl-render.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -40,6 +40,7 @@
 #include "oct-locbuf.h"
 
 #include "errwarn.h"
+#include "gh-manager.h"
 #include "gl-render.h"
 #include "interpreter-private.h"
 #include "oct-opengl.h"
@@ -113,7 +114,9 @@
         m_tx (double(m_w)/m_tw), m_ty (double(m_h)/m_th), m_valid (true)
     { }
 
-    ~texture_rep (void)
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (texture_rep)
+
+    ~texture_rep ()
     {
       if (m_valid)
         m_glfcns.glDeleteTextures (1, &m_id);
@@ -141,6 +144,8 @@
 
 public:
 
+  opengl_texture () = delete;
+
   opengl_texture (opengl_functions& glfcns)
     : m_rep (new texture_rep (glfcns))
   { }
@@ -150,11 +155,7 @@
     : m_rep (new texture_rep (glfcns, id, w, h, tw, th))
   { }
 
-  opengl_texture (const opengl_texture&) = default;
-
-  ~opengl_texture (void) = default;
-
-  opengl_texture& operator = (const opengl_texture&) = default;
+  OCTAVE_DEFAULT_COPY_DELETE (opengl_texture)
 
   static opengl_texture create (opengl_functions& glfcns,
                                 const octave_value& data);
@@ -163,7 +164,7 @@
 
   void tex_coord (double q, double r) const { m_rep->tex_coord (q, r); }
 
-  bool is_valid (void) const { return m_rep->m_valid; }
+  bool is_valid () const { return m_rep->m_valid; }
 
 private:
 
@@ -345,20 +346,16 @@
 #if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
   typedef GLvoid (CALLBACK *fcn) (...);
 #else
-  typedef void (CALLBACK *fcn) (void);
+  typedef void (CALLBACK *fcn) ();
 #endif
 
 public:
 
-  opengl_tessellator (void) : m_glu_tess (nullptr), m_fill () { init (); }
-
-  // No copying!
-
-  opengl_tessellator (const opengl_tessellator&) = delete;
-
-  opengl_tessellator operator = (const opengl_tessellator&) = delete;
-
-  virtual ~opengl_tessellator (void)
+  opengl_tessellator () : m_glu_tess (nullptr), m_fill () { init (); }
+
+  OCTAVE_DISABLE_COPY_MOVE (opengl_tessellator)
+
+  virtual ~opengl_tessellator ()
   { if (m_glu_tess) gluDeleteTess (m_glu_tess); }
 
   void begin_polygon (bool filled = true)
@@ -369,13 +366,13 @@
     gluTessBeginPolygon (m_glu_tess, this);
   }
 
-  void end_polygon (void) const
+  void end_polygon () const
   { gluTessEndPolygon (m_glu_tess); }
 
-  void begin_contour (void) const
+  void begin_contour () const
   { gluTessBeginContour (m_glu_tess); }
 
-  void end_contour (void) const
+  void end_contour () const
   { gluTessEndContour (m_glu_tess); }
 
   void add_vertex (double *loc, void *data) const
@@ -384,7 +381,7 @@
 protected:
   virtual void begin (GLenum /*type*/) { }
 
-  virtual void end (void) { }
+  virtual void end () { }
 
   virtual void vertex (void * /*data*/) { }
 
@@ -396,7 +393,7 @@
   virtual void error (GLenum err)
   { ::error ("OpenGL tessellation error (%d)", err); }
 
-  virtual void init (void)
+  virtual void init ()
   {
     m_glu_tess = gluNewTess ();
 
@@ -414,7 +411,7 @@
                      reinterpret_cast<fcn> (tess_error));
   }
 
-  bool is_filled (void) const { return m_fill; }
+  bool is_filled () const { return m_fill; }
 
 private:
   static void CALLBACK tess_begin (GLenum type, void *t)
@@ -450,7 +447,7 @@
   {
   public:
 
-    vertex_data_rep (void)
+    vertex_data_rep ()
       : m_coords (), m_color (), m_vertex_normal (), m_face_normal (),
         m_alpha (), m_ambient (), m_diffuse (), m_specular (),
         m_specular_exp (), m_specular_color_refl ()
@@ -464,6 +461,10 @@
         m_specular (ss), m_specular_exp (se), m_specular_color_refl (scr)
     { }
 
+    OCTAVE_DEFAULT_COPY (vertex_data_rep)
+
+    ~vertex_data_rep () = default;
+
     Matrix m_coords;
     Matrix m_color;
     Matrix m_vertex_normal;
@@ -479,7 +480,7 @@
 public:
 
   // Required to instantiate std::list<vertex_data> objects.
-  vertex_data (void) : m_rep (nil_rep ()) { }
+  vertex_data () : m_rep (nil_rep ()) { }
 
   vertex_data (const Matrix& c, const Matrix& col, const Matrix& vn,
                const Matrix& fn, double a, float as, float ds, float ss,
@@ -489,15 +490,15 @@
 
   vertex_data (const vertex_data&) = default;
 
-  ~vertex_data (void) = default;
+  ~vertex_data () = default;
 
   vertex_data& operator = (const vertex_data&) = default;
 
-  vertex_data_rep * get_rep (void) const { return m_rep.get (); }
+  vertex_data_rep * get_rep () const { return m_rep.get (); }
 
 private:
 
-  static std::shared_ptr<vertex_data_rep> nil_rep (void)
+  static std::shared_ptr<vertex_data_rep> nil_rep ()
   {
     static std::shared_ptr<vertex_data_rep> nr (new vertex_data_rep ());
 
@@ -511,6 +512,7 @@
 opengl_renderer::patch_tessellator : public opengl_tessellator
 {
 public:
+
   patch_tessellator (opengl_renderer *r, int cmode, int lmode, bool fl,
                      float idx = 0.0)
     : opengl_tessellator (), m_renderer (r),
@@ -518,6 +520,10 @@
       m_index (idx), m_first (true), m_tmp_vdata ()
   { }
 
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (patch_tessellator)
+
+  ~patch_tessellator () = default;
+
 protected:
   void begin (GLenum type)
   {
@@ -537,7 +543,7 @@
     glfcns.glBegin (type);
   }
 
-  void end (void)
+  void end ()
   {
     opengl_functions& glfcns = m_renderer->get_opengl_functions ();
 
@@ -656,12 +662,8 @@
 
 private:
 
-  // No copying!
-
-  patch_tessellator (const patch_tessellator&) = delete;
-
-  patch_tessellator& operator = (const patch_tessellator&) = delete;
-
+  // FIXME: We don't own this object; should it be a shared/weak/unique
+  // pointer?  Managed some other way?
   opengl_renderer *m_renderer;
   int m_color_mode;
   int m_light_mode;
@@ -1252,7 +1254,7 @@
 }
 
 void
-opengl_renderer::finish (void)
+opengl_renderer::finish ()
 {
 #if defined (HAVE_OPENGL)
 
@@ -1584,7 +1586,8 @@
       // X ticks and grid properties
       Matrix xticks = m_xform.xscale (props.get_xtick ().matrix_value ());
       Matrix xmticks = m_xform.xscale (props.get_xminortickvalues ().matrix_value ());
-      bool do_xminortick = props.is_xminortick () && ! xticks.isempty ();
+      bool do_xtick = ! props.tickdir_is ("none") && ! xticks.isempty ();
+      bool do_xminortick = do_xtick && props.is_xminortick ();
       string_vector xticklabels = props.get_xticklabel ().string_vector_value ();
       int wmax = 0;
       int hmax = 0;
@@ -1685,20 +1688,23 @@
         }
 
       // tick marks
-      if (tick_along_z)
-        render_tickmarks (xticks, x_min, x_max,
-                          is_origin ? y_axis_pos : ypTick, ypTick,
-                          zpTick, zpTickN, 0., 0.,
-                          (is_origin_low ? -1. : 1.) *
-                          math::signum (zpTick-zpTickN)*fz*xticklen,
-                          0, ! is_origin && mirror);
-      else
-        render_tickmarks (xticks, x_min, x_max,
-                          is_origin ? y_axis_pos : ypTick, ypTickN,
-                          zpTick, zpTick, 0.,
-                          (is_origin_low ? -1. : 1.) *
-                          math::signum (ypTick-ypTickN)*fy*xticklen,
-                          0., 0, ! is_origin && mirror);
+      if (do_xtick)
+        {
+          if (tick_along_z)
+            render_tickmarks (xticks, x_min, x_max,
+                              is_origin ? y_axis_pos : ypTick, ypTick,
+                              zpTick, zpTickN, 0., 0.,
+                              (is_origin_low ? -1. : 1.) *
+                              math::signum (zpTick-zpTickN)*fz*xticklen,
+                              0, ! is_origin && mirror);
+          else
+            render_tickmarks (xticks, x_min, x_max,
+                              is_origin ? y_axis_pos : ypTick, ypTickN,
+                              zpTick, zpTick, 0.,
+                              (is_origin_low ? -1. : 1.) *
+                              math::signum (ypTick-ypTickN)*fy*xticklen,
+                              0., 0, ! is_origin && mirror);
+        }
 
       // tick texts
       if (xticklabels.numel () > 0)
@@ -1780,7 +1786,8 @@
       // Y ticks and grid properties
       Matrix yticks = m_xform.yscale (props.get_ytick ().matrix_value ());
       Matrix ymticks = m_xform.yscale (props.get_yminortickvalues ().matrix_value ());
-      bool do_yminortick = props.is_yminortick () && ! yticks.isempty ();
+      bool do_ytick = ! props.tickdir_is ("none") && ! yticks.isempty ();
+      bool do_yminortick = do_ytick && props.is_yminortick ();
       string_vector yticklabels = props.get_yticklabel ().string_vector_value ();
       int wmax = 0;
       int hmax = 0;
@@ -1882,20 +1889,23 @@
         }
 
       // tick marks
-      if (tick_along_z)
-        render_tickmarks (yticks, y_min, y_max,
-                          is_origin ? x_axis_pos : xpTick, xpTick,
-                          zpTick, zpTickN, 0., 0.,
-                          (is_origin_low ? -1. : 1.) *
-                          math::signum (zpTick-zpTickN)*fz*yticklen,
-                          1, ! is_origin && mirror);
-      else
-        render_tickmarks (yticks, y_min, y_max,
-                          is_origin ? x_axis_pos : xpTick, xpTickN,
-                          zpTick, zpTick,
-                          (is_origin_low ? -1. : 1.) *
-                          math::signum (xPlaneN-xPlane)*fx*yticklen,
-                          0., 0., 1, ! is_origin && mirror);
+      if (do_ytick)
+        {
+          if (tick_along_z)
+            render_tickmarks (yticks, y_min, y_max,
+                              is_origin ? x_axis_pos : xpTick, xpTick,
+                              zpTick, zpTickN, 0., 0.,
+                              (is_origin_low ? -1. : 1.) *
+                              math::signum (zpTick-zpTickN)*fz*yticklen,
+                              1, ! is_origin && mirror);
+          else
+            render_tickmarks (yticks, y_min, y_max,
+                              is_origin ? x_axis_pos : xpTick, xpTickN,
+                              zpTick, zpTick,
+                              (is_origin_low ? -1. : 1.) *
+                              math::signum (xPlaneN-xPlane)*fx*yticklen,
+                              0., 0., 1, ! is_origin && mirror);
+        }
 
       // tick texts
       if (yticklabels.numel () > 0)
@@ -1966,7 +1976,8 @@
       // Z ticks and grid properties
       Matrix zticks = m_xform.zscale (props.get_ztick ().matrix_value ());
       Matrix zmticks = m_xform.zscale (props.get_zminortickvalues ().matrix_value ());
-      bool do_zminortick = props.is_zminortick () && ! zticks.isempty ();
+      bool do_ztick = ! props.tickdir_is ("none") && ! zticks.isempty ();
+      bool do_zminortick = do_ztick && props.is_zminortick ();
       string_vector zticklabels = props.get_zticklabel ().string_vector_value ();
       int wmax = 0;
       int hmax = 0;
@@ -2061,31 +2072,34 @@
         }
 
       // tick marks
-      if (xySym)
+      if (do_ztick)
         {
-          if (math::isinf (fy))
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
-                              yPlane, yPlane,
-                              math::signum (xPlaneN-xPlane)*fx*zticklen,
-                              0., 0., 2, mirror);
+          if (xySym)
+            {
+              if (math::isinf (fy))
+                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
+                                  yPlane, yPlane,
+                                  math::signum (xPlaneN-xPlane)*fx*zticklen,
+                                  0., 0., 2, mirror);
+              else
+                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
+                                  yPlane, yPlane, 0.,
+                                  math::signum (yPlane-yPlaneN)*fy*zticklen,
+                                  0., 2, false);
+            }
           else
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
-                              yPlane, yPlane, 0.,
-                              math::signum (yPlane-yPlaneN)*fy*zticklen,
-                              0., 2, false);
-        }
-      else
-        {
-          if (math::isinf (fx))
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
-                              yPlaneN, yPlane, 0.,
-                              math::signum (yPlaneN-yPlane)*fy*zticklen,
-                              0., 2, mirror);
-          else
-            render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
-                              yPlaneN, yPlane,
-                              math::signum (xPlane-xPlaneN)*fx*zticklen,
-                              0., 0., 2, false);
+            {
+              if (math::isinf (fx))
+                render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
+                                  yPlaneN, yPlane, 0.,
+                                  math::signum (yPlaneN-yPlane)*fy*zticklen,
+                                  0., 2, mirror);
+              else
+                render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
+                                  yPlaneN, yPlane,
+                                  math::signum (xPlane-xPlaneN)*fx*zticklen,
+                                  0., 0., 2, false);
+            }
         }
 
       // tick texts
@@ -2172,7 +2186,7 @@
     {
       graphics_object go = gh_mgr.get_object (children(i));
 
-      base_properties p = go.get_properties ();
+      base_properties& p = go.get_properties ();
 
       if (p.is_visible ()
           || (m_selecting && p.pickableparts_is ("all")))
@@ -2272,10 +2286,8 @@
 
   m_glfcns.glDisable (GL_DEPTH_TEST);
 
-  for (it = obj_list.begin (); it != obj_list.end (); it++)
+  for (const graphics_object& go : obj_list)
     {
-      graphics_object go = (*it);
-
       set_clipping (go.get_properties ().is_clipping ());
       draw (go);
     }
@@ -3880,7 +3892,7 @@
 }
 
 void
-opengl_renderer::set_ortho_coordinates (void)
+opengl_renderer::set_ortho_coordinates ()
 {
 #if defined (HAVE_OPENGL)
 
@@ -3905,7 +3917,7 @@
 }
 
 void
-opengl_renderer::restore_previous_coordinates (void)
+opengl_renderer::restore_previous_coordinates ()
 {
 #if defined (HAVE_OPENGL)
 
@@ -4100,7 +4112,7 @@
   // Expect RGB data
   if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4))
     {
-      opengl_texture tex  = opengl_texture::create (m_glfcns, cdata);
+      opengl_texture tex = opengl_texture::create (m_glfcns, cdata);
       if (tex.is_valid ())
         {
           m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0);
@@ -4191,7 +4203,7 @@
 }
 
 Matrix
-opengl_renderer::get_viewport_scaled (void) const
+opengl_renderer::get_viewport_scaled () const
 {
   Matrix retval (1, 4, 0.0);
 
@@ -4497,7 +4509,7 @@
 }
 
 void
-opengl_renderer::end_marker (void)
+opengl_renderer::end_marker ()
 {
 #if defined (HAVE_OPENGL)
 
@@ -4573,7 +4585,7 @@
 }
 
 void
-opengl_renderer::init_maxlights (void)
+opengl_renderer::init_maxlights ()
 {
 #if defined (HAVE_OPENGL)
 
--- a/libinterp/corefcn/gl-render.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gl-render.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,15 +43,11 @@
 
   opengl_renderer (opengl_functions& glfcns);
 
-  // No copying!
-
-  opengl_renderer (const opengl_renderer&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (opengl_renderer)
 
-  opengl_renderer& operator = (const opengl_renderer&) = delete;
+  virtual ~opengl_renderer () = default;
 
-  virtual ~opengl_renderer (void) = default;
-
-  opengl_functions& get_opengl_functions (void) const { return m_glfcns; }
+  opengl_functions& get_opengl_functions () const { return m_glfcns; }
 
   virtual void draw (const graphics_object& go, bool toplevel = true);
 
@@ -62,8 +58,8 @@
 
   virtual void set_viewport (int w, int h);
   virtual void set_device_pixel_ratio (double dpr) { m_devpixratio = dpr; }
-  virtual Matrix get_viewport_scaled (void) const;
-  virtual graphics_xform get_transform (void) const { return m_xform; }
+  virtual Matrix get_viewport_scaled () const;
+  virtual graphics_xform get_transform () const { return m_xform; }
   virtual uint8NDArray get_pixels (int width, int height);
 
   virtual void draw_zoom_box (int width, int height,
@@ -73,7 +69,7 @@
                               const Matrix& bordercolor,
                               double borderalpha, double borderwidth);
 
-  virtual void finish (void);
+  virtual void finish ();
 
 protected:
 
@@ -118,7 +114,7 @@
 
   virtual void init_marker (const std::string& m, double size, float width);
   virtual void change_marker (const std::string& m, double size);
-  virtual void end_marker (void);
+  virtual void end_marker ();
   virtual void draw_marker (double x, double y, double z,
                             const Matrix& lc, const Matrix& fc,
                             const double la = 1.0, const double fa = 1.0);
@@ -180,7 +176,7 @@
 
   class patch_tessellator;
 
-  void init_maxlights (void);
+  void init_maxlights ();
 
   std::string get_string (unsigned int id) const;
 
@@ -208,9 +204,9 @@
 
   void set_normal (int bfl_mode, const NDArray& n, int j, int i);
 
-  void set_ortho_coordinates (void);
+  void set_ortho_coordinates ();
 
-  void restore_previous_coordinates (void);
+  void restore_previous_coordinates ();
 
   double points_to_pixels (const double val) const;
 
--- a/libinterp/corefcn/gl2ps-print.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gl2ps-print.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,6 +47,7 @@
 #include "unistr-wrappers.h"
 #include "unwind-prot.h"
 
+#include "gh-manager.h"
 #include "gl-render.h"
 #include "interpreter-private.h"
 #include "oct-opengl.h"
@@ -68,7 +69,9 @@
       m_fontname (), m_buffer_overflow (false), m_svg_def_index (0)
   { }
 
-  ~gl2ps_renderer (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gl2ps_renderer)
+
+  ~gl2ps_renderer () = default;
 
   // 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
@@ -1009,8 +1012,8 @@
       // provide an x coordinate for each character in the string
       os << "x=\"";
       std::vector<double> xdata = p->get_xdata ();
-      for (auto q = xdata.begin (); q != xdata.end (); q++)
-        os << (*q) << " ";
+      for (const auto& q : xdata)
+        os << q << " ";
       os << '"';
 
       os << '>';
@@ -1021,10 +1024,10 @@
       else
         {
           const std::string str = p->get_string ();
-          for (auto q = str.begin (); q != str.end (); q++)
+          for (const auto& q : str)
             {
               std::stringstream chr;
-              chr << *q;
+              chr << q;
               if (chr.str () == "\"")
                 os << "&quot;";
               else if (chr.str () == "'")
--- a/libinterp/corefcn/graphics-toolkit.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/graphics-toolkit.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include "gh-manager.h"
 #include "graphics.h"
 #include "gtk-manager.h"
 #include "interpreter-private.h"
--- a/libinterp/corefcn/graphics-toolkit.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/graphics-toolkit.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,14 +55,16 @@
     : m_name (nm)
   { }
 
-  virtual ~base_graphics_toolkit (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_graphics_toolkit)
 
-  std::string get_name (void) const
+  virtual ~base_graphics_toolkit () = default;
+
+  std::string get_name () const
   {
     return m_name;
   }
 
-  virtual bool is_valid (void) const
+  virtual bool is_valid () const
   {
     return false;
   }
@@ -96,13 +98,13 @@
     return Matrix (1, 2, 0.0);
   }
 
-  virtual double get_screen_resolution (void) const
+  virtual double get_screen_resolution () const
   {
     gripe_if_tkit_invalid ("get_screen_resolution");
     return 72.0;
   }
 
-  virtual Matrix get_screen_size (void) const
+  virtual Matrix get_screen_size () const
   {
     gripe_if_tkit_invalid ("get_screen_size");
     return Matrix (1, 2, 0.0);
@@ -146,7 +148,7 @@
   void finalize (const graphics_handle&);
 
   // Close the graphics toolkit.
-  virtual void close (void)
+  virtual void close ()
   {
     gripe_if_tkit_invalid ("base_graphics_toolkit::close");
   }
@@ -183,14 +185,14 @@
 
   graphics_toolkit& operator = (const graphics_toolkit& b) = default;
 
-  ~graphics_toolkit (void) = default;
+  ~graphics_toolkit () = default;
 
-  operator bool (void) const
+  operator bool () const
   {
     return m_rep->is_valid ();
   }
 
-  std::string get_name (void) const
+  std::string get_name () const
   {
     return m_rep->get_name ();
   }
@@ -222,12 +224,12 @@
     return m_rep->get_canvas_size (fh);
   }
 
-  double get_screen_resolution (void) const
+  double get_screen_resolution () const
   {
     return m_rep->get_screen_resolution ();
   }
 
-  Matrix get_screen_size (void) const
+  Matrix get_screen_size () const
   {
     return m_rep->get_screen_size ();
   }
@@ -273,7 +275,7 @@
   }
 
   // Close the graphics toolkit.
-  void close (void)
+  void close ()
   {
     m_rep->close ();
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/graphics-utils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,181 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "caseless-str.h"
+
+#include "gh-manager.h"
+#include "graphics-utils.h"
+#include "graphics.h"
+#include "input.h"
+#include "interpreter-private.h"
+#include "ov.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+// Flag to stop redraws due to callbacks while deletion is in progress.
+bool delete_executing = false;
+
+void
+xset (const graphics_handle& h, const caseless_str& pname,
+      const octave_value& val)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  graphics_object go = gh_mgr.get_object (h);
+
+  go.set (pname, val);
+}
+
+void
+xset (const graphics_handle& h, const octave_value_list& args)
+{
+  if (args.length () > 0)
+    {
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+      graphics_object go = gh_mgr.get_object (h);
+
+      go.set (args);
+    }
+}
+
+octave_value
+xget (const graphics_handle& h, const caseless_str& pname)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  graphics_object go = gh_mgr.get_object (h);
+
+  return go.get (pname);
+}
+
+bool isfigure (double val)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  graphics_object go = gh_mgr.get_object (val);
+
+  return go && go.isa ("figure");
+}
+
+graphics_handle
+reparent (const octave_value& ov, const std::string& who,
+          const std::string& pname, const graphics_handle& new_parent,
+          bool adopt)
+{
+  double hv = ov.xdouble_value ("%s: %s must be a graphics handle",
+                                who.c_str (), pname.c_str ());
+
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  graphics_handle h = gh_mgr.lookup (hv);
+
+  if (! h.ok ())
+    error ("%s: invalid graphics handle (= %g) for %s",
+           who.c_str (), hv, pname.c_str ());
+
+  graphics_object go = gh_mgr.get_object (h);
+
+  graphics_handle parent_h = go.get_parent ();
+
+  graphics_object parent_go = gh_mgr.get_object (parent_h);
+
+  parent_go.remove_child (h);
+
+  if (adopt)
+    go.set ("parent", new_parent.value ());
+  else
+    go.reparent (new_parent);
+
+  return h;
+}
+
+void
+delete_graphics_object (const graphics_handle& h, bool from_root)
+{
+  if (h.ok ())
+    {
+      gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+      graphics_object go = gh_mgr.get_object (h);
+
+      // Don't do recursive deleting, due to callbacks
+      if (! go.get_properties ().is_beingdeleted ())
+        {
+          // NOTE: Freeing the handle also calls any deletefcn.  It also calls
+          //       the parent's delete_child function.
+
+          gh_mgr.free (h, from_root || go.isa ("figure"));
+
+          Vdrawnow_requested = true;
+        }
+    }
+}
+
+void
+delete_graphics_object (double val, bool from_root)
+{
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  delete_graphics_object (gh_mgr.lookup (val), from_root || isfigure (val));
+}
+
+void
+delete_graphics_objects (const NDArray vals, bool from_root)
+{
+  // Prevent redraw of partially deleted objects.
+  octave::unwind_protect_var<bool> restore_var (delete_executing, true);
+
+  for (octave_idx_type i = 0; i < vals.numel (); i++)
+    delete_graphics_object (vals.elem (i), from_root);
+}
+
+void
+close_figure (const graphics_handle& h)
+{
+  octave_value closerequestfcn = xget (h, "closerequestfcn");
+
+  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
+
+  gh_mgr.execute_callback (h, closerequestfcn);
+}
+
+void
+force_close_figure (const graphics_handle& h)
+{
+  // Remove the deletefcn and closerequestfcn callbacks
+  // and delete the object directly.
+
+  xset (h, "deletefcn", Matrix ());
+  xset (h, "closerequestfcn", Matrix ());
+
+  delete_graphics_object (h, true);
+}
+
+OCTAVE_END_NAMESPACE(octave)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/graphics-utils.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_graphics_utils_h)
+#define octave_graphics_utils_h 1
+
+// The functions defined here are private and should not be exported.
+// This header file should not be installed.
+
+#include "octave-config.h"
+
+#include <string>
+
+#include "graphics-handle.h"
+
+class caseless_str;
+class octave_value;
+class NDArray;
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+// Flag to stop redraws due to callbacks while deletion is in progress.
+extern bool delete_executing;
+
+extern void xset (const graphics_handle& h, const caseless_str& pname,
+                  const octave_value& val);
+
+extern void xset (const graphics_handle& h, const octave_value_list& args);
+
+extern octave_value xget (const graphics_handle& h, const caseless_str& pname);
+
+extern bool isfigure (double val);
+
+extern graphics_handle
+reparent (const octave_value& ov, const std::string& who,
+          const std::string& pname, const graphics_handle& new_parent,
+          bool adopt = true);
+
+extern void
+delete_graphics_object (const graphics_handle& h, bool from_root = false);
+
+extern void delete_graphics_object (double val, bool from_root = false);
+
+extern void
+delete_graphics_objects (const NDArray vals, bool from_root = false);
+
+extern void close_figure (const graphics_handle& h);
+
+extern void force_close_figure (const graphics_handle& h);
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- a/libinterp/corefcn/graphics.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/graphics.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,6 +44,7 @@
 #include "cmd-edit.h"
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-locbuf.h"
 #include "oct-time.h"
 
@@ -51,6 +52,8 @@
 #include "defun.h"
 #include "display.h"
 #include "error.h"
+#include "gh-manager.h"
+#include "graphics-utils.h"
 #include "graphics.h"
 #include "input.h"
 #include "interpreter-private.h"
@@ -60,7 +63,6 @@
 #include "oct-map.h"
 #include "ov-fcn-handle.h"
 #include "pager.h"
-#include "parse.h"
 #include "text-engine.h"
 #include "text-renderer.h"
 #include "unwind-prot.h"
@@ -69,9 +71,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-// forward declarations
-static octave_value xget (const graphics_handle& h, const caseless_str& name);
-
 OCTAVE_NORETURN static
 void
 err_set_invalid (const std::string& pname)
@@ -138,7 +137,7 @@
 }
 
 static Matrix
-viridis_colormap (void)
+viridis_colormap ()
 {
   // The values below have been produced by viridis (64)(:)
   // It would be nice to be able to feval the
@@ -222,7 +221,7 @@
 }
 
 static double
-default_screendepth (void)
+default_screendepth ()
 {
   octave::display_info& dpy_info = octave::__get_display_info__ ();
 
@@ -230,7 +229,7 @@
 }
 
 static Matrix
-default_screensize (void)
+default_screensize ()
 {
   Matrix retval (1, 4);
 
@@ -245,7 +244,7 @@
 }
 
 static double
-default_screenpixelsperinch (void)
+default_screenpixelsperinch ()
 {
   octave::display_info& dpy_info = octave::__get_display_info__ ();
 
@@ -253,7 +252,7 @@
 }
 
 static Matrix
-default_colororder (void)
+default_colororder ()
 {
   Matrix retval (7, 3, 0.0);
 
@@ -307,7 +306,7 @@
 }
 
 static Matrix
-default_data (void)
+default_data ()
 {
   Matrix retval (1, 2);
 
@@ -318,7 +317,7 @@
 }
 
 static Matrix
-default_data_lim (void)
+default_data_lim ()
 {
   Matrix retval (1, 4);
 
@@ -331,7 +330,7 @@
 }
 
 static Matrix
-default_image_cdata (void)
+default_image_cdata ()
 {
   Matrix m (64, 64);
 
@@ -347,7 +346,7 @@
 }
 
 static Matrix
-default_surface_xdata (void)
+default_surface_xdata ()
 {
   Matrix m (3, 3);
 
@@ -359,7 +358,7 @@
 }
 
 static Matrix
-default_surface_ydata (void)
+default_surface_ydata ()
 {
   Matrix m (3, 3);
 
@@ -371,7 +370,7 @@
 }
 
 static Matrix
-default_surface_zdata (void)
+default_surface_zdata ()
 {
   Matrix m (3, 3, 0.0);
 
@@ -382,13 +381,13 @@
 }
 
 static Matrix
-default_surface_cdata (void)
+default_surface_cdata ()
 {
   return default_surface_zdata ();
 }
 
 static Matrix
-default_patch_faces (void)
+default_patch_faces ()
 {
   Matrix m (1, 3);
 
@@ -400,7 +399,7 @@
 }
 
 static Matrix
-default_patch_vertices (void)
+default_patch_vertices ()
 {
   Matrix m (3, 2, 0.0);
 
@@ -412,7 +411,7 @@
 }
 
 static Matrix
-default_patch_xdata (void)
+default_patch_xdata ()
 {
   Matrix m (3, 1, 0.0);
 
@@ -422,7 +421,7 @@
 }
 
 static Matrix
-default_patch_ydata (void)
+default_patch_ydata ()
 {
   Matrix m (3, 1, 1.0);
 
@@ -432,7 +431,7 @@
 }
 
 static Matrix
-default_axes_position (void)
+default_axes_position ()
 {
   Matrix m (1, 4);
 
@@ -445,7 +444,7 @@
 }
 
 static Matrix
-default_axes_outerposition (void)
+default_axes_outerposition ()
 {
   Matrix m (1, 4);
 
@@ -458,7 +457,7 @@
 }
 
 static Matrix
-default_axes_view (void)
+default_axes_view ()
 {
   Matrix m (1, 2);
 
@@ -469,7 +468,7 @@
 }
 
 static Matrix
-default_axes_tick (void)
+default_axes_tick ()
 {
   Matrix m (1, 6);
 
@@ -484,7 +483,7 @@
 }
 
 static Matrix
-default_axes_ticklength (void)
+default_axes_ticklength ()
 {
   Matrix m (1, 2);
 
@@ -495,7 +494,7 @@
 }
 
 static Matrix
-default_figure_position (void)
+default_figure_position ()
 {
   Matrix m (1, 4);
 
@@ -508,7 +507,7 @@
 }
 
 static Matrix
-default_figure_papersize (void)
+default_figure_papersize ()
 {
   Matrix m (1, 2);
 
@@ -519,7 +518,7 @@
 }
 
 static Matrix
-default_figure_paperposition (void)
+default_figure_paperposition ()
 {
   Matrix m (1, 4);
 
@@ -533,7 +532,7 @@
 }
 
 static std::string
-default_graphics_toolkit (void)
+default_graphics_toolkit ()
 {
   octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();
 
@@ -541,7 +540,7 @@
 }
 
 static Matrix
-default_control_position (void)
+default_control_position ()
 {
   Matrix retval (1, 4);
 
@@ -554,7 +553,7 @@
 }
 
 static Matrix
-default_control_sliderstep (void)
+default_control_sliderstep ()
 {
   Matrix retval (1, 2);
 
@@ -565,7 +564,7 @@
 }
 
 static Matrix
-default_panel_position (void)
+default_panel_position ()
 {
   Matrix retval (1, 4);
 
@@ -578,7 +577,7 @@
 }
 
 static Matrix
-default_light_position (void)
+default_light_position ()
 {
   Matrix m (1, 3);
 
@@ -590,7 +589,7 @@
 }
 
 static Matrix
-default_table_position (void)
+default_table_position ()
 {
   Matrix retval (1, 4);
 
@@ -603,7 +602,7 @@
 }
 
 static Matrix
-default_table_backgroundcolor (void)
+default_table_backgroundcolor ()
 {
   Matrix retval (2, 3);
   retval(0, 0) = 1;
@@ -922,7 +921,7 @@
 
 // This function always returns the screensize in pixels
 static Matrix
-screen_size_pixels (void)
+screen_size_pixels ()
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -1202,10 +1201,10 @@
   return result;
 }
 
-static base_graphics_object *
+base_graphics_object *
 make_graphics_object_from_type (const caseless_str& type,
-                                const graphics_handle& h = graphics_handle (),
-                                const graphics_handle& p = graphics_handle ())
+                                const graphics_handle& h,
+                                const graphics_handle& p)
 {
   base_graphics_object *go = nullptr;
 
@@ -1330,7 +1329,7 @@
 }
 
 std::string
-radio_values::values_as_string (void) const
+radio_values::values_as_string () const
 {
   std::string retval;
 
@@ -1359,7 +1358,7 @@
 }
 
 Cell
-radio_values::values_as_cell (void) const
+radio_values::values_as_cell () const
 {
   octave_idx_type i = 0;
   Cell retval (nelem (), 1);
@@ -1725,7 +1724,7 @@
 }
 
 void
-array_property::get_data_limits (void)
+array_property::get_data_limits ()
 {
   m_min_val = m_min_pos = octave::numeric_limits<double>::Inf ();
   m_max_val = m_max_neg = -octave::numeric_limits<double>::Inf ();
@@ -1937,15 +1936,13 @@
 {
 public:
 
-  callback_props (void) : m_set () { }
-
-  callback_props (const callback_props&) = delete;
-
-  callback_props& operator = (const callback_props&) = delete;
-
-  ~callback_props (void) = default;
-
-  bool empty (void) const { return m_set.empty (); }
+  callback_props () : m_set () { }
+
+  OCTAVE_DISABLE_COPY_MOVE (callback_props)
+
+  ~callback_props () = default;
+
+  bool empty () const { return m_set.empty (); }
 
   void insert (const callback_property *ptr)
   {
@@ -2023,8 +2020,7 @@
       if (args.length () < 1)
         error ("addproperty: missing possible values for radio property");
 
-      std::string sv = args(
-                         0).xstring_value ("addproperty: argument for radio property must be a string");
+      std::string sv = args(0).xstring_value ("addproperty: argument for radio property must be a string");
 
       retval = property (new radio_property (name, h, sv));
 
@@ -2235,7 +2231,7 @@
 }
 
 void
-figure::properties::update_handlevisibility (void)
+figure::properties::update_handlevisibility ()
 {
   if (! is_handle_visible ())
     {
@@ -2294,7 +2290,7 @@
 }
 
 void
-figure::properties::update___device_pixel_ratio__ (void)
+figure::properties::update___device_pixel_ratio__ ()
 {
   update_text_pos (get___myhandle__ ());
 }
@@ -2544,18 +2540,18 @@
 {
   octave_scalar_map m;
 
-  for (auto p = begin (); p != end (); p++)
-    {
-      std::string prefix = prefix_arg + p->first;
-
-      for (const auto& prop_val : p->second)
+  for (const auto& p : *this)
+    {
+      std::string prefix = prefix_arg + p.first;
+
+      for (const auto& prop_val : p.second)
         m.assign (prefix + prop_val.first, prop_val.second);
     }
 
   return m;
 }
 
-// Set properties given as a cs-list of name, value pairs.
+// Set property given as either cs-list of name/value pairs or a struct.
 
 void
 graphics_object::set (const octave_value_list& args)
@@ -2567,7 +2563,7 @@
 
   for (int i = 0; i < nargin; )
     {
-      if (args(i).isstruct () )
+      if (args(i).isstruct ())
         {
           set (args(i).map_value ());
           i++;
@@ -2681,41 +2677,6 @@
 }
 
 /*
-## test set ticklabels for compatibility
-%!test
-%! hf = figure ("visible", "off");
-%! set (gca (), "xticklabel", [0, 0.2, 0.4, 0.6, 0.8, 1]);
-%! xticklabel = get (gca (), "xticklabel");
-%! close (hf);
-%! assert (class (xticklabel), "char");
-%! assert (size (xticklabel), [6, 3]);
-
-%!test
-%! hf = figure ("visible", "off");
-%! set (gca (), "xticklabel", "0|0.2|0.4|0.6|0.8|1");
-%! xticklabel = get (gca (), "xticklabel");
-%! close (hf);
-%! assert (class (xticklabel), "char");
-%! assert (size (xticklabel), [6, 3]);
-
-%!test
-%! hf = figure ("visible", "off");
-%! set (gca (), "xticklabel", ["0 "; "0.2"; "0.4"; "0.6"; "0.8"; "1 "]);
-%! xticklabel = get (gca (), "xticklabel");
-%! close (hf);
-%! assert (class (xticklabel), "char");
-%! assert (size (xticklabel), [6, 3]);
-
-%!test
-%! hf = figure ("visible", "off");
-%! set (gca (), "xticklabel", {"0", "0.2", "0.4", "0.6", "0.8", "1"});
-%! xticklabel = get (gca (), "xticklabel");
-%! close (hf);
-%! assert (class (xticklabel), "cell");
-%! assert (size (xticklabel), [6, 1]);
-*/
-
-/*
 ## test set with struct arguments
 %!test
 %! hf = figure ("visible", "off");
@@ -2818,226 +2779,9 @@
 %! end_unwind_protect
 */
 
-static double
-make_handle_fraction (void)
-{
-  static double maxrand = RAND_MAX + 2.0;
-
-  return (rand () + 1.0) / maxrand;
-}
-
-graphics_handle
-gh_manager::get_handle (bool integer_figure_handle)
-{
-  graphics_handle retval;
-
-  if (integer_figure_handle)
-    {
-      // Figure handles are positive integers corresponding
-      // to the figure number.
-
-      // We always want the lowest unused figure number.
-
-      retval = 1;
-
-      while (m_handle_map.find (retval) != m_handle_map.end ())
-        retval++;
-    }
-  else
-    {
-      // Other graphics handles are negative integers plus some random
-      // fractional part.  To avoid running out of integers, we recycle the
-      // integer part but tack on a new random part each time.
-
-      auto p = m_handle_free_list.begin ();
-
-      if (p != m_handle_free_list.end ())
-        {
-          retval = *p;
-          m_handle_free_list.erase (p);
-        }
-      else
-        {
-          retval = graphics_handle (m_next_handle);
-
-          m_next_handle = std::ceil (m_next_handle) - 1.0 - make_handle_fraction ();
-        }
-    }
-
-  return retval;
-}
-
-static bool
-isfigure (double val)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  graphics_object go = gh_mgr.get_object (val);
-
-  return go && go.isa ("figure");
-}
-
-void
-gh_manager::free (const graphics_handle& h, bool from_root)
-{
-  if (h.ok ())
-    {
-      if (h.value () == 0)
-        error ("graphics_handle::free: can't delete root object");
-
-      auto p = m_handle_map.find (h);
-
-      if (p == m_handle_map.end ())
-        error ("graphics_handle::free: invalid object %g", h.value ());
-
-      base_properties& bp = p->second.get_properties ();
-
-      if (! p->second.valid_object () || bp.is_beingdeleted ())
-        return;
-
-      graphics_handle parent_h = p->second.get_parent ();
-      graphics_object parent_go = nullptr;
-      if (! from_root || isfigure (h.value ()))
-        parent_go = get_object (parent_h);
-
-      bp.set_beingdeleted (true);
-
-      // delete listeners before invalidating object
-      p->second.remove_all_listeners ();
-
-      bp.delete_children (true, from_root);
-
-      // NOTE: Call the delete function while the object's state is still valid.
-      octave_value val = bp.get_deletefcn ();
-
-      bp.execute_deletefcn ();
-
-      // Notify graphics toolkit.
-      p->second.finalize ();
-
-
-      // 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 ((! from_root || isfigure (h.value ())) && parent_go.valid_object ()
-          && h.ok ())
-        parent_go.remove_child (h);
-
-      // Note: this will be valid only for first explicitly deleted
-      // object.  All its children will then have an
-      // unknown graphics toolkit.
-
-      // Graphics handles for non-figure objects are negative
-      // integers plus some random fractional part.  To avoid
-      // running out of integers, we recycle the integer part
-      // but tack on a new random part each time.
-
-      m_handle_map.erase (p);
-
-      if (h.value () < 0)
-        m_handle_free_list.insert
-        (std::ceil (h.value ()) - make_handle_fraction ());
-    }
-}
-
-void
-gh_manager::renumber_figure (const graphics_handle& old_gh,
-                             const graphics_handle& new_gh)
-{
-  auto p = m_handle_map.find (old_gh);
-
-  if (p == m_handle_map.end ())
-    error ("graphics_handle::free: invalid object %g", old_gh.value ());
-
-  graphics_object go = p->second;
-
-  m_handle_map.erase (p);
-
-  m_handle_map[new_gh] = go;
-
-  if (old_gh.value () < 0)
-    m_handle_free_list.insert (std::ceil (old_gh.value ())
-                               - make_handle_fraction ());
-
-  for (auto& hfig : m_figure_list)
-    {
-      if (hfig == old_gh)
-        {
-          hfig = new_gh;
-          break;
-        }
-    }
-}
-
-static void
-xset (const graphics_handle& h, const caseless_str& pname,
-      const octave_value& val)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  graphics_object go = gh_mgr.get_object (h);
-
-  go.set (pname, val);
-}
-
-static void
-xset (const graphics_handle& h, const octave_value_list& args)
-{
-  if (args.length () > 0)
-    {
-      gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-      graphics_object go = gh_mgr.get_object (h);
-
-      go.set (args);
-    }
-}
-
-static octave_value
-xget (const graphics_handle& h, const caseless_str& pname)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  graphics_object go = gh_mgr.get_object (h);
-
-  return go.get (pname);
-}
-
-static graphics_handle
-reparent (const octave_value& ov, const std::string& who,
-          const std::string& pname, const graphics_handle& new_parent,
-          bool adopt = true)
-{
-  double hv = ov.xdouble_value ("%s: %s must be a graphics handle",
-                                who.c_str (), pname.c_str ());
-
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  graphics_handle h = gh_mgr.lookup (hv);
-
-  if (! h.ok ())
-    error ("%s: invalid graphics handle (= %g) for %s",
-           who.c_str (), hv, pname.c_str ());
-
-  graphics_object go = gh_mgr.get_object (h);
-
-  graphics_handle parent_h = go.get_parent ();
-
-  graphics_object parent_go = gh_mgr.get_object (parent_h);
-
-  parent_go.remove_child (h);
-
-  if (adopt)
-    go.set ("parent", new_parent.value ());
-  else
-    go.reparent (new_parent);
-
-  return h;
-}
-
 // This function is NOT equivalent to the scripting language function gcf.
 graphics_handle
-gcf (void)
+gcf ()
 {
   octave_value val = xget (0, "currentfigure");
 
@@ -3047,7 +2791,7 @@
 
 // This function is NOT equivalent to the scripting language function gca.
 graphics_handle
-gca (void)
+gca ()
 {
   octave_value val = xget (gcf (), "currentaxes");
 
@@ -3056,115 +2800,6 @@
 }
 
 static void
-delete_graphics_object (const graphics_handle& h, bool from_root = false)
-{
-  if (h.ok ())
-    {
-      gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-      graphics_object go = gh_mgr.get_object (h);
-
-      // Don't do recursive deleting, due to callbacks
-      if (! go.get_properties ().is_beingdeleted ())
-        {
-          // NOTE: Freeing the handle also calls any deletefcn.  It also calls
-          //       the parent's delete_child function.
-
-          gh_mgr.free (h, from_root || go.isa ("figure"));
-
-          Vdrawnow_requested = true;
-        }
-    }
-}
-
-static void
-delete_graphics_object (double val, bool from_root = false)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  delete_graphics_object (gh_mgr.lookup (val), from_root || isfigure (val));
-}
-
-// 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, bool from_root = false)
-{
-  // Prevent redraw of partially deleted objects.
-  octave::unwind_protect_var<bool> restore_var (delete_executing, true);
-
-  for (octave_idx_type i = 0; i < vals.numel (); i++)
-    delete_graphics_object (vals.elem (i), from_root);
-}
-
-static void
-close_figure (const graphics_handle& h)
-{
-  octave_value closerequestfcn = xget (h, "closerequestfcn");
-
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  gh_mgr.execute_callback (h, closerequestfcn);
-}
-
-static void
-force_close_figure (const graphics_handle& h)
-{
-  // Remove the deletefcn and closerequestfcn callbacks
-  // and delete the object directly.
-
-  xset (h, "deletefcn", Matrix ());
-  xset (h, "closerequestfcn", Matrix ());
-
-  delete_graphics_object (h, true);
-}
-
-void
-gh_manager::close_all_figures (void)
-{
-  // FIXME: should we process or discard pending events?
-
-  m_event_queue.clear ();
-
-  // Don't use m_figure_list_iterator because we'll be removing elements
-  // from the list elsewhere.
-
-  Matrix hlist = figure_handle_list (true);
-
-  for (octave_idx_type i = 0; i < hlist.numel (); i++)
-    {
-      graphics_handle h = lookup (hlist(i));
-
-      if (h.ok ())
-        close_figure (h);
-    }
-
-  // They should all be closed now.  If not, force them to close.
-
-  hlist = figure_handle_list (true);
-
-  for (octave_idx_type i = 0; i < hlist.numel (); i++)
-    {
-      graphics_handle h = lookup (hlist(i));
-
-      if (h.ok ())
-        force_close_figure (h);
-    }
-
-  // None left now, right?
-
-  hlist = figure_handle_list (true);
-
-  if (hlist.numel () != 0)
-    warning ("gh_manager::close_all_figures: some graphics elements failed to close");
-
-  // Clear all callback objects from our list.
-
-  m_callback_objects.clear ();
-}
-
-static void
 adopt (const graphics_handle& parent_h, const graphics_handle& h)
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
@@ -3360,16 +2995,15 @@
 {
   octave_scalar_map m;
 
-  for (std::map<caseless_str, property, cmp_caseless_str>::const_iterator
-       it = m_all_props.begin (); it != m_all_props.end (); ++it)
-    if (all || ! it->second.is_hidden ())
-      m.assign (it->second.get_name (), it->second.get ());
+  for (const auto& it : m_all_props)
+    if (all || ! it.second.is_hidden ())
+      m.assign (it.second.get_name (), it.second.get ());
 
   return m;
 }
 
 std::set<std::string>
-base_properties::dynamic_property_names (void) const
+base_properties::dynamic_property_names () const
 {
   return m_dynamic_properties;
 }
@@ -3462,7 +3096,7 @@
 */
 
 void
-base_properties::mark_modified (void)
+base_properties::mark_modified ()
 {
   // Mark existing object as modified
   m___modified__ = "on";
@@ -3512,7 +3146,7 @@
 }
 
 void
-base_properties::update_contextmenu (void) const
+base_properties::update_contextmenu () const
 {
   if (m_contextmenu.get ().isempty ())
     return;
@@ -3530,14 +3164,14 @@
 }
 
 bool
-base_properties::is_handle_visible (void) const
+base_properties::is_handle_visible () const
 {
   return (m_handlevisibility.is ("on")
           || (! executing_callbacks.empty () && ! m_handlevisibility.is ("off")));
 }
 
 octave::graphics_toolkit
-base_properties::get_toolkit (void) const
+base_properties::get_toolkit () const
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -3550,7 +3184,7 @@
 }
 
 void
-base_properties::update_boundingbox (void)
+base_properties::update_boundingbox ()
 {
   Matrix kids = get_children ();
 
@@ -3577,7 +3211,7 @@
 }
 
 void
-base_properties::update_handlevisibility (void)
+base_properties::update_handlevisibility ()
 {
   if (is_handle_visible ())
     return;
@@ -3726,7 +3360,7 @@
 }
 
 void
-base_graphics_object::remove_all_listeners (void)
+base_graphics_object::remove_all_listeners ()
 {
   int state = toggle_warn ("Octave:deprecated-property", false);
   octave_map m = get (true).map_value ();
@@ -3785,7 +3419,7 @@
 }
 
 void
-base_graphics_object::reset_default_properties (void)
+base_graphics_object::reset_default_properties ()
 {
   if (valid_object ())
     {
@@ -3800,7 +3434,7 @@
 }
 
 std::string
-base_graphics_object::values_as_string (void)
+base_graphics_object::values_as_string ()
 {
   if (! valid_object ())
     error ("base_graphics_object::values_as_string: invalid graphics object");
@@ -3864,7 +3498,7 @@
 }
 
 octave_scalar_map
-base_graphics_object::values_as_struct (void)
+base_graphics_object::values_as_struct ()
 {
   octave_scalar_map retval;
 
@@ -4020,7 +3654,7 @@
 // FIXME: This should update monitorpositions and pointerlocation, but as these
 // properties aren't yet used, it doesn't matter that they aren't set either.
 void
-root_figure::properties::update_units (void)
+root_figure::properties::update_units ()
 {
   std::string xunits = get_units ();
 
@@ -4125,7 +3759,7 @@
 }
 
 void
-root_figure::reset_default_properties (void)
+root_figure::reset_default_properties ()
 {
   // empty list of local defaults
   m_default_properties = property_list ();
@@ -4179,7 +3813,7 @@
 }
 
 octave_value
-figure::properties::get_number (void) const
+figure::properties::get_number () const
 {
   if (m_integerhandle.is_on ())
     return m___myhandle__.value ();
@@ -4188,7 +3822,7 @@
 }
 
 octave::graphics_toolkit
-figure::properties::get_toolkit (void) const
+figure::properties::get_toolkit () const
 {
   return m_toolkit;
 }
@@ -4572,7 +4206,7 @@
 }
 
 Matrix
-figure::properties::get_auto_paperposition (void)
+figure::properties::get_auto_paperposition ()
 {
   Matrix pos = get_position ().matrix_value ();
   Matrix sz;
@@ -4742,7 +4376,7 @@
 }
 
 void
-figure::properties::update_papertype (void)
+figure::properties::update_papertype ()
 {
   std::string typ = get_papertype ();
   if (typ != "<custom>")
@@ -4760,7 +4394,7 @@
 }
 
 void
-figure::properties::update_papersize (void)
+figure::properties::update_papersize ()
 {
   Matrix sz = get_papersize ().matrix_value ();
   if (sz(0) > sz(1))
@@ -4928,7 +4562,7 @@
 */
 
 void
-figure::properties::update_paperorientation (void)
+figure::properties::update_paperorientation ()
 {
   std::string porient = get_paperorientation ();
   Matrix sz = get_papersize ().matrix_value ();
@@ -5011,7 +4645,7 @@
 */
 
 std::string
-figure::properties::get_title (void) const
+figure::properties::get_title () const
 {
   std::string title;
   if (! get_number ().isempty () && is_numbertitle ())
@@ -5056,7 +4690,7 @@
 }
 
 void
-figure::reset_default_properties (void)
+figure::reset_default_properties ()
 {
   // empty list of local defaults
   m_default_properties = property_list ();
@@ -5076,7 +4710,7 @@
 // ---------------------------------------------------------------------
 
 void
-axes::properties::init (void)
+axes::properties::init ()
 {
   m_position.add_constraint (dim_vector (1, 4));
   m_outerposition.add_constraint (dim_vector (1, 4));
@@ -5274,7 +4908,7 @@
 }
 
 void
-axes::properties::sync_positions (void)
+axes::properties::sync_positions ()
 {
   // First part is equivalent to 'update_tightinset ()'
   if (m_positionconstraint.is ("innerposition"))
@@ -5672,7 +5306,7 @@
 }
 
 octave_value
-axes::properties::get_colormap (void) const
+axes::properties::get_colormap () const
 {
   if (m___colormap__.get ().isempty ())
     {
@@ -5789,7 +5423,7 @@
 }
 
 inline Matrix
-xform_matrix (void)
+xform_matrix ()
 {
   Matrix m (4, 4, 0.0);
 
@@ -5800,7 +5434,7 @@
 }
 
 inline ColumnVector
-xform_vector (void)
+xform_vector ()
 {
   ColumnVector v (4, 0.0);
 
@@ -5919,7 +5553,7 @@
 }
 
 inline Matrix
-unit_cube (void)
+unit_cube ()
 {
   static double data[32] =
   {
@@ -5956,7 +5590,7 @@
 }
 
 void
-axes::properties::update_camera (void)
+axes::properties::update_camera ()
 {
   double xd = (xdir_is ("normal") ? 1 : -1);
   double yd = (ydir_is ("normal") ? 1 : -1);
@@ -6172,7 +5806,7 @@
 static bool updating_axes_layout = false;
 
 void
-axes::properties::update_axes_layout (void)
+axes::properties::update_axes_layout ()
 {
   if (updating_axes_layout)
     return;
@@ -6335,7 +5969,7 @@
 }
 
 void
-axes::properties::update_ticklength (void)
+axes::properties::update_ticklength ()
 {
   bool mode2D = (((m_xstate > AXE_DEPTH_DIR ? 1 : 0) +
                   (m_ystate > AXE_DEPTH_DIR ? 1 : 0) +
@@ -6344,7 +5978,16 @@
   if (tickdirmode_is ("auto"))
     m_tickdir.set (mode2D ? "in" : "out", true);
 
-  double ticksign = (tickdir_is ("in") ? -1 : 1);
+  double ticksign;
+  std::string tickdir = get_tickdir ();
+  if (tickdir == "in")
+    ticksign = -1;
+  else if (tickdir == "out")
+    ticksign = 1;
+  else if (tickdir == "both")
+    ticksign = 2;
+  else  // tickdir == "none"
+    ticksign = 0;
 
   Matrix bbox = get_boundingbox (true);
   Matrix ticklen = get_ticklength ().matrix_value ();
@@ -6422,7 +6065,7 @@
 static bool updating_xlabel_position = false;
 
 void
-axes::properties::update_xlabel_position (void)
+axes::properties::update_xlabel_position ()
 {
   if (updating_xlabel_position)
     return;
@@ -6526,7 +6169,7 @@
 static bool updating_ylabel_position = false;
 
 void
-axes::properties::update_ylabel_position (void)
+axes::properties::update_ylabel_position ()
 {
   if (updating_ylabel_position)
     return;
@@ -6630,7 +6273,7 @@
 static bool updating_zlabel_position = false;
 
 void
-axes::properties::update_zlabel_position (void)
+axes::properties::update_zlabel_position ()
 {
   if (updating_zlabel_position)
     return;
@@ -6756,7 +6399,7 @@
 static bool updating_title_position = false;
 
 void
-axes::properties::update_title_position (void)
+axes::properties::update_title_position ()
 {
   if (updating_title_position)
     return;
@@ -6857,7 +6500,7 @@
 static std::set<double> updating_aspectratios;
 
 void
-axes::properties::update_aspectratios (void)
+axes::properties::update_aspectratios ()
 {
   if (updating_aspectratios.find (get___myhandle__ ().value ())
       != updating_aspectratios.end ())
@@ -7161,6 +6804,13 @@
           for (octave_idx_type i = 0; i < val.numel (); i++)
             {
               oss.str ("");
+              // FIXME: Code should probably call out to display routines
+              // within Octave, rather than hack things up with C++ library.
+              // See FIXME in calc_ticklabels().
+              if (std::abs (data(i)) < 1.0)
+                oss.precision (4);
+              else
+                oss.precision (5);
               oss << data(i);
               sv.append (oss.str ());
             }
@@ -7366,7 +7016,7 @@
 }
 
 Matrix
-graphics_xform::xform_eye (void)
+graphics_xform::xform_eye ()
 {
   return octave::xform_matrix ();
 }
@@ -7497,7 +7147,7 @@
 }
 
 void
-axes::properties::update_outerposition (void)
+axes::properties::update_outerposition ()
 {
   set_positionconstraint ("outerposition");
   caseless_str old_units = get_units ();
@@ -7556,7 +7206,7 @@
 }
 
 void
-axes::properties::update_position (void)
+axes::properties::update_position ()
 {
   set_positionconstraint ("innerposition");
   caseless_str old_units = get_units ();
@@ -7604,7 +7254,7 @@
 }
 
 void
-axes::properties::update_looseinset (void)
+axes::properties::update_looseinset ()
 {
   caseless_str old_units = get_units ();
   set_units ("normalized");
@@ -8281,7 +7931,7 @@
 {
   Matrix values = ticks.get ().matrix_value ();
   Matrix lims = axis_lims.get ().matrix_value ();
-  Cell c (values.dims ());
+  Cell c (dim_vector (values.numel (), 1));  // column vector for ML compat.
   std::ostringstream os;
 
   // omit tick labels depending on location of other axis
@@ -8308,14 +7958,16 @@
     {
       double significand;
       double exponent;
-      double exp_max = 0.0;
-      double exp_min = 0.0;
+      bool is_2digit_exp = false;
 
       for (int i = 0; i < values.numel (); i++)
         {
-          double exp = std::log10 (values(i));
-          exp_min = std::min (exp_min, exp);
-          exp_max = std::max (exp_max, exp);
+          double exp = std::abs (std::log10 (values(i)));
+          if (exp >= 10.0)
+            {
+              is_2digit_exp = true;
+              break;
+            }
         }
 
       for (int i = 0; i < values.numel (); i++)
@@ -8334,8 +7986,9 @@
             exponent = std::floor (std::log10 (-values(i)));
           else
             exponent = std::floor (std::log10 (values(i)));
-          significand = values(i) * std::pow (10., -exponent);
-
+          significand = values(i) * std::pow (10.0, -exponent);
+
+          os.precision (5);
           os.str ("");
           if ((std::abs (significand) - 1) >
               10*std::numeric_limits<double>::epsilon())
@@ -8350,7 +8003,7 @@
               os << '-';
               exponent = -exponent;
             }
-          if (exponent < 10. && (exp_max > 9 || exp_min < -9))
+          if (exponent < 10.0 && is_2digit_exp)
             os << '0';
           os << exponent << '}';
 
@@ -8373,6 +8026,15 @@
           else
             {
               os.str ("");
+              // FIXME: Code should probably call out to display routines
+              // within Octave, rather than hack things up with C++ library.
+              // In particular, this fails for values much less than 1 where
+              // 4 significant digits will be preceded by zeros making the
+              // overall field length large.  For example, pi/1000.
+              if (std::abs (values(i)) < 1.0)
+                os.precision (4);
+              else
+                os.precision (5);
               os << values(i);
               c(i) = os.str ();
             }
@@ -9056,7 +8718,7 @@
 }
 
 void
-axes::properties::push_zoom_stack (void)
+axes::properties::push_zoom_stack ()
 {
   if (m_zoom_stack.empty ())
     {
@@ -9282,7 +8944,7 @@
 }
 
 void
-axes::properties::unzoom (void)
+axes::properties::unzoom ()
 {
   if (m_zoom_stack.size () >= 7)
     {
@@ -9318,7 +8980,7 @@
 }
 
 void
-axes::properties::update_handlevisibility (void)
+axes::properties::update_handlevisibility ()
 {
   if (! is_handle_visible ())
     {
@@ -9347,7 +9009,7 @@
 }
 
 void
-figure::properties::init_toolkit (void)
+figure::properties::init_toolkit ()
 {
   octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();
 
@@ -9367,7 +9029,7 @@
 }
 
 void
-axes::properties::trigger_normals_calc (void)
+axes::properties::trigger_normals_calc ()
 {
   // Find all patch (and surface) objects within axes
   std::list<graphics_object> children_list;
@@ -9396,7 +9058,7 @@
 }
 
 void
-axes::reset_default_properties (void)
+axes::reset_default_properties ()
 {
   // empty list of local defaults
   m_default_properties = property_list ();
@@ -9427,7 +9089,7 @@
 // ---------------------------------------------------------------------
 
 Matrix
-line::properties::compute_xlim (void) const
+line::properties::compute_xlim () const
 {
   Matrix m (1, 4);
 
@@ -9440,7 +9102,7 @@
 }
 
 Matrix
-line::properties::compute_ylim (void) const
+line::properties::compute_ylim () const
 {
   Matrix m (1, 4);
 
@@ -9455,7 +9117,7 @@
 // ---------------------------------------------------------------------
 
 Matrix
-text::properties::get_data_position (void) const
+text::properties::get_data_position () const
 {
   Matrix pos = get_position ().matrix_value ();
 
@@ -9510,7 +9172,7 @@
 }
 
 octave_value
-text::properties::get_extent (void) const
+text::properties::get_extent () const
 {
   // FIXME: This doesn't work right for 3D plots.
   // (It doesn't in Matlab either, at least not in version 6.5.)
@@ -9567,7 +9229,7 @@
 }
 
 void
-text::properties::update_font (void)
+text::properties::update_font ()
 {
   double dpr = device_pixel_ratio (get___myhandle__ ());
 
@@ -9589,7 +9251,7 @@
 }
 
 void
-text::properties::update_text_extent (void)
+text::properties::update_text_extent ()
 {
   int halign = 0;
   int valign = 0;
@@ -9634,7 +9296,7 @@
 }
 
 void
-text::properties::request_autopos (void)
+text::properties::request_autopos ()
 {
   if (__autopos_tag___is ("xlabel") || __autopos_tag___is ("ylabel")
       || __autopos_tag___is ("zlabel") || __autopos_tag___is ("title"))
@@ -9642,7 +9304,7 @@
 }
 
 void
-text::properties::update_units (void)
+text::properties::update_units ()
 {
   if (! units_is ("data"))
     {
@@ -9699,7 +9361,7 @@
 // ---------------------------------------------------------------------
 
 octave_value
-image::properties::get_color_data (void) const
+image::properties::get_color_data () const
 {
   return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
 }
@@ -9718,7 +9380,7 @@
 }
 
 void
-light::properties::update_visible (void)
+light::properties::update_visible ()
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -9735,7 +9397,7 @@
 // ---------------------------------------------------------------------
 
 bool
-patch::properties::get_do_lighting (void) const
+patch::properties::get_do_lighting () const
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -9748,7 +9410,7 @@
 }
 
 octave_value
-patch::properties::get_color_data (void) const
+patch::properties::get_color_data () const
 {
   octave_value fvc = get_facevertexcdata ();
   if (fvc.is_undefined () || fvc.isempty ())
@@ -9760,7 +9422,7 @@
 static bool updating_patch_data = false;
 
 void
-patch::properties::update_fvc (void)
+patch::properties::update_fvc ()
 {
   if (updating_patch_data)
     return;
@@ -9939,7 +9601,7 @@
 }
 
 void
-patch::properties::update_data (void)
+patch::properties::update_data ()
 {
   if (updating_patch_data)
     return;
@@ -10320,7 +9982,7 @@
 
 
 void
-patch::reset_default_properties (void)
+patch::reset_default_properties ()
 {
   // empty list of local defaults
   m_default_properties = property_list ();
@@ -10335,7 +9997,7 @@
 // ---------------------------------------------------------------------
 
 octave_value
-scatter::properties::get_color_data (void) const
+scatter::properties::get_color_data () const
 {
   octave_value c = get_cdata ();
   if (c.is_undefined () || c.isempty ())
@@ -10345,7 +10007,7 @@
 }
 
 void
-scatter::properties::update_data (void)
+scatter::properties::update_data ()
 {
   Matrix xd = get_xdata ().matrix_value ();
   Matrix yd = get_ydata ().matrix_value ();
@@ -10385,7 +10047,7 @@
 static bool updating_scatter_cdata = false;
 
 void
-scatter::properties::update_color (void)
+scatter::properties::update_color ()
 {
   if (updating_scatter_cdata)
     return;
@@ -10448,13 +10110,13 @@
 // ---------------------------------------------------------------------
 
 octave_value
-surface::properties::get_color_data (void) const
+surface::properties::get_color_data () const
 {
   return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
 }
 
 bool
-surface::properties::get_do_lighting (void) const
+surface::properties::get_do_lighting () const
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -10780,7 +10442,7 @@
 }
 
 void
-hggroup::properties::update_limits (void) const
+hggroup::properties::update_limits () const
 {
   gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -11014,7 +10676,7 @@
 // ---------------------------------------------------------------------
 
 void
-uicontextmenu::properties::update_beingdeleted (void)
+uicontextmenu::properties::update_beingdeleted ()
 {
   // Clear the uicontextmenu property of dependent objects
   if (m_beingdeleted.is ("on"))
@@ -11064,7 +10726,7 @@
 // ---------------------------------------------------------------------
 
 octave_value
-uicontrol::properties::get_extent (void) const
+uicontrol::properties::get_extent () const
 {
   Matrix m = m_extent.get ().matrix_value ();
 
@@ -11079,7 +10741,7 @@
 }
 
 void
-uicontrol::properties::update_text_extent (void)
+uicontrol::properties::update_text_extent ()
 {
   // FIXME: support multiline text
 
@@ -11091,7 +10753,7 @@
 }
 
 void
-uicontrol::properties::update_units (void)
+uicontrol::properties::update_units ()
 {
   Matrix pos = get_position ().matrix_value ();
 
@@ -11829,14 +11491,14 @@
 }
 
 Matrix
-uitable::properties::get_backgroundcolor_rgb (void)
+uitable::properties::get_backgroundcolor_rgb ()
 {
   Matrix bg = m_backgroundcolor.get ().matrix_value ();
   return bg.row (0);
 }
 
 Matrix
-uitable::properties::get_alternatebackgroundcolor_rgb (void)
+uitable::properties::get_alternatebackgroundcolor_rgb ()
 {
   int i = 0;
   Matrix bg = m_backgroundcolor.get ().matrix_value ();
@@ -11847,13 +11509,13 @@
 }
 
 Matrix
-uitable::properties::get_extent_matrix (void) const
+uitable::properties::get_extent_matrix () const
 {
   return m_extent.get ().matrix_value ();
 }
 
 octave_value
-uitable::properties::get_extent (void) const
+uitable::properties::get_extent () const
 {
   // FIXME: Is it really acceptable to just let the toolkit update the extent?
   Matrix m = m_extent.get ().matrix_value ();
@@ -11895,7 +11557,7 @@
 }
 
 void
-uitoolbar::reset_default_properties (void)
+uitoolbar::reset_default_properties ()
 {
   // empty list of local defaults
   m_default_properties = property_list ();
@@ -11928,118 +11590,6 @@
   return parent_go.get_factory_default (type () + name);
 }
 
-// We use a random value for the handle to avoid issues with plots and
-// scalar values for the first argument.
-gh_manager::gh_manager (octave::interpreter& interp)
-  : m_interpreter (interp), m_handle_map (), m_handle_free_list (),
-    m_next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)),
-    m_figure_list (), m_graphics_lock (),  m_event_queue (),
-    m_callback_objects (), m_event_processing (0)
-{
-  m_handle_map[0] = graphics_object (new root_figure ());
-
-  octave::gtk_manager& gtk_mgr = octave::__get_gtk_manager__ ();
-
-  // Make sure the default graphics toolkit is registered.
-  gtk_mgr.default_toolkit ();
-}
-
-graphics_handle
-gh_manager::make_graphics_handle (const std::string& go_name,
-                                  const graphics_handle& p,
-                                  bool integer_figure_handle,
-                                  bool call_createfcn, bool notify_toolkit)
-{
-  graphics_handle h = get_handle (integer_figure_handle);
-
-  base_graphics_object *bgo = make_graphics_object_from_type (go_name, h, p);
-
-  if (! bgo)
-    error ("gh_manager::make_graphics_handle: invalid object type '%s'",
-           go_name.c_str ());
-
-  graphics_object go (bgo);
-
-  m_handle_map[h] = go;
-
-  if (go_name == "axes")
-    {
-      // Handle defaults for labels since overriding defaults for
-      // them can't work before the axes object is fully
-      // constructed.
-
-      axes::properties& props
-        = dynamic_cast<axes::properties&> (go.get_properties ());
-
-      graphics_object tgo;
-
-      tgo = get_object (props.get_xlabel ());
-      tgo.override_defaults ();
-
-      tgo = get_object (props.get_ylabel ());
-      tgo.override_defaults ();
-
-      tgo = get_object (props.get_zlabel ());
-      tgo.override_defaults ();
-
-      tgo = get_object (props.get_title ());
-      tgo.override_defaults ();
-    }
-
-  // Overriding defaults will work now because the handle is valid
-  // and we can find parent objects (not just handles).
-  go.override_defaults ();
-
-  if (call_createfcn)
-    bgo->get_properties ().execute_createfcn ();
-
-  // Notify graphics toolkit.
-  if (notify_toolkit)
-    go.initialize ();
-
-  return h;
-}
-
-graphics_handle
-gh_manager::make_figure_handle (double val, bool notify_toolkit)
-{
-  graphics_handle h = val;
-
-  base_graphics_object *bgo = new figure (h, 0);
-  graphics_object go (bgo);
-
-  m_handle_map[h] = go;
-
-  // Notify graphics toolkit.
-  if (notify_toolkit)
-    go.initialize ();
-
-  go.override_defaults ();
-
-  return h;
-}
-
-void
-gh_manager::push_figure (const graphics_handle& h)
-{
-  pop_figure (h);
-
-  m_figure_list.push_front (h);
-}
-
-void
-gh_manager::pop_figure (const graphics_handle& h)
-{
-  for (auto it = m_figure_list.begin (); it != m_figure_list.end (); it++)
-    {
-      if (*it == h)
-        {
-          m_figure_list.erase (it);
-          break;
-        }
-    }
-}
-
 class
 callback_event : public base_graphics_event
 {
@@ -12056,7 +11606,11 @@
     : base_graphics_event (busyaction), m_handle (h), m_callback_name (),
       m_callback (cb), m_callback_data (data) { }
 
-  void execute (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (callback_event)
+
+  ~callback_event () = default;
+
+  void execute ()
   {
     gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -12067,12 +11621,6 @@
   }
 
 private:
-  callback_event (void)
-    : base_graphics_event (), m_handle (), m_callback_name (),
-      m_callback_data ()
-  { }
-
-private:
   graphics_handle m_handle;
   std::string m_callback_name;
   octave_value m_callback;
@@ -12088,7 +11636,11 @@
     : base_graphics_event (busyaction), m_handle (h), m_mcode (cmd)
   { }
 
-  void execute (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mcode_event)
+
+  ~mcode_event () = default;
+
+  void execute ()
   {
     if (! m_mcode.empty ())
       {
@@ -12105,11 +11657,6 @@
   }
 
 private:
-  mcode_event (void)
-    : base_graphics_event (), m_handle (), m_mcode ()
-  { }
-
-private:
   graphics_handle m_handle;
   std::string m_mcode;
 };
@@ -12119,21 +11666,15 @@
 {
 public:
 
-  // function_event objects must be created with at least a function.
-
-  function_event (void) = delete;
-
   function_event (graphics_event::event_fcn fcn, void *data = nullptr)
     : base_graphics_event (), m_function (fcn), m_function_data (data)
   { }
 
-  // No copying!
-
-  function_event (const function_event&) = delete;
-
-  function_event& operator = (const function_event&) = delete;
-
-  void execute (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (function_event)
+
+  ~function_event () = default;
+
+  void execute ()
   {
     m_function (m_function_data);
   }
@@ -12157,7 +11698,11 @@
       m_redraw_figure (redraw_figure)
   { }
 
-  void execute (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (set_event)
+
+  ~set_event () = default;
+
+  void execute ()
   {
     gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -12209,11 +11754,6 @@
   }
 
 private:
-  set_event (void)
-    : base_graphics_event (), m_handle (), m_property_name (), m_property_value ()
-  { }
-
-private:
   graphics_handle m_handle;
   std::string m_property_name;
   octave_value m_property_value;
@@ -12264,375 +11804,8 @@
                                         redraw_figure));
 }
 
-static void
-xset_gcbo (const graphics_handle& h)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  graphics_object go = gh_mgr.get_object (0);
-
-  root_figure::properties& props
-    = dynamic_cast<root_figure::properties&> (go.get_properties ());
-
-  props.set_callbackobject (h.as_octave_value ());
-}
-
-void
-gh_manager::restore_gcbo (void)
-{
-  octave::autolock guard (m_graphics_lock);
-
-  m_callback_objects.pop_front ();
-
-  xset_gcbo (m_callback_objects.empty ()
-             ? graphics_handle () : m_callback_objects.front ().get_handle ());
-}
-
-void
-gh_manager::execute_listener (const graphics_handle& h, const octave_value& l)
-{
-  if (octave::thread::is_thread ())
-    execute_callback (h, l, octave_value ());
-  else
-    {
-      octave::autolock guard (m_graphics_lock);
-
-      post_event (graphics_event::create_callback_event (h, l));
-    }
-}
-
-void
-gh_manager::execute_callback (const graphics_handle& h,
-                              const octave_value& cb_arg,
-                              const octave_value& data)
-{
-  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 ();
-      if (data.is_defined ())
-        args(1) = data;
-      else
-        args(1) = Matrix ();
-
-      octave::unwind_action_safe restore_gcbo_action
-      (&gh_manager::restore_gcbo, this);
-
-      graphics_object go (get_object (h));
-      if (go)
-        {
-          // FIXME: Is the lock necessary when we're only calling a
-          //        const "get" method?
-          octave::autolock guard (m_graphics_lock);
-          m_callback_objects.push_front (go);
-          xset_gcbo (h);
-        }
-
-      // Copy CB because "function_value" method is non-const.
-      octave_value cb = cb_arg;
-
-      if (cb.is_function ())
-        fcn = cb.function_value ();
-      else if (cb.is_function_handle ())
-        ov_fcn = cb;
-      else if (cb.is_string ())
-        {
-          int status;
-          std::string s = cb.string_value ();
-
-          try
-            {
-              m_interpreter.eval_string (s, false, status, 0);
-            }
-          catch (const octave::execution_exception& ee)
-            {
-              m_interpreter.handle_exception (ee);
-            }
-        }
-      else if (cb.iscell () && cb.length () > 0
-               && (cb.rows () == 1 || cb.columns () == 1)
-               && (cb.cell_value ()(0).is_function ()
-                   || cb.cell_value ()(0).is_function_handle ()))
-        {
-          Cell c = cb.cell_value ();
-
-          ov_fcn = c(0);
-
-          for (int i = 1; i < c.numel () ; i++)
-            args(1+i) = c(i);
-        }
-      else
-        {
-          std::string nm = cb.class_name ();
-          error ("trying to execute non-executable object (class = %s)",
-                 nm.c_str ());
-        }
-
-      if (fcn || ov_fcn.is_defined ())
-        try
-          {
-            if (ov_fcn.is_defined ())
-              octave::feval (ov_fcn, args);
-            else
-              octave::feval (fcn, args);
-          }
-        catch (const octave::execution_exception& ee)
-          {
-            m_interpreter.handle_exception (ee);
-          }
-
-      // Redraw after interacting with a user-interface (ui*) object.
-      if (Vdrawnow_requested)
-        {
-          if (go)
-            {
-              std::string go_name
-                = go.get_properties ().graphics_object_name ();
-
-              if (go_name.length () > 1
-                  && go_name[0] == 'u' && go_name[1] == 'i')
-                {
-                  Fdrawnow (m_interpreter);
-                  Vdrawnow_requested = false;
-                }
-            }
-        }
-    }
-}
-
-static int
-process_graphics_events (void)
-{
-  gh_manager& gh_mgr = octave::__get_gh_manager__ ();
-
-  return gh_mgr.process_events ();
-}
-
-void
-gh_manager::post_event (const graphics_event& e)
-{
-  m_event_queue.push_back (e);
-
-  octave::command_editor::add_event_hook (process_graphics_events);
-}
-
-void
-gh_manager::post_callback (const graphics_handle& h, const std::string& name,
-                           const octave_value& data)
-{
-  octave::autolock guard (m_graphics_lock);
-
-  graphics_object go = get_object (h);
-
-  if (go.valid_object ())
-    {
-      caseless_str cname (name);
-      int busyaction = base_graphics_event::QUEUE;
-
-      if (cname == "deletefcn" || cname == "createfcn"
-          || cname == "closerequestfcn"
-          || ((go.isa ("figure") || go.isa ("uipanel")
-               || go.isa ("uibuttongroup"))
-              && (cname == "resizefcn" || cname == "sizechangedfcn")))
-        busyaction = base_graphics_event::INTERRUPT;
-      else if (go.get_properties ().get_busyaction () == "cancel")
-        busyaction = base_graphics_event::CANCEL;
-
-      // The "closerequestfcn" callback must be executed once the figure has
-      // been made current.  Let "close" do the job.
-      if (cname == "closerequestfcn")
-        {
-          std::string cmd ("close (gcbf ());");
-          post_event (graphics_event::create_mcode_event (h, cmd, busyaction));
-        }
-      else
-        post_event (graphics_event::create_callback_event (h, name, data,
-                    busyaction));
-    }
-}
-
-void
-gh_manager::post_function (graphics_event::event_fcn fcn, void *fcn_data)
-{
-  octave::autolock guard (m_graphics_lock);
-
-  post_event (graphics_event::create_function_event (fcn, fcn_data));
-}
-
-void
-gh_manager::post_set (const graphics_handle& h, const std::string& name,
-                      const octave_value& value, bool notify_toolkit,
-                      bool redraw_figure)
-{
-  octave::autolock guard (m_graphics_lock);
-
-  post_event (graphics_event::create_set_event (h, name, value, notify_toolkit,
-              redraw_figure));
-}
-
-int
-gh_manager::process_events (bool force)
-{
-  graphics_event e;
-  bool old_Vdrawnow_requested = Vdrawnow_requested;
-  bool events_executed = false;
-
-  do
-    {
-      e = graphics_event ();
-
-      {
-        octave::autolock guard (m_graphics_lock);
-
-        if (! m_event_queue.empty ())
-          {
-            if (m_callback_objects.empty () || force)
-              {
-                e = m_event_queue.front ();
-
-                m_event_queue.pop_front ();
-              }
-            else
-              {
-                const graphics_object& go = m_callback_objects.front ();
-
-                if (go.get_properties ().is_interruptible ())
-                  {
-                    e = m_event_queue.front ();
-
-                    m_event_queue.pop_front ();
-                  }
-                else
-                  {
-                    std::list<graphics_event>::iterator p = m_event_queue.begin ();
-
-                    while (p != m_event_queue.end ())
-                      if (p->get_busyaction () == base_graphics_event::CANCEL)
-                        {
-                          p = m_event_queue.erase (p);
-                        }
-                      else if (p->get_busyaction ()
-                               == base_graphics_event::INTERRUPT)
-                        {
-                          e = (*p);
-                          m_event_queue.erase (p);
-                          break;
-                        }
-                      else
-                        p++;
-                  }
-              }
-          }
-      }
-
-      if (e.ok ())
-        {
-          e.execute ();
-          events_executed = true;
-        }
-    }
-  while (e.ok ());
-
-  {
-    octave::autolock guard (m_graphics_lock);
-
-    if (m_event_queue.empty () && m_event_processing == 0)
-      octave::command_editor::remove_event_hook (process_graphics_events);
-  }
-
-  if (events_executed)
-    octave::flush_stdout ();
-
-  if (Vdrawnow_requested && ! old_Vdrawnow_requested)
-    {
-      Fdrawnow (m_interpreter);
-
-      Vdrawnow_requested = false;
-    }
-
-  return 0;
-}
-
-
-/*
-## Test interruptible/busyaction properties
-%!function cb (h, ~)
-%! setappdata (gcbf (), "cb_exec", [getappdata(gcbf (), "cb_exec") h]);
-%! drawnow ();
-%! setappdata (gcbf (), "cb_exec", [getappdata(gcbf (), "cb_exec") h]);
-%!endfunction
-%!
-%!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);
-%!   hui2 = uicontrol ("parent", hf, "busyaction", "queue", "callback", @cb);
-%!   hui3 = uicontrol ("parent", hf, "busyaction", "queue", "callback", @cb);
-%!   __go_post_callback__ (hui1, "callback");
-%!   __go_post_callback__ (hui2, "callback");
-%!   __go_post_callback__ (hui3, "callback");
-%!
-%!   assert (getappdata (hf, "cb_exec"), []);
-%!   drawnow ();
-%!   assert (getappdata (hf, "cb_exec"), [hui1 hui2 hui3 hui3 hui2 hui1]);
-%!
-%!   ## Interruptible off
-%!   setappdata (hf, "cb_exec", []);
-%!   set (hui1, "interruptible", "off");
-%!   __go_post_callback__ (hui1, "callback");
-%!   __go_post_callback__ (hui2, "callback");
-%!   __go_post_callback__ (hui3, "callback");
-%!   drawnow ();
-%!   assert (getappdata (hf, "cb_exec"), [hui1 hui1 hui2 hui3 hui3 hui2]);
-%!
-%!   ## "resizefcn" callback interrupts regardless of interruptible property
-%!   setappdata (hf, "cb_exec", []);
-%!   __go_post_callback__ (hui1, "callback");
-%!   __go_post_callback__ (hf, "resizefcn");
-%!   drawnow ();
-%!   assert (getappdata (hf, "cb_exec"), [hui1 hf hf hui1]);
-%!
-%!   ## test "busyaction" "cancel"
-%!   setappdata (hf, "cb_exec", []);
-%!   set (hui2, "busyaction", "cancel");
-%!   __go_post_callback__ (hui1, "callback");
-%!   __go_post_callback__ (hui2, "callback");
-%!   __go_post_callback__ (hui3, "callback");
-%!   __go_post_callback__ (hf, "resizefcn");
-%!   drawnow ();
-%!   assert (getappdata (hf, "cb_exec"), [hui1 hf hui3 hui3 hf hui1]);
-%! unwind_protect_cleanup
-%!   close (hf)
-%! end_unwind_protect
-*/
-
-void
-gh_manager::enable_event_processing (bool enable)
-{
-  octave::autolock guard (m_graphics_lock);
-
-  if (enable)
-    {
-      m_event_processing++;
-
-      octave::command_editor::add_event_hook (process_graphics_events);
-    }
-  else
-    {
-      m_event_processing--;
-
-      if (m_event_queue.empty () && m_event_processing == 0)
-        octave::command_editor::remove_event_hook (process_graphics_events);
-    }
-}
-
 property_list::plist_map_type
-root_figure::init_factory_properties (void)
+root_figure::init_factory_properties ()
 {
   property_list::plist_map_type plist_map;
 
@@ -12963,6 +12136,8 @@
 @end example
 @end itemize
 
+The three syntaxes for setting properties may appear in any combination.
+
 @code{set} is also used to query the list of values a named property will
 take.  @code{@var{clist} = set (@var{h}, "property")} will return the list
 of possible values for @qcode{"property"} in the cell list @var{clist}.
@@ -12975,7 +12150,10 @@
 property.  If no output variable is used then the list is formatted and
 printed to the screen.
 
-For example,
+When querying properties only a single graphics handle @var{h} for a single
+graphics object is permitted.
+
+Example Query
 
 @example
 @group
@@ -12991,23 +12169,85 @@
 @seealso{get}
 @end deftypefn */)
 {
-  gh_manager& gh_mgr = interp.get_gh_manager ();
-
-  octave::autolock guard (gh_mgr.graphics_lock ());
-
   int nargin = args.length ();
 
   if (nargin == 0)
     print_usage ();
 
-  octave_value retval;
-
   // get vector of graphics handles
   ColumnVector hcv = args(0).xvector_value ("set: H must be a graphics handle");
 
+  gh_manager& gh_mgr = interp.get_gh_manager ();
+
+  octave::autolock guard (gh_mgr.graphics_lock ());
+
+  octave_value retval;
+
+  // Process requests for default value(s)
+  if (nargin == 1)
+    {
+      if (hcv.numel () > 1)
+        error ("set: H must be a single graphics handle when querying properties");
+
+      graphics_object go = gh_mgr.get_object (hcv(0));
+      if (! go)
+        error ("set: invalid handle (= %g)", hcv(0));
+
+      if (nargout > 0)
+        retval = go.values_as_struct ();
+      else
+        {
+          std::string s = go.values_as_string ();
+
+          octave_stdout << s;
+        }
+
+      return retval;
+    }
+  else if (nargin == 2 && args(1).is_string ())
+    {
+      if (hcv.numel () > 1)
+        error ("set: H must be a single graphics handle when querying properties");
+
+      std::string property = args(1).string_value ();
+      std::transform (property.begin (), property.end (),
+                      property.begin (), tolower);
+
+      graphics_object go = gh_mgr.get_object (hcv(0));
+
+      if (! go)
+        error ("set: invalid handle (= %g)", hcv(0));
+
+      octave_map pmap = go.values_as_struct ();
+
+      if (go.has_readonly_property (property))
+        {
+          if (nargout > 0)
+            retval = Matrix ();
+          else
+            octave_stdout << "set: " << property << " is read-only"
+                          << std::endl;
+        }
+      else if (pmap.isfield (property))
+        {
+          if (nargout != 0)
+            retval = pmap.getfield (property)(0);
+          else
+            {
+              std::string s = go.value_as_string (property);
+
+              octave_stdout << s;
+            }
+        }
+      else
+        error (R"(set: unknown property "%s")", property.c_str ());
+
+      return retval;
+    }
+
   bool request_drawnow = false;
 
-  // loop over graphics objects
+  // Loop over graphics objects
   for (octave_idx_type n = 0; n < hcv.numel (); n++)
     {
       graphics_object go = gh_mgr.get_object (hcv(n));
@@ -13015,62 +12255,40 @@
       if (! go)
         error ("set: invalid handle (= %g)", hcv(n));
 
-      if (nargin == 3 && args(1).iscellstr () && args(2).iscell ())
-        {
-          if (args(2).cell_value ().rows () == 1)
-            go.set (args(1).cellstr_value (), args(2).cell_value (), 0);
-          else if (hcv.numel () == args(2).cell_value ().rows ())
-            go.set (args(1).cellstr_value (), args(2).cell_value (), n);
-          else
-            error ("set: number of graphics handles must match number of "
-                   "value rows (%" OCTAVE_IDX_TYPE_FORMAT " != "
-                   "%" OCTAVE_IDX_TYPE_FORMAT ")",
-                   hcv.numel (), args(2).cell_value ().rows ());
-        }
-      else if (nargin == 2 && args(1).isstruct ())
-        go.set (args(1).map_value ());
-      else if (nargin == 2 && args(1).is_string ())
-        {
-          std::string property = args(1).string_value ();
-          std::transform (property.begin (), property.end (),
-                          property.begin (), tolower);
-
-          octave_map pmap = go.values_as_struct ();
-
-          if (go.has_readonly_property (property))
-            if (nargout != 0)
-              retval = Matrix ();
-            else
-              octave_stdout << "set: " << property
-                            <<" is read-only" << std::endl;
-          else if (pmap.isfield (property))
-            {
-              if (nargout != 0)
-                retval = pmap.getfield (property)(0);
+      // Loop over input arguments
+      for (octave_idx_type i = 1; i < args.length (); )
+        {
+          if (args(i).is_string ())
+            {
+              if (i == nargin - 1)
+                error ("set: PROPERTY name must be followed by a VALUE");
+              const caseless_str pname = args(i).string_value ();
+              const octave_value val = args(i+1);
+              go.set_value_or_default (pname, val);
+              i += 2;
+            }
+          else if (args(i).iscellstr ())
+            {
+              if ((i == nargin - 1) || ! args(i+1).iscell ())
+                error ("set: cell array of PROPERTIES must be followed by cell array of VALUES");
+              if (args(i+1).cell_value ().rows () == 1)
+                go.set (args(i).cellstr_value (), args(i+1).cell_value (), 0);
+              else if (hcv.numel () == args(i+1).cell_value ().rows ())
+                go.set (args(i).cellstr_value (), args(i+1).cell_value (), n);
               else
-                {
-                  std::string s = go.value_as_string (property);
-
-                  octave_stdout << s;
-                }
+                error ("set: number of graphics handles must match number of "
+                       "value rows (%" OCTAVE_IDX_TYPE_FORMAT " != "
+                       "%" OCTAVE_IDX_TYPE_FORMAT ")",
+                       hcv.numel (), args(i+1).cell_value ().rows ());
+              i += 2;
+            }
+          else if (args(i).isstruct ())
+            {
+              go.set (args(i).map_value ());
+              i += 1;
             }
           else
-            error (R"(set: unknown property "%s")", property.c_str ());
-        }
-      else if (nargin == 1)
-        {
-          if (nargout != 0)
-            retval = go.values_as_struct ();
-          else
-            {
-              std::string s = go.values_as_string ();
-
-              octave_stdout << s;
-            }
-        }
-      else
-        {
-          go.set (args.splice (0, 1));
+            error ("set: invalid syntax");
         }
 
       request_drawnow = true;
@@ -13082,6 +12300,41 @@
   return retval;
 }
 
+/*
+## test setting ticklabels for compatibility
+%!test
+%! hf = figure ("visible", "off");
+%! set (gca (), "xticklabel", [0, 0.2, 0.4, 0.6, 0.8, 1]);
+%! xticklabel = get (gca (), "xticklabel");
+%! close (hf);
+%! assert (class (xticklabel), "char");
+%! assert (size (xticklabel), [6, 3]);
+
+%!test
+%! hf = figure ("visible", "off");
+%! set (gca (), "xticklabel", "0|0.2|0.4|0.6|0.8|1");
+%! xticklabel = get (gca (), "xticklabel");
+%! close (hf);
+%! assert (class (xticklabel), "char");
+%! assert (size (xticklabel), [6, 3]);
+
+%!test
+%! hf = figure ("visible", "off");
+%! set (gca (), "xticklabel", ["0 "; "0.2"; "0.4"; "0.6"; "0.8"; "1 "]);
+%! xticklabel = get (gca (), "xticklabel");
+%! close (hf);
+%! assert (class (xticklabel), "char");
+%! assert (size (xticklabel), [6, 3]);
+
+%!test
+%! hf = figure ("visible", "off");
+%! set (gca (), "xticklabel", {"0", "0.2", "0.4", "0.6", "0.8", "1"});
+%! xticklabel = get (gca (), "xticklabel");
+%! close (hf);
+%! assert (class (xticklabel), "cell");
+%! assert (size (xticklabel), [6, 1]);
+*/
+
 static std::string
 get_graphics_object_type (double val)
 {
@@ -13174,8 +12427,7 @@
       caseless_str property;
 
       if (nargin > 1)
-        property = args(
-                     1).xstring_value ("get: second argument must be property name or cell array of property names");
+        property = args(1).xstring_value ("get: second argument must be property name or cell array of property names");
 
       vals.resize (dim_vector (hcv_len, 1));
 
@@ -14031,9 +13283,7 @@
                 {
                   std::string dirname = file.substr (0, pos+1);
 
-                  octave::sys::file_stat fs (dirname);
-
-                  if (! fs || ! fs.is_dir ())
+                  if (! octave::sys::dir_exists (dirname))
                     error ("drawnow: nonexistent directory '%s'",
                            dirname.c_str ());
 
@@ -14332,14 +13582,15 @@
 }
 
 static bool
-compare_property_values (const octave_value& ov1, const octave_value& ov2)
+compare_property_values (octave::interpreter& interp,
+                         const octave_value& ov1, const octave_value& ov2)
 {
   octave_value_list args(2);
 
   args(0) = ov1;
   args(1) = ov2;
 
-  octave_value_list result = octave::feval ("isequal", args, 1);
+  octave_value_list result = interp.feval ("isequal", args, 1);
 
   if (result.length () > 0)
     return result(0).bool_value ();
@@ -14397,7 +13648,7 @@
 cleanup_waitfor_predelete_listener (const octave_value& listener)
 { do_cleanup_waitfor_listener (listener, GCB_PREDELETE); }
 
-DECLARE_STATIC_FUNX (waitfor_listener, args, )
+DECLARE_STATIC_METHODX (waitfor_listener, interp, args, )
 {
   if (args.length () > 3)
     {
@@ -14420,7 +13671,7 @@
               graphics_object go = gh_mgr.get_object (gh);
               octave_value pvalue = go.get (pname);
 
-              if (compare_property_values (pvalue, args(5)))
+              if (compare_property_values (interp, pvalue, args(5)))
                 waitfor_results[id] = true;
             }
         }
@@ -14574,7 +13825,7 @@
               graphics_object go = gh_mgr.get_object (gh);
 
               if (max_arg_index >= 2
-                  && compare_property_values (go.get (pname), args(2)))
+                  && compare_property_values (interp, go.get (pname), args(2)))
                 waitfor_results[id] = true;
               else
                 {
--- a/libinterp/corefcn/graphics.in.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/graphics.in.h	Fri Jun 23 20:51:51 2023 +0200
@@ -66,9 +66,10 @@
 class OCTINTERP_API base_scaler
 {
 public:
-  base_scaler (void) { }
-
-  virtual ~base_scaler (void) = default;
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (base_scaler)
+
+  virtual ~base_scaler () = default;
 
   virtual Matrix scale (const Matrix&) const
   {
@@ -93,14 +94,15 @@
   virtual base_scaler * clone () const
   { return new base_scaler (); }
 
-  virtual bool is_linear (void) const
+  virtual bool is_linear () const
   { return false; }
 };
 
 class lin_scaler : public base_scaler
 {
 public:
-  lin_scaler (void) { }
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (lin_scaler)
 
   Matrix scale (const Matrix& m) const { return m; }
 
@@ -110,15 +112,16 @@
 
   double unscale (double d) const { return d; }
 
-  base_scaler * clone (void) const { return new lin_scaler (); }
-
-  bool is_linear (void) const { return true; }
+  base_scaler * clone () const { return new lin_scaler (); }
+
+  bool is_linear () const { return true; }
 };
 
 class log_scaler : public base_scaler
 {
 public:
-  log_scaler (void) { }
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (log_scaler)
 
   Matrix scale (const Matrix& m) const
   {
@@ -144,7 +147,7 @@
   double unscale (double d) const
   { return std::pow (10.0, d); }
 
-  base_scaler * clone (void) const
+  base_scaler * clone () const
   { return new log_scaler (); }
 
 private:
@@ -158,7 +161,8 @@
 class OCTINTERP_API neg_log_scaler : public base_scaler
 {
 public:
-  neg_log_scaler (void) { }
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (neg_log_scaler)
 
   Matrix scale (const Matrix& m) const
   {
@@ -184,7 +188,7 @@
   double unscale (double d) const
   { return -std::pow (10.0, -d); }
 
-  base_scaler * clone (void) const
+  base_scaler * clone () const
   { return new neg_log_scaler (); }
 
 private:
@@ -198,7 +202,8 @@
 class OCTINTERP_API scaler
 {
 public:
-  scaler (void) : m_rep (new base_scaler ()) { }
+
+  scaler () : m_rep (new base_scaler ()) { }
 
   scaler (const scaler& s) : m_rep (s.m_rep->clone ()) { }
 
@@ -212,7 +217,7 @@
                    : new base_scaler ())))
   { }
 
-  ~scaler (void) { delete m_rep; }
+  ~scaler () { delete m_rep; }
 
   Matrix scale (const Matrix& m) const
   { return m_rep->scale (m); }
@@ -226,7 +231,7 @@
   double unscale (double d) const
   { return m_rep->unscale (d); }
 
-  bool is_linear (void) const
+  bool is_linear () const
   { return m_rep->is_linear (); }
 
   scaler& operator = (const scaler& s)
@@ -286,7 +291,7 @@
   friend class property;
 
 public:
-  base_property (void)
+  base_property ()
     : m_id (-1), m_count (1), m_name (), m_parent (), m_hidden (),
       m_listeners ()
   { }
@@ -301,25 +306,28 @@
       m_hidden (p.m_hidden), m_listeners ()
   { }
 
-  virtual ~base_property (void) = default;
-
-  bool ok (void) const { return m_parent.ok (); }
-
-  std::string get_name (void) const { return m_name; }
+  // FIXME: should we define assignment?
+  base_property& operator = (const base_property&) = delete;
+
+  virtual ~base_property () = default;
+
+  bool ok () const { return m_parent.ok (); }
+
+  std::string get_name () const { return m_name; }
 
   void set_name (const std::string& s) { m_name = s; }
 
-  graphics_handle get_parent (void) const { return m_parent; }
+  graphics_handle get_parent () const { return m_parent; }
 
   void set_parent (const graphics_handle& h) { m_parent = h; }
 
-  bool is_hidden (void) const { return m_hidden; }
+  bool is_hidden () const { return m_hidden; }
 
   void set_hidden (bool flag) { m_hidden = flag; }
 
-  virtual bool is_radio (void) const { return false; }
-
-  int get_id (void) const { return m_id; }
+  virtual bool is_radio () const { return false; }
+
+  int get_id () const { return m_id; }
 
   void set_id (int d) { m_id = d; }
 
@@ -328,17 +336,17 @@
   OCTINTERP_API bool set (const octave_value& v, bool do_run = true,
                           bool do_notify_toolkit = true);
 
-  virtual octave_value get (void) const
+  virtual octave_value get () const
   {
     error (R"(get: invalid property "%s")", m_name.c_str ());
   }
 
-  virtual std::string values_as_string (void) const
+  virtual std::string values_as_string () const
   {
     error (R"(values_as_string: invalid property "%s")", m_name.c_str ());
   }
 
-  virtual Cell values_as_cell (void) const
+  virtual Cell values_as_cell () const
   {
     error (R"(values_as_cell: invalid property "%s")", m_name.c_str ());
   }
@@ -408,7 +416,7 @@
 
   OCTINTERP_API void run_listeners (listener_mode mode = GCB_POSTSET);
 
-  virtual base_property * clone (void) const
+  virtual base_property * clone () const
   { return new base_property (*this); }
 
 protected:
@@ -438,17 +446,24 @@
 class OCTINTERP_API string_property : public base_property
 {
 public:
+
+  string_property () = delete;
+
   string_property (const std::string& s, const graphics_handle& h,
                    const std::string& val = "")
     : base_property (s, h), m_str (val) { }
 
-  string_property (const string_property& p)
-    : base_property (p), m_str (p.m_str) { }
-
-  octave_value get (void) const
+  string_property (const string_property&) = default;
+
+  // FIXME: should we define assignment?
+  string_property& operator = (const string_property&) = delete;
+
+  ~string_property () = default;
+
+  octave_value get () const
   { return octave_value (m_str); }
 
-  std::string string_value (void) const { return m_str; }
+  std::string string_value () const { return m_str; }
 
   string_property& operator = (const octave_value& val)
   {
@@ -456,7 +471,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new string_property (*this); }
+  base_property * clone () const { return new string_property (*this); }
 
 protected:
   bool do_set (const octave_value& val)
@@ -486,6 +501,8 @@
 public:
   enum desired_enum { string_t, cell_t };
 
+  string_array_property () = delete;
+
   string_array_property (const std::string& s, const graphics_handle& h,
                          const std::string& val = "", const char& sep = '|',
                          const desired_enum& typ = string_t)
@@ -526,11 +543,14 @@
     m_str = strings;
   }
 
-  string_array_property (const string_array_property& p)
-    : base_property (p), m_desired_type (p.m_desired_type),
-      m_separator (p.m_separator), m_str (p.m_str) { }
-
-  octave_value get (void) const
+  string_array_property (const string_array_property&) = default;
+
+  // FIXME: should we define assignment?
+  string_array_property& operator = (const string_array_property&) = delete;
+
+  ~string_array_property () = default;
+
+  octave_value get () const
   {
     if (m_desired_type == string_t)
       return octave_value (string_value ());
@@ -538,7 +558,7 @@
       return octave_value (cell_value ());
   }
 
-  std::string string_value (void) const
+  std::string string_value () const
   {
     std::string s;
 
@@ -552,9 +572,9 @@
     return s;
   }
 
-  Cell cell_value (void) const {return Cell (m_str);}
-
-  string_vector string_vector_value (void) const { return m_str; }
+  Cell cell_value () const {return Cell (m_str);}
+
+  string_vector string_vector_value () const { return m_str; }
 
   string_array_property& operator = (const octave_value& val)
   {
@@ -562,7 +582,7 @@
     return *this;
   }
 
-  base_property * clone (void) const
+  base_property * clone () const
   { return new string_array_property (*this); }
 
 protected:
@@ -686,6 +706,8 @@
 public:
   enum type { char_t, cellstr_t };
 
+  text_label_property () = delete;
+
   text_label_property (const std::string& s, const graphics_handle& h,
                        const std::string& val = "")
     : base_property (s, h), m_value (val), m_stored_type (char_t)
@@ -732,17 +754,20 @@
       }
   }
 
-  text_label_property (const text_label_property& p)
-    : base_property (p), m_value (p.m_value), m_stored_type (p.m_stored_type)
-  { }
-
-  bool empty (void) const
+  text_label_property (const text_label_property&) = default;
+
+  // FIXME: should we define assignment?
+  text_label_property& operator = (const text_label_property&) = delete;
+
+  ~text_label_property () = default;
+
+  bool empty () const
   {
     octave_value tmp = get ();
     return tmp.isempty ();
   }
 
-  octave_value get (void) const
+  octave_value get () const
   {
     if (m_stored_type == char_t)
       return octave_value (char_value ());
@@ -750,16 +775,16 @@
       return octave_value (cell_value ());
   }
 
-  std::string string_value (void) const
+  std::string string_value () const
   {
     return m_value.empty () ? "" : m_value[0];
   }
 
-  string_vector string_vector_value (void) const { return m_value; }
-
-  charMatrix char_value (void) const { return charMatrix (m_value, ' '); }
-
-  Cell cell_value (void) const {return Cell (m_value); }
+  string_vector string_vector_value () const { return m_value; }
+
+  charMatrix char_value () const { return charMatrix (m_value, ' '); }
+
+  Cell cell_value () const {return Cell (m_value); }
 
   text_label_property& operator = (const octave_value& val)
   {
@@ -767,7 +792,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new text_label_property (*this); }
+  base_property * clone () const { return new text_label_property (*this); }
 
 protected:
 
@@ -848,21 +873,9 @@
 public:
   OCTINTERP_API radio_values (const std::string& opt_string = "");
 
-  radio_values (const radio_values& a)
-    : m_default_val (a.m_default_val), m_possible_vals (a.m_possible_vals) { }
-
-  radio_values& operator = (const radio_values& a)
-  {
-    if (&a != this)
-      {
-        m_default_val = a.m_default_val;
-        m_possible_vals = a.m_possible_vals;
-      }
-
-    return *this;
-  }
-
-  std::string default_value (void) const { return m_default_val; }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (radio_values)
+
+  std::string default_value () const { return m_default_val; }
 
   bool validate (const std::string& val, std::string& match)
   {
@@ -913,11 +926,11 @@
       return false;
   }
 
-  OCTINTERP_API std::string values_as_string (void) const;
-
-  OCTINTERP_API Cell values_as_cell (void) const;
-
-  octave_idx_type nelem (void) const { return m_possible_vals.size (); }
+  OCTINTERP_API std::string values_as_string () const;
+
+  OCTINTERP_API Cell values_as_cell () const;
+
+  octave_idx_type nelem () const { return m_possible_vals.size (); }
 
 private:
   // Might also want to cache
@@ -928,6 +941,9 @@
 class OCTINTERP_API radio_property : public base_property
 {
 public:
+
+  radio_property () = delete;
+
   radio_property (const std::string& nm, const graphics_handle& h,
                   const radio_values& v = radio_values ())
     : base_property (nm, h),
@@ -943,22 +959,24 @@
     : base_property (nm, h),
       m_vals (v), m_current_val (def) { }
 
-  radio_property (const radio_property& p)
-    : base_property (p), m_vals (p.m_vals), m_current_val (p.m_current_val) { }
-
-  octave_value get (void) const { return octave_value (m_current_val); }
-
-  const std::string& current_value (void) const { return m_current_val; }
-
-  std::string values_as_string (void) const
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (radio_property)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (radio_property)
+
+  ~radio_property () = default;
+
+  octave_value get () const { return octave_value (m_current_val); }
+
+  const std::string& current_value () const { return m_current_val; }
+
+  std::string values_as_string () const
   { return m_vals.values_as_string (); }
 
-  Cell values_as_cell (void) const { return m_vals.values_as_cell (); }
+  Cell values_as_cell () const { return m_vals.values_as_cell (); }
 
   bool is (const caseless_str& v) const
   { return v.compare (m_current_val); }
 
-  bool is_radio (void) const { return true; }
+  bool is_radio () const { return true; }
 
   radio_property& operator = (const octave_value& val)
   {
@@ -966,7 +984,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new radio_property (*this); }
+  base_property * clone () const { return new radio_property (*this); }
 
 protected:
   bool do_set (const octave_value& newval)
@@ -1023,17 +1041,7 @@
       error ("invalid color specification: %s", str.c_str ());
   }
 
-  color_values (const color_values& c)
-    : m_rgb (c.m_rgb)
-  { }
-
-  color_values& operator = (const color_values& c)
-  {
-    if (&c != this)
-      m_rgb = c.m_rgb;
-
-    return *this;
-  }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (color_values)
 
   bool operator == (const color_values& c) const
   {
@@ -1045,11 +1053,11 @@
   bool operator != (const color_values& c) const
   { return ! (*this == c); }
 
-  Matrix rgb (void) const { return m_rgb; }
-
-  operator octave_value (void) const { return m_rgb; }
-
-  void validate (void) const
+  Matrix rgb () const { return m_rgb; }
+
+  operator octave_value () const { return m_rgb; }
+
+  void validate () const
   {
     for (int i = 0; i < 3; i++)
       {
@@ -1067,6 +1075,9 @@
 class OCTINTERP_API color_property : public base_property
 {
 public:
+
+  color_property () = delete;
+
   color_property (const color_values& c, const radio_values& v)
     : base_property ("", graphics_handle ()),
       m_current_type (color_t), m_color_val (c), m_radio_val (v),
@@ -1108,12 +1119,12 @@
       m_radio_val (v.m_radio_val), m_current_val (v.m_current_val)
   { }
 
-  color_property (const color_property& p)
-    : base_property (p), m_current_type (p.m_current_type),
-      m_color_val (p.m_color_val), m_radio_val (p.m_radio_val),
-      m_current_val (p.m_current_val) { }
-
-  octave_value get (void) const
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (color_property)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (color_property)
+
+  ~color_property () = default;
+
+  octave_value get () const
   {
     if (m_current_type == color_t)
       return m_color_val.rgb ();
@@ -1121,14 +1132,14 @@
     return m_current_val;
   }
 
-  bool is_rgb (void) const { return (m_current_type == color_t); }
-
-  bool is_radio (void) const { return (m_current_type == radio_t); }
+  bool is_rgb () const { return (m_current_type == color_t); }
+
+  bool is_radio () const { return (m_current_type == radio_t); }
 
   bool is (const std::string& v) const
   { return (is_radio () && m_current_val == v); }
 
-  Matrix rgb (void) const
+  Matrix rgb () const
   {
     if (m_current_type != color_t)
       error ("color has no RGB value");
@@ -1136,7 +1147,7 @@
     return m_color_val.rgb ();
   }
 
-  const std::string& current_value (void) const
+  const std::string& current_value () const
   {
     if (m_current_type != radio_t)
       error ("color has no radio value");
@@ -1150,14 +1161,14 @@
     return *this;
   }
 
-  operator octave_value (void) const { return get (); }
-
-  base_property * clone (void) const { return new color_property (*this); }
-
-  std::string values_as_string (void) const
+  operator octave_value () const { return get (); }
+
+  base_property * clone () const { return new color_property (*this); }
+
+  std::string values_as_string () const
   { return m_radio_val.values_as_string (); }
 
-  Cell values_as_cell (void) const { return m_radio_val.values_as_cell (); }
+  Cell values_as_cell () const { return m_radio_val.values_as_cell (); }
 
 protected:
   OCTINTERP_API bool do_set (const octave_value& newval);
@@ -1182,6 +1193,9 @@
 class OCTINTERP_API double_property : public base_property
 {
 public:
+
+  double_property () = delete;
+
   double_property (const std::string& nm, const graphics_handle& h,
                    double d = 0)
     : base_property (nm, h),
@@ -1195,9 +1209,14 @@
       m_minval (std::pair<double, bool> (octave_NaN, true)),
       m_maxval (std::pair<double, bool> (octave_NaN, true)) { }
 
-  octave_value get (void) const { return octave_value (m_current_val); }
-
-  double double_value (void) const { return m_current_val; }
+  // FIXME: should we define assignment?
+  double_property& operator = (const double_property&) = delete;
+
+  ~double_property () = default;
+
+  octave_value get () const { return octave_value (m_current_val); }
+
+  double double_value () const { return m_current_val; }
 
   double_property& operator = (const octave_value& val)
   {
@@ -1205,7 +1224,7 @@
     return *this;
   }
 
-  base_property * clone (void) const
+  base_property * clone () const
   {
     double_property *p = new double_property (*this);
 
@@ -1294,6 +1313,9 @@
 class OCTINTERP_API double_radio_property : public base_property
 {
 public:
+
+  double_radio_property () = delete;
+
   double_radio_property (double d, const radio_values& v)
     : base_property ("", graphics_handle ()),
       m_current_type (double_t), m_dval (d), m_radio_val (v),
@@ -1314,12 +1336,12 @@
       m_radio_val (v.m_radio_val), m_current_val (v.m_current_val)
   { }
 
-  double_radio_property (const double_radio_property& p)
-    : base_property (p), m_current_type (p.m_current_type),
-      m_dval (p.m_dval), m_radio_val (p.m_radio_val),
-      m_current_val (p.m_current_val) { }
-
-  octave_value get (void) const
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (double_radio_property)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (double_radio_property)
+
+  ~double_radio_property () = default;
+
+  octave_value get () const
   {
     if (m_current_type == double_t)
       return m_dval;
@@ -1327,14 +1349,14 @@
     return m_current_val;
   }
 
-  bool is_double (void) const { return (m_current_type == double_t); }
-
-  bool is_radio (void) const { return (m_current_type == radio_t); }
+  bool is_double () const { return (m_current_type == double_t); }
+
+  bool is_radio () const { return (m_current_type == radio_t); }
 
   bool is (const std::string& v) const
   { return (is_radio () && m_current_val == v); }
 
-  double double_value (void) const
+  double double_value () const
   {
     if (m_current_type != double_t)
       error ("%s: property has no double", get_name ().c_str ());
@@ -1342,7 +1364,7 @@
     return m_dval;
   }
 
-  const std::string& current_value (void) const
+  const std::string& current_value () const
   {
     if (m_current_type != radio_t)
       error ("%s: property has no radio value", get_name ().c_str ());
@@ -1356,9 +1378,9 @@
     return *this;
   }
 
-  operator octave_value (void) const { return get (); }
-
-  base_property * clone (void) const
+  operator octave_value () const { return get (); }
+
+  base_property * clone () const
   { return new double_radio_property (*this); }
 
 protected:
@@ -1376,7 +1398,7 @@
 class OCTINTERP_API array_property : public base_property
 {
 public:
-  array_property (void)
+  array_property ()
     : base_property ("", graphics_handle ()), m_data (Matrix ()),
       m_min_val (), m_max_val (), m_min_pos (), m_max_neg (),
       m_type_constraints (), m_size_constraints (),
@@ -1412,7 +1434,12 @@
       m_maxval (std::pair<double, bool> (octave_NaN, true))
   { }
 
-  octave_value get (void) const { return m_data; }
+  // FIXME: Should we define assignment?
+  array_property& operator = (const array_property&) = delete;
+
+  ~array_property () = default;
+
+  octave_value get () const { return m_data; }
 
   void add_constraint (const std::string& type)
   { m_type_constraints.insert (type); }
@@ -1431,12 +1458,12 @@
       m_maxval = std::pair<double, bool> (val, inclusive);
   }
 
-  double min_val (void) const { return m_min_val; }
-  double max_val (void) const { return m_max_val; }
-  double min_pos (void) const { return m_min_pos; }
-  double max_neg (void) const { return m_max_neg; }
-
-  Matrix get_limits (void) const
+  double min_val () const { return m_min_val; }
+  double max_val () const { return m_max_val; }
+  double min_pos () const { return m_min_pos; }
+  double max_neg () const { return m_max_neg; }
+
+  Matrix get_limits () const
   {
     Matrix m (1, 4);
 
@@ -1454,7 +1481,7 @@
     return *this;
   }
 
-  base_property * clone (void) const
+  base_property * clone () const
   {
     array_property *p = new array_property (*this);
 
@@ -1494,7 +1521,7 @@
 
   OCTINTERP_API bool is_equal (const octave_value& v) const;
 
-  OCTINTERP_API void get_data_limits (void);
+  OCTINTERP_API void get_data_limits ();
 
 protected:
   octave_value m_data;
@@ -1511,6 +1538,9 @@
 class OCTINTERP_API row_vector_property : public array_property
 {
 public:
+
+  row_vector_property () = delete;
+
   row_vector_property (const std::string& nm, const graphics_handle& h,
                        const octave_value& m)
     : array_property (nm, h, m)
@@ -1528,6 +1558,11 @@
     add_constraint (dim_vector (0, 0));
   }
 
+  // FIXME: should we define assignment?
+  row_vector_property& operator = (const row_vector_property&) = delete;
+
+  ~row_vector_property () = default;
+
   void add_constraint (const std::string& type)
   {
     array_property::add_constraint (type);
@@ -1564,7 +1599,7 @@
     return *this;
   }
 
-  base_property * clone (void) const
+  base_property * clone () const
   {
     row_vector_property *p = new row_vector_property (*this);
 
@@ -1605,6 +1640,9 @@
 class OCTINTERP_API bool_property : public radio_property
 {
 public:
+
+  bool_property () = delete;
+
   bool_property (const std::string& nm, const graphics_handle& h,
                  bool val)
     : radio_property (nm, h, radio_values (val ? "{on}|off" : "on|{off}"))
@@ -1616,10 +1654,12 @@
                                            "{on}|off" : "on|{off}"), val)
   { }
 
-  bool_property (const bool_property& p)
-    : radio_property (p) { }
-
-  bool is_on (void) const { return is ("on"); }
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (bool_property)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (bool_property)
+
+  ~bool_property () = default;
+
+  bool is_on () const { return is ("on"); }
 
   bool_property& operator = (const octave_value& val)
   {
@@ -1627,7 +1667,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new bool_property (*this); }
+  base_property * clone () const { return new bool_property (*this); }
 
 protected:
   bool do_set (const octave_value& val)
@@ -1644,17 +1684,24 @@
 class OCTINTERP_API handle_property : public base_property
 {
 public:
+
+  handle_property () = delete;
+
   handle_property (const std::string& nm, const graphics_handle& h,
                    const graphics_handle& val = graphics_handle ())
     : base_property (nm, h),
       m_current_val (val) { }
 
-  handle_property (const handle_property& p)
-    : base_property (p), m_current_val (p.m_current_val) { }
-
-  octave_value get (void) const { return m_current_val.as_octave_value (); }
-
-  graphics_handle handle_value (void) const { return m_current_val; }
+  handle_property (const handle_property&) = default;
+
+  // FIXME: should we define assignment?
+  handle_property& operator = (const handle_property&) = delete;
+
+  ~handle_property () = default;
+
+  octave_value get () const { return m_current_val.as_octave_value (); }
+
+  graphics_handle handle_value () const { return m_current_val; }
 
   handle_property& operator = (const octave_value& val)
   {
@@ -1668,10 +1715,10 @@
     return *this;
   }
 
-  void invalidate (void)
+  void invalidate ()
   { m_current_val = octave::numeric_limits<double>::NaN (); }
 
-  base_property * clone (void) const { return new handle_property (*this); }
+  base_property * clone () const { return new handle_property (*this); }
 
   void add_constraint (const std::string& type)
   { m_type_constraints.insert (type); }
@@ -1689,14 +1736,19 @@
 class OCTINTERP_API any_property : public base_property
 {
 public:
+
+  any_property () = delete;
+
   any_property (const std::string& nm, const graphics_handle& h,
                 const octave_value& m = Matrix ())
     : base_property (nm, h), m_data (m) { }
 
-  any_property (const any_property& p)
-    : base_property (p), m_data (p.m_data) { }
-
-  octave_value get (void) const { return m_data; }
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (any_property)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (any_property)
+
+  ~any_property () = default;
+
+  octave_value get () const { return m_data; }
 
   any_property& operator = (const octave_value& val)
   {
@@ -1704,7 +1756,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new any_property (*this); }
+  base_property * clone () const { return new any_property (*this); }
 
 protected:
   bool do_set (const octave_value& v)
@@ -1722,7 +1774,7 @@
 class OCTINTERP_API children_property : public base_property
 {
 public:
-  children_property (void)
+  children_property ()
     : base_property ("", graphics_handle ()), m_children_list ()
   {
     do_init_children (Matrix ());
@@ -1747,7 +1799,12 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new children_property (*this); }
+  // FIXME: should we define assignment?
+  children_property& operator = (const children_property&) = delete;
+
+  ~children_property () = default;
+
+  base_property * clone () const { return new children_property (*this); }
 
   bool remove_child (double val)
   {
@@ -1759,22 +1816,22 @@
     do_adopt_child (val);
   }
 
-  Matrix get_children (void) const
+  Matrix get_children () const
   {
     return do_get_children (false);
   }
 
-  Matrix get_hidden (void) const
+  Matrix get_hidden () const
   {
     return do_get_children (true);
   }
 
-  Matrix get_all (void) const
+  Matrix get_all () const
   {
     return do_get_all_children ();
   }
 
-  octave_value get (void) const
+  octave_value get () const
   {
     return octave_value (get_children ());
   }
@@ -1877,7 +1934,7 @@
 
   OCTINTERP_API Matrix do_get_children (bool return_hidden) const;
 
-  Matrix do_get_all_children (void) const
+  Matrix do_get_all_children () const
   {
     Matrix retval (m_children_list.size (), 1);
     octave_idx_type i = 0;
@@ -1914,18 +1971,25 @@
 class OCTINTERP_API callback_property : public base_property
 {
 public:
+
+  callback_property () = delete;
+
   callback_property (const std::string& nm, const graphics_handle& h,
                      const octave_value& m)
     : base_property (nm, h), m_callback (m) { }
 
-  callback_property (const callback_property& p)
-    : base_property (p), m_callback (p.m_callback) { }
-
-  octave_value get (void) const { return m_callback; }
+  callback_property (const callback_property&) = default;
+
+  // FIXME: should we define assignment?
+  callback_property& operator = (const callback_property&) = delete;
+
+  ~callback_property () = default;
+
+  octave_value get () const { return m_callback; }
 
   OCTINTERP_API void execute (const octave_value& data = octave_value ()) const;
 
-  bool is_defined (void) const
+  bool is_defined () const
   {
     return (m_callback.is_defined () && ! m_callback.isempty ());
   }
@@ -1936,7 +2000,7 @@
     return *this;
   }
 
-  base_property * clone (void) const { return new callback_property (*this); }
+  base_property * clone () const { return new callback_property (*this); }
 
 protected:
   bool do_set (const octave_value& v)
@@ -1962,7 +2026,7 @@
 class OCTINTERP_API property
 {
 public:
-  property (void) : m_rep (new base_property ("", graphics_handle ()))
+  property () : m_rep (new base_property ("", graphics_handle ()))
   { }
 
   property (base_property *bp, bool persist = false) : m_rep (bp)
@@ -1973,53 +2037,53 @@
     m_rep->m_count++;
   }
 
-  ~property (void)
+  ~property ()
   {
     if (--m_rep->m_count == 0)
       delete m_rep;
   }
 
-  bool ok (void) const
+  bool ok () const
   { return m_rep->ok (); }
 
-  std::string get_name (void) const
+  std::string get_name () const
   { return m_rep->get_name (); }
 
   void set_name (const std::string& name)
   { m_rep->set_name (name); }
 
-  graphics_handle get_parent (void) const
+  graphics_handle get_parent () const
   { return m_rep->get_parent (); }
 
   void set_parent (const graphics_handle& h)
   { m_rep->set_parent (h); }
 
-  bool is_hidden (void) const
+  bool is_hidden () const
   { return m_rep->is_hidden (); }
 
   void set_hidden (bool flag)
   { m_rep->set_hidden (flag); }
 
-  bool is_radio (void) const
+  bool is_radio () const
   { return m_rep->is_radio (); }
 
-  int get_id (void) const
+  int get_id () const
   { return m_rep->get_id (); }
 
   void set_id (int d)
   { m_rep->set_id (d); }
 
-  octave_value get (void) const
+  octave_value get () const
   { return m_rep->get (); }
 
   bool set (const octave_value& val, bool do_run = true,
             bool do_notify_toolkit = true)
   { return m_rep->set (val, do_run, do_notify_toolkit); }
 
-  std::string values_as_string (void) const
+  std::string values_as_string () const
   { return m_rep->values_as_string (); }
 
-  Cell values_as_cell (void) const
+  Cell values_as_cell () const
   { return m_rep->values_as_cell (); }
 
   property& operator = (const octave_value& val)
@@ -2053,29 +2117,9 @@
   create (const std::string& name, const graphics_handle& parent,
           const caseless_str& type, const octave_value_list& args);
 
-  property clone (void) const
+  property clone () const
   { return property (m_rep->clone ()); }
 
-#if 0
-  const string_property& as_string_property (void) const
-  { return *(dynamic_cast<string_property *> (m_rep)); }
-
-  const radio_property& as_radio_property (void) const
-  { return *(dynamic_cast<radio_property *> (m_rep)); }
-
-  const color_property& as_color_property (void) const
-  { return *(dynamic_cast<color_property *> (m_rep)); }
-
-  const double_property& as_double_property (void) const
-  { return *(dynamic_cast<double_property *> (m_rep)); }
-
-  const bool_property& as_bool_property (void) const
-  { return *(dynamic_cast<bool_property *> (m_rep)); }
-
-  const handle_property& as_handle_property (void) const
-  { return *(dynamic_cast<handle_property *> (m_rep)); }
-#endif
-
 private:
   base_property *m_rep;
 };
@@ -2163,17 +2207,17 @@
   property_list (const plist_map_type& m = plist_map_type ())
     : m_plist_map (m) { }
 
-  ~property_list (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (property_list)
 
   OCTINTERP_API void set (const caseless_str& name, const octave_value& val);
 
   OCTINTERP_API octave_value lookup (const caseless_str& name) const;
 
-  plist_map_iterator begin (void) { return m_plist_map.begin (); }
-  plist_map_const_iterator begin (void) const { return m_plist_map.begin (); }
-
-  plist_map_iterator end (void) { return m_plist_map.end (); }
-  plist_map_const_iterator end (void) const { return m_plist_map.end (); }
+  plist_map_iterator begin () { return m_plist_map.begin (); }
+  plist_map_const_iterator begin () const { return m_plist_map.begin (); }
+
+  plist_map_iterator end () { return m_plist_map.end (); }
+  plist_map_const_iterator end () const { return m_plist_map.end (); }
 
   plist_map_iterator find (const std::string& go_name)
   {
@@ -2204,11 +2248,13 @@
                    const graphics_handle& mh = graphics_handle (),
                    const graphics_handle& p = graphics_handle ());
 
-  virtual ~base_properties (void) = default;
-
-  virtual std::string graphics_object_name (void) const { return "unknown"; }
-
-  OCTINTERP_API void mark_modified (void);
+  OCTAVE_DISABLE_COPY_MOVE (base_properties)
+
+  virtual ~base_properties () = default;
+
+  virtual std::string graphics_object_name () const { return "unknown"; }
+
+  OCTINTERP_API void mark_modified ();
 
   OCTINTERP_API void override_defaults (base_graphics_object& obj);
 
@@ -2257,7 +2303,7 @@
     return false;
   }
 
-  bool is_modified (void) const { return is___modified__ (); }
+  bool is_modified () const { return is___modified__ (); }
 
   virtual void remove_child (const graphics_handle& h, bool = false)
   {
@@ -2275,14 +2321,14 @@
     mark_modified ();
   }
 
-  virtual octave::graphics_toolkit get_toolkit (void) const;
+  virtual octave::graphics_toolkit get_toolkit () const;
 
   virtual Matrix
   get_boundingbox (bool /* finternal */ = false,
                    const Matrix& /* parent_pix_size */ = Matrix ()) const
   { return Matrix (1, 4, 0.0); }
 
-  virtual void update_boundingbox (void);
+  virtual void update_boundingbox ();
 
   virtual void update_autopos (const std::string& elem_type);
 
@@ -2302,17 +2348,17 @@
 
   OCTINTERP_API void set_parent (const octave_value& val);
 
-  Matrix get_children (void) const
+  Matrix get_children () const
   {
     return m_children.get_children ();
   }
 
-  Matrix get_all_children (void) const
+  Matrix get_all_children () const
   {
     return m_children.get_all ();
   }
 
-  Matrix get_hidden_children (void) const
+  Matrix get_hidden_children () const
   {
     return m_children.get_hidden ();
   }
@@ -2328,7 +2374,7 @@
 
   // Redirect calls to "uicontextmenu" to "contextmenu".
 
-  graphics_handle get_uicontextmenu (void) const
+  graphics_handle get_uicontextmenu () const
   {
     return get_contextmenu ();
   }
@@ -2348,7 +2394,7 @@
   virtual void update_axis_limits (const std::string& axis_type,
                                    const graphics_handle& h) const;
 
-  virtual void update_contextmenu (void) const;
+  virtual void update_contextmenu () const;
 
   virtual void delete_children (bool clear = false, bool from_root = false)
   {
@@ -2365,28 +2411,28 @@
     m_parent = new_gh;
   }
 
-  static OCTINTERP_API property_list::pval_map_type factory_defaults (void);
+  static OCTINTERP_API property_list::pval_map_type factory_defaults ();
 
   // FIXME: These functions should be generated automatically by the
   //        genprops.awk script.
   //
   // EMIT_BASE_PROPERTIES_GET_FUNCTIONS
 
-  virtual octave_value get_alim (void) const { return octave_value (); }
-  virtual octave_value get_clim (void) const { return octave_value (); }
-  virtual octave_value get_xlim (void) const { return octave_value (); }
-  virtual octave_value get_ylim (void) const { return octave_value (); }
-  virtual octave_value get_zlim (void) const { return octave_value (); }
-
-  virtual bool is_aliminclude (void) const { return false; }
-  virtual bool is_climinclude (void) const { return false; }
-  virtual bool is_xliminclude (void) const { return false; }
-  virtual bool is_yliminclude (void) const { return false; }
-  virtual bool is_zliminclude (void) const { return false; }
-
-  OCTINTERP_API bool is_handle_visible (void) const;
-
-  OCTINTERP_API std::set<std::string> dynamic_property_names (void) const;
+  virtual octave_value get_alim () const { return octave_value (); }
+  virtual octave_value get_clim () const { return octave_value (); }
+  virtual octave_value get_xlim () const { return octave_value (); }
+  virtual octave_value get_ylim () const { return octave_value (); }
+  virtual octave_value get_zlim () const { return octave_value (); }
+
+  virtual bool is_aliminclude () const { return false; }
+  virtual bool is_climinclude () const { return false; }
+  virtual bool is_xliminclude () const { return false; }
+  virtual bool is_yliminclude () const { return false; }
+  virtual bool is_zliminclude () const { return false; }
+
+  OCTINTERP_API bool is_handle_visible () const;
+
+  OCTINTERP_API std::set<std::string> dynamic_property_names () const;
 
   OCTINTERP_API bool has_dynamic_property (const std::string& pname) const;
 
@@ -2431,11 +2477,11 @@
     graphics_handle __myhandle__ fhrs , mh
   END_PROPERTIES
 
-  virtual void update_beingdeleted (void) { };
-
-  virtual void update_handlevisibility (void);
-
-  virtual void update_visible (void) { };
+  virtual void update_beingdeleted () { };
+
+  virtual void update_handlevisibility ();
+
+  virtual void update_visible () { };
 
 protected:
   struct cmp_caseless_str
@@ -2456,7 +2502,7 @@
 
 protected:
 
-  virtual void init (void)
+  virtual void init ()
   {
     m_contextmenu.add_constraint ("uicontextmenu");
   }
@@ -2467,17 +2513,13 @@
 public:
   friend class graphics_object;
 
-  base_graphics_object (void) : m_toolkit_flag (false) { }
-
-  // No copying!
-
-  base_graphics_object (const base_graphics_object&) = delete;
-
-  base_graphics_object& operator = (const base_graphics_object&) = delete;
-
-  virtual ~base_graphics_object (void) = default;
-
-  virtual void mark_modified (void)
+  base_graphics_object () : m_toolkit_flag (false) { }
+
+  OCTAVE_DISABLE_COPY_MOVE (base_graphics_object)
+
+  virtual ~base_graphics_object () = default;
+
+  virtual void mark_modified ()
   {
     if (! valid_object ())
       error ("base_graphics_object::mark_modified: invalid graphics object");
@@ -2539,12 +2581,12 @@
 
   virtual octave_value get_factory_default (const caseless_str&) const;
 
-  virtual octave_value get_defaults (void) const
+  virtual octave_value get_defaults () const
   {
     error ("base_graphics_object::get_defaults: invalid graphics object");
   }
 
-  virtual property_list get_defaults_list (void) const
+  virtual property_list get_defaults_list () const
   {
     if (! valid_object ())
       error ("base_graphics_object::get_defaults_list: invalid graphics object");
@@ -2552,12 +2594,12 @@
     return property_list ();
   }
 
-  virtual octave_value get_factory_defaults (void) const
+  virtual octave_value get_factory_defaults () const
   {
     error ("base_graphics_object::get_factory_defaults: invalid graphics object");
   }
 
-  virtual property_list get_factory_defaults_list (void) const
+  virtual property_list get_factory_defaults_list () const
   {
     error ("base_graphics_object::get_factory_defaults_list: invalid graphics object");
   }
@@ -2569,7 +2611,7 @@
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
-  virtual std::string values_as_string (void);
+  virtual std::string values_as_string ();
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
@@ -2577,9 +2619,9 @@
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
-  virtual octave_scalar_map values_as_struct (void);
-
-  virtual graphics_handle get_parent (void) const
+  virtual octave_scalar_map values_as_struct ();
+
+  virtual graphics_handle get_parent () const
   {
     if (! valid_object ())
       error ("base_graphics_object::get_parent: invalid graphics object");
@@ -2587,7 +2629,7 @@
     return get_properties ().get_parent ();
   }
 
-  graphics_handle get_handle (void) const
+  graphics_handle get_handle () const
   {
     if (! valid_object ())
       error ("base_graphics_object::get_handle: invalid graphics object");
@@ -2619,7 +2661,7 @@
     get_properties ().reparent (np);
   }
 
-  virtual void defaults (void) const
+  virtual void defaults () const
   {
     if (! valid_object ())
       error ("base_graphics_object::default: invalid graphics object");
@@ -2628,14 +2670,14 @@
     err_not_implemented (msg.c_str ());
   }
 
-  virtual base_properties& get_properties (void)
+  virtual base_properties& get_properties ()
   {
     static base_properties properties;
     warning ("base_graphics_object::get_properties: invalid graphics object");
     return properties;
   }
 
-  virtual const base_properties& get_properties (void) const
+  virtual const base_properties& get_properties () const
   {
     static base_properties properties;
     warning ("base_graphics_object::get_properties: invalid graphics object");
@@ -2647,11 +2689,11 @@
   virtual void update_axis_limits (const std::string& axis_type,
                                    const graphics_handle& h);
 
-  virtual bool valid_object (void) const { return false; }
-
-  bool valid_toolkit_object (void) const { return m_toolkit_flag; }
-
-  virtual std::string type (void) const
+  virtual bool valid_object () const { return false; }
+
+  bool valid_toolkit_object () const { return m_toolkit_flag; }
+
+  virtual std::string type () const
   {
     return (valid_object () ? get_properties ().graphics_object_name ()
                             : "unknown");
@@ -2662,7 +2704,7 @@
     return type () == go_name;
   }
 
-  virtual octave::graphics_toolkit get_toolkit (void) const
+  virtual octave::graphics_toolkit get_toolkit () const
   {
     if (! valid_object ())
       error ("base_graphics_object::get_toolkit: invalid graphics object");
@@ -2686,9 +2728,9 @@
       get_properties ().delete_listener (nm, v, mode);
   }
 
-  virtual void remove_all_listeners (void);
-
-  virtual void reset_default_properties (void);
+  virtual void remove_all_listeners ();
+
+  virtual void reset_default_properties ();
 
 protected:
   virtual void initialize (const graphics_object& go)
@@ -2723,7 +2765,7 @@
 {
 public:
 
-  graphics_object (void) : m_rep (new base_graphics_object ()) { }
+  graphics_object () : m_rep (new base_graphics_object ()) { }
 
   graphics_object (base_graphics_object *new_rep) : m_rep (new_rep) { }
 
@@ -2731,16 +2773,16 @@
 
   graphics_object& operator = (const graphics_object&) = default;
 
-  ~graphics_object (void) = default;
-
-  void mark_modified (void) { m_rep->mark_modified (); }
+  ~graphics_object () = default;
+
+  void mark_modified () { m_rep->mark_modified (); }
 
   void override_defaults (base_graphics_object& obj)
   {
     m_rep->override_defaults (obj);
   }
 
-  void override_defaults (void)
+  void override_defaults ()
   {
     m_rep->override_defaults (*m_rep);
   }
@@ -2800,19 +2842,19 @@
     return m_rep->get_factory_default (name);
   }
 
-  octave_value get_defaults (void) const { return m_rep->get_defaults (); }
-
-  property_list get_defaults_list (void) const
+  octave_value get_defaults () const { return m_rep->get_defaults (); }
+
+  property_list get_defaults_list () const
   {
     return m_rep->get_defaults_list ();
   }
 
-  octave_value get_factory_defaults (void) const
+  octave_value get_factory_defaults () const
   {
     return m_rep->get_factory_defaults ();
   }
 
-  property_list get_factory_defaults_list (void) const
+  property_list get_factory_defaults_list () const
   {
     return m_rep->get_factory_defaults_list ();
   }
@@ -2824,7 +2866,7 @@
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
-  std::string values_as_string (void) { return m_rep->values_as_string (); }
+  std::string values_as_string () { return m_rep->values_as_string (); }
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
@@ -2835,11 +2877,11 @@
 
   // FIXME: It seems like this function should be const, but that is
   // currently not possible.
-  octave_map values_as_struct (void) { return m_rep->values_as_struct (); }
-
-  graphics_handle get_parent (void) const { return m_rep->get_parent (); }
-
-  graphics_handle get_handle (void) const { return m_rep->get_handle (); }
+  octave_map values_as_struct () { return m_rep->values_as_struct (); }
+
+  graphics_handle get_parent () const { return m_rep->get_parent (); }
+
+  graphics_handle get_handle () const { return m_rep->get_handle (); }
 
   OCTINTERP_API graphics_object get_ancestor (const std::string& type) const;
 
@@ -2849,13 +2891,13 @@
 
   void reparent (const graphics_handle& h) { m_rep->reparent (h); }
 
-  void defaults (void) const { m_rep->defaults (); }
+  void defaults () const { m_rep->defaults (); }
 
   bool isa (const std::string& go_name) const { return m_rep->isa (go_name); }
 
-  base_properties& get_properties (void) { return m_rep->get_properties (); }
-
-  const base_properties& get_properties (void) const
+  base_properties& get_properties () { return m_rep->get_properties (); }
+
+  const base_properties& get_properties () const
   {
     return m_rep->get_properties ();
   }
@@ -2871,51 +2913,51 @@
     m_rep->update_axis_limits (axis_type, h);
   }
 
-  bool valid_object (void) const { return m_rep->valid_object (); }
-
-  std::string type (void) const { return m_rep->type (); }
-
-  operator bool (void) const { return m_rep->valid_object (); }
+  bool valid_object () const { return m_rep->valid_object (); }
+
+  std::string type () const { return m_rep->type (); }
+
+  operator bool () const { return m_rep->valid_object (); }
 
   // FIXME: These functions should be generated automatically by the
   //        genprops.awk script.
   //
   // EMIT_GRAPHICS_OBJECT_GET_FUNCTIONS
 
-  octave_value get_alim (void) const
+  octave_value get_alim () const
   { return get_properties ().get_alim (); }
 
-  octave_value get_clim (void) const
+  octave_value get_clim () const
   { return get_properties ().get_clim (); }
 
-  octave_value get_xlim (void) const
+  octave_value get_xlim () const
   { return get_properties ().get_xlim (); }
 
-  octave_value get_ylim (void) const
+  octave_value get_ylim () const
   { return get_properties ().get_ylim (); }
 
-  octave_value get_zlim (void) const
+  octave_value get_zlim () const
   { return get_properties ().get_zlim (); }
 
-  bool is_aliminclude (void) const
+  bool is_aliminclude () const
   { return get_properties ().is_aliminclude (); }
 
-  bool is_climinclude (void) const
+  bool is_climinclude () const
   { return get_properties ().is_climinclude (); }
 
-  bool is_xliminclude (void) const
+  bool is_xliminclude () const
   { return get_properties ().is_xliminclude (); }
 
-  bool is_yliminclude (void) const
+  bool is_yliminclude () const
   { return get_properties ().is_yliminclude (); }
 
-  bool is_zliminclude (void) const
+  bool is_zliminclude () const
   { return get_properties ().is_zliminclude (); }
 
-  bool is_handle_visible (void) const
+  bool is_handle_visible () const
   { return get_properties ().is_handle_visible (); }
 
-  octave::graphics_toolkit get_toolkit (void) const
+  octave::graphics_toolkit get_toolkit () const
   { return m_rep->get_toolkit (); }
 
   void add_property_listener (const std::string& nm, const octave_value& v,
@@ -2926,15 +2968,15 @@
                                  listener_mode mode = GCB_POSTSET)
   { m_rep->delete_property_listener (nm, v, mode); }
 
-  void remove_all_listeners (void) { m_rep->remove_all_listeners (); }
-
-  void initialize (void) { m_rep->initialize (*this); }
-
-  void finalize (void) { m_rep->finalize (*this); }
+  void remove_all_listeners () { m_rep->remove_all_listeners (); }
+
+  void initialize () { m_rep->initialize (*this); }
+
+  void finalize () { m_rep->finalize (*this); }
 
   void update (int id) { m_rep->update (*this, id); }
 
-  void reset_default_properties (void)
+  void reset_default_properties ()
   { m_rep->reset_default_properties (); }
 
 private:
@@ -3001,20 +3043,18 @@
 
 protected:
 
-  root_figure (void)
+  root_figure ()
     : m_properties (0, graphics_handle ()), m_default_properties (),
       m_factory_properties (init_factory_properties ())
   { }
 
 public:
 
-  ~root_figure (void) = default;
-
-  root_figure (const root_figure&) = delete;
-
-  root_figure& operator = (const root_figure&) = delete;
-
-  void mark_modified (void) { }
+  OCTAVE_DISABLE_COPY_MOVE (root_figure)
+
+  ~root_figure () = default;
+
+  void mark_modified () { }
 
   void override_defaults (base_graphics_object& obj)
   {
@@ -3077,33 +3117,33 @@
     return retval;
   }
 
-  octave_value get_defaults (void) const
+  octave_value get_defaults () const
   {
     return m_default_properties.as_struct ("default");
   }
 
-  property_list get_defaults_list (void) const
+  property_list get_defaults_list () const
   {
     return m_default_properties;
   }
 
-  octave_value get_factory_defaults (void) const
+  octave_value get_factory_defaults () const
   {
     return m_factory_properties.as_struct ("factory");
   }
 
-  property_list get_factory_defaults_list (void) const
+  property_list get_factory_defaults_list () const
   {
     return m_factory_properties;
   }
 
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
-
-  OCTINTERP_API void reset_default_properties (void);
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
+
+  OCTINTERP_API void reset_default_properties ();
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -3120,7 +3160,7 @@
   property_list m_factory_properties;
 
   static OCTINTERP_API property_list::plist_map_type
-  init_factory_properties (void);
+  init_factory_properties ();
 };
 
 // ---------------------------------------------------------------------
@@ -3142,7 +3182,7 @@
 
     OCTINTERP_API void set_visible (const octave_value& val);
 
-    OCTINTERP_API octave::graphics_toolkit get_toolkit (void) const;
+    OCTINTERP_API octave::graphics_toolkit get_toolkit () const;
 
     OCTINTERP_API void set_toolkit (const octave::graphics_toolkit& b);
 
@@ -3151,7 +3191,7 @@
     OCTINTERP_API void adopt (const graphics_handle& h);
 
     // Alias "innerposition" to "position".
-    octave_value get_innerposition (void) const
+    octave_value get_innerposition () const
     {
       return get_position ();
     }
@@ -3185,7 +3225,7 @@
 
     OCTINTERP_API void update_paperunits (const caseless_str& old_paperunits);
 
-    OCTINTERP_API std::string get_title (void) const;
+    OCTINTERP_API std::string get_title () const;
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -3270,7 +3310,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_alphamap.add_constraint (dim_vector (-1, 1));
       m_alphamap.add_constraint (dim_vector (1, -1));
@@ -3292,17 +3332,17 @@
     }
 
   private:
-    OCTINTERP_API Matrix get_auto_paperposition (void);
-
-    void update_paperpositionmode (void)
+    OCTINTERP_API Matrix get_auto_paperposition ();
+
+    void update_paperpositionmode ()
     {
       if (m_paperpositionmode.is ("auto"))
         m_paperposition.set (get_auto_paperposition ());
     }
 
-    OCTINTERP_API void update_handlevisibility (void);
-
-    OCTINTERP_API void init_toolkit (void);
+    OCTINTERP_API void update_handlevisibility ();
+
+    OCTINTERP_API void init_toolkit ();
 
     octave::graphics_toolkit m_toolkit;
   };
@@ -3311,11 +3351,14 @@
   properties m_properties;
 
 public:
+
   figure (const graphics_handle& mh, const graphics_handle& p)
     : base_graphics_object (), m_properties (mh, p), m_default_properties ()
   { }
 
-  ~figure (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (figure)
+
+  ~figure () = default;
 
   void override_defaults (base_graphics_object& obj)
   {
@@ -3356,23 +3399,23 @@
 
   OCTINTERP_API octave_value get_default (const caseless_str& name) const;
 
-  octave_value get_defaults (void) const
+  octave_value get_defaults () const
   {
     return m_default_properties.as_struct ("default");
   }
 
-  property_list get_defaults_list (void) const
+  property_list get_defaults_list () const
   {
     return m_default_properties;
   }
 
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
-
-  OCTINTERP_API void reset_default_properties (void);
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
+
+  OCTINTERP_API void reset_default_properties ();
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -3392,7 +3435,7 @@
 {
 public:
 
-  graphics_xform (void)
+  graphics_xform ()
     : m_xform (xform_eye ()), m_xform_inv (xform_eye ()),
       m_sx ("linear"), m_sy ("linear"), m_sz ("linear"),  m_zlim (1, 2, 0.0)
   {
@@ -3410,7 +3453,7 @@
     : m_xform (g.m_xform), m_xform_inv (g.m_xform_inv), m_sx (g.m_sx),
       m_sy (g.m_sy), m_sz (g.m_sz), m_zlim (g.m_zlim) { }
 
-  ~graphics_xform (void) = default;
+  ~graphics_xform () = default;
 
   graphics_xform& operator = (const graphics_xform& g)
   {
@@ -3426,7 +3469,7 @@
 
   static OCTINTERP_API ColumnVector xform_vector (double x, double y, double z);
 
-  static OCTINTERP_API Matrix xform_eye (void);
+  static OCTINTERP_API Matrix xform_eye ();
 
   OCTINTERP_API ColumnVector
   transform (double x, double y, double z, bool use_scale = true) const;
@@ -3495,9 +3538,9 @@
 
     OCTINTERP_API void adopt (const graphics_handle& h);
 
-    const scaler& get_x_scaler (void) const { return m_sx; }
-    const scaler& get_y_scaler (void) const { return m_sy; }
-    const scaler& get_z_scaler (void) const { return m_sz; }
+    const scaler& get_x_scaler () const { return m_sx; }
+    const scaler& get_y_scaler () const { return m_sy; }
+    const scaler& get_z_scaler () const { return m_sz; }
 
     OCTINTERP_API Matrix
     get_boundingbox (bool internal = false,
@@ -3509,7 +3552,7 @@
     OCTINTERP_API double
     get___fontsize_points__ (double box_pix_height = 0) const;
 
-    void update_boundingbox (void)
+    void update_boundingbox ()
     {
       if (units_is ("normalized"))
         {
@@ -3518,21 +3561,21 @@
         }
     }
 
-    OCTINTERP_API void update_camera (void);
-    OCTINTERP_API void update_axes_layout (void);
-    OCTINTERP_API void update_aspectratios (void);
-    void update_transform (void)
+    OCTINTERP_API void update_camera ();
+    OCTINTERP_API void update_axes_layout ();
+    OCTINTERP_API void update_aspectratios ();
+    void update_transform ()
     {
       update_aspectratios ();
       update_camera ();
       update_axes_layout ();
     }
 
-    OCTINTERP_API void sync_positions (void);
+    OCTINTERP_API void sync_positions ();
 
     // Redirect calls to "activepositionproperty" to "positionconstraint".
 
-    std::string get_activepositionproperty (void) const
+    std::string get_activepositionproperty () const
     {
       std::string cur_val;
 
@@ -3557,7 +3600,7 @@
 
     // Redirect calls to "innerposition" to "position".
 
-    octave_value get_innerposition (void) const
+    octave_value get_innerposition () const
     {
       return get_position ();
     }
@@ -3568,63 +3611,63 @@
     }
 
     OCTINTERP_API void update_autopos (const std::string& elem_type);
-    OCTINTERP_API void update_xlabel_position (void);
-    OCTINTERP_API void update_ylabel_position (void);
-    OCTINTERP_API void update_zlabel_position (void);
-    OCTINTERP_API void update_title_position (void);
-
-    graphics_xform get_transform (void) const
+    OCTINTERP_API void update_xlabel_position ();
+    OCTINTERP_API void update_ylabel_position ();
+    OCTINTERP_API void update_zlabel_position ();
+    OCTINTERP_API void update_title_position ();
+
+    graphics_xform get_transform () const
     {
       return graphics_xform (m_x_render, m_x_render_inv,
                              m_sx, m_sy, m_sz, m_x_zlim);
     }
 
-    Matrix get_transform_matrix (void) const { return m_x_render; }
-    Matrix get_inverse_transform_matrix (void) const { return m_x_render_inv; }
-    Matrix get_opengl_matrix_1 (void) const { return m_x_gl_mat1; }
-    Matrix get_opengl_matrix_2 (void) const { return m_x_gl_mat2; }
-    Matrix get_transform_zlim (void) const { return m_x_zlim; }
-
-    int get_xstate (void) const { return m_xstate; }
-    int get_ystate (void) const { return m_ystate; }
-    int get_zstate (void) const { return m_zstate; }
-    double get_xPlane (void) const { return m_xPlane; }
-    double get_xPlaneN (void) const { return m_xPlaneN; }
-    double get_yPlane (void) const { return m_yPlane; }
-    double get_yPlaneN (void) const { return m_yPlaneN; }
-    double get_zPlane (void) const { return m_zPlane; }
-    double get_zPlaneN (void) const { return m_zPlaneN; }
-    double get_xpTick (void) const { return m_xpTick; }
-    double get_xpTickN (void) const { return m_xpTickN; }
-    double get_ypTick (void) const { return m_ypTick; }
-    double get_ypTickN (void) const { return m_ypTickN; }
-    double get_zpTick (void) const { return m_zpTick; }
-    double get_zpTickN (void) const { return m_zpTickN; }
-    double get_x_min (void) const { return std::min (m_xPlane, m_xPlaneN); }
-    double get_x_max (void) const { return std::max (m_xPlane, m_xPlaneN); }
-    double get_y_min (void) const { return std::min (m_yPlane, m_yPlaneN); }
-    double get_y_max (void) const { return std::max (m_yPlane, m_yPlaneN); }
-    double get_z_min (void) const { return std::min (m_zPlane, m_zPlaneN); }
-    double get_z_max (void) const { return std::max (m_zPlane, m_zPlaneN); }
-    double get_fx (void) const { return m_fx; }
-    double get_fy (void) const { return m_fy; }
-    double get_fz (void) const { return m_fz; }
-    double get_xticklen (void) const { return m_xticklen; }
-    double get_yticklen (void) const { return m_yticklen; }
-    double get_zticklen (void) const { return m_zticklen; }
-    double get_xtickoffset (void) const { return m_xtickoffset; }
-    double get_ytickoffset (void) const { return m_ytickoffset; }
-    double get_ztickoffset (void) const { return m_ztickoffset; }
-    bool get_x2Dtop (void) const { return m_x2Dtop; }
-    bool get_y2Dright (void) const { return m_y2Dright; }
-    bool get_layer2Dtop (void) const { return m_layer2Dtop; }
+    Matrix get_transform_matrix () const { return m_x_render; }
+    Matrix get_inverse_transform_matrix () const { return m_x_render_inv; }
+    Matrix get_opengl_matrix_1 () const { return m_x_gl_mat1; }
+    Matrix get_opengl_matrix_2 () const { return m_x_gl_mat2; }
+    Matrix get_transform_zlim () const { return m_x_zlim; }
+
+    int get_xstate () const { return m_xstate; }
+    int get_ystate () const { return m_ystate; }
+    int get_zstate () const { return m_zstate; }
+    double get_xPlane () const { return m_xPlane; }
+    double get_xPlaneN () const { return m_xPlaneN; }
+    double get_yPlane () const { return m_yPlane; }
+    double get_yPlaneN () const { return m_yPlaneN; }
+    double get_zPlane () const { return m_zPlane; }
+    double get_zPlaneN () const { return m_zPlaneN; }
+    double get_xpTick () const { return m_xpTick; }
+    double get_xpTickN () const { return m_xpTickN; }
+    double get_ypTick () const { return m_ypTick; }
+    double get_ypTickN () const { return m_ypTickN; }
+    double get_zpTick () const { return m_zpTick; }
+    double get_zpTickN () const { return m_zpTickN; }
+    double get_x_min () const { return std::min (m_xPlane, m_xPlaneN); }
+    double get_x_max () const { return std::max (m_xPlane, m_xPlaneN); }
+    double get_y_min () const { return std::min (m_yPlane, m_yPlaneN); }
+    double get_y_max () const { return std::max (m_yPlane, m_yPlaneN); }
+    double get_z_min () const { return std::min (m_zPlane, m_zPlaneN); }
+    double get_z_max () const { return std::max (m_zPlane, m_zPlaneN); }
+    double get_fx () const { return m_fx; }
+    double get_fy () const { return m_fy; }
+    double get_fz () const { return m_fz; }
+    double get_xticklen () const { return m_xticklen; }
+    double get_yticklen () const { return m_yticklen; }
+    double get_zticklen () const { return m_zticklen; }
+    double get_xtickoffset () const { return m_xtickoffset; }
+    double get_ytickoffset () const { return m_ytickoffset; }
+    double get_ztickoffset () const { return m_ztickoffset; }
+    bool get_x2Dtop () const { return m_x2Dtop; }
+    bool get_y2Dright () const { return m_y2Dright; }
+    bool get_layer2Dtop () const { return m_layer2Dtop; }
     bool get_is2D (bool include_kids = false) const
     { return (include_kids ? (m_is2D && ! m_has3Dkids) : m_is2D); }
     void set_has3Dkids (bool val) { m_has3Dkids = val; }
-    bool get_xySym (void) const { return m_xySym; }
-    bool get_xyzSym (void) const { return m_xyzSym; }
-    bool get_zSign (void) const { return m_zSign; }
-    bool get_nearhoriz (void) const { return m_nearhoriz; }
+    bool get_xySym () const { return m_xySym; }
+    bool get_xyzSym () const { return m_xyzSym; }
+    bool get_zSign () const { return m_zSign; }
+    bool get_nearhoriz () const { return m_nearhoriz; }
 
     ColumnVector pixel2coord (double px, double py) const
     {
@@ -3662,9 +3705,9 @@
     rotate_view (double delta_az, double delta_el,
                  bool push_to_zoom_stack = true);
 
-    OCTINTERP_API void unzoom (void);
-    OCTINTERP_API void update_handlevisibility (void);
-    OCTINTERP_API void push_zoom_stack (void);
+    OCTINTERP_API void unzoom ();
+    OCTINTERP_API void update_handlevisibility ();
+    OCTINTERP_API void push_zoom_stack ();
     OCTINTERP_API void clear_zoom_stack (bool do_unzoom = true);
 
     OCTINTERP_API void update_units (const caseless_str& old_units);
@@ -3673,9 +3716,9 @@
 
     OCTINTERP_API void update_fontunits (const caseless_str& old_fontunits);
 
-    void increase_num_lights (void) { m_num_lights++; }
-    void decrease_num_lights (void) { m_num_lights--; }
-    unsigned int get_num_lights (void) const { return m_num_lights; }
+    void increase_num_lights () { m_num_lights++; }
+    void decrease_num_lights () { m_num_lights--; }
+    unsigned int get_num_lights () const { return m_num_lights; }
 
   private:
 
@@ -3820,7 +3863,7 @@
       radio_property positionconstraint , "{outerposition}|innerposition"
       radio_property projection , "{orthographic}|perspective"
       radio_property sortmethod , "{depth}|childorder"
-      radio_property tickdir mu , "{in}|out"
+      radio_property tickdir mu , "{in}|out|both|none"
       radio_property tickdirmode u , "{auto}|manual"
       // FIXME: Added recently to Matlab, should replace interpreter property.
       radio_property ticklabelinterpreter u , "{tex}|latex|none"
@@ -3908,7 +3951,7 @@
    END_PROPERTIES
 
   protected:
-    OCTINTERP_API void init (void);
+    OCTINTERP_API void init ();
 
   private:
 
@@ -3923,67 +3966,67 @@
       return retval;
     }
 
-    void update_xscale (void)
+    void update_xscale ()
     {
       m_sx = get_scale (get_xscale (), m_xlim.get ().matrix_value ());
     }
 
-    void update_yscale (void)
+    void update_yscale ()
     {
       m_sy = get_scale (get_yscale (), m_ylim.get ().matrix_value ());
     }
 
-    void update_zscale (void)
+    void update_zscale ()
     {
       m_sz = get_scale (get_zscale (), m_zlim.get ().matrix_value ());
     }
 
     OCTINTERP_API void
     update_label_color (handle_property label, color_property col);
-    void update_xcolor (void)
+    void update_xcolor ()
     { update_label_color (m_xlabel, m_xcolor); }
 
-    void update_ycolor (void)
+    void update_ycolor ()
     { update_label_color (m_ylabel, m_ycolor); }
 
-    void update_zcolor (void)
+    void update_zcolor ()
     { update_label_color (m_zlabel, m_zcolor); }
 
-    void update_view (void) { sync_positions (); }
-
-    void update_cameraposition (void) { update_transform (); }
-    void update_cameratarget (void) { update_transform (); }
-    void update_cameraupvector (void) { update_transform (); }
-    void update_cameraviewangle (void) { update_transform (); }
-
-    void update_camerapositionmode (void)
+    void update_view () { sync_positions (); }
+
+    void update_cameraposition () { update_transform (); }
+    void update_cameratarget () { update_transform (); }
+    void update_cameraupvector () { update_transform (); }
+    void update_cameraviewangle () { update_transform (); }
+
+    void update_camerapositionmode ()
     {
       if (camerapositionmode_is ("auto"))
         update_cameraposition ();
     }
-    void update_cameratargetmode (void)
+    void update_cameratargetmode ()
     {
       if (cameratargetmode_is ("auto"))
         update_cameratarget ();
     }
-    void update_cameraupvectormode (void)
+    void update_cameraupvectormode ()
     {
       if (cameraupvectormode_is ("auto"))
         update_cameraupvector ();
     }
-    void update_cameraviewanglemode (void)
+    void update_cameraviewanglemode ()
     {
       if (cameraviewanglemode_is ("auto"))
         update_cameraviewangle ();
     }
 
-    void update_dataaspectratio (void) { sync_positions (); }
-    void update_dataaspectratiomode (void) { sync_positions (); }
-    void update_plotboxaspectratio (void) { sync_positions (); }
-    void update_plotboxaspectratiomode (void) { sync_positions (); }
-
-    void update_layer (void) { update_axes_layout (); }
-    void update_box (void)
+    void update_dataaspectratio () { sync_positions (); }
+    void update_dataaspectratiomode () { sync_positions (); }
+    void update_plotboxaspectratio () { sync_positions (); }
+    void update_plotboxaspectratiomode () { sync_positions (); }
+
+    void update_layer () { update_axes_layout (); }
+    void update_box ()
     {
       if (m_xticklabelmode.is ("auto"))
         calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is ("log"),
@@ -4000,7 +4043,7 @@
                              (xaxislocation_is ("bottom") ? -1 : 1)),
                          m_ylim);
     }
-    void update_yaxislocation (void)
+    void update_yaxislocation ()
     {
       sync_positions ();
       update_axes_layout ();
@@ -4020,7 +4063,7 @@
                          m_ylim);
       update_ylabel_position ();
     }
-    void update_xaxislocation (void)
+    void update_xaxislocation ()
     {
       sync_positions ();
       update_axes_layout ();
@@ -4041,15 +4084,15 @@
       update_xlabel_position ();
     }
 
-    void update_xdir (void) { update_camera (); update_axes_layout (); }
-    void update_ydir (void) { update_camera (); update_axes_layout (); }
-    void update_zdir (void) { update_camera (); update_axes_layout (); }
-
-    void update_ticklength (void);
-    void update_tickdir (void) { update_ticklength (); }
-    void update_tickdirmode (void) { update_ticklength (); }
-
-    void update_ticklabelinterpreter (void)
+    void update_xdir () { update_camera (); update_axes_layout (); }
+    void update_ydir () { update_camera (); update_axes_layout (); }
+    void update_zdir () { update_camera (); update_axes_layout (); }
+
+    void update_ticklength ();
+    void update_tickdir () { update_ticklength (); }
+    void update_tickdirmode () { update_ticklength (); }
+
+    void update_ticklabelinterpreter ()
     {
       update_xtick (false);
       update_ytick (false);
@@ -4104,23 +4147,23 @@
         sync_positions ();
     }
 
-    void update_xtickmode (void)
+    void update_xtickmode ()
     {
       if (m_xtickmode.is ("auto"))
         update_xtick ();
     }
-    void update_ytickmode (void)
+    void update_ytickmode ()
     {
       if (m_ytickmode.is ("auto"))
         update_ytick ();
     }
-    void update_ztickmode (void)
+    void update_ztickmode ()
     {
       if (m_ztickmode.is ("auto"))
         update_ztick ();
     }
 
-    void update_xticklabelmode (void)
+    void update_xticklabelmode ()
     {
       if (m_xticklabelmode.is ("auto"))
         calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is ("log"),
@@ -4130,7 +4173,7 @@
                              (yaxislocation_is ("left") ? -1 : 1)),
                          m_xlim);
     }
-    void update_yticklabelmode (void)
+    void update_yticklabelmode ()
     {
       if (m_yticklabelmode.is ("auto"))
         calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is ("log"),
@@ -4140,61 +4183,61 @@
                              (xaxislocation_is ("bottom") ? -1 : 1)),
                          m_ylim);
     }
-    void update_zticklabelmode (void)
+    void update_zticklabelmode ()
     {
       if (m_zticklabelmode.is ("auto"))
         calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is ("log"),
                          false, 2, m_zlim);
     }
 
-    void update_fontname (void)
+    void update_fontname ()
     {
       update_font ("fontname");
       sync_positions ();
     }
-    void update_fontsize (void)
+    void update_fontsize ()
     {
       update_font ("fontsize");
       sync_positions ();
     }
-    void update_fontsmoothing (void)
+    void update_fontsmoothing ()
     {
       update_font ("fontsmoothing");
     }
-    void update_fontangle (void)
+    void update_fontangle ()
     {
       update_font ("fontangle");
       sync_positions ();
     }
-    void update_fontweight (void)
+    void update_fontweight ()
     {
       update_font ("fontweight");
       sync_positions ();
     }
 
-    void update_titlefontsizemultiplier (void)
+    void update_titlefontsizemultiplier ()
     {
       // update_font handles title and axis labels
       update_font ("fontsize");
       sync_positions ();
     }
 
-    void update_labelfontsizemultiplier (void)
+    void update_labelfontsizemultiplier ()
     {
       update_font ("fontsize");
       sync_positions ();
     }
 
-    void update_titlefontweight (void)
+    void update_titlefontweight ()
     {
       // update_font handles title and axis labels
       update_font ("fontweight");
       sync_positions ();
     }
 
-    OCTINTERP_API void update_outerposition (void);
-    OCTINTERP_API void update_position (void);
-    OCTINTERP_API void update_looseinset (void);
+    OCTINTERP_API void update_outerposition ();
+    OCTINTERP_API void update_position ();
+    OCTINTERP_API void update_looseinset ();
 
     OCTINTERP_API double calc_tick_sep (double minval, double maxval);
     OCTINTERP_API void
@@ -4239,12 +4282,12 @@
       set___colormap__ (val);
     }
 
-    void update___colormap__ (void)
+    void update___colormap__ ()
     {
       m_colormap.run_listeners (GCB_POSTSET);
     }
 
-    OCTINTERP_API octave_value get_colormap (void) const;
+    OCTINTERP_API octave_value get_colormap () const;
 
   public:
     OCTINTERP_API Matrix
@@ -4284,7 +4327,7 @@
       update_xlim ();
     }
 
-    void update_ylim (void)
+    void update_ylim ()
     {
       update_axis_limits ("ylim");
 
@@ -4312,7 +4355,7 @@
       update_ylim ();
     }
 
-    void update_zlim (void)
+    void update_zlim ()
     {
       update_axis_limits ("zlim");
 
@@ -4336,7 +4379,7 @@
       update_zlim ();
     }
 
-    void trigger_normals_calc (void);
+    void trigger_normals_calc ();
 
   };
 
@@ -4350,7 +4393,9 @@
     m_properties.update_transform ();
   }
 
-  ~axes (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (axes)
+
+  ~axes () = default;
 
   void override_defaults (base_graphics_object& obj)
   {
@@ -4397,28 +4442,28 @@
 
   OCTINTERP_API octave_value get_default (const caseless_str& name) const;
 
-  octave_value get_defaults (void) const
+  octave_value get_defaults () const
   {
     return m_default_properties.as_struct ("default");
   }
 
-  property_list get_defaults_list (void) const
+  property_list get_defaults_list () const
   {
     return m_default_properties;
   }
 
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
 
   OCTINTERP_API void update_axis_limits (const std::string& axis_type);
 
   OCTINTERP_API void update_axis_limits (const std::string& axis_type,
                                          const graphics_handle& h);
 
-  bool valid_object (void) const { return true; }
-
-  OCTINTERP_API void reset_default_properties (void);
+  bool valid_object () const { return true; }
+
+  OCTINTERP_API void reset_default_properties ();
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -4476,21 +4521,21 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_linewidth.add_constraint ("min", 0, false);
       m_markersize.add_constraint ("min", 0, false);
     }
 
   private:
-    OCTINTERP_API Matrix compute_xlim (void) const;
-    OCTINTERP_API Matrix compute_ylim (void) const;
-
-    void update_xdata (void) { set_xlim (compute_xlim ()); }
-
-    void update_ydata (void) { set_ylim (compute_ylim ()); }
-
-    void update_zdata (void) { set_zlim (m_zdata.get_limits ()); }
+    OCTINTERP_API Matrix compute_xlim () const;
+    OCTINTERP_API Matrix compute_ylim () const;
+
+    void update_xdata () { set_xlim (compute_xlim ()); }
+
+    void update_ydata () { set_ylim (compute_ylim ()); }
+
+    void update_zdata () { set_zlim (m_zdata.get_limits ()); }
   };
 
 private:
@@ -4501,13 +4546,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~line (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (line)
+
+  ~line () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -4531,9 +4578,9 @@
     OCTINTERP_API double
     get___fontsize_points__ (double box_pix_height = 0) const;
 
-    OCTINTERP_API void update_text_extent (void);
-
-    OCTINTERP_API void update_font (void);
+    OCTINTERP_API void update_text_extent ();
+
+    OCTINTERP_API void update_font ();
 
     void set_position (const octave_value& val)
     {
@@ -4601,15 +4648,15 @@
       double_property __fontsize_points__ hgr , 0
     END_PROPERTIES
 
-    OCTINTERP_API Matrix get_data_position (void) const;
+    OCTINTERP_API Matrix get_data_position () const;
     OCTINTERP_API Matrix get_extent_matrix (bool rotated = false) const;
-    const uint8NDArray& get_pixels (void) const { return m_pixels; }
+    const uint8NDArray& get_pixels () const { return m_pixels; }
 
     // Text renderer, used for calculation of text size
     octave::text_renderer m_txt_renderer;
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint (dim_vector (1, 3));
       m_fontsize.add_constraint ("min", 0.0, false);
@@ -4620,7 +4667,7 @@
     }
 
   private:
-    void update_position (void)
+    void update_position ()
     {
       Matrix pos = get_data_position ();
       Matrix lim;
@@ -4646,19 +4693,19 @@
         }
     }
 
-    OCTINTERP_API void request_autopos (void);
-    void update_positionmode (void) { request_autopos (); }
-    void update_rotationmode (void) { request_autopos (); }
-    void update_horizontalalignmentmode (void) { request_autopos (); }
-    void update_verticalalignmentmode (void) { request_autopos (); }
-
-    void update_string (void) { request_autopos (); update_text_extent (); }
-    void update_rotation (void) { update_text_extent (); }
-    void update_fontname (void) { update_font (); update_text_extent (); }
-    void update_fontsize (void) { update_font (); update_text_extent (); }
-    void update_fontsmoothing (void) { update_font (); update_text_extent (); }
-
-    void update_color (void)
+    OCTINTERP_API void request_autopos ();
+    void update_positionmode () { request_autopos (); }
+    void update_rotationmode () { request_autopos (); }
+    void update_horizontalalignmentmode () { request_autopos (); }
+    void update_verticalalignmentmode () { request_autopos (); }
+
+    void update_string () { request_autopos (); update_text_extent (); }
+    void update_rotation () { update_text_extent (); }
+    void update_fontname () { update_font (); update_text_extent (); }
+    void update_fontsize () { update_font (); update_text_extent (); }
+    void update_fontsmoothing () { update_font (); update_text_extent (); }
+
+    void update_color ()
     {
       if (! m_color.is ("none"))
         {
@@ -4667,18 +4714,18 @@
         }
     }
 
-    void update_fontangle (void)
+    void update_fontangle ()
     {
       update_font ();
       update_text_extent ();
     }
-    void update_fontweight (void) { update_font (); update_text_extent (); }
-
-    void update_interpreter (void) { update_text_extent (); }
-    void update_horizontalalignment (void) { update_text_extent (); }
-    void update_verticalalignment (void) { update_text_extent (); }
-
-    OCTINTERP_API void update_units (void);
+    void update_fontweight () { update_font (); update_text_extent (); }
+
+    void update_interpreter () { update_text_extent (); }
+    void update_horizontalalignment () { update_text_extent (); }
+    void update_verticalalignment () { update_text_extent (); }
+
+    OCTINTERP_API void update_units ();
     OCTINTERP_API void update_fontunits (const caseless_str& old_fontunits);
 
   private:
@@ -4696,13 +4743,15 @@
     m_properties.set_clipping ("off");
   }
 
-  ~text (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text)
+
+  ~text () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -4723,19 +4772,19 @@
   {
   public:
 
-    bool is_aliminclude (void) const
+    bool is_aliminclude () const
     { return (m_aliminclude.is_on () && m_alphadatamapping.is ("scaled")); }
-    std::string get_aliminclude (void) const
+    std::string get_aliminclude () const
     { return m_aliminclude.current_value (); }
 
-    bool is_climinclude (void) const
+    bool is_climinclude () const
     { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
-    std::string get_climinclude (void) const
+    std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
-    OCTINTERP_API octave_value get_color_data (void) const;
-
-    void initialize_data (void) { update_cdata (); }
+    OCTINTERP_API octave_value get_color_data () const;
+
+    void initialize_data () { update_cdata (); }
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -4762,7 +4811,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_xdata.add_constraint (2);
       m_xdata.add_constraint (dim_vector (0, 0));
@@ -4788,7 +4837,7 @@
     }
 
   private:
-    void update_alphadata (void)
+    void update_alphadata ()
     {
       if (alphadatamapping_is ("scaled"))
         set_alim (m_alphadata.get_limits ());
@@ -4796,7 +4845,7 @@
         m_alim = m_alphadata.get_limits ();
     }
 
-    void update_cdata (void)
+    void update_cdata ()
     {
       if (cdatamapping_is ("scaled"))
         set_clim (m_cdata.get_limits ());
@@ -4810,7 +4859,7 @@
         update_ydata ();
     }
 
-    void update_xdata (void)
+    void update_xdata ()
     {
       if (m_xdata.get ().isempty ())
         set_xdatamode ("auto");
@@ -4829,7 +4878,7 @@
       set_xlim (limits);
     }
 
-    void update_ydata (void)
+    void update_ydata ()
     {
       if (m_ydata.get ().isempty ())
         set_ydatamode ("auto");
@@ -4848,7 +4897,7 @@
       set_ylim (limits);
     }
 
-    Matrix get_auto_xdata (void)
+    Matrix get_auto_xdata ()
     {
       dim_vector dv = get_cdata ().dims ();
       Matrix data;
@@ -4860,7 +4909,7 @@
       return data;
     }
 
-    Matrix get_auto_ydata (void)
+    Matrix get_auto_ydata ()
     {
       dim_vector dv = get_cdata ().dims ();
       Matrix data;
@@ -4890,12 +4939,12 @@
     }
 
   public:
-    float pixel_xsize (void)
+    float pixel_xsize ()
     {
       return pixel_size ((get_cdata ().dims ())(1), m_xdata.get_limits ());
     }
 
-    float pixel_ysize (void)
+    float pixel_ysize ()
     {
       return pixel_size ((get_cdata ().dims ())(0), m_ydata.get_limits ());
     }
@@ -4911,13 +4960,15 @@
     m_properties.initialize_data ();
   }
 
-  ~image (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (image)
+
+  ~image () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -4947,13 +4998,13 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint (dim_vector (1, 3));
     }
 
   private:
-    OCTINTERP_API void update_visible (void);
+    OCTINTERP_API void update_visible ();
   };
 
 private:
@@ -4964,13 +5015,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~light (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (light)
+
+  ~light () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -4994,7 +5047,7 @@
   {
   public:
 
-    octave_value get_color_data (void) const;
+    octave_value get_color_data () const;
 
     // Matlab allows incoherent data to be stored into patch properties.
     // The patch should then be ignored by the renderer.
@@ -5004,17 +5057,17 @@
       return ! msg.empty ();
     }
 
-    bool is_aliminclude (void) const
+    bool is_aliminclude () const
     { return (m_aliminclude.is_on () && m_alphadatamapping.is ("scaled")); }
-    std::string get_aliminclude (void) const
+    std::string get_aliminclude () const
     { return m_aliminclude.current_value (); }
 
-    bool is_climinclude (void) const
+    bool is_climinclude () const
     { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
-    std::string get_climinclude (void) const
+    std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
-    OCTINTERP_API bool get_do_lighting (void) const;
+    OCTINTERP_API bool get_do_lighting () const;
 
     std::vector<std::vector<octave_idx_type>> m_coplanar_last_idx;
 
@@ -5071,7 +5124,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_xdata.add_constraint (dim_vector (-1, -1));
       m_ydata.add_constraint (dim_vector (-1, -1));
@@ -5127,15 +5180,15 @@
   private:
     std::string m_bad_data_msg;
 
-    void update_faces (void) { update_data ();}
-
-    void update_vertices (void) { update_data ();}
-
-    void update_facevertexcdata (void) { update_data ();}
-
-    OCTINTERP_API void update_fvc (void);
-
-    void update_xdata (void)
+    void update_faces () { update_data ();}
+
+    void update_vertices () { update_data ();}
+
+    void update_facevertexcdata () { update_data ();}
+
+    OCTINTERP_API void update_fvc ();
+
+    void update_xdata ()
     {
       if (get_xdata ().isempty ())
         {
@@ -5156,7 +5209,7 @@
       set_xlim (m_xdata.get_limits ());
     }
 
-    void update_ydata (void)
+    void update_ydata ()
     {
       if (get_ydata ().isempty ())
         {
@@ -5174,14 +5227,14 @@
       set_ylim (m_ydata.get_limits ());
     }
 
-    void update_zdata (void)
+    void update_zdata ()
     {
       update_fvc ();
       update_normals (true);
       set_zlim (m_zdata.get_limits ());
     }
 
-    void update_cdata (void)
+    void update_cdata ()
     {
       update_fvc ();
       update_normals (false);
@@ -5192,33 +5245,33 @@
         m_clim = m_cdata.get_limits ();
     }
 
-    OCTINTERP_API void update_data (void);
+    OCTINTERP_API void update_data ();
 
     OCTINTERP_API void calc_face_normals (Matrix& normals);
     OCTINTERP_API void update_face_normals (bool reset, bool force = false);
     OCTINTERP_API void update_vertex_normals (bool reset, bool force = false);
 
-    void update_edgelighting (void)
+    void update_edgelighting ()
     {
       update_normals (false);
     }
 
-    void update_facelighting (void)
+    void update_facelighting ()
     {
       update_normals (false);
     }
 
-    void update_facenormalsmode (void)
+    void update_facenormalsmode ()
     {
       update_face_normals (false);
     }
 
-    void update_vertexnormalsmode (void)
+    void update_vertexnormalsmode ()
     {
       update_vertex_normals (false);
     }
 
-    void update_visible (void)
+    void update_visible ()
     {
       if (is_visible ())
         update_normals (false);
@@ -5234,13 +5287,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~patch (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (patch)
+
+  ~patch () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -5250,7 +5305,7 @@
     return retval;
   }
 
-  OCTINTERP_API void reset_default_properties (void);
+  OCTINTERP_API void reset_default_properties ();
 
 protected:
   OCTINTERP_API void initialize (const graphics_object& go);
@@ -5267,7 +5322,7 @@
   {
   public:
 
-    OCTINTERP_API octave_value get_color_data (void) const;
+    OCTINTERP_API octave_value get_color_data () const;
 
     // Matlab allows incoherent data to be stored in scatter properties.
     // The scatter object should then be ignored by the renderer.
@@ -5277,14 +5332,14 @@
       return ! msg.empty ();
     }
 
-    bool is_aliminclude (void) const
+    bool is_aliminclude () const
     { return m_aliminclude.is_on (); }
-    std::string get_aliminclude (void) const
+    std::string get_aliminclude () const
     { return m_aliminclude.current_value (); }
 
-    bool is_climinclude (void) const
+    bool is_climinclude () const
     { return m_climinclude.is_on (); }
-    std::string get_climinclude (void) const
+    std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
     // See the genprops.awk script for an explanation of the
@@ -5336,7 +5391,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_xdata.add_constraint (dim_vector (-1, 1));
       m_xdata.add_constraint (dim_vector (1, -1));
@@ -5379,12 +5434,12 @@
     }
 
   public:
-    OCTINTERP_API void update_color (void);
+    OCTINTERP_API void update_color ();
 
   private:
     std::string m_bad_data_msg;
 
-    void update_xdata (void)
+    void update_xdata ()
     {
       if (get_xdata ().isempty ())
         {
@@ -5403,7 +5458,7 @@
       update_data ();
     }
 
-    void update_ydata (void)
+    void update_ydata ()
     {
       if (get_ydata ().isempty ())
         {
@@ -5420,19 +5475,19 @@
       update_data ();
     }
 
-    void update_zdata (void)
+    void update_zdata ()
     {
       set_zlim (m_zdata.get_limits ());
 
       update_data ();
     }
 
-    void update_sizedata (void)
+    void update_sizedata ()
     {
       update_data ();
     }
 
-    void update_cdata (void)
+    void update_cdata ()
     {
       if (get_cdata ().matrix_value ().rows () == 1)
         set_clim (m_cdata.get_limits ());
@@ -5442,19 +5497,19 @@
       update_data ();
     }
 
-    void update_cdatamode (void)
+    void update_cdatamode ()
     {
       if (m_cdatamode.is ("auto"))
         update_color ();
     }
 
-    void update_seriesindex (void)
+    void update_seriesindex ()
     {
       if (m_cdatamode.is ("auto"))
         update_color ();
     }
 
-    void update_data (void);
+    void update_data ();
 
   };
 
@@ -5470,13 +5525,15 @@
     // object is added to the axes.
   }
 
-  ~scatter (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (scatter)
+
+  ~scatter () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -5501,19 +5558,19 @@
   {
   public:
 
-    octave_value get_color_data (void) const;
-
-    bool is_aliminclude (void) const
+    octave_value get_color_data () const;
+
+    bool is_aliminclude () const
     { return (m_aliminclude.is_on () && m_alphadatamapping.is ("scaled")); }
-    std::string get_aliminclude (void) const
+    std::string get_aliminclude () const
     { return m_aliminclude.current_value (); }
 
-    bool is_climinclude (void) const
+    bool is_climinclude () const
     { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
-    std::string get_climinclude (void) const
+    std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
-    OCTINTERP_API bool get_do_lighting (void) const;
+    OCTINTERP_API bool get_do_lighting () const;
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -5570,7 +5627,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_xdata.add_constraint (dim_vector (-1, -1));
       m_ydata.add_constraint (dim_vector (-1, -1));
@@ -5619,7 +5676,7 @@
 
 
   private:
-    void update_alphadata (void)
+    void update_alphadata ()
     {
       if (alphadatamapping_is ("scaled"))
         set_alim (m_alphadata.get_limits ());
@@ -5627,7 +5684,7 @@
         m_alim = m_alphadata.get_limits ();
     }
 
-    void update_cdata (void)
+    void update_cdata ()
     {
       if (cdatamapping_is ("scaled"))
         set_clim (m_cdata.get_limits ());
@@ -5635,19 +5692,19 @@
         m_clim = m_cdata.get_limits ();
     }
 
-    void update_xdata (void)
+    void update_xdata ()
     {
       update_normals (true);
       set_xlim (m_xdata.get_limits ());
     }
 
-    void update_ydata (void)
+    void update_ydata ()
     {
       update_normals (true);
       set_ylim (m_ydata.get_limits ());
     }
 
-    void update_zdata (void)
+    void update_zdata ()
     {
       update_normals (true);
       set_zlim (m_zdata.get_limits ());
@@ -5656,19 +5713,19 @@
     OCTINTERP_API void update_face_normals (bool reset, bool force = false);
     OCTINTERP_API void update_vertex_normals (bool reset, bool force = false);
 
-    void update_facenormalsmode (void)
+    void update_facenormalsmode ()
     { update_face_normals (false); }
 
-    void update_vertexnormalsmode (void)
+    void update_vertexnormalsmode ()
     { update_vertex_normals (false); }
 
-    void update_edgelighting (void)
+    void update_edgelighting ()
     { update_normals (false); }
 
-    void update_facelighting (void)
+    void update_facelighting ()
     { update_normals (false); }
 
-    void update_visible (void)
+    void update_visible ()
     {
       if (is_visible ())
         update_normals (false);
@@ -5684,13 +5741,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~surface (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (surface)
+
+  ~surface () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -5737,12 +5796,12 @@
     END_PROPERTIES
 
   private:
-    OCTINTERP_API void update_limits (void) const;
+    OCTINTERP_API void update_limits () const;
 
     OCTINTERP_API void update_limits (const graphics_handle& h) const;
 
   protected:
-    void init (void)
+    void init ()
     { }
 
   };
@@ -5755,13 +5814,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~hggroup (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (hggroup)
+
+  ~hggroup () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   OCTINTERP_API void update_axis_limits (const std::string& axis_type);
 
@@ -5824,7 +5885,7 @@
     END_PROPERTIES
 
     // Make "Label" an alias for "Text".
-    std::string get_label (void) const
+    std::string get_label () const
     {
       return get_text ();
     }
@@ -5835,7 +5896,7 @@
     }
 
     // Make "Callback" an alias for "MenuSelectedFcn".
-    octave_value get_callback (void) const
+    octave_value get_callback () const
     {
       return get_menuselectedfcn ();
     }
@@ -5846,7 +5907,7 @@
     }
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint ("min", 0, true);
     }
@@ -5860,13 +5921,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uimenu (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uimenu)
+
+  ~uimenu () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -5894,7 +5957,7 @@
 
     // FIXME: the list may contain duplicates.
     //        Should we return only unique elements?
-    const std::list<graphics_handle> get_dependent_obj_list (void)
+    const std::list<graphics_handle> get_dependent_obj_list ()
     { return m_dependent_obj_list; }
 
     // See the genprops.awk script for an explanation of the
@@ -5910,7 +5973,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint (dim_vector (1, 2));
       m_position.add_constraint (dim_vector (2, 1));
@@ -5921,7 +5984,7 @@
     // List of objects that might depend on this uicontextmenu object
     std::list<graphics_handle> m_dependent_obj_list;
 
-    OCTINTERP_API void update_beingdeleted (void);
+    OCTINTERP_API void update_beingdeleted ();
 
   };
 
@@ -5933,13 +5996,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uicontextmenu (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uicontextmenu)
+
+  ~uicontextmenu () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6008,7 +6073,7 @@
     std::string m_cached_units;
 
   protected:
-    void init (void)
+    void init ()
     {
       m_cdata.add_constraint ("double");
       m_cdata.add_constraint ("single");
@@ -6021,20 +6086,20 @@
       m_cached_units = get_units ();
     }
 
-    OCTINTERP_API void update_text_extent (void);
-
-    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)
+    OCTINTERP_API void update_text_extent ();
+
+    void update_string () { update_text_extent (); }
+    void update_fontname () { update_text_extent (); }
+    void update_fontsize () { update_text_extent (); }
+    void update_fontangle ()
     {
       update_text_extent ();
     }
-    void update_fontweight (void) { update_text_extent (); }
+    void update_fontweight () { update_text_extent (); }
 
     OCTINTERP_API void update_fontunits (const caseless_str& old_units);
 
-    OCTINTERP_API void update_units (void);
+    OCTINTERP_API void update_units ();
 
   };
 
@@ -6046,13 +6111,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uicontrol (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uicontrol)
+
+  ~uicontrol () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6119,19 +6186,19 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint (dim_vector (1, 4));
       m_borderwidth.add_constraint ("min", 0.0, true);
       m_fontsize.add_constraint ("min", 0.0, false);
     }
 
-    // void update_text_extent (void);
-    // 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) { update_fontweight (); }
+    // void update_text_extent ();
+    // void update_string () { update_text_extent (); }
+    // void update_fontname () { update_text_extent (); }
+    // void update_fontsize () { update_text_extent (); }
+    // void update_fontangle () { update_text_extent (); }
+    // void update_fontweight () { update_fontweight (); }
 
     OCTINTERP_API void update_units (const caseless_str& old_units);
     OCTINTERP_API void update_fontunits (const caseless_str& old_units);
@@ -6146,13 +6213,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uibuttongroup (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uibuttongroup)
+
+  ~uibuttongroup () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6211,7 +6280,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_borderwidth.add_constraint ("min", 0.0, true);
       m_fontsize.add_constraint ("min", 0.0, false);
@@ -6231,13 +6300,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uipanel (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uipanel)
+
+  ~uipanel () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6303,14 +6374,14 @@
       radio_property units S , "normalized|inches|centimeters|points|{pixels}|characters"
     END_PROPERTIES
 
-    OCTINTERP_API Matrix get_extent_matrix (void) const;
-
-    OCTINTERP_API Matrix get_backgroundcolor_rgb (void);
-
-    OCTINTERP_API Matrix get_alternatebackgroundcolor_rgb (void);
+    OCTINTERP_API Matrix get_extent_matrix () const;
+
+    OCTINTERP_API Matrix get_backgroundcolor_rgb ();
+
+    OCTINTERP_API Matrix get_alternatebackgroundcolor_rgb ();
 
   protected:
-    void init (void)
+    void init ()
     {
       m_position.add_constraint (dim_vector (1, 4));
       m_extent.add_constraint (dim_vector (1, 4));
@@ -6321,15 +6392,15 @@
 
     OCTINTERP_API void update_units (const caseless_str& old_units);
     OCTINTERP_API void update_fontunits (const caseless_str& old_units);
-    void update_table_extent (void) { };
-    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)
+    void update_table_extent () { };
+    void update_data () { update_table_extent (); }
+    void update_fontname () { update_table_extent (); }
+    void update_fontsize () { update_table_extent (); }
+    void update_fontangle ()
     {
       update_table_extent ();
     }
-    void update_fontweight (void) { update_table_extent (); }
+    void update_fontweight () { update_table_extent (); }
   };
 
 private:
@@ -6340,13 +6411,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uitable (void) { }
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitable)
+
+  ~uitable () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6377,7 +6450,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     { }
   };
 
@@ -6389,7 +6462,9 @@
     : base_graphics_object (), m_properties (mh, p), m_default_properties ()
   { }
 
-  ~uitoolbar (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitoolbar)
+
+  ~uitoolbar () = default;
 
   void override_defaults (base_graphics_object& obj)
   {
@@ -6430,23 +6505,23 @@
 
   OCTINTERP_API octave_value get_default (const caseless_str& name) const;
 
-  octave_value get_defaults (void) const
+  octave_value get_defaults () const
   {
     return m_default_properties.as_struct ("default");
   }
 
-  property_list get_defaults_list (void) const
+  property_list get_defaults_list () const
   {
     return m_default_properties;
   }
 
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
-
-  OCTINTERP_API void reset_default_properties (void);
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
+
+  OCTINTERP_API void reset_default_properties ();
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6487,7 +6562,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_cdata.add_constraint ("double");
       m_cdata.add_constraint ("single");
@@ -6505,13 +6580,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uipushtool (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uipushtool)
+
+  ~uipushtool () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6553,7 +6630,7 @@
     END_PROPERTIES
 
   protected:
-    void init (void)
+    void init ()
     {
       m_cdata.add_constraint ("double");
       m_cdata.add_constraint ("single");
@@ -6571,13 +6648,15 @@
     : base_graphics_object (), m_properties (mh, p)
   { }
 
-  ~uitoggletool (void) = default;
-
-  base_properties& get_properties (void) { return m_properties; }
-
-  const base_properties& get_properties (void) const { return m_properties; }
-
-  bool valid_object (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (uitoggletool)
+
+  ~uitoggletool () = default;
+
+  base_properties& get_properties () { return m_properties; }
+
+  const base_properties& get_properties () const { return m_properties; }
+
+  bool valid_object () const { return true; }
 
   bool has_readonly_property (const caseless_str& pname) const
   {
@@ -6611,7 +6690,7 @@
 
   friend class graphics_event;
 
-  base_graphics_event (void)
+  base_graphics_event ()
     : m_busyaction (QUEUE)
   { };
 
@@ -6619,11 +6698,13 @@
     : m_busyaction (busyaction)
   { };
 
-  virtual ~base_graphics_event (void) = default;
-
-  int get_busyaction (void) { return m_busyaction; };
-
-  virtual void execute (void) = 0;
+  OCTAVE_DEFAULT_COPY_MOVE (base_graphics_event)
+
+  virtual ~base_graphics_event () = default;
+
+  int get_busyaction () { return m_busyaction; };
+
+  virtual void execute () = 0;
 
 private:
   int m_busyaction;
@@ -6637,17 +6718,17 @@
 
   typedef void (*event_fcn) (void *);
 
-  graphics_event (void) = default;
+  graphics_event () = default;
 
   graphics_event (base_graphics_event *new_rep) : m_rep (new_rep) { }
 
   graphics_event (const graphics_event&) = default;
 
-  ~graphics_event (void) = default;
+  ~graphics_event () = default;
 
   graphics_event& operator = (const graphics_event&) = default;
 
-  int get_busyaction (void)
+  int get_busyaction ()
   {
     if (ok ())
       return m_rep->get_busyaction ();
@@ -6655,13 +6736,13 @@
       error ("graphics_event::busyaction: invalid graphics_event");
   }
 
-  void execute (void)
+  void execute ()
   {
     if (ok ())
       m_rep->execute ();
   }
 
-  bool ok (void) const { return (m_rep != nullptr); }
+  bool ok () const { return (m_rep != nullptr); }
 
   static OCTINTERP_API graphics_event
   create_callback_event (const graphics_handle& h,
@@ -6691,255 +6772,10 @@
   std::shared_ptr <base_graphics_event> m_rep;
 };
 
-class OCTINTERP_API gh_manager
-{
-public:
-
-  typedef std::pair<uint8NDArray /*pixels*/, std::string /*svg*/> latex_data;
-
-  OCTINTERP_API gh_manager (octave::interpreter& interp);
-
-  // FIXME: eventually eliminate these static functions and access
-  // gh_manager object through the interpreter.
-
-  OCTINTERP_API graphics_handle get_handle (bool integer_figure_handle);
-
-  OCTINTERP_API void free (const graphics_handle& h, bool from_root = false);
-
-  OCTINTERP_API void renumber_figure (const graphics_handle& old_gh,
-                                      const graphics_handle& new_gh);
-
-  graphics_handle lookup (double val) const
-  {
-    const_iterator p = (octave::math::isnan (val)
-                        ? m_handle_map.end () : m_handle_map.find (val));
-
-    return (p != m_handle_map.end ()) ? p->first : graphics_handle ();
-  }
-
-  graphics_handle lookup (const octave_value& val) const
-  {
-    return (val.is_real_scalar ()
-            ? lookup (val.double_value ()) : graphics_handle ());
-  }
-
-  graphics_object get_object (double val) const
-  {
-    return get_object (lookup (val));
-  }
-
-  graphics_object get_object (const graphics_handle& h) const
-  {
-    const_iterator p = (h.ok () ? m_handle_map.find (h) : m_handle_map.end ());
-
-    return (p != m_handle_map.end ()) ? p->second : graphics_object ();
-  }
-
-  OCTINTERP_API graphics_handle
-  make_graphics_handle (const std::string& go_name,
-                        const graphics_handle& p,
-                        bool integer_figure_handle = false,
-                        bool call_createfcn = true,
-                        bool notify_toolkit = true);
-
-  OCTINTERP_API graphics_handle
-  make_figure_handle (double val, bool notify_toolkit = true);
-
-  OCTINTERP_API void push_figure (const graphics_handle& h);
-
-  OCTINTERP_API void pop_figure (const graphics_handle& h);
-
-  graphics_handle current_figure (void) const
-  {
-    graphics_handle retval;
-
-    for (const auto& hfig : m_figure_list)
-      {
-        if (is_handle_visible (hfig))
-          retval = hfig;
-      }
-
-    return retval;
-  }
-
-  Matrix handle_list (bool show_hidden = false)
-  {
-    Matrix retval (1, m_handle_map.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& h_iter : m_handle_map)
-      {
-        graphics_handle h = h_iter.first;
-
-        if (show_hidden || is_handle_visible (h))
-          retval(i++) = h.value ();
-      }
-
-    retval.resize (1, i);
-
-    return retval;
-  }
-
-  void lock (void) { m_graphics_lock.lock (); }
-
-  bool try_lock (void) { return m_graphics_lock.try_lock (); }
-
-  void unlock (void) { m_graphics_lock.unlock (); }
-
-  Matrix figure_handle_list (bool show_hidden = false)
-  {
-    Matrix retval (1, m_figure_list.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& hfig : m_figure_list)
-      {
-        if (show_hidden || is_handle_visible (hfig))
-          retval(i++) = hfig.value ();
-      }
-
-    retval.resize (1, i);
-
-    return retval;
-  }
-
-  OCTINTERP_API void
-  execute_listener (const graphics_handle& h, const octave_value& l);
-
-  void execute_callback (const graphics_handle& h,
-                         const std::string& name,
-                         const octave_value& data = Matrix ())
-  {
-    octave_value cb;
-
-    if (true)
-      {
-        octave::autolock guard (graphics_lock ());
-
-        graphics_object go = get_object (h);
-
-        if (go.valid_object ())
-          cb = go.get (name);
-      }
-
-    execute_callback (h, cb, data);
-  }
-
-  OCTINTERP_API void
-  execute_callback (const graphics_handle& h, const octave_value& cb,
-                    const octave_value& data = Matrix ());
-
-  OCTINTERP_API void
-  post_callback (const graphics_handle& h, const std::string& name,
-                 const octave_value& data = Matrix ());
-
-  OCTINTERP_API void
-  post_function (graphics_event::event_fcn fcn, void *fcn_data = nullptr);
-
-  OCTINTERP_API void
-  post_set (const graphics_handle& h, const std::string& name,
-            const octave_value& value, bool notify_toolkit = true,
-            bool redraw_figure = false);
-
-  OCTINTERP_API int process_events (bool force = false);
-
-  OCTINTERP_API void enable_event_processing (bool enable = true);
-
-  bool is_handle_visible (const graphics_handle& h) const
-  {
-    bool retval = false;
-
-    graphics_object go = get_object (h);
-
-    if (go.valid_object ())
-      retval = go.is_handle_visible ();
-
-    return retval;
-  }
-
-  OCTINTERP_API void close_all_figures (void);
-
-  OCTINTERP_API void restore_gcbo (void);
-
-  OCTINTERP_API void post_event (const graphics_event& e);
-
-  octave::mutex graphics_lock (void)
-  {
-    return m_graphics_lock;
-  }
-
-  latex_data get_latex_data (const std::string& key) const
-  {
-    latex_data retval;
-
-    const auto it = m_latex_cache.find (key);
-
-    if (it != m_latex_cache.end ())
-      retval = it->second;
-
-    return retval;
-  }
-
-  void set_latex_data (const std::string& key, latex_data val)
-  {
-    // Limit the number of cache entries to 500
-    if (m_latex_keys.size () >= 500)
-      {
-        auto it = m_latex_cache.find (m_latex_keys.front ());
-
-        if (it != m_latex_cache.end ())
-          m_latex_cache.erase (it);
-
-        m_latex_keys.pop_front ();
-      }
-
-    m_latex_cache[key] = val;
-    m_latex_keys.push_back (key);
-  }
-
-private:
-
-  typedef std::map<graphics_handle, graphics_object>::iterator iterator;
-  typedef std::map<graphics_handle, graphics_object>::const_iterator
-    const_iterator;
-
-  typedef std::set<graphics_handle>::iterator free_list_iterator;
-  typedef std::set<graphics_handle>::const_iterator const_free_list_iterator;
-
-  typedef std::list<graphics_handle>::iterator figure_list_iterator;
-  typedef std::list<graphics_handle>::const_iterator const_figure_list_iterator;
-
-  octave::interpreter& m_interpreter;
-
-  // A map of handles to graphics objects.
-  std::map<graphics_handle, graphics_object> m_handle_map;
-
-  // The available graphics handles.
-  std::set<graphics_handle> m_handle_free_list;
-
-  // The next handle available if m_handle_free_list is empty.
-  double m_next_handle;
-
-  // The allocated figure handles.  Top of the stack is most recently
-  // created.
-  std::list<graphics_handle> m_figure_list;
-
-  // The lock for accessing the graphics sytsem.
-  octave::mutex m_graphics_lock;
-
-  // The list of events queued by graphics toolkits.
-  std::list<graphics_event> m_event_queue;
-
-  // The stack of callback objects.
-  std::list<graphics_object> m_callback_objects;
-
-  // A flag telling whether event processing must be constantly on.
-  int m_event_processing;
-
-  // Cache of already parsed latex strings. Store a separate list of keys
-  // to allow for erasing oldest entries if cache size becomes too large.
-  std::unordered_map<std::string, latex_data> m_latex_cache;
-  std::list<std::string> m_latex_keys;
-};
+OCTINTERP_API base_graphics_object *
+make_graphics_object_from_type (const caseless_str& type,
+                                const graphics_handle& h = graphics_handle (),
+                                const graphics_handle& p = graphics_handle ());
 
 OCTINTERP_API void
 get_children_limits (double& min_val, double& max_val,
@@ -6949,173 +6785,13 @@
 OCTINTERP_API int calc_dimensions (const graphics_object& gh);
 
 // This function is NOT equivalent to the scripting language function gcf.
-OCTINTERP_API graphics_handle gcf (void);
+OCTINTERP_API graphics_handle gcf ();
 
 // This function is NOT equivalent to the scripting language function gca.
-OCTINTERP_API graphics_handle gca (void);
-
-OCTINTERP_API void close_all_figures (void);
+OCTINTERP_API graphics_handle gca ();
+
+OCTINTERP_API void close_all_figures ();
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_scaler' instead")
-typedef octave::base_scaler base_scaler;
-
-OCTAVE_DEPRECATED (7, "use 'octave::lin_scaler' instead")
-typedef octave::lin_scaler lin_scaler;
-
-OCTAVE_DEPRECATED (7, "use 'octave::log_scaler' instead")
-typedef octave::log_scaler log_scaler;
-
-OCTAVE_DEPRECATED (7, "use 'octave::neg_log_scaler' instead")
-typedef octave::neg_log_scaler neg_log_scaler;
-
-OCTAVE_DEPRECATED (7, "use 'octave::scaler' instead")
-typedef octave::scaler scaler;
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_property' instead")
-typedef octave::base_property base_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::string_property' instead")
-typedef octave::string_property string_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::string_array_property' instead")
-typedef octave::string_array_property string_array_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::text_label_property' instead")
-typedef octave::text_label_property text_label_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::radio_values' instead")
-typedef octave::radio_values radio_values;
-
-OCTAVE_DEPRECATED (7, "use 'octave::radio_property' instead")
-typedef octave::radio_property radio_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::color_values' instead")
-typedef octave::color_values color_values;
-
-OCTAVE_DEPRECATED (7, "use 'octave::color_property' instead")
-typedef octave::color_property color_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::double_property' instead")
-typedef octave::double_property double_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::double_radio_property' instead")
-typedef octave::double_radio_property double_radio_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::array_property' instead")
-typedef octave::array_property array_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::row_vector_property' instead")
-typedef octave::row_vector_property row_vector_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::bool_property' instead")
-typedef octave::bool_property bool_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::handle_property' instead")
-typedef octave::handle_property handle_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::any_property' instead")
-typedef octave::any_property any_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::children_property' instead")
-typedef octave::children_property children_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::callback_property' instead")
-typedef octave::callback_property callback_property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::property' instead")
-typedef octave::property property;
-
-OCTAVE_DEPRECATED (7, "use 'octave::pval_vector' instead")
-typedef octave::pval_vector pval_vector;
-
-OCTAVE_DEPRECATED (7, "use 'octave::property_list' instead")
-typedef octave::property_list property_list;
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_properties' instead")
-typedef octave::base_properties base_properties;
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_object' instead")
-typedef octave::base_graphics_object base_graphics_object;
-
-OCTAVE_DEPRECATED (7, "use 'octave::graphics_object' instead")
-typedef octave::graphics_object graphics_object;
-
-OCTAVE_DEPRECATED (7, "use 'octave::root_figure' instead")
-typedef octave::root_figure root_figure;
-
-OCTAVE_DEPRECATED (7, "use 'octave::figure' instead")
-typedef octave::figure figure;
-
-OCTAVE_DEPRECATED (7, "use 'octave::graphics_xform' instead")
-typedef octave::graphics_xform graphics_xform;
-
-OCTAVE_DEPRECATED (7, "use 'octave::axes' instead")
-typedef octave::axes axes;
-
-OCTAVE_DEPRECATED (7, "use 'octave::line' instead")
-typedef octave::line line;
-
-OCTAVE_DEPRECATED (7, "use 'octave::text' instead")
-typedef octave::text text;
-
-OCTAVE_DEPRECATED (7, "use 'octave::image' instead")
-typedef octave::image image;
-
-OCTAVE_DEPRECATED (7, "use 'octave::light' instead")
-typedef octave::light light;
-
-OCTAVE_DEPRECATED (7, "use 'octave::patch' instead")
-typedef octave::patch patch;
-
-OCTAVE_DEPRECATED (7, "use 'octave::scatter' instead")
-typedef octave::scatter scatter;
-
-OCTAVE_DEPRECATED (7, "use 'octave::surface' instead")
-typedef octave::surface surface;
-
-OCTAVE_DEPRECATED (7, "use 'octave::hggroup' instead")
-typedef octave::hggroup hggroup;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uimenu' instead")
-typedef octave::uimenu uimenu;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uicontextmenu' instead")
-typedef octave::uicontextmenu uicontextmenu;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uicontrol' instead")
-typedef octave::uicontrol uicontrol;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uibuttongroup' instead")
-typedef octave::uibuttongroup uibuttongroup;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uipanel' instead")
-typedef octave::uipanel uipanel;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uitable' instead")
-typedef octave::uitable uitable;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uitoolbar' instead")
-typedef octave::uitoolbar uitoolbar;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uipushtool' instead")
-typedef octave::uipushtool uipushtool;
-
-OCTAVE_DEPRECATED (7, "use 'octave::uitoggletool' instead")
-typedef octave::uitoggletool uitoggletool;
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_event' instead")
-typedef octave::base_graphics_event base_graphics_event;
-
-OCTAVE_DEPRECATED (7, "use 'octave::graphics_event' instead")
-typedef octave::graphics_event graphics_event;
-
-OCTAVE_DEPRECATED (7, "use 'octave::gh_manager' instead")
-typedef octave::gh_manager gh_manager;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/gtk-manager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gtk-manager.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -28,15 +28,15 @@
 #endif
 
 #include "error.h"
+#include "interpreter.h"
 #include "graphics-toolkit.h"
 #include "gtk-manager.h"
 #include "ovl.h"
-#include "parse.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 graphics_toolkit
-gtk_manager::get_toolkit (void) const
+gtk_manager::get_toolkit () const
 {
   graphics_toolkit retval;
 
@@ -55,7 +55,7 @@
 
       octave_value_list args;
       args(0) = m_dtk;
-      feval ("graphics_toolkit", args);
+      m_interpreter.feval ("graphics_toolkit", args);
 
       pl = m_loaded_toolkits.find (m_dtk);
 
--- a/libinterp/corefcn/gtk-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gtk-manager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,18 +37,22 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class interpreter;
+
 class OCTINTERP_API gtk_manager
 {
 public:
 
-  gtk_manager (void) { }
+  gtk_manager (interpreter& interp) : m_interpreter (interp) { }
 
-  ~gtk_manager (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gtk_manager)
+
+  ~gtk_manager ()
   {
     unload_all_toolkits ();
   }
 
-  graphics_toolkit get_toolkit (void) const;
+  graphics_toolkit get_toolkit () const;
 
   void register_toolkit (const std::string& name);
 
@@ -74,7 +78,7 @@
       return graphics_toolkit ();
   }
 
-  Cell available_toolkits_list (void) const
+  Cell available_toolkits_list () const
   {
     Cell m (1, m_available_toolkits.size ());
 
@@ -85,7 +89,7 @@
     return m;
   }
 
-  Cell loaded_toolkits_list (void) const
+  Cell loaded_toolkits_list () const
   {
     Cell m (1, m_loaded_toolkits.size ());
 
@@ -96,7 +100,7 @@
     return m;
   }
 
-  void unload_all_toolkits (void)
+  void unload_all_toolkits ()
   {
     while (! m_loaded_toolkits.empty ())
       {
@@ -112,10 +116,12 @@
       }
   }
 
-  std::string default_toolkit (void) const { return m_dtk; }
+  std::string default_toolkit () const { return m_dtk; }
 
 private:
 
+  interpreter& m_interpreter;
+
   // The name of the default toolkit.
   std::string m_dtk;
 
--- a/libinterp/corefcn/gzfstream.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/gzfstream.h	Fri Jun 23 20:51:51 2023 +0200
@@ -58,11 +58,7 @@
   //  Default constructor.
   gzfilebuf ();
 
-  // No copying!
-
-  gzfilebuf (const gzfilebuf&) = delete;
-
-  gzfilebuf& operator = (const gzfilebuf&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (gzfilebuf)
 
   //  Destructor.
   virtual ~gzfilebuf ();
@@ -469,11 +465,11 @@
 private:
   // Underlying manipulator function
   gzofstream&
-  (*fcn)(gzofstream&, T1, T2);
+  (*m_fcn)(gzofstream&, T1, T2);
 
   // Arguments for manipulator function
-  T1 val1;
-  T2 val2;
+  T1 m_val1;
+  T2 m_val2;
 };
 
 // Manipulator function thunks through to stream buffer
@@ -490,14 +486,14 @@
 gzomanip2<T1, T2>::gzomanip2 (gzofstream &(*f)(gzofstream&, T1, T2),
                               T1 v1,
                               T2 v2)
-  : fcn(f), val1(v1), val2(v2)
+  : m_fcn(f), m_val1(v1), m_val2(v2)
 { }
 
 // Insertor applies underlying manipulator function to stream
 template <typename T1, typename T2>
 inline gzofstream&
 operator<<(gzofstream& s, const gzomanip2<T1, T2>& m)
-{ return (*m.fcn)(s, m.val1, m.val2); }
+{ return (*m.m_fcn)(s, m.m_val1, m.m_val2); }
 
 // Insert this onto stream to simplify setting of compression level
 inline gzomanip2<int, int>
--- a/libinterp/corefcn/help.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/help.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -320,7 +320,7 @@
   return which (name, type);
 }
 
-string_vector help_system::make_name_list (void) const
+string_vector help_system::make_name_list () const
 {
   const static string_vector keywords
     = Fiskeyword ()(0).string_vector_value ();
@@ -447,7 +447,7 @@
     }
 }
 
-std::string help_system::init_built_in_docstrings_file (void)
+std::string help_system::init_built_in_docstrings_file ()
 {
   std::string df = sys::env::getenv ("OCTAVE_BUILT_IN_DOCSTRINGS_FILE");
 
@@ -459,7 +459,7 @@
   return df;
 }
 
-std::string help_system::init_doc_cache_file (void)
+std::string help_system::init_doc_cache_file ()
 {
   std::string def_file = config::prepend_octave_home (OCTAVE_DOC_CACHE_FILE);
 
@@ -468,7 +468,7 @@
   return (env_file.empty () ? def_file : env_file);
 }
 
-std::string help_system::init_info_file (void)
+std::string help_system::init_info_file ()
 {
   std::string std_info_file = config::prepend_octave_home (OCTAVE_INFOFILE);
 
@@ -477,7 +477,7 @@
   return (oct_info_file.empty () ? std_info_file : oct_info_file);
 }
 
-std::string help_system::init_info_program (void)
+std::string help_system::init_info_program ()
 {
   std::string info_prog = sys::env::getenv ("OCTAVE_INFO_PROGRAM");
 
@@ -487,7 +487,7 @@
   return info_prog;
 }
 
-std::string help_system::init_texi_macros_file (void)
+std::string help_system::init_texi_macros_file ()
 {
   std::string def_file
     = config::prepend_octave_home (OCTAVE_TEXI_MACROS_FILE);
@@ -499,7 +499,7 @@
 
 // Return a vector of all functions from this file,
 // for use in command line auto-completion.
-string_vector help_system::local_functions (void) const
+string_vector help_system::local_functions () const
 {
   string_vector retval;
 
@@ -725,7 +725,7 @@
 
 // FIXME: It's not likely that this does the right thing now.
 
-string_vector make_name_list (void)
+string_vector make_name_list ()
 {
   help_system& help_sys = __get_help_system__ ();
 
--- a/libinterp/corefcn/help.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/help.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,7 +59,7 @@
   built_in_docstrings_file (const octave_value_list& args, int nargout);
 
   std::string
-  built_in_docstrings_file (void) const { return m_built_in_docstrings_file; }
+  built_in_docstrings_file () const { return m_built_in_docstrings_file; }
 
   std::string built_in_docstrings_file (const std::string& file)
   {
@@ -68,7 +68,7 @@
 
   octave_value doc_cache_file (const octave_value_list& args, int nargout);
 
-  std::string doc_cache_file (void) const { return m_doc_cache_file; }
+  std::string doc_cache_file () const { return m_doc_cache_file; }
 
   std::string doc_cache_file (const std::string& file)
   {
@@ -77,7 +77,7 @@
 
   octave_value info_file (const octave_value_list& args, int nargout);
 
-  std::string info_file (void) const { return m_info_file; }
+  std::string info_file () const { return m_info_file; }
 
   std::string info_file (const std::string& file)
   {
@@ -86,7 +86,7 @@
 
   octave_value info_program (const octave_value_list& args, int nargout);
 
-  std::string info_program (void) const { return m_info_program; }
+  std::string info_program () const { return m_info_program; }
 
   std::string info_program (const std::string& file)
   {
@@ -95,7 +95,7 @@
 
   octave_value makeinfo_program (const octave_value_list& args, int nargout);
 
-  std::string makeinfo_program (void) const { return m_makeinfo_program; }
+  std::string makeinfo_program () const { return m_makeinfo_program; }
 
   std::string makeinfo_program (const std::string& file)
   {
@@ -105,7 +105,7 @@
   octave_value
   suppress_verbose_help_message (const octave_value_list& args, int nargout);
 
-  bool suppress_verbose_help_message (void) const
+  bool suppress_verbose_help_message () const
   {
     return m_suppress_verbose_help_message;
   }
@@ -117,7 +117,7 @@
 
   octave_value texi_macros_file (const octave_value_list& args, int nargout);
 
-  std::string texi_macros_file (void) const { return m_texi_macros_file; }
+  std::string texi_macros_file () const { return m_texi_macros_file; }
 
   std::string texi_macros_file (const std::string& file)
   {
@@ -129,7 +129,7 @@
   std::string which (const std::string& name) const;
   std::string which (const std::string& name, std::string& type) const;
 
-  string_vector make_name_list (void) const;
+  string_vector make_name_list () const;
 
   void get_help_text (const std::string& name, std::string& text,
                       std::string& format) const;
@@ -169,15 +169,15 @@
   // (--texi-macros-file)
   std::string m_texi_macros_file;
 
-  static std::string init_built_in_docstrings_file (void);
+  static std::string init_built_in_docstrings_file ();
 
-  static std::string init_doc_cache_file (void);
+  static std::string init_doc_cache_file ();
 
-  static std::string init_info_file (void);
+  static std::string init_info_file ();
 
-  static std::string init_info_program (void);
+  static std::string init_info_program ();
 
-  static std::string init_texi_macros_file (void);
+  static std::string init_texi_macros_file ();
 
   template <typename T>
   T set (T& var, const T& new_val)
@@ -187,7 +187,7 @@
     return old_val;
   }
 
-  string_vector local_functions (void) const;
+  string_vector local_functions () const;
 
   bool raw_help_from_symbol_table (const std::string& nm,
                                    std::string& h, std::string& w,
@@ -201,7 +201,7 @@
                                       bool& symbol_found) const;
 };
 
-extern string_vector make_name_list (void);
+extern string_vector make_name_list ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/libinterp/corefcn/hook-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/hook-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -28,7 +28,8 @@
 #endif
 
 #include "hook-fcn.h"
-#include "parse.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -55,7 +56,9 @@
   if (m_data.is_defined ())
     args.append (m_data);
 
-  feval (m_name, args, 0);
+  interpreter& interp = __get_interpreter__ ();
+
+  interp.feval (m_name, args, 0);
 }
 
 void fcn_handle_hook_function::eval (const octave_value_list& initial_args)
@@ -65,7 +68,9 @@
   if (m_data.is_defined ())
     args.append (m_data);
 
-  feval (m_fcn_handle, args, 0);
+  interpreter& interp = __get_interpreter__ ();
+
+  interp.feval (m_fcn_handle, args, 0);
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/hook-fcn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/hook-fcn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,15 +42,13 @@
 {
 public:
 
-  base_hook_function (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY (base_hook_function)
 
-  base_hook_function (const base_hook_function&) = default;
+  virtual ~base_hook_function () = default;
 
-  virtual ~base_hook_function (void) = default;
+  virtual std::string id () const { return ""; }
 
-  virtual std::string id (void) const { return ""; }
-
-  virtual bool is_valid (void) const { return false; }
+  virtual bool is_valid () const { return false; }
 
   virtual void eval (const octave_value_list&) { }
 };
@@ -59,7 +57,7 @@
 {
 public:
 
-  hook_function (void)
+  hook_function ()
   {
     static std::shared_ptr<base_hook_function>
     nil_rep (new base_hook_function ());
@@ -70,15 +68,13 @@
   hook_function (const octave_value& f,
                  const octave_value& d = octave_value ());
 
-  ~hook_function (void) = default;
+  OCTAVE_DEFAULT_COPY (hook_function)
 
-  hook_function (const hook_function& hf) = default;
+  ~hook_function () = default;
 
-  hook_function& operator = (const hook_function& hf) = default;
+  std::string id () const { return m_rep->id (); }
 
-  std::string id (void) const { return m_rep->id (); }
-
-  bool is_valid (void) const { return m_rep->is_valid (); }
+  bool is_valid () const { return m_rep->is_valid (); }
 
   void eval (const octave_value_list& initial_args)
   {
@@ -94,15 +90,19 @@
 {
 public:
 
+  named_hook_function () = delete;
+
   named_hook_function (const std::string& n, const octave_value& d)
     : m_name (n), m_data (d)
   { }
 
+  OCTAVE_DEFAULT_COPY_DELETE (named_hook_function)
+
   void eval (const octave_value_list& initial_args);
 
-  std::string id (void) const { return m_name; }
+  std::string id () const { return m_name; }
 
-  bool is_valid (void) const { return is_valid_function (m_name); }
+  bool is_valid () const { return is_valid_function (m_name); }
 
 private:
 
@@ -115,6 +115,8 @@
 {
 public:
 
+  fcn_handle_hook_function () = delete;
+
   fcn_handle_hook_function (const octave_value& fh_arg, const octave_value& d)
     : m_ident (), m_valid (false), m_fcn_handle (fh_arg), m_data (d)
   {
@@ -130,11 +132,13 @@
       }
   }
 
+  OCTAVE_DEFAULT_COPY_DELETE (fcn_handle_hook_function)
+
   void eval (const octave_value_list& initial_args);
 
-  std::string id (void) const { return m_ident; }
+  std::string id () const { return m_ident; }
 
-  bool is_valid (void) const { return m_valid; }
+  bool is_valid () const { return m_valid; }
 
 private:
 
@@ -156,17 +160,11 @@
   typedef map_type::iterator iterator;
   typedef map_type::const_iterator const_iterator;
 
-  hook_function_list (void) = default;
-
-  ~hook_function_list (void) = default;
-
-  hook_function_list (const hook_function_list& lst) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_DELETE (hook_function_list)
 
-  hook_function_list& operator = (const hook_function_list& lst) = default;
+  bool empty () const { return m_fcn_map.empty (); }
 
-  bool empty (void) const { return m_fcn_map.empty (); }
-
-  void clear (void) { m_fcn_map.clear (); }
+  void clear () { m_fcn_map.clear (); }
 
   void insert (const std::string& id, const hook_function& f)
   {
@@ -183,9 +181,9 @@
     return m_fcn_map.find (id);
   }
 
-  iterator end (void) { return m_fcn_map.end (); }
+  iterator end () { return m_fcn_map.end (); }
 
-  const_iterator end (void) const { return m_fcn_map.end (); }
+  const_iterator end () const { return m_fcn_map.end (); }
 
   void erase (iterator p) { m_fcn_map.erase (p); }
 
@@ -214,21 +212,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::base_hook_function' instead")
-typedef octave::base_hook_function base_hook_function;
-
-OCTAVE_DEPRECATED (7, "use 'octave::hook_function' instead")
-typedef octave::hook_function hook_function;
-
-OCTAVE_DEPRECATED (7, "use 'octave::named_hook_function' instead")
-typedef octave::named_hook_function named_hook_function;
-
-OCTAVE_DEPRECATED (7, "use 'octave::fcn_handle_hook_function' instead")
-typedef octave::fcn_handle_hook_function fcn_handle_hook_function;
-
-OCTAVE_DEPRECATED (7, "use 'octave::hook_function_list' instead")
-typedef octave::hook_function_list hook_function_list;
 #endif
-
-#endif
--- a/libinterp/corefcn/input.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/input.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -70,7 +70,6 @@
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
-#include "parse.h"
 #include "pt-eval.h"
 #include "pt-stmt.h"
 #include "sighandlers.h"
@@ -259,7 +258,7 @@
 }
 
 static bool
-is_completing_dirfns (void)
+is_completing_dirfns ()
 {
   static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"};
   static const std::size_t dirfns_commands_length = 4;
@@ -386,7 +385,7 @@
   return retval;
 }
 
-static int internal_input_event_hook_fcn (void)
+static int internal_input_event_hook_fcn ()
 {
   octave_quit ();
 
@@ -489,7 +488,7 @@
 
   octave_value retval
     = set_internal_variable (m_mfile_encoding, args, nargout,
-                             "__mfile_encoding__");
+                             "mfile_encoding");
 
   // Additional validation if the encoding has changed.
 
@@ -516,10 +515,10 @@
             {
               m_mfile_encoding = saved_encoding;
               if (errno == EINVAL)
-                error ("__mfile_encoding__: conversion from encoding '%s' "
+                error ("mfile_encoding: conversion from encoding '%s' "
                        "not supported", encoding.c_str ());
               else
-                error ("__mfile_encoding__: error %d opening encoding '%s'",
+                error ("mfile_encoding: error %d opening encoding '%s'",
                        errno, encoding.c_str ());
             }
           else
@@ -529,8 +528,7 @@
     }
 
   // Synchronize the related gui preference for editor encoding
-  feval ("__event_manager_gui_preference__",
-         ovl ("editor/default_encoding", m_mfile_encoding));
+  F__event_manager_gui_preference__ (m_interpreter, ovl ("editor/default_encoding", m_mfile_encoding));
 
   return retval;
 }
@@ -747,7 +745,7 @@
   return retval;
 }
 
-bool input_system::have_input_event_hooks (void) const
+bool input_system::have_input_event_hooks () const
 {
   return ! m_input_event_hook_functions.empty ();
 }
@@ -769,12 +767,12 @@
   return true;
 }
 
-void input_system::clear_input_event_hooks (void)
+void input_system::clear_input_event_hooks ()
 {
   m_input_event_hook_functions.clear ();
 }
 
-void input_system::run_input_event_hooks (void)
+void input_system::run_input_event_hooks ()
 {
   m_input_event_hook_functions.run ();
 }
@@ -889,9 +887,9 @@
 
   std::string get_input (const std::string& prompt, bool& eof);
 
-  std::string input_source (void) const { return s_in_src; }
+  std::string input_source () const { return s_in_src; }
 
-  bool input_from_terminal (void) const { return true; }
+  bool input_from_terminal () const { return true; }
 
 private:
 
@@ -918,9 +916,9 @@
 
   std::string get_input (const std::string& prompt, bool& eof);
 
-  std::string input_source (void) const { return s_in_src; }
+  std::string input_source () const { return s_in_src; }
 
-  bool input_from_file (void) const { return true; }
+  bool input_from_file () const { return true; }
 
 private:
 
@@ -942,9 +940,9 @@
 
   std::string get_input (const std::string& prompt, bool& eof);
 
-  std::string input_source (void) const { return s_in_src; }
+  std::string input_source () const { return s_in_src; }
 
-  bool input_from_eval_string (void) const { return true; }
+  bool input_from_eval_string () const { return true; }
 
 private:
 
@@ -1444,8 +1442,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  std::string hook_fcn_id = args(
-                              0).xstring_value ("remove_input_event_hook: argument not valid as a hook function name or id");
+  std::string hook_fcn_id = args(0).xstring_value ("remove_input_event_hook: argument not valid as a hook function name or id");
 
   bool warn = (nargin < 2);
 
@@ -1497,9 +1494,7 @@
 @seealso{PS2, PS4}
 @end deftypefn */)
 {
-  input_system& input_sys = interp.get_input_system ();
-
-  return input_sys.PS1 (args, nargout);
+  return interp.PS1 (args, nargout);
 }
 
 DEFMETHOD (PS2, interp, args, nargout,
@@ -1521,9 +1516,7 @@
 @seealso{PS1, PS4}
 @end deftypefn */)
 {
-  input_system& input_sys = interp.get_input_system ();
-
-  return input_sys.PS2 (args, nargout);
+  return interp.PS2 (args, nargout);
 }
 
 DEFMETHOD (completion_append_char, interp, args, nargout,
@@ -1577,14 +1570,31 @@
   return input_sys.gud_mode (args, nargout);
 }
 
-DEFMETHOD (__mfile_encoding__, interp, args, nargout,
+DEFMETHOD (mfile_encoding, interp, args, nargout,
            doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{current_encoding} =} __mfile_encoding__ ()
-@deftypefnx {} {} __mfile_encoding__ (@var{new_encoding})
-@deftypefnx {} {@var{old_encoding} =} __mfile_encoding__ (@var{new_encoding})
-Query or set the codepage that is used for reading m-files.
+@deftypefn  {} {@var{current_encoding} =} mfile_encoding ()
+@deftypefnx {} {} mfile_encoding (@var{new_encoding})
+@deftypefnx {} {@var{old_encoding} =} mfile_encoding (@var{new_encoding})
+Query or set the encoding that is used for reading m-files.
+
+The input and output are strings naming an encoding, e.g., "utf-8".
+
+This encoding is used by Octave's parser when reading m-files unless a
+different encoding was set for a specific directory containing m-files using
+the function @code{dir_encoding} or in a file @file{.oct-config} in that
+directory.
 
-The input and output are strings naming a particular codepage, e.g., "utf-8".
+The special value @qcode{"system"} selects the encoding that matches the system
+locale.
+
+If the m-file encoding is changed after the m-files have already been parsed,
+the files have to be parsed again for that change to take effect.  That can be
+triggered with the command @code{clear all}.
+
+Additionally, this encoding is used to load and save files with the built-in
+editor in Octave's GUI.
+
+@seealso{dir_encoding}
 @end deftypefn */)
 {
   input_system& input_sys = interp.get_input_system ();
@@ -1592,6 +1602,8 @@
   return input_sys.mfile_encoding (args, nargout);
 }
 
+DEFALIAS (__mfile_encoding__, mfile_encoding);
+
 DEFMETHOD (dir_encoding, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{current_encoding} =} dir_encoding (@var{dir})
@@ -1600,7 +1612,8 @@
 @deftypefnx {} {@var{old_encoding} =} dir_encoding (@var{dir}, @var{new_encoding})
 Query or set the @var{encoding} that is used for reading m-files in @var{dir}.
 
-The per-directory encoding overrides the (globally set) m-file encoding.
+The per-directory encoding overrides the (globally set) m-file encoding,
+@pxref{XREFmfile_encoding,,@code{mfile_encoding}}.
 
 The string @var{DIR} must match how the directory would appear in the load
 path.
@@ -1629,7 +1642,7 @@
 files have to be parsed again for that change to take effect.  That can be done
 with the command @code{clear all}.
 
-@seealso{addpath, path}
+@seealso{addpath, path, mfile_encoding}
 @end deftypefn */)
 {
   int nargin = args.length ();
--- a/libinterp/corefcn/input.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/input.h	Fri Jun 23 20:51:51 2023 +0200
@@ -66,7 +66,7 @@
 
   octave_value PS1 (const octave_value_list& args, int nargout);
 
-  std::string PS1 (void) const { return m_PS1; }
+  std::string PS1 () const { return m_PS1; }
 
   std::string PS1 (const std::string& s)
   {
@@ -79,7 +79,7 @@
 
   octave_value PS2 (const octave_value_list& args, int nargout);
 
-  std::string PS2 (void) const { return m_PS2; }
+  std::string PS2 () const { return m_PS2; }
 
   std::string PS2 (const std::string& s)
   {
@@ -90,7 +90,7 @@
 
   void set_PS2 (const std::string& s) { m_PS2 = s; }
 
-  std::string last_debugging_command (void) const
+  std::string last_debugging_command () const
   {
     return m_last_debugging_command;
   }
@@ -105,7 +105,7 @@
   octave_value
   completion_append_char (const octave_value_list& args, int nargout);
 
-  char completion_append_char (void) const
+  char completion_append_char () const
   {
     return m_completion_append_char;
   }
@@ -121,7 +121,7 @@
 
   octave_value gud_mode (const octave_value_list& args, int nargout);
 
-  bool gud_mode (void) const { return m_gud_mode; }
+  bool gud_mode () const { return m_gud_mode; }
 
   bool gud_mode (bool flag)
   {
@@ -134,7 +134,7 @@
 
   octave_value mfile_encoding (const octave_value_list& args, int nargout);
 
-  std::string mfile_encoding (void) const { return m_mfile_encoding; }
+  std::string mfile_encoding () const { return m_mfile_encoding; }
 
   std::string mfile_encoding (const std::string& s)
   {
@@ -152,7 +152,7 @@
   octave_value
   auto_repeat_debug_command (const octave_value_list& args, int nargout);
 
-  bool auto_repeat_debug_command (void) const
+  bool auto_repeat_debug_command () const
   {
     return m_auto_repeat_debug_command;
   }
@@ -171,15 +171,15 @@
   octave_value_list
   get_user_input (const octave_value_list& args, int nargout);
 
-  bool have_input_event_hooks (void) const;
+  bool have_input_event_hooks () const;
 
   void add_input_event_hook (const hook_function& hook_fcn);
 
   bool remove_input_event_hook (const std::string& hook_fcn_id);
 
-  void clear_input_event_hooks (void);
+  void clear_input_event_hooks ();
 
-  void run_input_event_hooks (void);
+  void run_input_event_hooks ();
 
 private:
 
@@ -229,23 +229,21 @@
     : m_interpreter (interp)
   { }
 
-  base_reader (const base_reader& x)
-    : m_interpreter (x.m_interpreter)
-  { }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_reader)
 
-  virtual ~base_reader (void) = default;
+  virtual ~base_reader () = default;
 
   virtual std::string get_input (const std::string& prompt, bool& eof) = 0;
 
-  virtual std::string input_source (void) const { return s_in_src; }
+  virtual std::string input_source () const { return s_in_src; }
 
   std::string octave_gets (const std::string& prompt, bool& eof);
 
-  virtual bool input_from_terminal (void) const { return false; }
+  virtual bool input_from_terminal () const { return false; }
 
-  virtual bool input_from_file (void) const { return false; }
+  virtual bool input_from_file () const { return false; }
 
-  virtual bool input_from_eval_string (void) const { return false; }
+  virtual bool input_from_eval_string () const { return false; }
 
 protected:
 
@@ -260,6 +258,8 @@
 {
 public:
 
+  input_reader () = delete;
+
   input_reader (interpreter& interp);
 
   input_reader (interpreter& interp, FILE *file);
@@ -268,33 +268,29 @@
 
   input_reader (interpreter& interp, const std::string& str);
 
-  input_reader (const input_reader& ir) = default;
-
-  input_reader& operator = (const input_reader& ir) = default;
-
-  ~input_reader (void) = default;
+  OCTAVE_DEFAULT_COPY_DELETE (input_reader)
 
   std::string get_input (const std::string& prompt, bool& eof)
   {
     return m_rep->get_input (prompt, eof);
   }
 
-  std::string input_source (void) const
+  std::string input_source () const
   {
     return m_rep->input_source ();
   }
 
-  bool input_from_terminal (void) const
+  bool input_from_terminal () const
   {
     return m_rep->input_from_terminal ();
   }
 
-  bool input_from_file (void) const
+  bool input_from_file () const
   {
     return m_rep->input_from_file ();
   }
 
-  bool input_from_eval_string (void) const
+  bool input_from_eval_string () const
   {
     return m_rep->input_from_eval_string ();
   }
--- a/libinterp/corefcn/interpreter-private.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/interpreter-private.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,7 +51,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-interpreter& __get_interpreter__ (void)
+interpreter& __get_interpreter__ ()
 {
   interpreter *interp = interpreter::the_interpreter ();
 
@@ -64,91 +64,91 @@
   return *interp;
 }
 
-dynamic_loader& __get_dynamic_loader__ (void)
+dynamic_loader& __get_dynamic_loader__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_dynamic_loader ();
 }
 
-error_system& __get_error_system__ (void)
+error_system& __get_error_system__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_error_system ();
 }
 
-gh_manager& __get_gh_manager__ (void)
+gh_manager& __get_gh_manager__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_gh_manager ();
 }
 
-help_system& __get_help_system__ (void)
+help_system& __get_help_system__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_help_system ();
 }
 
-input_system& __get_input_system__ (void)
+input_system& __get_input_system__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_input_system ();
 }
 
-output_system& __get_output_system__ (void)
+output_system& __get_output_system__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_output_system ();
 }
 
-load_path& __get_load_path__ (void)
+load_path& __get_load_path__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_load_path ();
 }
 
-load_save_system& __get_load_save_system__ (void)
+load_save_system& __get_load_save_system__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_load_save_system ();
 }
 
-event_manager& __get_event_manager__ (void)
+event_manager& __get_event_manager__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_event_manager ();
 }
 
-type_info& __get_type_info__ (void)
+type_info& __get_type_info__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_type_info ();
 }
 
-symbol_table& __get_symbol_table__ (void)
+symbol_table& __get_symbol_table__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_symbol_table ();
 }
 
-symbol_scope __get_current_scope__ (void)
+symbol_scope __get_current_scope__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_current_scope ();
 }
 
-symbol_scope __require_current_scope__ (void)
+symbol_scope __require_current_scope__ ()
 {
   symbol_scope scope = __get_current_scope__ ();
 
@@ -158,42 +158,42 @@
   return scope;
 }
 
-tree_evaluator& __get_evaluator__ (void)
+tree_evaluator& __get_evaluator__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_evaluator ();
 }
 
-bp_table& __get_bp_table__ (void)
+bp_table& __get_bp_table__ ()
 {
   tree_evaluator& tw = __get_evaluator__ ();
 
   return tw.get_bp_table ();
 }
 
-child_list& __get_child_list__ (void)
+child_list& __get_child_list__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_child_list ();
 }
 
-cdef_manager& __get_cdef_manager__ (void)
+cdef_manager& __get_cdef_manager__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_cdef_manager ();
 }
 
-display_info& __get_display_info__ (void)
+display_info& __get_display_info__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
   return interp.get_display_info ();
 }
 
-gtk_manager& __get_gtk_manager__ (void)
+gtk_manager& __get_gtk_manager__ ()
 {
   interpreter& interp = __get_interpreter__ ();
 
--- a/libinterp/corefcn/interpreter-private.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/interpreter-private.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,45 +53,45 @@
 class tree_evaluator;
 class type_info;
 
-extern OCTINTERP_API interpreter& __get_interpreter__ (void);
+extern OCTINTERP_API interpreter& __get_interpreter__ ();
 
-extern OCTINTERP_API dynamic_loader& __get_dynamic_loader__ (void);
+extern OCTINTERP_API dynamic_loader& __get_dynamic_loader__ ();
 
-extern OCTINTERP_API error_system& __get_error_system__ (void);
+extern OCTINTERP_API error_system& __get_error_system__ ();
 
-extern OCTINTERP_API gh_manager& __get_gh_manager__ (void);
+extern OCTINTERP_API gh_manager& __get_gh_manager__ ();
 
-extern OCTINTERP_API help_system& __get_help_system__ (void);
+extern OCTINTERP_API help_system& __get_help_system__ ();
 
-extern OCTINTERP_API input_system& __get_input_system__ (void);
+extern OCTINTERP_API input_system& __get_input_system__ ();
 
-extern OCTINTERP_API load_path& __get_load_path__ (void);
+extern OCTINTERP_API load_path& __get_load_path__ ();
 
-extern OCTINTERP_API load_save_system& __get_load_save_system__ (void);
+extern OCTINTERP_API load_save_system& __get_load_save_system__ ();
 
-extern OCTINTERP_API event_manager& __get_event_manager__ (void);
+extern OCTINTERP_API event_manager& __get_event_manager__ ();
 
-extern OCTINTERP_API output_system& __get_output_system__ (void);
+extern OCTINTERP_API output_system& __get_output_system__ ();
 
-extern OCTINTERP_API type_info& __get_type_info__ (void);
+extern OCTINTERP_API type_info& __get_type_info__ ();
 
-extern OCTINTERP_API symbol_table& __get_symbol_table__ (void);
+extern OCTINTERP_API symbol_table& __get_symbol_table__ ();
 
-extern OCTINTERP_API symbol_scope __get_current_scope__ (void);
+extern OCTINTERP_API symbol_scope __get_current_scope__ ();
 
-extern OCTINTERP_API symbol_scope __require_current_scope__ (void);
+extern OCTINTERP_API symbol_scope __require_current_scope__ ();
 
-extern OCTINTERP_API tree_evaluator& __get_evaluator__ (void);
+extern OCTINTERP_API tree_evaluator& __get_evaluator__ ();
 
-extern OCTINTERP_API bp_table& __get_bp_table__ (void);
+extern OCTINTERP_API bp_table& __get_bp_table__ ();
 
-extern OCTINTERP_API child_list& __get_child_list__ (void);
+extern OCTINTERP_API child_list& __get_child_list__ ();
 
-extern OCTINTERP_API cdef_manager& __get_cdef_manager__ (void);
+extern OCTINTERP_API cdef_manager& __get_cdef_manager__ ();
 
-extern OCTINTERP_API display_info& __get_display_info__ (void);
+extern OCTINTERP_API display_info& __get_display_info__ ();
 
-extern OCTINTERP_API gtk_manager& __get_gtk_manager__ (void);
+extern OCTINTERP_API gtk_manager& __get_gtk_manager__ ();
 
 // Functions that could be methods in the interpreter class but maybe
 // shouldn't be exposed as part of the public interface.
--- a/libinterp/corefcn/interpreter.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/interpreter.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,6 +43,7 @@
 #include "fpucw-wrappers.h"
 #include "lo-blas-proto.h"
 #include "lo-error.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "quit.h"
 #include "str-vec.h"
@@ -91,7 +92,7 @@
 bool octave_interpreter_ready = false;
 
 // TRUE means we've processed all the init code and we are good to go.
-bool octave_initialized = false;
+std::atomic<bool> octave_initialized{false};
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -314,7 +315,7 @@
   return ovl (interp.traditional ());
 }
 
-temporary_file_list::~temporary_file_list (void)
+temporary_file_list::~temporary_file_list ()
 {
   cleanup ();
 }
@@ -324,7 +325,7 @@
   m_files.insert (file);
 }
 
-void temporary_file_list::cleanup (void)
+void temporary_file_list::cleanup ()
 {
   while (! m_files.empty ())
     {
@@ -339,56 +340,24 @@
 // The time we last time we changed directories.
 sys::time Vlast_chdir_time = 0.0;
 
-// Execute commands from a file and catch potential exceptions in a consistent
-// way.  This function should be called anywhere we might parse and execute
-// commands from a file before we have entered the main loop in
-// toplev.cc.
-
-static int safe_source_file (const std::string& file_name,
-                             const std::string& context = "",
-                             bool verbose = false,
-                             bool require_file = true)
+static void initialize_version_info ()
 {
-  interpreter& interp = __get_interpreter__ ();
-
-  try
-    {
-      source_file (file_name, context, verbose, require_file);
-    }
-  catch (const interrupt_exception&)
-    {
-      interp.recover_from_exception ();
-
-      return 1;
-    }
-  catch (const execution_exception& ee)
-    {
-      interp.handle_exception (ee);
-
-      return 1;
-    }
-
-  return 0;
+  octave_value_list args (4);
+
+  args(0) = "GNU Octave";
+  args(1) = OCTAVE_VERSION;
+  args(2) = config::release ();
+  args(3) = OCTAVE_RELEASE_DATE;
+
+  F__version_info__ (args);
 }
 
-static void initialize_version_info (void)
-{
-  octave_value_list args;
-
-  args(3) = OCTAVE_RELEASE_DATE;
-  args(2) = config::release ();
-  args(1) = OCTAVE_VERSION;
-  args(0) = "GNU Octave";
-
-  F__version_info__ (args, 0);
-}
-
-static void xerbla_abort (void)
+static void xerbla_abort ()
 {
   error ("Fortran procedure terminated by call to XERBLA");
 }
 
-static void initialize_xerbla_error_handler (void)
+static void initialize_xerbla_error_handler ()
 {
   // The idea here is to force xerbla to be referenced so that we will
   // link to our own version instead of the one provided by the BLAS
@@ -400,7 +369,7 @@
   if (numeric_limits<double>::NaN () == -1)
     F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
 
-  typedef void (*xerbla_handler_ptr) (void);
+  typedef void (*xerbla_handler_ptr) ();
 
   typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr);
 
@@ -439,7 +408,7 @@
   throw execution_exception ();
 }
 
-static void initialize_error_handlers (void)
+static void initialize_error_handlers ()
 {
   set_liboctave_error_handler (lo_error_handler);
   set_liboctave_error_with_id_handler (lo_error_with_id_handler);
@@ -473,7 +442,7 @@
     m_child_list (),
     m_url_handle_manager (),
     m_cdef_manager (*this),
-    m_gtk_manager (),
+    m_gtk_manager (*this),
     m_event_manager (*this),
     m_gh_manager (nullptr),
     m_interactive (false),
@@ -495,11 +464,11 @@
   //
   //   only one Octave interpreter may be active in any given thread
 
-  if (m_instance)
+  if (s_instance)
     throw std::runtime_error
     ("only one Octave interpreter may be active");
 
-  m_instance = this;
+  s_instance = this;
 
 #if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE)
   // Force a UTF-8 locale on Windows if possible
@@ -607,23 +576,23 @@
 
       std::string docstrings_file = options.docstrings_file ();
       if (! docstrings_file.empty ())
-        Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file));
+        Fbuilt_in_docstrings_file (*this, ovl (docstrings_file));
 
       std::string doc_cache_file = options.doc_cache_file ();
       if (! doc_cache_file.empty ())
-        Fdoc_cache_file (*this, octave_value (doc_cache_file));
+        Fdoc_cache_file (*this, ovl (doc_cache_file));
 
       std::string info_file = options.info_file ();
       if (! info_file.empty ())
-        Finfo_file (*this, octave_value (info_file));
+        Finfo_file (*this, ovl (info_file));
 
       std::string info_program = options.info_program ();
       if (! info_program.empty ())
-        Finfo_program (*this, octave_value (info_program));
+        Finfo_program (*this, ovl (info_program));
 
       std::string texi_macros_file = options.texi_macros_file ();
       if (! texi_macros_file.empty ())
-        Ftexi_macros_file (*this, octave_value (texi_macros_file));
+        Ftexi_macros_file (*this, ovl (texi_macros_file));
     }
 
   // FIXME: we defer creation of the gh_manager object because it
@@ -655,9 +624,9 @@
   octave_interpreter_ready = true;
 }
 
-OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr;
-
-interpreter::~interpreter (void)
+OCTAVE_THREAD_LOCAL interpreter *interpreter::s_instance = nullptr;
+
+interpreter::~interpreter ()
 {
   if (! m_app_context)
     shutdown ();
@@ -736,7 +705,7 @@
 
 // This may be called separately from execute
 
-void interpreter::initialize (void)
+void interpreter::initialize ()
 {
   if (m_initialized)
     return;
@@ -789,7 +758,7 @@
 // Note: this function is currently only used with the new
 // experimental terminal widget.
 
-void interpreter::get_line_and_eval (void)
+void interpreter::get_line_and_eval ()
 {
   m_evaluator.get_line_and_eval ();
 }
@@ -804,11 +773,9 @@
   cli_input_reader (interpreter& interp)
     : m_interpreter (interp), m_thread () { }
 
-  cli_input_reader (const cli_input_reader&) = delete;
-
-  cli_input_reader& operator = (const cli_input_reader&) = delete;
-
-  ~cli_input_reader (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (cli_input_reader)
+
+  ~cli_input_reader ()
   {
     // FIXME: Would it be better to ensure that
     // interpreter::get_line_and_eval exits and then call
@@ -817,7 +784,7 @@
     m_thread.detach ();
   }
 
-  void start (void)
+  void start ()
   {
     m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter);
   }
@@ -838,7 +805,7 @@
 // FIXME: this function is intended to be executed only once.  Should
 // we enforce that restriction?
 
-int interpreter::execute (void)
+int interpreter::execute ()
 {
   int exit_status = 0;
 
@@ -965,7 +932,7 @@
     }                                                                   \
   while (0)
 
-void interpreter::shutdown (void)
+void interpreter::shutdown ()
 {
   // Attempt to prevent more than one call to shutdown.
 
@@ -1075,7 +1042,7 @@
   // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
 }
 
-void interpreter::execute_atexit_fcns (void)
+void interpreter::execute_atexit_fcns ()
 {
   // Prevent atexit functions from adding new functions to the list.
   m_executing_atexit = true;
@@ -1092,7 +1059,7 @@
     }
 }
 
-void interpreter::display_startup_message (void) const
+void interpreter::display_startup_message () const
 {
   bool inhibit_startup_message = false;
 
@@ -1107,11 +1074,11 @@
     std::cout << octave_startup_message () << "\n" << std::endl;
 }
 
-// Initialize by reading startup files.  Return non-zero if an exception
+// Initialize by reading startup files.  Return nonzero if an exception
 // occurs when reading any of them, but don't exit early because of an
 // exception.
 
-int interpreter::execute_startup_files (void)
+int interpreter::execute_startup_files ()
 {
   bool read_site_files = m_read_site_files;
   bool read_init_files = m_read_init_files;
@@ -1227,16 +1194,14 @@
 
           // Names alone are not enough.
 
-          sys::file_stat fs_home_rc (home_rc);
-
-          if (fs_home_rc)
+          if (sys::file_exists (home_rc))
             {
               // We want to check for curr_dir after executing home_rc
               // because doing that may change the working directory.
 
               local_rc = sys::env::make_absolute (initfile);
 
-              home_rc_already_executed = same_file (home_rc, local_rc);
+              home_rc_already_executed = sys::same_file (home_rc, local_rc);
             }
         }
 
@@ -1261,7 +1226,7 @@
 
 // Execute any code specified with --eval 'CODE'
 
-int interpreter::execute_eval_option_code (void)
+int interpreter::execute_eval_option_code ()
 {
   if (! m_app_context)
     return 0;
@@ -1294,7 +1259,7 @@
   return parse_status;
 }
 
-int interpreter::execute_command_line_file (void)
+int interpreter::execute_command_line_file ()
 {
   if (! m_app_context)
     return 0;
@@ -1343,41 +1308,41 @@
   return safe_source_file (fname, context, verbose, require_file);
 }
 
-int interpreter::main_loop (void)
+int interpreter::main_loop ()
 {
   command_editor::add_event_hook (release_unreferenced_dynamic_libraries);
 
   return m_evaluator.repl ();
 }
 
-int interpreter::server_loop (void)
+int interpreter::server_loop ()
 {
   return m_evaluator.server_loop ();
 }
 
-tree_evaluator& interpreter::get_evaluator (void)
+tree_evaluator& interpreter::get_evaluator ()
 {
   return m_evaluator;
 }
 
-stream_list& interpreter::get_stream_list (void)
+stream_list& interpreter::get_stream_list ()
 {
   return m_stream_list;
 }
 
-url_handle_manager& interpreter::get_url_handle_manager (void)
+url_handle_manager& interpreter::get_url_handle_manager ()
 {
   return m_url_handle_manager;
 }
 
 symbol_scope
-interpreter::get_top_scope (void) const
+interpreter::get_top_scope () const
 {
   return m_evaluator.get_top_scope ();
 }
 
 symbol_scope
-interpreter::get_current_scope (void) const
+interpreter::get_current_scope () const
 {
   return m_evaluator.get_current_scope ();
 }
@@ -1393,7 +1358,7 @@
   return scope;
 }
 
-profiler& interpreter::get_profiler (void)
+profiler& interpreter::get_profiler ()
 {
   return m_evaluator.get_profiler ();
 }
@@ -1710,7 +1675,7 @@
   m_evaluator.source_file (file_name, context, verbose, require_file);
 }
 
-bool interpreter::at_top_level (void) const
+bool interpreter::at_top_level () const
 {
   return m_evaluator.at_top_level ();
 }
@@ -1730,7 +1695,7 @@
   m_evaluator.clear_all (force);
 }
 
-void interpreter::clear_objects (void)
+void interpreter::clear_objects ()
 {
   m_evaluator.clear_objects ();
 }
@@ -1750,7 +1715,7 @@
   m_evaluator.clear_variable_regexp (pattern);
 }
 
-void interpreter::clear_variables (void)
+void interpreter::clear_variables ()
 {
   m_evaluator.clear_variables ();
 }
@@ -1770,7 +1735,7 @@
   m_evaluator.clear_global_variable_regexp (pattern);
 }
 
-void interpreter::clear_global_variables (void)
+void interpreter::clear_global_variables ()
 {
   m_evaluator.clear_global_variables ();
 }
@@ -1810,27 +1775,27 @@
   return m_evaluator.clear_symbol_regexp (pat);
 }
 
-std::list<std::string> interpreter::global_variable_names (void)
+std::list<std::string> interpreter::global_variable_names ()
 {
   return m_evaluator.global_variable_names ();
 }
 
-std::list<std::string> interpreter::top_level_variable_names (void)
+std::list<std::string> interpreter::top_level_variable_names ()
 {
   return m_evaluator.top_level_variable_names ();
 }
 
-std::list<std::string> interpreter::variable_names (void)
+std::list<std::string> interpreter::variable_names ()
 {
   return m_evaluator.variable_names ();
 }
 
-std::list<std::string> interpreter::user_function_names (void)
+std::list<std::string> interpreter::user_function_names ()
 {
   return m_symbol_table.user_function_names ();
 }
 
-std::list<std::string> interpreter::autoloaded_functions (void) const
+std::list<std::string> interpreter::autoloaded_functions () const
 {
   return m_evaluator.autoloaded_functions ();
 }
@@ -1838,7 +1803,7 @@
 // May be used to send an interrupt signal to the the interpreter from
 // another thread (for example, the GUI).
 
-void interpreter::interrupt (void)
+void interpreter::interrupt ()
 {
   static int sigint = 0;
   static bool first = true;
@@ -1866,7 +1831,7 @@
   octave_kill_wrapper (pid, sigint);
 }
 
-void interpreter::pause (void)
+void interpreter::pause ()
 {
   // FIXME: To be reliable, these tree_evaluator functions must be
   // made thread safe.
@@ -1875,7 +1840,7 @@
   m_evaluator.reset_debug_state ();
 }
 
-void interpreter::stop (void)
+void interpreter::stop ()
 {
   // FIXME: To be reliable, these tree_evaluator functions must be
   // made thread safe.
@@ -1886,7 +1851,7 @@
     interrupt ();
 }
 
-void interpreter::resume (void)
+void interpreter::resume ()
 {
   // FIXME: To be reliable, these tree_evaluator functions must be
   // made thread safe.
@@ -1898,9 +1863,69 @@
     m_evaluator.dbcont ();
 }
 
+octave_value interpreter::PS1 (const octave_value_list& args, int nargout)
+{
+  return m_input_system.PS1 (args, nargout);
+}
+
+std::string interpreter::PS1 () const
+{
+  return m_input_system.PS1 ();
+}
+
+std::string interpreter::PS1 (const std::string& s)
+{
+  return m_input_system.PS1 (s);
+}
+
+void interpreter::set_PS1 (const std::string& s)
+{
+  m_input_system.set_PS1 (s);
+}
+
+octave_value interpreter::PS2 (const octave_value_list& args, int nargout)
+{
+  return m_input_system.PS2 (args, nargout);
+}
+
+std::string interpreter::PS2 () const
+{
+  return m_input_system.PS2 ();
+}
+
+std::string interpreter::PS2 (const std::string& s)
+{
+  return m_input_system.PS2 (s);
+}
+
+void interpreter::set_PS2 (const std::string& s)
+{
+  m_input_system.set_PS2 (s);
+}
+
+octave_value interpreter::PS4 (const octave_value_list& args, int nargout)
+{
+  return m_evaluator.PS4 (args, nargout);
+}
+
+std::string interpreter::PS4 () const
+{
+  return m_evaluator.PS4 ();
+}
+
+std::string interpreter::PS4 (const std::string& s)
+{
+  return m_evaluator.PS4 (s);
+}
+
+void interpreter::set_PS4 (const std::string& s)
+{
+  m_evaluator.set_PS4 (s);
+}
+
 // Provided for convenience.  Will be removed once we eliminate the
 // old terminal widget.
-bool interpreter::experimental_terminal_widget (void) const
+bool interpreter::experimental_terminal_widget () const
 {
   if (! m_app_context)
     return false;
@@ -1921,12 +1946,12 @@
   m_evaluator.remove_debug_watch_expression (expr);
 }
 
-void interpreter::clear_debug_watch_expressions (void)
+void interpreter::clear_debug_watch_expressions ()
 {
   m_evaluator.clear_debug_watch_expressions ();
 }
 
-std::set<std::string> interpreter::debug_watch_expressions (void) const
+std::set<std::string> interpreter::debug_watch_expressions () const
 {
   return m_evaluator.debug_watch_expressions ();
 }
@@ -1943,14 +1968,14 @@
   recover_from_exception ();
 }
 
-void interpreter::recover_from_exception (void)
+void interpreter::recover_from_exception ()
 {
   if (octave_interrupt_state)
     m_event_manager.interpreter_interrupted ();
 
   can_interrupt = true;
   octave_interrupt_state = 0;
-  octave_signal_caught = 0;
+  octave_signal_caught = false;
   octave_restore_signal_mask ();
   catch_interrupts ();
 }
@@ -1960,7 +1985,7 @@
   m_tmp_files.insert (file);
 }
 
-void interpreter::cleanup_tmp_files (void)
+void interpreter::cleanup_tmp_files ()
 {
   m_tmp_files.cleanup ();
 }
@@ -2035,12 +2060,11 @@
 
 // What internal options get configured by --traditional.
 
-void interpreter::maximum_braindamage (void)
+void interpreter::maximum_braindamage ()
 {
-  m_input_system.PS1 (">> ");
-  m_input_system.PS2 ("");
-
-  m_evaluator.PS4 ("");
+  PS1 (">> ");
+  PS2 ("");
+  PS4 ("");
 
   m_load_save_system.crash_dumps_octave_core (false);
   m_load_save_system.save_default_options ("-mat-binary");
@@ -2049,14 +2073,14 @@
 
   m_error_system.beep_on_error (true);
 
-  Fconfirm_recursive_rmdir (octave_value (false));
-  Foptimize_diagonal_matrix (octave_value (false));
-  Foptimize_permutation_matrix (octave_value (false));
-  Foptimize_range (octave_value (false));
-  Ffixed_point_format (octave_value (true));
-  Fprint_empty_dimensions (octave_value (false));
-  Fprint_struct_array_contents (octave_value (true));
-  Fstruct_levels_to_print (octave_value (0));
+  Fconfirm_recursive_rmdir (ovl (false));
+  Foptimize_diagonal_matrix (ovl (false));
+  Foptimize_permutation_matrix (ovl (false));
+  Foptimize_range (ovl (false));
+  Ffixed_point_format (ovl (true));
+  Fprint_empty_dimensions (ovl (false));
+  Fprint_struct_array_contents (ovl (true));
+  Fstruct_levels_to_print (ovl (0));
 
   m_error_system.disable_warning ("Octave:abbreviated-property-match");
   m_error_system.disable_warning ("Octave:colon-nonscalar-argument");
@@ -2082,4 +2106,33 @@
     }
 }
 
+// Execute commands from a file and catch potential exceptions in a consistent
+// way.  This function should be called anywhere we might parse and execute
+// commands from a file before we have entered the main loop in
+// toplev.cc.
+
+int interpreter::safe_source_file (const std::string& file_name,
+                                   const std::string& context,
+                                   bool verbose, bool require_file)
+{
+  try
+    {
+      source_file (file_name, context, verbose, require_file);
+    }
+  catch (const interrupt_exception&)
+    {
+      recover_from_exception ();
+
+      return 1;
+    }
+  catch (const execution_exception& ee)
+    {
+      handle_exception (ee);
+
+      return 1;
+    }
+
+  return 0;
+}
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/interpreter.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/interpreter.h	Fri Jun 23 20:51:51 2023 +0200
@@ -28,6 +28,7 @@
 
 #include "octave-config.h"
 
+#include <atomic>
 #include <map>
 #include <set>
 #include <stack>
@@ -44,6 +45,7 @@
 #include "environment.h"
 #include "error.h"
 #include "event-manager.h"
+#include "gh-manager.h"
 #include "graphics.h"
 #include "gtk-manager.h"
 #include "help.h"
@@ -66,7 +68,7 @@
 extern OCTINTERP_API bool octave_interpreter_ready;
 
 // TRUE means we've processed all the init code and we are good to go.
-extern OCTINTERP_API bool octave_initialized;
+extern OCTINTERP_API std::atomic<bool> octave_initialized;
 
 #include "oct-time.h"
 
@@ -90,19 +92,15 @@
 {
 public:
 
-  temporary_file_list (void) : m_files () { }
-
-  // No copying!
+  temporary_file_list () : m_files () { }
 
-  temporary_file_list (const temporary_file_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (temporary_file_list)
 
-  temporary_file_list& operator = (const temporary_file_list&) = delete;
-
-  ~temporary_file_list (void);
+  ~temporary_file_list ();
 
   void insert (const std::string& file);
 
-  void cleanup (void);
+  void cleanup ();
 
 private:
 
@@ -119,15 +117,11 @@
 
   interpreter (application *app_context = nullptr);
 
-  // No copying, at least not yet...
-
-  interpreter (const interpreter&) = delete;
-
-  interpreter& operator = (const interpreter&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (interpreter)
 
   // Clean up the interpreter object.
 
-  ~interpreter (void);
+  ~interpreter ();
 
   void intern_nargin (octave_idx_type nargs);
 
@@ -147,12 +141,12 @@
 
   // Load command line history, set the load path.
 
-  void initialize (void);
+  void initialize ();
 
   // Note: GET_LINE_AND_EVAL is only used by new experimental terminal
   // widget.
 
-  void get_line_and_eval (void);
+  void get_line_and_eval ();
 
   // Parse a line of input.  If input ends at a complete statement
   // boundary, execute the resulting parse tree.  Useful to handle
@@ -164,11 +158,11 @@
   // call to initialize), execute startup files, --eval option code,
   // script files, and/or interactive commands.
 
-  int execute (void);
+  int execute ();
 
-  bool server_mode (void) const { return m_evaluator.server_mode (); }
+  bool server_mode () const { return m_evaluator.server_mode (); }
 
-  bool interactive (void) const
+  bool interactive () const
   {
     return m_interactive;
   }
@@ -198,7 +192,7 @@
     m_traditional = flag;
   }
 
-  bool traditional (void) const
+  bool traditional () const
   {
     return m_traditional;
   }
@@ -208,12 +202,12 @@
     m_inhibit_startup_message = flag;
   }
 
-  bool in_top_level_repl (void) const
+  bool in_top_level_repl () const
   {
     return m_evaluator.in_top_level_repl ();
   }
 
-  bool initialized (void) const
+  bool initialized () const
   {
     return m_initialized;
   }
@@ -223,114 +217,114 @@
     m_interrupt_all_in_process_group = b;
   }
 
-  bool interrupt_all_in_process_group (void) const
+  bool interrupt_all_in_process_group () const
   {
     return m_interrupt_all_in_process_group;
   }
 
-  application * get_app_context (void)
+  application * get_app_context ()
   {
     return m_app_context;
   }
 
-  display_info& get_display_info (void)
+  display_info& get_display_info ()
   {
     return m_display_info;
   }
 
-  environment& get_environment (void)
+  environment& get_environment ()
   {
     return m_environment;
   }
 
-  settings& get_settings (void)
+  settings& get_settings ()
   {
     return m_settings;
   }
 
-  error_system& get_error_system (void)
+  error_system& get_error_system ()
   {
     return m_error_system;
   }
 
-  tree_evaluator& get_evaluator (void);
+  tree_evaluator& get_evaluator ();
 
-  help_system& get_help_system (void)
+  help_system& get_help_system ()
   {
     return m_help_system;
   }
 
-  input_system& get_input_system (void)
+  input_system& get_input_system ()
   {
     return m_input_system;
   }
 
-  output_system& get_output_system (void)
+  output_system& get_output_system ()
   {
     return m_output_system;
   }
 
-  history_system& get_history_system (void)
+  history_system& get_history_system ()
   {
     return m_history_system;
   }
 
-  dynamic_loader& get_dynamic_loader (void)
+  dynamic_loader& get_dynamic_loader ()
   {
     return m_dynamic_loader;
   }
 
-  load_path& get_load_path (void)
+  load_path& get_load_path ()
   {
     return m_load_path;
   }
 
-  load_save_system& get_load_save_system (void)
+  load_save_system& get_load_save_system ()
   {
     return m_load_save_system;
   }
 
-  type_info& get_type_info (void)
+  type_info& get_type_info ()
   {
     return m_type_info;
   }
 
-  symbol_table& get_symbol_table (void)
+  symbol_table& get_symbol_table ()
   {
     return m_symbol_table;
   }
 
-  symbol_scope get_top_scope (void) const;
-  symbol_scope get_current_scope (void) const;
+  symbol_scope get_top_scope () const;
+  symbol_scope get_current_scope () const;
   symbol_scope require_current_scope (const std::string& who) const;
 
-  profiler& get_profiler (void);
+  profiler& get_profiler ();
 
-  stream_list& get_stream_list (void);
+  stream_list& get_stream_list ();
 
-  child_list& get_child_list (void)
+  child_list& get_child_list ()
   {
     return m_child_list;
   }
 
-  url_handle_manager& get_url_handle_manager (void);
+  url_handle_manager& get_url_handle_manager ();
 
-  cdef_manager& get_cdef_manager (void)
+  cdef_manager& get_cdef_manager ()
   {
     return m_cdef_manager;
   }
 
-  gtk_manager& get_gtk_manager (void)
+  gtk_manager& get_gtk_manager ()
   {
     return m_gtk_manager;
   }
 
-  event_manager& get_event_manager (void)
+  event_manager& get_event_manager ()
   {
     return m_event_manager;
   }
 
-  gh_manager& get_gh_manager (void)
+  gh_manager& get_gh_manager ()
   {
     return *m_gh_manager;
   }
@@ -432,7 +426,7 @@
                     const std::string& context = "",
                     bool verbose = false, bool require_file = true);
 
-  bool at_top_level (void) const;
+  bool at_top_level () const;
 
   bool isglobal (const std::string& name) const;
 
@@ -440,7 +434,7 @@
 
   void clear_all (bool force = false);
 
-  void clear_objects (void);
+  void clear_objects ();
 
   void clear_variable (const std::string& name);
 
@@ -448,7 +442,7 @@
 
   void clear_variable_regexp (const std::string& pattern);
 
-  void clear_variables (void);
+  void clear_variables ();
 
   void clear_global_variable (const std::string& name);
 
@@ -456,7 +450,7 @@
 
   void clear_global_variable_regexp (const std::string& pattern);
 
-  void clear_global_variables (void);
+  void clear_global_variables ();
 
   void clear_functions (bool force = false);
 
@@ -472,25 +466,25 @@
 
   void clear_symbol_regexp (const std::string& pat);
 
-  std::list<std::string> variable_names (void);
+  std::list<std::string> variable_names ();
 
-  std::list<std::string> top_level_variable_names (void);
+  std::list<std::string> top_level_variable_names ();
 
-  std::list<std::string> global_variable_names (void);
+  std::list<std::string> global_variable_names ();
 
-  std::list<std::string> user_function_names (void);
+  std::list<std::string> user_function_names ();
 
-  std::list<std::string> autoloaded_functions (void) const;
+  std::list<std::string> autoloaded_functions () const;
 
-  void interrupt (void);
+  void interrupt ();
 
   // Pause interpreter execution at the next available statement and
   // enter the debugger.
-  void pause (void);
+  void pause ();
 
   // Exit debugger or stop execution and return to the top-level REPL
   // or server loop.
-  void stop (void);
+  void stop ();
 
   // Add EXPR to the set of expressions that may be evaluated when the
   // debugger stops at a breakpoint.
@@ -502,32 +496,47 @@
 
   // Clear the set of expressions that may be evaluated when the
   // debugger stops at a breakpoint.
-  void clear_debug_watch_expressions (void);
+  void clear_debug_watch_expressions ();
 
   // Return the set of expressions that may be evaluated when the
   // debugger stops at a breakpoint.
-  std::set<std::string> debug_watch_expressions (void) const;
+  std::set<std::string> debug_watch_expressions () const;
 
   // Resume interpreter execution if paused.
-  void resume (void);
+  void resume ();
+
+  octave_value PS1 (const octave_value_list& args, int nargout);
+  std::string PS1 () const;
+  std::string PS1 (const std::string& s);
+  void set_PS1 (const std::string& s);
+
+  octave_value PS2 (const octave_value_list& args, int nargout);
+  std::string PS2 () const;
+  std::string PS2 (const std::string& s);
+  void set_PS2 (const std::string& s);
+
+  octave_value PS4 (const octave_value_list& args, int nargout);
+  std::string PS4 () const;
+  std::string PS4 (const std::string& s);
+  void set_PS4 (const std::string& s);
 
   // Provided for convenience.  Will be removed once we eliminate the
   // old terminal widget.
-  bool experimental_terminal_widget (void) const;
+  bool experimental_terminal_widget () const;
 
   void handle_exception (const execution_exception& ee);
 
-  void recover_from_exception (void);
+  void recover_from_exception ();
 
   void mark_for_deletion (const std::string& file);
 
-  void cleanup_tmp_files (void);
+  void cleanup_tmp_files ();
 
   void quit (int exit_status, bool force = false, bool confirm = true);
 
   void cancel_quit (bool flag) { m_cancel_quit = flag; }
 
-  bool executing_finish_script (void) const
+  bool executing_finish_script () const
   {
     return m_executing_finish_script;
   }
@@ -536,30 +545,34 @@
 
   bool remove_atexit_fcn (const std::string& fname);
 
-  static interpreter * the_interpreter (void) { return m_instance; }
+  static interpreter * the_interpreter () { return s_instance; }
 
 private:
 
-  void display_startup_message (void) const;
+  void display_startup_message () const;
 
-  int execute_startup_files (void);
+  int execute_startup_files ();
 
-  int execute_eval_option_code (void);
+  int execute_eval_option_code ();
 
-  int execute_command_line_file (void);
+  int execute_command_line_file ();
 
-  int main_loop (void);
+  int main_loop ();
 
-  int server_loop (void);
+  int server_loop ();
 
-  void shutdown (void);
+  void shutdown ();
 
-  void execute_atexit_fcns (void);
+  void execute_atexit_fcns ();
 
-  void maximum_braindamage (void);
+  void maximum_braindamage ();
 
   void execute_pkg_add (const std::string& dir);
 
+  int safe_source_file (const std::string& file_name,
+                        const std::string& context = "",
+                        bool verbose = false, bool require_file = true);
+
   //--------
 
   // The interpreter instance;  Currently it is only possible to
@@ -570,7 +583,7 @@
   // replaced by the C++ thread_local keyword.  For now, use a macro
   // to allow experimenting with thread_local storage.
 
-  OCTAVE_THREAD_LOCAL static interpreter *m_instance;
+  OCTAVE_THREAD_LOCAL static interpreter *s_instance;
 
   application *m_app_context;
 
--- a/libinterp/corefcn/jsondecode.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/jsondecode.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -612,7 +612,7 @@
     = use_makeValidName ? new make_valid_name_options (make_valid_name_params)
       : nullptr;
 
-  unwind_action del_opts ([options] (void) { if (options) delete options; });
+  unwind_action del_opts ([options] () { if (options) delete options; });
 
   if (! args(0).is_string ())
     error ("jsondecode: JSON_TXT must be a character string");
--- a/libinterp/corefcn/kron.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/kron.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -275,6 +275,7 @@
 
 @noindent
 Since the Kronecker product is associative, this is well-defined.
+@seealso{tensorprod}
 @end deftypefn */)
 {
   int nargin = args.length ();
--- a/libinterp/corefcn/latex-text-renderer.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/latex-text-renderer.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,10 +53,9 @@
 OCTINTERP_API
 latex_renderer : public base_text_renderer
 {
-
 public:
 
-  latex_renderer (void)
+  latex_renderer ()
     : m_fontsize (10.0), m_fontname ("cmr"), m_tmp_dir (),
       m_color (dim_vector (1, 3), 0), m_latex_binary ("latex"),
       m_dvipng_binary ("dvipng"), m_dvisvg_binary ("dvisvgm"),
@@ -77,7 +76,9 @@
     m_debug = ! sys::env::getenv ("OCTAVE_LATEX_DEBUG_FLAG").empty ();
   }
 
-  ~latex_renderer (void)
+  OCTAVE_DISABLE_COPY_MOVE (latex_renderer)
+
+  ~latex_renderer ()
   {
     if (! m_tmp_dir.empty () && ! m_debug)
       sys::recursive_rmdir (m_tmp_dir);
@@ -144,9 +145,9 @@
 
   void set_anti_aliasing (bool /*val*/) { }
 
-  octave_map get_system_fonts (void) { return octave_map (); }
+  octave_map get_system_fonts () { return octave_map (); }
 
-  bool ok (void);
+  bool ok ();
 
 private:
 
@@ -183,7 +184,7 @@
 };
 
 bool
-latex_renderer::ok (void)
+latex_renderer::ok ()
 {
   // Only run the test once in a session
   static bool tested = false;
@@ -522,7 +523,7 @@
 }
 
 base_text_renderer *
-make_latex_text_renderer (void)
+make_latex_text_renderer ()
 {
   latex_renderer *renderer = new latex_renderer ();
 
--- a/libinterp/corefcn/latex-text-renderer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/latex-text-renderer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 
 class base_text_renderer;
 
-extern base_text_renderer * make_latex_text_renderer (void);
+extern base_text_renderer * make_latex_text_renderer ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/libinterp/corefcn/load-path.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/load-path.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,9 +32,12 @@
 
 #include "dir-ops.h"
 #include "file-ops.h"
-#include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "pathsearch.h"
+#if ! defined (OCTAVE_USE_WINDOWS_API)
+#  include "file-stat.h"
+#endif
 
 #include "defaults.h"
 #include "defun.h"
@@ -147,45 +150,6 @@
   return dir;
 }
 
-// Should we cache all files in private directories, or is it OK to just
-// look them up each time as needed?
-
-static std::string
-find_private_file (const std::string& fname)
-{
-  std::string retval;
-
-  // Look in private directory corresponding to current function (if
-  // any).
-
-  symbol_scope scope = __get_current_scope__ ();
-
-  octave_user_code *curr_code = scope ? scope.user_code () : nullptr;
-
-  if (curr_code)
-    {
-      // Even for private functions, dir_name doesn't contain the
-      // "private" directory component so we append it here in all
-      // cases.
-
-      std::string dir_name = curr_code->dir_name ();
-
-      if (! dir_name.empty ())
-        {
-          std::string pfname = dir_name + sys::file_ops::dir_sep_str ()
-                               + "private" + sys::file_ops::dir_sep_str ()
-                               + fname;
-
-          sys::file_stat fs (pfname);
-
-          if (fs.exists () && fs.is_reg ())
-            retval = pfname;
-        }
-    }
-
-  return retval;
-}
-
 // True if a path is contained in a path list separated by path_sep_char
 
 static bool
@@ -207,24 +171,6 @@
   return false;
 }
 
-static void
-rehash_internal (void)
-{
-  load_path& lp = __get_load_path__ ();
-
-  lp.update ();
-
-  // Signal the GUI allowing updating the load path dialog
-  event_manager& evmgr = __get_event_manager__ ();
-  evmgr.update_path_dialog ();
-
-  // FIXME: maybe we should rename this variable since it is being
-  // used for more than keeping track of the prompt time.
-
-  // This will force updated functions to be found.
-  Vlast_prompt_time.stamp ();
-}
-
 //! Check if directory contains modified subdirectories.
 //!
 //! @param d directory to check
@@ -249,7 +195,7 @@
 //! @return true if directory contains modified subdirectories
 
 static bool
-subdirs_modified (const std::string& d, const sys::time& last_checked)
+subdirs_modified (const std::string& d, const sys::file_time& last_checked)
 {
   sys::dir_entry dir (d);
 
@@ -265,13 +211,22 @@
 
           std::string full_name = sys::file_ops::concat (d, fname);
 
-          sys::file_stat fs (full_name);
-
           // Check if directory AND if relevant (@,+,private)
           // AND (if modified OR recursion into (@,+) sub-directories)
+#if defined (OCTAVE_USE_WINDOWS_API)
+          if (sys::dir_exists (full_name)
+#else
+          sys::file_stat fs (full_name);
+
           if (fs && fs.is_dir ()
+#endif
               && (fname[0] == '@' || fname[0] == '+' || fname == "private")
-              && ((fs.mtime () + fs.time_resolution () > last_checked)
+#if defined (OCTAVE_USE_WINDOWS_API)
+              && ((sys::file_time (full_name)
+#else
+              && ((sys::file_time (fs.mtime ().unix_time ())
+#endif
+                   + sys::file_time::time_resolution () > last_checked)
                   || ((fname[0] == '@' || fname[0] == '+')
                       && subdirs_modified (full_name, last_checked))))
             return true;
@@ -290,12 +245,14 @@
 load_path::abs_dir_cache_type load_path::s_abs_dir_cache;
 
 load_path::load_path (interpreter& interp)
-  : add_hook ([=] (const std::string& dir) { this->execute_pkg_add (dir); }),
-remove_hook ([=] (const std::string& dir) { this->execute_pkg_del (dir); }),
+  : m_add_hook ([=] (const std::string& dir) { this->execute_pkg_add (dir); }),
+m_remove_hook ([=] (const std::string& dir) { this->execute_pkg_del (dir); }),
 m_interpreter (interp), m_package_map (), m_top_level_package (),
 m_dir_info_list (), m_init_dirs (), m_command_line_path ()
 { }
 
+std::atomic<octave_idx_type> load_path::s_n_updated;
+
 void
 load_path::initialize (bool set_initial_path)
 {
@@ -335,8 +292,10 @@
 }
 
 void
-load_path::clear (void)
+load_path::clear ()
 {
+  signal_clear_fcn_cache ();
+
   m_dir_info_list.clear ();
 
   m_top_level_package.clear ();
@@ -374,9 +333,9 @@
   // Temporarily disable add hook.
 
   unwind_protect frame;
-  frame.protect_var (add_hook);
-
-  add_hook = nullptr;
+  frame.protect_var (m_add_hook);
+
+  m_add_hook = nullptr;
 
   clear ();
 
@@ -390,8 +349,8 @@
   //        Why not use const here?  Does add_hook change dir_info_list?
   for (auto& di : m_dir_info_list)
     {
-      if (add_hook)
-        add_hook (di.dir_name);
+      if (m_add_hook)
+        m_add_hook (di.dir_name);
     }
 
   // Always prepend current directory.
@@ -419,7 +378,7 @@
 
   if (! dir_arg.empty ())
     {
-      if (same_file (dir_arg, "."))
+      if (sys::same_file (dir_arg, "."))
         {
           warning (R"(rmpath: can't remove "." from path)");
 
@@ -438,8 +397,8 @@
             {
               retval = true;
 
-              if (remove_hook)
-                remove_hook (dir);
+              if (m_remove_hook)
+                m_remove_hook (dir);
 
               dir_info& di = *i;
 
@@ -454,12 +413,14 @@
 }
 
 void
-load_path::update (void)
+load_path::update ()
 {
   // I don't see a better way to do this because we need to
   // preserve the correct directory ordering for new files that
   // have appeared.
 
+  signal_clear_fcn_cache ();
+
   m_top_level_package.clear ();
 
   m_package_map.clear ();
@@ -485,7 +446,7 @@
 
   for (const auto& d : m_dir_info_list)
     {
-      if (same_file (dir, d.dir_name))
+      if (sys::same_file (dir, d.dir_name))
         {
           retval = true;
           break;
@@ -504,7 +465,7 @@
 
   std::string curr_dir = sys::env::get_current_directory ();
 
-  if (same_file (curr_dir, dir))
+  if (sys::same_file (curr_dir, dir))
     ok = true;
   else
     {
@@ -519,7 +480,7 @@
 
       if (dir_in_load_path)
         {
-          if (same_file (lp_file, file))
+          if (sys::same_file (lp_file, file))
             ok = true;
         }
       else
@@ -530,9 +491,9 @@
           // not enough because the file in the current directory would
           // still be found.
 
-          if (same_file (lp_file, base_file))
+          if (sys::same_file (lp_file, base_file))
             {
-              if (same_file (curr_dir, dir))
+              if (sys::same_file (curr_dir, dir))
                 ok = true;
               else
                 addpath_option = false;
@@ -605,11 +566,7 @@
 
   if (sys::env::absolute_pathname (file)
       || sys::env::rooted_relative_pathname (file))
-    {
-      sys::file_stat fs (file);
-
-      return fs.exists () ? file : retval;
-    }
+    return sys::file_exists (file) ? file : retval;
   else
     {
       std::string tfile = find_private_file (file);
@@ -627,9 +584,7 @@
         {
           std::string tfile = sys::file_ops::concat (di.abs_dir_name, file);
 
-          sys::file_stat fs (tfile);
-
-          if (fs.exists ())
+          if (sys::file_exists (tfile))
             return tfile;
         }
     }
@@ -662,9 +617,7 @@
       && (sys::env::absolute_pathname (dir)
           || sys::env::rooted_relative_pathname (dir)))
     {
-      sys::file_stat fs (dir);
-
-      if (fs.exists () && fs.is_dir ())
+      if (sys::dir_exists (dir))
         return dir;
     }
   else
@@ -687,13 +640,9 @@
 
           if (dname_len > dir_len
               && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-              && canon_dir == dname.substr (dname_len - dir_len))
-            {
-              sys::file_stat fs (di.dir_name);
-
-              if (fs.exists () && fs.is_dir ())
-                return di.abs_dir_name;
-            }
+              && canon_dir == dname.substr (dname_len - dir_len)
+              && sys::dir_exists (di.dir_name))
+            return di.abs_dir_name;
         }
     }
 
@@ -709,9 +658,7 @@
       && (sys::env::absolute_pathname (dir)
           || sys::env::rooted_relative_pathname (dir)))
     {
-      sys::file_stat fs (dir);
-
-      if (fs.exists () && fs.is_dir ())
+      if (sys::dir_exists (dir))
         retlist.push_back (dir);
     }
   else
@@ -734,13 +681,9 @@
 
           if (dname_len > dir_len
               && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-              && canon_dir == dname.substr (dname_len - dir_len))
-            {
-              sys::file_stat fs (di.dir_name);
-
-              if (fs.exists () && fs.is_dir ())
-                retlist.push_back (di.abs_dir_name);
-            }
+              && canon_dir == dname.substr (dname_len - dir_len)
+              && sys::dir_exists (di.dir_name))
+            retlist.push_back (di.abs_dir_name);
         }
     }
 
@@ -770,9 +713,7 @@
           if (sys::env::absolute_pathname (file)
               || sys::env::rooted_relative_pathname (file))
             {
-              sys::file_stat fs (file);
-
-              if (fs.exists ())
+              if (sys::file_exists (file))
                 return file;
             }
           else
@@ -782,9 +723,7 @@
                   std::string tfile;
                   tfile = sys::file_ops::concat (di.abs_dir_name, file);
 
-                  sys::file_stat fs (tfile);
-
-                  if (fs.exists ())
+                  if (sys::file_exists (tfile))
                     return tfile;
                 }
             }
@@ -847,9 +786,7 @@
           if (sys::env::absolute_pathname (file)
               || sys::env::rooted_relative_pathname (file))
             {
-              sys::file_stat fs (file);
-
-              if (fs.exists ())
+              if (sys::file_exists (file))
                 retlist.push_back (file);
             }
           else
@@ -859,9 +796,7 @@
                   std::string tfile;
                   tfile = sys::file_ops::concat (di.abs_dir_name, file);
 
-                  sys::file_stat fs (tfile);
-
-                  if (fs.exists ())
+                  if (sys::file_exists (tfile))
                     retlist.push_back (tfile);
                 }
             }
@@ -893,7 +828,7 @@
 }
 
 string_vector
-load_path::dirs (void) const
+load_path::dirs () const
 {
   std::size_t len = m_dir_info_list.size ();
 
@@ -908,7 +843,7 @@
 }
 
 std::list<std::string>
-load_path::dir_list (void) const
+load_path::dir_list () const
 {
   std::list<std::string> retval;
 
@@ -947,13 +882,13 @@
 }
 
 string_vector
-load_path::fcn_names (void) const
+load_path::fcn_names () const
 {
   return m_top_level_package.fcn_names ();
 }
 
 std::string
-load_path::path (void) const
+load_path::path () const
 {
   std::string xpath;
 
@@ -1021,6 +956,23 @@
   execute_pkg_add_or_del (dir, "PKG_DEL");
 }
 
+void load_path::rehash ()
+{
+  update ();
+
+  // Signal the GUI allowing updating the load path dialog
+
+  event_manager& evmgr = m_interpreter.get_event_manager ();
+
+  evmgr.update_path_dialog ();
+
+  // FIXME: maybe we should rename this variable since it is being
+  // used for more than keeping track of the prompt time.
+
+  // This will force updated functions to be found.
+  Vlast_prompt_time.stamp ();
+}
+
 void load_path::execute_pkg_add_or_del (const std::string& dir,
                                         const std::string& script_file)
 {
@@ -1029,9 +981,7 @@
 
   std::string file = sys::file_ops::concat (dir, script_file);
 
-  sys::file_stat fs (file);
-
-  if (fs.exists ())
+  if (sys::file_exists (file))
     source_file (file, "base");
 }
 
@@ -1143,34 +1093,27 @@
     move (i, at_end);
   else
     {
-      sys::file_stat fs (dir);
-
-      if (fs)
+      std::string msg;
+
+      if (sys::dir_exists (dir, msg))
         {
-          if (fs.is_dir ())
-            {
-              read_dir_config (dir);
-
-              dir_info di (dir);
-
-              if (at_end)
-                m_dir_info_list.push_back (di);
-              else
-                m_dir_info_list.push_front (di);
-
-              add (di, at_end);
-
-              if (add_hook)
-                add_hook (dir);
-            }
-          else if (warn)
-            warning ("addpath: %s: not a directory", dir_arg.c_str ());
+          read_dir_config (dir);
+
+          dir_info di (dir);
+
+          if (at_end)
+            m_dir_info_list.push_back (di);
+          else
+            m_dir_info_list.push_front (di);
+
+          add (di, at_end);
+
+          if (m_add_hook)
+            m_add_hook (dir);
         }
-      else if (warn)
-        {
-          std::string msg = fs.error ();
-          warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
-        }
+
+      if (warn && ! msg.empty ())
+        warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
     }
 
   // FIXME: is there a better way to do this?
@@ -1223,7 +1166,7 @@
       return;
     }
 
-  unwind_action close_file ([cfile] (void) { fclose (cfile); });
+  unwind_action close_file ([cfile] () { fclose (cfile); });
 
   // find line with character encoding and read it
   bool eof = false;
@@ -1334,6 +1277,43 @@
   return retval;
 }
 
+// Should we cache all files in private directories, or is it OK to just
+// look them up each time as needed?
+
+std::string
+load_path::find_private_file (const std::string& fname) const
+{
+  std::string retval;
+
+  // Look in private directory corresponding to current function (if
+  // any).
+
+  symbol_scope scope = m_interpreter.get_current_scope ();
+
+  octave_user_code *curr_code = scope ? scope.user_code () : nullptr;
+
+  if (curr_code)
+    {
+      // Even for private functions, dir_name doesn't contain the
+      // "private" directory component so we append it here in all
+      // cases.
+
+      std::string dir_name = curr_code->dir_name ();
+
+      if (! dir_name.empty ())
+        {
+          std::string pfname = dir_name + sys::file_ops::dir_sep_str ()
+                               + "private" + sys::file_ops::dir_sep_str ()
+                               + fname;
+
+          if (sys::file_exists (pfname, false))
+            retval = pfname;
+        }
+    }
+
+  return retval;
+}
+
 load_path::dir_info::fcn_file_map_type
 get_fcn_files (const std::string& d)
 {
@@ -1389,13 +1369,20 @@
 }
 
 bool
-load_path::dir_info::update (void)
+load_path::dir_info::update ()
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::string msg;
+
+  if (! sys::dir_exists (dir_name, msg))
+    {
+#else
   sys::file_stat fs (dir_name);
 
   if (! fs)
     {
       std::string msg = fs.error ();
+#endif
       warning_with_id ("Octave:load-path:dir-info:update-failed",
                        "load_path: %s: %s", dir_name.c_str (), msg.c_str ());
 
@@ -1419,7 +1406,12 @@
               // slow things down tremendously for large directories.
               const dir_info& di = p->second;
 
-              if ((fs.mtime () + fs.time_resolution ()
+#if defined (OCTAVE_USE_WINDOWS_API)
+              if ((sys::file_time (dir_name)
+#else
+              if ((sys::file_time (fs.mtime ().unix_time ())
+#endif
+                   + sys::file_time::time_resolution ()
                    > di.dir_time_last_checked)
                   || subdirs_modified (dir_name, dir_time_last_checked))
                 initialize ();
@@ -1454,7 +1446,12 @@
         }
     }
   // Absolute path, check timestamp to see whether it requires re-caching
-  else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked
+#if defined (OCTAVE_USE_WINDOWS_API)
+  else if (sys::file_time (dir_name)
+#else
+  else if (sys::file_time (fs.mtime ().unix_time ())
+#endif
+           + sys::file_time::time_resolution () > dir_time_last_checked
            || subdirs_modified (dir_name, dir_time_last_checked))
     initialize ();
 
@@ -1483,21 +1480,32 @@
 }
 
 void
-load_path::dir_info::initialize (void)
+load_path::dir_info::initialize ()
 {
   is_relative = ! sys::env::absolute_pathname (dir_name);
 
-  dir_time_last_checked = sys::time (static_cast<OCTAVE_TIME_T> (0));
-
+  dir_time_last_checked = sys::file_time (static_cast<OCTAVE_TIME_T> (0));
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::string msg;
+
+  if (sys::dir_exists (dir_name, msg))
+#else
   sys::file_stat fs (dir_name);
 
   if (fs)
+#endif
     {
       method_file_map.clear ();
       package_dir_map.clear ();
 
-      dir_mtime = fs.mtime ();
-      dir_time_last_checked = sys::time ();
+#if defined (OCTAVE_USE_WINDOWS_API)
+      dir_mtime = sys::file_time (dir_name);
+#else
+      dir_mtime = fs.mtime ().unix_time ();
+#endif
+
+      dir_time_last_checked = sys::file_time ();
 
       get_file_list (dir_name);
 
@@ -1523,7 +1531,9 @@
     }
   else
     {
+#if ! defined (OCTAVE_USE_WINDOWS_API)
       std::string msg = fs.error ();
+#endif
       warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
     }
 }
@@ -1554,36 +1564,31 @@
 
       std::string full_name = sys::file_ops::concat (d, fname);
 
-      sys::file_stat fs (full_name);
-
-      if (fs)
+      if (sys::dir_exists (full_name))
         {
-          if (fs.is_dir ())
-            {
-              if (fname == "private")
-                get_private_file_map (full_name);
-              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));
-            }
-          else
+          if (fname == "private")
+            get_private_file_map (full_name);
+          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));
+        }
+      else if (sys::file_exists (full_name))
+        {
+          all_files[all_files_count++] = fname;
+
+          std::size_t pos = fname.rfind ('.');
+
+          if (pos != std::string::npos)
             {
-              all_files[all_files_count++] = fname;
-
-              std::size_t pos = fname.rfind ('.');
-
-              if (pos != std::string::npos)
+              std::string ext = fname.substr (pos);
+
+              if (ext == ".m" || ext == ".oct" || ext == ".mex")
                 {
-                  std::string ext = fname.substr (pos);
-
-                  if (ext == ".m" || ext == ".oct" || ext == ".mex")
-                    {
-                      std::string base = fname.substr (0, pos);
-
-                      if (valid_identifier (base))
-                        fcn_files[fcn_files_count++] = fname;
-                    }
+                  std::string base = fname.substr (0, pos);
+
+                  if (valid_identifier (base))
+                    fcn_files[fcn_files_count++] = fname;
                 }
             }
         }
@@ -1607,9 +1612,7 @@
 
   std::string pd = sys::file_ops::concat (d, "private");
 
-  sys::file_stat fs (pd);
-
-  if (fs && fs.is_dir ())
+  if (sys::dir_exists (pd))
     method_file_map[class_name].private_file_map = get_fcn_files (pd);
 }
 
@@ -1746,11 +1749,10 @@
 
           retval = find_method (class_name, meth, dir_name);
         }
-      else
-        retval = "";
     }
   else
     {
+      // Ensure that dir_name is empty if function is not found.
       dir_name = "";
 
       const_fcn_map_iterator p = m_fcn_map.find (fcn);
@@ -1820,6 +1822,7 @@
 
   //  update ();
 
+  // Ensure that dir_name is empty if method is not found.
   dir_name = "";
 
   const_method_map_iterator q = m_method_map.find (class_name);
@@ -1897,7 +1900,7 @@
 }
 
 string_vector
-load_path::package_info::fcn_names (void) const
+load_path::package_info::fcn_names () const
 {
   std::size_t len = m_fcn_map.size ();
 
@@ -2445,9 +2448,7 @@
             {
               std::string nm = sys::file_ops::concat (dirname, elt);
 
-              sys::file_stat fs (nm);
-
-              if (fs && fs.is_dir ())
+              if (sys::dir_exists (nm))
                 retval += (directory_path::path_sep_str ()
                            + genpath (nm, skip));
             }
@@ -2500,13 +2501,15 @@
   return retval;
 }
 
-DEFUN (rehash, , ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (rehash, interp, , ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} rehash ()
 Reinitialize Octave's load path directory cache.
 @end deftypefn */)
 {
-  rehash_internal ();
+  load_path& lp = interp.get_load_path ();
+
+  lp.rehash ();
 
   return ovl ();
 }
@@ -2599,7 +2602,7 @@
 
       lp.set (path, true);
 
-      rehash_internal ();
+      lp.rehash ();
     }
 
   if (nargout > 0)
@@ -2754,7 +2757,7 @@
     }
 
   if (need_to_update)
-    rehash_internal ();
+    lp.rehash ();
 
   return retval;
 }
@@ -2814,7 +2817,7 @@
     }
 
   if (need_to_update)
-    rehash_internal ();
+    lp.rehash ();
 
   return retval;
 }
--- a/libinterp/corefcn/load-path.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/load-path.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,15 +51,13 @@
 
   typedef void (*hook_fcn_ptr) (const std::string& dir);
 
-  load_path (const load_path&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (load_path)
 
-  load_path& operator = (const load_path&) = delete;
-
-  ~load_path (void) = default;
+  ~load_path () = default;
 
   void initialize (bool set_initial_path = false);
 
-  void clear (void);
+  void clear ();
 
   void set (const std::string& p, bool warn = false, bool is_init = false);
 
@@ -69,7 +67,7 @@
 
   bool remove (const std::string& dir);
 
-  void update (void);
+  void update ();
 
   bool contains_canonical (const std::string& dir_name) const;
 
@@ -159,36 +157,36 @@
 
   string_vector find_all_first_of (const string_vector& files) const;
 
-  string_vector dirs (void) const;
+  string_vector dirs () const;
 
-  std::list<std::string> dir_list (void) const;
+  std::list<std::string> dir_list () const;
 
   string_vector files (const std::string& dir, bool omit_exts = false) const;
 
-  string_vector fcn_names (void) const;
+  string_vector fcn_names () const;
 
-  std::string path (void) const;
+  std::string path () const;
 
   void display (std::ostream& os) const;
 
-  std::function<void (const std::string&)> get_add_hook (void)
+  std::function<void (const std::string&)> get_add_hook ()
   {
-    return add_hook;
+    return m_add_hook;
   }
 
-  std::function<void (const std::string&)> get_remove_hook (void)
+  std::function<void (const std::string&)> get_remove_hook ()
   {
-    return remove_hook;
+    return m_remove_hook;
   }
 
   void set_add_hook (const std::function<void (const std::string&)>& f)
   {
-    add_hook = f;
+    m_add_hook = f;
   }
 
   void set_remove_hook (const std::function<void (const std::string&)>& f)
   {
-    remove_hook = f;
+    m_remove_hook = f;
   }
 
   void read_dir_config (const std::string& dir) const;
@@ -204,18 +202,28 @@
       m_command_line_path += directory_path::path_sep_str () + p;
   }
 
-  std::string get_command_line_path (void) const
+  std::string get_command_line_path () const
   {
     return m_command_line_path;
   }
 
-  std::string system_path (void) const { return s_sys_path; }
+  std::string system_path () const { return s_sys_path; }
+
+  void rehash ();
 
   static const int M_FILE = 1;
   static const int OCT_FILE = 2;
   static const int MEX_FILE = 4;
 
+  static octave_idx_type get_weak_n_updated () { return s_n_updated; }
+
+  static void signal_clear_fcn_cache ()
+  {
+    s_n_updated++;
+  }
+
 private:
+  static std::atomic<octave_idx_type> s_n_updated;
 
   class dir_info
   {
@@ -230,7 +238,7 @@
     struct class_info
     {
     public:
-      class_info (void) : method_file_map (), private_file_map () { }
+      class_info () : method_file_map (), private_file_map () { }
 
       class_info (const class_info& ci)
         : method_file_map (ci.method_file_map),
@@ -247,7 +255,7 @@
         return *this;
       }
 
-      ~class_info (void) = default;
+      ~class_info () = default;
 
       fcn_file_map_type method_file_map;
       fcn_file_map_type private_file_map;
@@ -268,7 +276,7 @@
     // This default constructor is only provided so we can create a
     // std::map of dir_info objects.  You should not use this
     // constructor for any other purpose.
-    dir_info (void) = default;
+    dir_info () = default;
 
     dir_info (const std::string& d)
       : dir_name (d), abs_dir_name (), is_relative (false),
@@ -280,17 +288,17 @@
 
     dir_info (const dir_info&) = default;
 
-    ~dir_info (void) = default;
+    ~dir_info () = default;
 
     dir_info& operator = (const dir_info&) = default;
 
-    bool update (void);
+    bool update ();
 
     std::string dir_name;
     std::string abs_dir_name;
     bool is_relative;
-    sys::time dir_mtime;
-    sys::time dir_time_last_checked;
+    sys::file_time dir_mtime;
+    sys::file_time dir_time_last_checked;
     string_vector all_files;
     string_vector fcn_files;
     fcn_file_map_type private_file_map;
@@ -301,7 +309,7 @@
 
   private:
 
-    void initialize (void);
+    void initialize ();
 
     void get_file_list (const std::string& d);
 
@@ -320,12 +328,14 @@
   {
   public:
 
+    file_info () = delete;
+
     file_info (const std::string& d, int t) : dir_name (d), types (t) { }
 
     file_info (const file_info& fi)
       : dir_name (fi.dir_name), types (fi.types) { }
 
-    ~file_info (void) = default;
+    ~file_info () = default;
 
     file_info& operator = (const file_info& fi)
     {
@@ -404,7 +414,7 @@
         m_private_fcn_map (l.m_private_fcn_map), m_method_map (l.m_method_map)
     { }
 
-    ~package_info (void) = default;
+    ~package_info () = default;
 
     package_info& operator = (const package_info& l)
     {
@@ -438,7 +448,7 @@
 
     void remove (const dir_info& di);
 
-    void clear (void)
+    void clear ()
     {
       m_dir_list.clear ();
 
@@ -468,7 +478,7 @@
 
     void overloads (const std::string& meth, std::list<std::string>& l) const;
 
-    string_vector fcn_names (void) const;
+    string_vector fcn_names () const;
 
   private:
 
@@ -515,9 +525,9 @@
   typedef package_map_type::const_iterator const_package_map_iterator;
   typedef package_map_type::iterator package_map_iterator;
 
-  std::function<void (const std::string&)> add_hook;
+  std::function<void (const std::string&)> m_add_hook;
 
-  std::function<void (const std::string&)> remove_hook;
+  std::function<void (const std::string&)> m_remove_hook;
 
   void execute_pkg_add_or_del (const std::string& dir,
                                const std::string& script_file);
@@ -558,6 +568,8 @@
 
   string_vector get_file_list (const dir_info::fcn_file_map_type& lst) const;
 
+  std::string find_private_file (const std::string& fname) const;
+
   friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d);
 
   //--------
--- a/libinterp/corefcn/load-save.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/load-save.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,6 +43,7 @@
 #include "file-stat.h"
 #include "glob-match.h"
 #include "lo-mappers.h"
+#include "lo-sysdep.h"
 #include "mach-info.h"
 #include "oct-env.h"
 #include "oct-locbuf.h"
@@ -193,16 +194,12 @@
       // Either no '.' in name or no '.' appears after last directory
       // separator.
 
-      sys::file_stat fs (fname);
-
-      if (! (fs.exists () && fs.is_reg ()))
+      if (! (sys::file_exists (fname, false)))
         fname = find_file_to_load (fname + ".mat", orig_name);
     }
   else
     {
-      sys::file_stat fs (fname);
-
-      if (! (fs.exists () && fs.is_reg ()))
+      if (! (sys::file_exists (fname, false)))
         {
           fname = "";
 
@@ -268,7 +265,7 @@
 #endif
 }
 
-load_save_system::~load_save_system (void)
+load_save_system::~load_save_system ()
 {
 #if defined (HAVE_HDF5)
   H5close ();
@@ -732,7 +729,7 @@
     }
 }
 
-void load_save_system::dump_octave_core (void)
+void load_save_system::dump_octave_core ()
 {
   if (m_crash_dumps_octave_core)
     {
@@ -1074,7 +1071,7 @@
   m_interpreter.install_variable (name, val, global);
 }
 
-std::string load_save_system::init_save_header_format (void)
+std::string load_save_system::init_save_header_format ()
 {
   return
     (std::string ("# Created by Octave " OCTAVE_VERSION
@@ -1465,7 +1462,16 @@
     print_usage ();
   else
     {
-      std::string fname = sys::file_ops::tilde_expand (argv[i]);
+      // For non-append mode, we make a new temporary filename, write to that
+      // instead of the file specified, then rename it at the end.
+      // That way, if something goes wrong during the save like OOM,
+      // we won't overwrite already-saved data in a file.
+      // See bug #63803 for context.
+      // In append mode, this kind of guard is counterproductive so we write
+      // directly to the specified file.
+
+      std::string desiredname = sys::file_ops::tilde_expand (argv[i]);
+      std::string fname = desiredname + (append ? "" : ".saving_in_progress");
 
       i++;
 
@@ -1542,6 +1548,20 @@
               file.close ();
             }
         }
+
+      // If we are all the way here without Octave crashing or running
+      // out of memory etc, then we can say that writing to the
+      // temporary file was successful. So now we try to rename it to
+      // the actual file that was specified, unless we were in append mode
+      // in which case we take no action.
+
+      if (! append)
+        {
+          std::string msg;
+          if (octave::sys::rename (fname, desiredname, msg) < 0)
+            error ("save: unable to save to %s  %s",
+                   desiredname.c_str (), msg.c_str ());
+        }
     }
 
   return retval;
@@ -2060,13 +2080,3 @@
 }
 
 OCTAVE_END_NAMESPACE(octave)
-
-// DEPRECATED in Octave 7
-
-void
-dump_octave_core (void)
-{
-  octave::load_save_system& load_save_sys = octave::__get_load_save_system__ ();
-
-  load_save_sys.dump_octave_core ();
-}
--- a/libinterp/corefcn/load-save.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/load-save.h	Fri Jun 23 20:51:51 2023 +0200
@@ -75,16 +75,14 @@
 
   OCTINTERP_API load_save_system (interpreter& interp);
 
-  OCTINTERP_API ~load_save_system (void);
+  OCTINTERP_API ~load_save_system ();
 
-  load_save_system (const load_save_system&) = delete;
-
-  load_save_system& operator = (const load_save_system&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (load_save_system)
 
   OCTINTERP_API octave_value
   crash_dumps_octave_core (const octave_value_list& args, int nargout);
 
-  bool crash_dumps_octave_core (void) const
+  bool crash_dumps_octave_core () const
   {
     return m_crash_dumps_octave_core;
   }
@@ -97,7 +95,7 @@
   octave_value octave_core_file_limit (const octave_value_list& args,
                                        int nargout);
 
-  double octave_core_file_limit (void) const
+  double octave_core_file_limit () const
   {
     return m_octave_core_file_limit;
   }
@@ -110,7 +108,7 @@
   OCTINTERP_API octave_value
   octave_core_file_name (const octave_value_list& args, int nargout);
 
-  std::string octave_core_file_name (void) const
+  std::string octave_core_file_name () const
   {
     return m_octave_core_file_name;
   }
@@ -123,7 +121,7 @@
   OCTINTERP_API octave_value
   save_default_options (const octave_value_list& args, int nargout);
 
-  std::string save_default_options (void) const
+  std::string save_default_options () const
   {
     return m_save_default_options;
   }
@@ -136,7 +134,7 @@
   OCTINTERP_API octave_value
   octave_core_file_options (const octave_value_list& args, int nargout);
 
-  std::string octave_core_file_options (void) const
+  std::string octave_core_file_options () const
   {
     return m_octave_core_file_options;
   }
@@ -149,7 +147,7 @@
   OCTINTERP_API octave_value
   save_header_format_string (const octave_value_list& args, int nargout);
 
-  std::string save_header_format_string (void) const
+  std::string save_header_format_string () const
   {
     return m_save_header_format_string;
   }
@@ -186,7 +184,7 @@
              std::ostream& os, const load_save_format& fmt,
              bool save_as_floats, bool write_header_info);
 
-  OCTINTERP_API void dump_octave_core (void);
+  OCTINTERP_API void dump_octave_core ();
 
   OCTINTERP_API octave_value_list
   load (const octave_value_list& args = octave_value_list (),
@@ -252,7 +250,7 @@
   install_loaded_variable (const std::string& name, const octave_value& val,
                            bool global, const std::string& /*doc*/);
 
-  static OCTINTERP_API std::string init_save_header_format (void);
+  static OCTINTERP_API std::string init_save_header_format ();
 
   static OCTINTERP_API load_save_format
   get_file_format (std::istream& file, const std::string& filename);
@@ -277,14 +275,14 @@
 
   void set_type (load_save_system::format_type type) { m_type = type; }
 
-  load_save_system::format_type type (void) const { return m_type; }
+  load_save_system::format_type type () const { return m_type; }
 
   void set_option (load_save_system::format_options option)
   {
     m_options |= option;
   }
 
-  int options (void) const { return m_options; }
+  int options () const { return m_options; }
 
 private:
 
@@ -294,7 +292,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-OCTAVE_DEPRECATED (7, "use 'load_save_system::dump_octave_core' instead")
-extern OCTINTERP_API void dump_octave_core (void);
-
 #endif
--- a/libinterp/corefcn/ls-ascii-helper.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ls-ascii-helper.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,29 +44,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::skip_until_newline' instead")
-inline void
-skip_until_newline (std::istream& is, bool keep_newline = false)
-{
-  return octave::skip_until_newline (is, keep_newline);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::skip_preceding_newline' instead")
-inline void
-skip_preceeding_newline (std::istream& is)
-{
-  return octave::skip_preceeding_newline (is);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::read_until_newline' instead")
-inline std::string
-read_until_newline (std::istream& is, bool keep_newline = false)
-{
-  return octave::read_until_newline (is, keep_newline);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/ls-hdf5.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ls-hdf5.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -100,7 +100,7 @@
 }
 
 void
-hdf5_fstreambase::close (void)
+hdf5_fstreambase::close ()
 {
 #if defined (HAVE_HDF5)
 
--- a/libinterp/corefcn/ls-hdf5.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ls-hdf5.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,12 +51,14 @@
 
   hdf5_fstreambase () : file_id (-1), current_item () { }
 
+  OCTAVE_DISABLE_COPY_MOVE (hdf5_fstreambase)
+
   ~hdf5_fstreambase () { close (); }
 
   OCTINTERP_API hdf5_fstreambase (const char *name, int mode,
                                   int /* prot */ = 0);
 
-  OCTINTERP_API void close (void);
+  OCTINTERP_API void close ();
 
   OCTINTERP_API void open (const char *name, int mode, int);
 
@@ -101,9 +103,12 @@
 struct hdf5_callback_data
 {
 public:
-  hdf5_callback_data (void)
+
+  hdf5_callback_data ()
     : name (), global (false), tc (), doc () { }
 
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (hdf5_callback_data)
+
   // the following fields are set by hdf5_read_data on successful return:
 
   // the name of the variable
--- a/libinterp/corefcn/ls-mat5.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ls-mat5.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,6 +44,7 @@
 #include "file-stat.h"
 #include "glob-match.h"
 #include "lo-mappers.h"
+#include "lo-sysdep.h"
 #include "mach-info.h"
 #include "oct-env.h"
 #include "oct-locbuf.h"
@@ -897,9 +898,8 @@
                     std::string str
                       = (octave::config::octave_exec_home ()
                          + fpath.substr (mroot.length ()));
-                    octave::sys::file_stat fs (str);
-
-                    if (fs.exists ())
+
+                    if (octave::sys::file_exists (str))
                       {
                         std::size_t xpos
                           = str.find_last_of (octave::sys::file_ops::dir_sep_chars ());
@@ -1239,7 +1239,7 @@
                       {
                         try
                           {
-                            octave_value_list tmp = octave::feval ("loadobj", tc, 1);
+                            octave_value_list tmp = interp.feval ("loadobj", tc, 1);
 
                             tc = tmp(0);
                           }
@@ -2724,14 +2724,16 @@
 
       octave_map m;
 
-      octave::load_path& lp = octave::__get_load_path__ ();
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
+      octave::load_path& lp = interp.get_load_path ();
 
       if (tc.isobject ()
           && lp.find_method (tc.class_name (), "saveobj") != "")
         {
           try
             {
-              octave_value_list tmp = octave::feval ("saveobj", tc, 1);
+              octave_value_list tmp = interp.feval ("saveobj", tc, 1);
 
               m = tmp(0).map_value ();
             }
--- a/libinterp/corefcn/ls-utils.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ls-utils.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,22 +40,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead")
-inline save_type
-get_save_type (double max_val, double min_val)
-{
-  return octave::get_save_type (max_val, min_val);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead")
-inline save_type
-get_save_type (float max_val, float min_val)
-{
-  return octave::get_save_type (max_val, min_val);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/lsode.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/lsode.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,11 +37,11 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "parse.h"
 #include "pr-output.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -79,7 +79,9 @@
 
       try
         {
-          tmp = octave::feval (lsode_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (lsode_fcn, args, 1);
         }
       catch (octave::execution_exception& ee)
         {
@@ -119,7 +121,9 @@
 
       try
         {
-          tmp = octave::feval (lsode_jac, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (lsode_jac, args, 1);
         }
       catch (octave::execution_exception& ee)
         {
@@ -135,8 +139,7 @@
           warned_jac_imaginary = true;
         }
 
-      retval = tmp(
-                 0).xmatrix_value ("lsode: expecting user supplied jacobian function to return numeric array");
+      retval = tmp(0).xmatrix_value ("lsode: expecting user supplied jacobian function to return numeric array");
 
       if (retval.isempty ())
         err_user_supplied_eval ("lsode");
--- a/libinterp/corefcn/mappers.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/mappers.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -2163,10 +2163,10 @@
 %!error tanh (1, 2)
 */
 
-DEFUNX ("tolower", Ftolower, args, ,
-        doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{y} =} tolower (@var{s})
-@deftypefnx {} {@var{y} =} lower (@var{s})
+DEFUN (lower, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{y} =} lower (@var{s})
+@deftypefnx {} {@var{y} =} tolower (@var{s})
 Return a copy of the string or cell string @var{s}, with each uppercase
 character replaced by the corresponding lowercase one; non-alphabetic
 characters are left unchanged.
@@ -2175,15 +2175,15 @@
 
 @example
 @group
-tolower ("MiXeD cAsE 123")
-      @result{} "mixed case 123"
+lower ("MiXeD cAsE 123")
+    @result{} "mixed case 123"
 @end group
 @end example
 
-Programming Note: @code{lower} is an alias for @code{tolower} and either name
+Programming Note: @code{tolower} is an alias for @code{lower} and either name
 can be used in Octave.
 
-@seealso{toupper}
+@seealso{upper}
 @end deftypefn */)
 {
   if (args.length () != 1)
@@ -2192,24 +2192,24 @@
   return ovl (args(0).xtolower ());
 }
 
-DEFALIAS (lower, tolower);
+DEFALIAS (tolower, lower);
 
 /*
-%!assert (tolower ("OCTAVE"), "octave")
-%!assert (tolower ("123OCTave! _&"), "123octave! _&")
-%!assert (tolower ({"ABC", "DEF", {"GHI", {"JKL"}}}),
+%!assert (lower ("OCTAVE"), "octave")
+%!assert (lower ("123OCTave! _&"), "123octave! _&")
+%!assert (lower ({"ABC", "DEF", {"GHI", {"JKL"}}}),
 %!        {"abc", "def", {"ghi", {"jkl"}}})
-%!assert (tolower (["ABC"; "DEF"]), ["abc"; "def"])
-%!assert (tolower ({["ABC"; "DEF"]}), {["abc";"def"]})
-%!assert (tolower (["ABCÄÖÜSS"; "abcäöüß"]),
+%!assert (lower (["ABC"; "DEF"]), ["abc"; "def"])
+%!assert (lower ({["ABC"; "DEF"]}), {["abc";"def"]})
+%!assert (lower (["ABCÄÖÜSS"; "abcäöüß"]),
 %!        ["abcäöüss"; "abcäöüß"])
-%!assert (tolower (repmat ("ÄÖÜ", 2, 1, 3)), repmat ("äöü", 2, 1, 3))
-%!assert (tolower (68), 68)
-%!assert (tolower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]})
-%!assert (tolower (68i), 68i)
-%!assert (tolower ({[68i, 68; 68, 68i]}), {[68i, 68; 68, 68i]})
-%!assert (tolower (single (68i)), single (68i))
-%!assert (tolower ({single([68i, 68; 68, 68i])}), {single([68i, 68; 68, 68i])})
+%!assert (lower (repmat ("ÄÖÜ", 2, 1, 3)), repmat ("äöü", 2, 1, 3))
+%!assert (lower (68), 68)
+%!assert (lower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]})
+%!assert (lower (68i), 68i)
+%!assert (lower ({[68i, 68; 68, 68i]}), {[68i, 68; 68, 68i]})
+%!assert (lower (single (68i)), single (68i))
+%!assert (lower ({single([68i, 68; 68, 68i])}), {single([68i, 68; 68, 68i])})
 
 %!test
 %! classes = {@char, @double, @single, ...
@@ -2217,28 +2217,28 @@
 %!            @uint8, @uint16, @uint32, @uint64};
 %! for i = 1:numel (classes)
 %!   cls = classes{i};
-%!   assert (class (tolower (cls (97))), class (cls (97)));
-%!   assert (class (tolower (cls ([98, 99]))), class (cls ([98, 99])));
+%!   assert (class (lower (cls (97))), class (cls (97)));
+%!   assert (class (lower (cls ([98, 99]))), class (cls ([98, 99])));
 %! endfor
 %!test
 %! a(3,3,3,3) = "D";
-%! assert (tolower (a)(3,3,3,3), "d");
+%! assert (lower (a)(3,3,3,3), "d");
 
 %!test
 %! charset = char (0:127);
 %! result = charset;
 %! result (double ("A":"Z") + 1) = result (double ("a":"z") + 1);
-%! assert (tolower (charset), result);
+%! assert (lower (charset), result);
 
-%!error <Invalid call to tolower> lower ()
-%!error <Invalid call to tolower> tolower ()
-%!error tolower (1, 2)
+%!error <Invalid call to lower> lower ()
+%!error <Invalid call to lower> tolower ()
+%!error lower (1, 2)
 */
 
-DEFUNX ("toupper", Ftoupper, args, ,
-        doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{y} =} toupper (@var{s})
-@deftypefnx {} {@var{y} =} upper (@var{s})
+DEFUN (upper, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{y} =} upper (@var{s})
+@deftypefnx {} {@var{y} =} toupper (@var{s})
 Return a copy of the string or cell string @var{s}, with each lowercase
 character replaced by the corresponding uppercase one; non-alphabetic
 characters are left unchanged.
@@ -2247,15 +2247,15 @@
 
 @example
 @group
-toupper ("MiXeD cAsE 123")
-      @result{} "MIXED CASE 123"
+upper ("MiXeD cAsE 123")
+    @result{} "MIXED CASE 123"
 @end group
 @end example
 
-Programming Note: @code{upper} is an alias for @code{toupper} and either name
+Programming Note: @code{toupper} is an alias for @code{upper} and either name
 can be used in Octave.
 
-@seealso{tolower}
+@seealso{lower}
 @end deftypefn */)
 {
   if (args.length () != 1)
@@ -2264,25 +2264,25 @@
   return ovl (args(0).xtoupper ());
 }
 
-DEFALIAS (upper, toupper);
+DEFALIAS (toupper, upper);
 
 /*
-%!assert (toupper ("octave"), "OCTAVE")
-%!assert (toupper ("123OCTave! _&"), "123OCTAVE! _&")
-%!assert (toupper ({"abc", "def", {"ghi", {"jkl"}}}),
+%!assert (upper ("octave"), "OCTAVE")
+%!assert (upper ("123OCTave! _&"), "123OCTAVE! _&")
+%!assert (upper ({"abc", "def", {"ghi", {"jkl"}}}),
 %!        {"ABC", "DEF", {"GHI", {"JKL"}}})
-%!assert (toupper (["abc"; "def"]), ["ABC"; "DEF"])
-%!assert (toupper ({["abc"; "def"]}), {["ABC";"DEF"]})
-%!assert (toupper (["ABCÄÖÜSS"; "abcäöüß"]),
+%!assert (upper (["abc"; "def"]), ["ABC"; "DEF"])
+%!assert (upper ({["abc"; "def"]}), {["ABC";"DEF"]})
+%!assert (upper (["ABCÄÖÜSS"; "abcäöüß"]),
 %!        ["ABCÄÖÜSS"; "ABCÄÖÜSS"])
-%!assert (toupper (repmat ("äöü", 2, 1, 3)), repmat ("ÄÖÜ", 2, 1, 3))
-%!assert (toupper (100), 100)
-%!assert (toupper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]})
-%!assert (toupper (100i), 100i)
-%!assert (toupper ({[100i, 100; 100, 100i]}), {[100i, 100; 100, 100i]})
-%!assert (toupper (single (100i)), single (100i))
-%!assert (toupper ({single([100i, 100; 100, 100i])}),
-%!                 {single([100i, 100; 100, 100i])})
+%!assert (upper (repmat ("äöü", 2, 1, 3)), repmat ("ÄÖÜ", 2, 1, 3))
+%!assert (upper (100), 100)
+%!assert (upper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]})
+%!assert (upper (100i), 100i)
+%!assert (upper ({[100i, 100; 100, 100i]}), {[100i, 100; 100, 100i]})
+%!assert (upper (single (100i)), single (100i))
+%!assert (upper ({single([100i, 100; 100, 100i])}),
+%!        {single([100i, 100; 100, 100i])})
 
 %!test
 %! classes = {@char, @double, @single, ...
@@ -2290,21 +2290,21 @@
 %!            @uint8, @uint16, @uint32, @uint64};
 %! for i = 1:numel (classes)
 %!   cls = classes{i};
-%!   assert (class (toupper (cls (97))), class (cls (97)));
-%!   assert (class (toupper (cls ([98, 99]))), class (cls ([98, 99])));
+%!   assert (class (upper (cls (97))), class (cls (97)));
+%!   assert (class (upper (cls ([98, 99]))), class (cls ([98, 99])));
 %! endfor
 %!test
 %! a(3,3,3,3) = "d";
-%! assert (toupper (a)(3,3,3,3), "D");
+%! assert (upper (a)(3,3,3,3), "D");
 %!test
 %! charset = char (0:127);
 %! result = charset;
 %! result (double  ("a":"z") + 1) = result (double  ("A":"Z") + 1);
-%! assert (toupper (charset), result);
+%! assert (upper (charset), result);
 
-%!error <Invalid call to toupper> toupper ()
-%!error <Invalid call to toupper> upper ()
-%!error toupper (1, 2)
+%!error <Invalid call to upper> upper ()
+%!error <Invalid call to upper> toupper ()
+%!error upper (1, 2)
 */
 
 DEFALIAS (gammaln, lgamma);
--- a/libinterp/corefcn/mex.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/mex.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -65,7 +65,6 @@
 #include "ov-mex-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
-#include "parse.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -218,17 +217,6 @@
 
   extern OCTINTERP_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);
   extern OCTINTERP_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);
-#if 0
-  /* We don't have these yet. */
-  extern OCTINTERP_API mxComplexInt8 * mxGetComplexInt8s (const mxArray *p);
-  extern OCTINTERP_API mxComplexInt16 * mxGetComplexInt16s (const mxArray *p);
-  extern OCTINTERP_API mxComplexInt32 * mxGetComplexInt32s (const mxArray *p);
-  extern OCTINTERP_API mxComplexInt64 * mxGetComplexInt64s (const mxArray *p);
-  extern OCTINTERP_API mxComplexUint8 * mxGetComplexUint8s (const mxArray *p);
-  extern OCTINTERP_API mxComplexUint16 * mxGetComplexUint16s (const mxArray *p);
-  extern OCTINTERP_API mxComplexUint32 * mxGetComplexUint32s (const mxArray *p);
-  extern OCTINTERP_API mxComplexUint64 * mxGetComplexUint64s (const mxArray *p);
-#endif
 
   extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
   extern OCTINTERP_API void * mxGetImagData (const mxArray *ptr);
@@ -246,17 +234,6 @@
 
   extern OCTINTERP_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);
   extern OCTINTERP_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);
-#if 0
-  /* We don't have these yet. */
-  extern OCTINTERP_API int mxSetComplexInt8s (mxArray *p, mxComplexInt8 *d);
-  extern OCTINTERP_API int mxSetComplexInt16s (mxArray *p, mxComplexInt16 *d);
-  extern OCTINTERP_API int mxSetComplexInt32s (mxArray *p, mxComplexInt32 *d);
-  extern OCTINTERP_API int mxSetComplexInt64s (mxArray *p, mxComplexInt64 *d);
-  extern OCTINTERP_API int mxSetComplexUint8s (mxArray *p, mxComplexUint8 *d);
-  extern OCTINTERP_API int mxSetComplexUint16s (mxArray *p, mxComplexUint16 *d);
-  extern OCTINTERP_API int mxSetComplexUint32s (mxArray *p, mxComplexUint32 *d);
-  extern OCTINTERP_API int mxSetComplexUint64s (mxArray *p, mxComplexUint64 *d);
-#endif
 
   extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
   extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
@@ -471,6 +448,8 @@
 {
 public:
 
+  mxArray_octave_value () = delete;
+
   mxArray_octave_value (bool interleaved, const octave_value& ov)
     : mxArray_base (interleaved), m_val (ov), m_mutate_flag (false),
       m_id (mxUNKNOWN_CLASS), m_class_name (nullptr), m_ndims (-1),
@@ -728,7 +707,7 @@
   {
     if (m_val.issparse ())
       {
-        // For sparse arrays, return the first non-zero value.
+        // For sparse arrays, return the first nonzero value.
         const void *m_data = m_val.mex_get_data ();
         if (m_data == nullptr)
           return 0.0;
@@ -805,25 +784,6 @@
   GET_DATA_METHOD (mxComplexSingle, get_complex_singles,
                    mxDOUBLE_CLASS, mxCOMPLEX);
 
-#if 0
-  /* We don't have these yet. */
-  GET_DATA_METHOD (mxComplexInt8 *, get_complex_int8s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexInt16 *, get_complex_int16s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexInt32 *, get_complex_int32s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexInt64 *, get_complex_int64s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexUint8 *, get_complex_uint8s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexUint16 *, get_complex_uint16s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexUint32 *, get_complex_uint32s, (void), nullptr);
-
-  GET_DATA_METHOD (mxComplexUint64 *, get_complex_uint64s, (void), nullptr);
-#endif
-
   void * get_imag_data (void) const
   {
     void *retval = nullptr;
@@ -852,17 +812,6 @@
 
   MUTATION_METHOD (int, set_complex_doubles, (mxComplexDouble *), 0)
   MUTATION_METHOD (int, set_complex_singles, (mxComplexSingle *), 0)
-#if 0
-  /* We don't have these yet. */
-  MUTATION_METHOD (int, set_complex_int8s, (mxComplexInt8 *), 0)
-  MUTATION_METHOD (int, set_complex_int16s, (mxComplexInt16 *), 0)
-  MUTATION_METHOD (int, set_complex_int32s, (mxComplexInt32 *), 0)
-  MUTATION_METHOD (int, set_complex_int64s, (mxComplexInt64 *), 0)
-  MUTATION_METHOD (int, set_complex_uint8s, (mxComplexUint8 *), 0)
-  MUTATION_METHOD (int, set_complex_uint16s, (mxComplexUint16 *), 0)
-  MUTATION_METHOD (int, set_complex_uint32s, (mxComplexUint32 *), 0)
-  MUTATION_METHOD (int, set_complex_uint64s, (mxComplexUint64 *), 0)
-#endif
 
   // Not allowed.
   VOID_MUTATION_METHOD (set_imag_data, (void *))
@@ -1052,11 +1001,13 @@
 {
 public:
 
+  mxArray_matlab () = delete;
+
   // No assignment!
   // FIXME: should this be implemented?
   //        Note that we *do* have a copy constructor.
 
-  mxArray_matlab& operator = (const mxArray_matlab&);
+  mxArray_matlab& operator = (const mxArray_matlab&) = delete;
 
   ~mxArray_matlab (void)
   {
@@ -1290,49 +1241,6 @@
     err_invalid_type ("get_complex_singles");
   }
 
-#if 0
-  /* We don't have these yet. */
-  mxComplexInt8 * get_complex_int8s (void) const
-  {
-    err_invalid_type ("get_complex_int8s");
-  }
-
-  mxComplexInt16 * get_complex_int16s (void) const
-  {
-    err_invalid_type ("get_complex_int16s");
-  }
-
-  mxComplexInt32 * get_complex_int32s (void) const
-  {
-    err_invalid_type ("get_complex_int32s");
-  }
-
-  mxComplexInt64 * get_complex_int64s (void) const
-  {
-    err_invalid_type ("get_complex_int64s");
-  }
-
-  mxComplexUint8 * get_complex_uint8s (void) const
-  {
-    err_invalid_type ("get_complex_uint8s");
-  }
-
-  mxComplexUint16 * get_complex_uint16s (void) const
-  {
-    err_invalid_type ("get_complex_uint16s");
-  }
-
-  mxComplexUint32 * get_complex_uint32s (void) const
-  {
-    err_invalid_type ("get_complex_uint32s");
-  }
-
-  mxComplexUint64 * get_complex_uint64s (void) const
-  {
-    err_invalid_type ("get_complex_uint64s");
-  }
-#endif
-
   void * get_imag_data (void) const
   {
     err_invalid_type ("get_imag_data");
@@ -1403,49 +1311,6 @@
     err_invalid_type ("set_complex_singles");
   }
 
-#if 0
-  /* We don't have these yet. */
-  int set_complex_int8s (mxComplexInt8 *)
-  {
-    err_invalid_type ("set_complex_int8s");
-  }
-
-  int set_complex_int16s (mxComplexInt16 *)
-  {
-    err_invalid_type ("set_complex_int16s");
-  }
-
-  int set_complex_int32s (mxComplexInt32 *)
-  {
-    err_invalid_type ("set_complex_int32s");
-  }
-
-  int set_complex_int64s (mxComplexInt64 *)
-  {
-    err_invalid_type ("set_complex_int64s");
-  }
-
-  int set_complex_uint8s (mxComplexUint8 *)
-  {
-    err_invalid_type ("set_complex_uint8s");
-  }
-
-  int set_complex_uint16s (mxComplexUint16 *)
-  {
-    err_invalid_type ("set_complex_uint16s");
-  }
-
-  int set_complex_uint32s (mxComplexUint32 *)
-  {
-    err_invalid_type ("set_complex_uint32s");
-  }
-
-  int set_complex_uint64s (mxComplexUint64 *)
-  {
-    err_invalid_type ("set_complex_uint64s");
-  }
-#endif
-
   void set_imag_data (void * /*pi*/)
   {
     err_invalid_type ("set_imag_data");
@@ -1661,6 +1526,8 @@
 {
 public:
 
+  mxArray_base_full () = delete;
+
   mxArray_base_full (bool interleaved, mxClassID id, mwSize ndims,
                      const mwSize *dims, bool init = true)
     : mxArray_matlab (interleaved, id, ndims, dims),
@@ -1734,7 +1601,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_base_full& operator = (const mxArray_base_full&);
+  mxArray_base_full& operator = (const mxArray_base_full&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -1878,58 +1745,6 @@
     return static_cast<mxComplexSingle *> (m_pr);
   }
 
-#if 0
-  // We don't have these data types.
-
-  int get_complex_int8s (mxComplexInt8 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_int16s (mxComplexInt16 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_int32s (mxComplexInt32 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_int64s (mxComplexInt64 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_uint8s (mxComplexUint8 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_uint16s (mxComplexUint16 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_uint32s (mxComplexUint32 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int get_complex_uint64s (mxComplexUint64 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-#endif
-
   int set_doubles (mxDouble *d)
   {
     m_pr = d;
@@ -2002,58 +1817,6 @@
     return 0;
   }
 
-#if 0
-  // We don't have these data types.
-
-  int set_complex_int8s (mxComplexInt8 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_int16s (mxComplexInt16 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_int32s (mxComplexInt32 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_int64s (mxComplexInt64 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_uint8s (mxComplexUint8 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_uint16s (mxComplexUint16 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_uint32s (mxComplexUint32 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-
-  int set_complex_uint64s (mxComplexUint64 *d)
-  {
-    m_pr = d;
-    return 0;
-  }
-#endif
-
   int get_string (char *buf, mwSize buflen) const
   {
     int retval = 0;
@@ -2211,17 +1974,6 @@
 
     ELT_T *ppr = static_cast<ELT_T *> (m_pr);
 
-#if 0 && defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR)
-
-    // FIXME: Currently not allowed because we don't have the necessary
-    // constructors for integer arrays.
-
-    octave::unwind_action act ([=] () { maybe_disown_ptr (m_pr); });
-
-    return ARRAY_T (ppr, dv, current_mx_memory_resource);
-
-#else
-
     // Copy data instead of allowing the octave_value object to borrow
     // the mxArray object data.
 
@@ -2236,7 +1988,6 @@
 
     return octave_value (val);
 
-#endif
   }
 
 protected:
@@ -2251,6 +2002,8 @@
 {
 public:
 
+  mxArray_interleaved_full () = delete;
+
   mxArray_interleaved_full (mxClassID id, mwSize ndims, const mwSize *dims,
                             mxComplexity flag = mxREAL, bool init = true)
     : mxArray_base_full (true, id, ndims, dims, init),
@@ -2289,7 +2042,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_interleaved_full& operator = (const mxArray_interleaved_full&);
+  mxArray_interleaved_full& operator = (const mxArray_interleaved_full&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -2318,6 +2071,8 @@
 {
 public:
 
+  mxArray_separate_full () = delete;
+
   mxArray_separate_full (mxClassID id, mwSize ndims, const mwSize *dims,
                          mxComplexity flag = mxREAL, bool init = true)
     : mxArray_base_full (false, id, ndims, dims, init),
@@ -2362,7 +2117,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_separate_full& operator = (const mxArray_separate_full&);
+  mxArray_separate_full& operator = (const mxArray_separate_full&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -2512,6 +2267,8 @@
 {
 public:
 
+  mxArray_base_sparse () = delete;
+
   mxArray_base_sparse (bool interleaved, mxClassID id, mwSize m, mwSize n,
                        mwSize nzmax)
     : mxArray_matlab (interleaved, id, m, n),
@@ -2545,7 +2302,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_base_sparse& operator = (const mxArray_base_sparse&);
+  mxArray_base_sparse& operator = (const mxArray_base_sparse&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -2695,6 +2452,8 @@
 {
 public:
 
+  mxArray_interleaved_sparse () = delete;
+
   mxArray_interleaved_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
                               mxComplexity flag = mxREAL)
     : mxArray_base_sparse (true, id, m, n, nzmax),
@@ -2712,7 +2471,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_interleaved_sparse& operator = (const mxArray_interleaved_sparse&);
+  mxArray_interleaved_sparse& operator = (const mxArray_interleaved_sparse&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -2738,6 +2497,8 @@
 {
 public:
 
+  mxArray_separate_sparse () = delete;
+
   mxArray_separate_sparse (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
                            mxComplexity flag = mxREAL)
     : mxArray_base_sparse (false, id, m, n, nzmax),
@@ -2763,7 +2524,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_separate_sparse& operator = (const mxArray_separate_sparse&);
+  mxArray_separate_sparse& operator = (const mxArray_separate_sparse&) = delete;
 
   mxArray_base * dup (void) const
   {
@@ -2844,6 +2605,8 @@
 {
 public:
 
+  mxArray_struct () = delete;
+
   mxArray_struct (bool interleaved, mwSize ndims, const mwSize *dims,
                   int num_keys, const char **keys)
     : mxArray_matlab (interleaved, mxSTRUCT_CLASS, ndims, dims),
@@ -2910,7 +2673,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_struct& operator = (const mxArray_struct& val);
+  mxArray_struct& operator = (const mxArray_struct& val) = delete;
 
   void init (const char **keys)
   {
@@ -3111,30 +2874,28 @@
 {
 public:
 
+  mxArray_cell () = delete;
+
   mxArray_cell (bool interleaved, mwSize ndims, const mwSize *dims)
     : mxArray_matlab (interleaved, mxCELL_CLASS, ndims, dims),
-      m_data (static_cast<mxArray * *> (
-                mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
+      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
   { }
 
   mxArray_cell (bool interleaved, const dim_vector& dv)
     : mxArray_matlab (interleaved, mxCELL_CLASS, dv),
-      m_data (static_cast<mxArray * *> (
-                mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
+      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
   { }
 
   mxArray_cell (bool interleaved, mwSize m, mwSize n)
     : mxArray_matlab (interleaved, mxCELL_CLASS, m, n),
-      m_data (static_cast<mxArray * *> (
-                mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
+      m_data (static_cast<mxArray **> (mxArray::calloc (get_number_of_elements (), sizeof (mxArray *))))
   { }
 
 private:
 
   mxArray_cell (const mxArray_cell& val)
     : mxArray_matlab (val),
-      m_data (static_cast<mxArray * *> (
-                mxArray::malloc (get_number_of_elements () * sizeof (mxArray *))))
+      m_data (static_cast<mxArray **> (mxArray::malloc (get_number_of_elements () * sizeof (mxArray *))))
   {
     mwSize nel = get_number_of_elements ();
 
@@ -3150,7 +2911,7 @@
   // No assignment!  FIXME: should this be implemented?  Note that we
   // do have a copy constructor.
 
-  mxArray_cell& operator = (const mxArray_cell&);
+  mxArray_cell& operator = (const mxArray_cell&) = delete;
 
   mxArray_base * dup (void) const { return new mxArray_cell (*this); }
 
@@ -3415,11 +3176,7 @@
   mex (octave_mex_function& f)
     : m_curr_mex_fcn (f), m_memlist (), m_arraylist (), m_fname (nullptr) { }
 
-  // No copying!
-
-  mex (const mex&) = delete;
-
-  mex& operator = (const mex&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mex)
 
   ~mex (void)
   {
@@ -4441,49 +4198,6 @@
   return ptr->get_complex_singles ();
 }
 
-#if 0
-/* We don't have these yet. */
-mxComplexInt8 * mxGetComplexInt8s (const mxArray *ptr)
-{
-  return ptr->get_complex_int8s ();
-}
-
-mxComplexInt16 * mxGetComplexInt16s (const mxArray *ptr)
-{
-  return ptr->get_complex_int16s ();
-}
-
-mxComplexInt32 * mxGetComplexInt32s (const mxArray *ptr)
-{
-  return ptr->get_complex_int32s ();
-}
-
-mxComplexInt64 * mxGetComplexInt64s (const mxArray *ptr)
-{
-  return ptr->get_complex_int64s ();
-}
-
-mxComplexUint8 * mxGetComplexUint8s (const mxArray *ptr)
-{
-  return ptr->get_complex_uint8s ();
-}
-
-mxComplexUint16 * mxGetComplexUint16s (const mxArray *ptr)
-{
-  return ptr->get_complex_uint16s ();
-}
-
-mxComplexUint32 * mxGetComplexUint32s (const mxArray *ptr)
-{
-  return ptr->get_complex_uint32s ();
-}
-
-mxComplexUint64 * mxGetComplexUint64s (const mxArray *ptr)
-{
-  return ptr->get_complex_uint64s ();
-}
-#endif
-
 // Data setters.
 void
 mxSetPr (mxArray *ptr, double *pr)
@@ -4557,49 +4271,6 @@
   return ptr->set_complex_singles (maybe_unmark (data));
 }
 
-#if 0
-/* We don't have these yet. */
-int mxSetComplexInt8s (mxArray *ptr, mxComplexInt8 *data)
-{
-  return ptr->set_complex_int8s (maybe_unmark (data));
-}
-
-int mxSetComplexInt16s (mxArray *ptr, mxComplexInt16 *data)
-{
-  return ptr->set_complex_int16s (maybe_unmark (data));
-}
-
-int mxSetComplexInt32s (mxArray *ptr, mxComplexInt32 *data)
-{
-  return ptr->set_complex_int32s (maybe_unmark (data));
-}
-
-int mxSetComplexInt64s (mxArray *ptr, mxComplexInt64 *data)
-{
-  return ptr->set_complex_int64s (maybe_unmark (data));
-}
-
-int mxSetComplexUint8s (mxArray *ptr, mxComplexUint8 *data)
-{
-  return ptr->set_complex_uint8s (maybe_unmark (data));
-}
-
-int mxSetComplexUint16s (mxArray *ptr, mxComplexUint16 *data)
-{
-  return ptr->set_complex_uint16s (maybe_unmark (data));
-}
-
-int mxSetComplexUint32s (mxArray *ptr, mxComplexUint32 *data)
-{
-  return ptr->set_complex_uint32s (maybe_unmark (data));
-}
-
-int mxSetComplexUint64s (mxArray *ptr, mxComplexUint64 *data)
-{
-  return ptr->set_complex_uint64s (maybe_unmark (data));
-}
-#endif
-
 void
 mxSetPi (mxArray *ptr, double *pi)
 {
@@ -4917,7 +4588,7 @@
 
       tw.set_lvalue_list (nullptr);
 
-      retval = octave::feval (fname, args, nargout);
+      retval = interp.feval (fname, args, nargout);
     }
   catch (const octave::execution_exception&)
     {
--- a/libinterp/corefcn/mexproto.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/mexproto.h	Fri Jun 23 20:51:51 2023 +0200
@@ -287,17 +287,6 @@
 
 extern OCTINTERP_API mxComplexDouble * mxGetComplexDoubles (const mxArray *p);
 extern OCTINTERP_API mxComplexSingle * mxGetComplexSingles (const mxArray *p);
-#if 0
-/* We don't have these yet. */
-extern OCTINTERP_API mxComplexInt8 * mxGetComplexInt8s (const mxArray *p);
-extern OCTINTERP_API mxComplexInt16 * mxGetComplexInt16s (const mxArray *p);
-extern OCTINTERP_API mxComplexInt32 * mxGetComplexInt32s (const mxArray *p);
-extern OCTINTERP_API mxComplexInt64 * mxGetComplexInt64s (const mxArray *p);
-extern OCTINTERP_API mxComplexUint8 * mxGetComplexUint8s (const mxArray *p);
-extern OCTINTERP_API mxComplexUint16 * mxGetComplexUint16s (const mxArray *p);
-extern OCTINTERP_API mxComplexUint32 * mxGetComplexUint32s (const mxArray *p);
-extern OCTINTERP_API mxComplexUint64 * mxGetComplexUint64s (const mxArray *p);
-#endif
 #else
 extern OCTINTERP_API double * mxGetPi (const mxArray *ptr);
 extern OCTINTERP_API void * mxGetImagData (const mxArray *ptr);
@@ -320,17 +309,6 @@
 
 extern OCTINTERP_API int mxSetComplexDoubles (mxArray *p, mxComplexDouble *d);
 extern OCTINTERP_API int mxSetComplexSingles (mxArray *p, mxComplexSingle *d);
-#if 0
-/* We don't have these yet. */
-extern OCTINTERP_API int mxSetComplexInt8s (mxArray *p, mxComplexInt8 *d);
-extern OCTINTERP_API int mxSetComplexInt16s (mxArray *p, mxComplexInt16 *d);
-extern OCTINTERP_API int mxSetComplexInt32s (mxArray *p, mxComplexInt32 *d);
-extern OCTINTERP_API int mxSetComplexInt64s (mxArray *p, mxComplexInt64 *d);
-extern OCTINTERP_API int mxSetComplexUint8s (mxArray *p, mxComplexUint8 *d);
-extern OCTINTERP_API int mxSetComplexUint16s (mxArray *p, mxComplexUint16 *d);
-extern OCTINTERP_API int mxSetComplexUint32s (mxArray *p, mxComplexUint32 *d);
-extern OCTINTERP_API int mxSetComplexUint64s (mxArray *p, mxComplexUint64 *d);
-#endif
 #else
 extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
 extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
--- a/libinterp/corefcn/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -38,6 +38,7 @@
   %reldir%/fcn-info.h \
   %reldir%/file-io.h \
   %reldir%/ft-text-renderer.h \
+  %reldir%/gh-manager.h \
   %reldir%/gl-render.h \
   %reldir%/gl2ps-print.h \
   %reldir%/graphics-handle.h \
@@ -102,6 +103,7 @@
   %reldir%/gzfstream.h
 
 NOINSTALL_COREFCN_INC = \
+  %reldir%/graphics-utils.h \
   %reldir%/interpreter-private.h \
   %reldir%/mex-private.h \
   %reldir%/oct-hdf5.h \
@@ -142,6 +144,7 @@
   %reldir%/coct-hdf5-types.c \
   %reldir%/colamd.cc \
   %reldir%/colloc.cc \
+  %reldir%/compile.cc \
   %reldir%/conv2.cc \
   %reldir%/daspk.cc \
   %reldir%/dasrt.cc \
@@ -176,10 +179,12 @@
   %reldir%/getgrent.cc \
   %reldir%/getpwent.cc \
   %reldir%/getrusage.cc \
+  %reldir%/gh-manager.cc \
   %reldir%/givens.cc \
   %reldir%/gl-render.cc \
   %reldir%/gl2ps-print.cc \
   %reldir%/graphics-toolkit.cc \
+  %reldir%/graphics-utils.cc \
   %reldir%/graphics.cc \
   %reldir%/gsvd.cc \
   %reldir%/gtk-manager.cc \
@@ -231,6 +236,7 @@
   %reldir%/ordqz.cc \
   %reldir%/ordschur.cc \
   %reldir%/pager.cc \
+  %reldir%/perms.cc \
   %reldir%/pinv.cc \
   %reldir%/pow2.cc \
   %reldir%/pr-flt-fmt.cc \
--- a/libinterp/corefcn/mxarray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/mxarray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -94,17 +94,21 @@
 
 public:
 
-  virtual mxArray_base * dup (void) const = 0;
+  mxArray_base () = delete;
+
+  OCTAVE_DEFAULT_COPY_MOVE (mxArray_base)
 
-  virtual mxArray * as_mxArray (void) const { return nullptr; }
+  virtual mxArray_base * dup () const = 0;
 
-  virtual ~mxArray_base (void) = default;
+  virtual mxArray * as_mxArray () const { return nullptr; }
 
-  virtual bool is_octave_value (void) const { return false; }
+  virtual ~mxArray_base () = default;
+
+  virtual bool is_octave_value () const { return false; }
 
-  virtual int iscell (void) const = 0;
+  virtual int iscell () const = 0;
 
-  virtual int is_char (void) const = 0;
+  virtual int is_char () const = 0;
 
   virtual int is_class (const char *name_arg) const
   {
@@ -118,52 +122,52 @@
     return retval;
   }
 
-  virtual int is_complex (void) const = 0;
+  virtual int is_complex () const = 0;
 
-  virtual int is_double (void) const = 0;
+  virtual int is_double () const = 0;
 
-  virtual int is_function_handle (void) const = 0;
+  virtual int is_function_handle () const = 0;
 
-  virtual int is_int16 (void) const = 0;
+  virtual int is_int16 () const = 0;
 
-  virtual int is_int32 (void) const = 0;
+  virtual int is_int32 () const = 0;
 
-  virtual int is_int64 (void) const = 0;
+  virtual int is_int64 () const = 0;
 
-  virtual int is_int8 (void) const = 0;
+  virtual int is_int8 () const = 0;
 
-  virtual int is_logical (void) const = 0;
+  virtual int is_logical () const = 0;
 
-  virtual int is_numeric (void) const = 0;
+  virtual int is_numeric () const = 0;
 
-  virtual int is_single (void) const = 0;
+  virtual int is_single () const = 0;
 
-  virtual int is_sparse (void) const = 0;
+  virtual int is_sparse () const = 0;
 
-  virtual int is_struct (void) const = 0;
+  virtual int is_struct () const = 0;
 
-  virtual int is_uint16 (void) const = 0;
+  virtual int is_uint16 () const = 0;
 
-  virtual int is_uint32 (void) const = 0;
+  virtual int is_uint32 () const = 0;
 
-  virtual int is_uint64 (void) const = 0;
+  virtual int is_uint64 () const = 0;
 
-  virtual int is_uint8 (void) const = 0;
+  virtual int is_uint8 () const = 0;
 
-  virtual int is_logical_scalar (void) const
+  virtual int is_logical_scalar () const
   {
     return is_logical () && get_number_of_elements () == 1;
   }
 
-  virtual int is_logical_scalar_true (void) const = 0;
+  virtual int is_logical_scalar_true () const = 0;
 
-  virtual mwSize get_m (void) const = 0;
+  virtual mwSize get_m () const = 0;
 
-  virtual mwSize get_n (void) const = 0;
+  virtual mwSize get_n () const = 0;
 
-  virtual mwSize * get_dimensions (void) const = 0;
+  virtual mwSize * get_dimensions () const = 0;
 
-  virtual mwSize get_number_of_dimensions (void) const = 0;
+  virtual mwSize get_number_of_dimensions () const = 0;
 
   virtual void set_m (mwSize m) = 0;
 
@@ -171,15 +175,15 @@
 
   virtual int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
 
-  virtual mwSize get_number_of_elements (void) const = 0;
+  virtual mwSize get_number_of_elements () const = 0;
 
-  virtual int isempty (void) const = 0;
+  virtual int isempty () const = 0;
 
-  virtual bool is_scalar (void) const = 0;
+  virtual bool is_scalar () const = 0;
 
-  virtual mxClassID get_class_id (void) const = 0;
+  virtual mxClassID get_class_id () const = 0;
 
-  virtual const char * get_class_name (void) const = 0;
+  virtual const char * get_class_name () const = 0;
 
   virtual void set_class_name (const char *name_arg) = 0;
 
@@ -207,36 +211,25 @@
 
   virtual void set_cell (mwIndex idx, mxArray *val) = 0;
 
-  virtual double get_scalar (void) const = 0;
-
-  virtual void * get_data (void) const = 0;
+  virtual double get_scalar () const = 0;
 
-  virtual mxDouble * get_doubles (void) const = 0;
-  virtual mxSingle * get_singles (void) const = 0;
-  virtual mxInt8 * get_int8s (void) const = 0;
-  virtual mxInt16 * get_int16s (void) const = 0;
-  virtual mxInt32 * get_int32s (void) const = 0;
-  virtual mxInt64 * get_int64s (void) const = 0;
-  virtual mxUint8 * get_uint8s (void) const = 0;
-  virtual mxUint16 * get_uint16s (void) const = 0;
-  virtual mxUint32 * get_uint32s (void) const = 0;
-  virtual mxUint64 * get_uint64s (void) const = 0;
+  virtual void * get_data () const = 0;
 
-  virtual mxComplexDouble * get_complex_doubles (void) const = 0;
-  virtual mxComplexSingle * get_complex_singles (void) const = 0;
-#if 0
-  /* We don't have these yet. */
-  virtual mxComplexInt8 * get_complex_int8s (void) const = 0;
-  virtual mxComplexInt16 * get_complex_int16s (void) const = 0;
-  virtual mxComplexInt32 * get_complex_int32s (void) const = 0;
-  virtual mxComplexInt64 * get_complex_int64s (void) const = 0;
-  virtual mxComplexUint8 * get_complex_uint8s (void) const = 0;
-  virtual mxComplexUint16 * get_complex_uint16s (void) const = 0;
-  virtual mxComplexUint32 * get_complex_uint32s (void) const = 0;
-  virtual mxComplexUint64 * get_complex_uint64s (void) const = 0;
-#endif
+  virtual mxDouble * get_doubles () const = 0;
+  virtual mxSingle * get_singles () const = 0;
+  virtual mxInt8 * get_int8s () const = 0;
+  virtual mxInt16 * get_int16s () const = 0;
+  virtual mxInt32 * get_int32s () const = 0;
+  virtual mxInt64 * get_int64s () const = 0;
+  virtual mxUint8 * get_uint8s () const = 0;
+  virtual mxUint16 * get_uint16s () const = 0;
+  virtual mxUint32 * get_uint32s () const = 0;
+  virtual mxUint64 * get_uint64s () const = 0;
 
-  virtual void * get_imag_data (void) const = 0;
+  virtual mxComplexDouble * get_complex_doubles () const = 0;
+  virtual mxComplexSingle * get_complex_singles () const = 0;
+
+  virtual void * get_imag_data () const = 0;
 
   virtual void set_data (void *pr) = 0;
 
@@ -253,25 +246,14 @@
 
   virtual int set_complex_doubles (mxComplexDouble *data) = 0;
   virtual int set_complex_singles (mxComplexSingle *data) = 0;
-#if 0
-  /* We don't have these yet. */
-  virtual int set_complex_int8s (mxComplexInt8 *data) = 0;
-  virtual int set_complex_int16s (mxComplexInt16 *data) = 0;
-  virtual int set_complex_int32s (mxComplexInt32 *data) = 0;
-  virtual int set_complex_int64s (mxComplexInt64 *data) = 0;
-  virtual int set_complex_uint8s (mxComplexUint8 *data) = 0;
-  virtual int set_complex_uint16s (mxComplexUint16 *data) = 0;
-  virtual int set_complex_uint32s (mxComplexUint32 *data) = 0;
-  virtual int set_complex_uint64s (mxComplexUint64 *data) = 0;
-#endif
 
   virtual void set_imag_data (void *pi) = 0;
 
-  virtual mwIndex * get_ir (void) const = 0;
+  virtual mwIndex * get_ir () const = 0;
 
-  virtual mwIndex * get_jc (void) const = 0;
+  virtual mwIndex * get_jc () const = 0;
 
-  virtual mwSize get_nzmax (void) const = 0;
+  virtual mwSize get_nzmax () const = 0;
 
   virtual void set_ir (mwIndex *ir) = 0;
 
@@ -288,7 +270,7 @@
   virtual void
   set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
 
-  virtual int get_number_of_fields (void) const = 0;
+  virtual int get_number_of_fields () const = 0;
 
   virtual const char * get_field_name_by_number (int key_num) const = 0;
 
@@ -296,22 +278,20 @@
 
   virtual int get_string (char *buf, mwSize buflen) const = 0;
 
-  virtual char * array_to_string (void) const = 0;
+  virtual char * array_to_string () const = 0;
 
   virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
 
-  virtual std::size_t get_element_size (void) const = 0;
+  virtual std::size_t get_element_size () const = 0;
 
-  virtual bool mutation_needed (void) const { return false; }
+  virtual bool mutation_needed () const { return false; }
 
-  virtual mxArray * mutate (void) const { return nullptr; }
+  virtual mxArray * mutate () const { return nullptr; }
 
-  virtual octave_value as_octave_value (void) const = 0;
+  virtual octave_value as_octave_value () const = 0;
 
 protected:
 
-  mxArray_base (const mxArray_base&) = default;
-
   std::size_t get_numeric_element_size (std::size_t size) const
   {
     return (m_interleaved
@@ -377,7 +357,7 @@
 
   OCTINTERP_API mxArray (bool interleaved, mwSize m, mwSize n);
 
-  mxArray * dup (void) const
+  mxArray * dup () const
   {
     mxArray *retval = m_rep->as_mxArray ();
 
@@ -393,66 +373,62 @@
     return retval;
   }
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mxArray)
 
-  mxArray (const mxArray&) = delete;
-
-  mxArray& operator = (const mxArray&) = delete;
+  OCTINTERP_API ~mxArray ();
 
-  OCTINTERP_API ~mxArray (void);
-
-  bool is_octave_value (void) const { return m_rep->is_octave_value (); }
+  bool is_octave_value () const { return m_rep->is_octave_value (); }
 
-  int iscell (void) const { return m_rep->iscell (); }
+  int iscell () const { return m_rep->iscell (); }
 
-  int is_char (void) const { return m_rep->is_char (); }
+  int is_char () const { return m_rep->is_char (); }
 
   int is_class (const char *name_arg) const { return m_rep->is_class (name_arg); }
 
-  int is_complex (void) const { return m_rep->is_complex (); }
+  int is_complex () const { return m_rep->is_complex (); }
 
-  int is_double (void) const { return m_rep->is_double (); }
+  int is_double () const { return m_rep->is_double (); }
 
-  int is_function_handle (void) const { return m_rep->is_function_handle (); }
+  int is_function_handle () const { return m_rep->is_function_handle (); }
 
-  int is_int16 (void) const { return m_rep->is_int16 (); }
+  int is_int16 () const { return m_rep->is_int16 (); }
 
-  int is_int32 (void) const { return m_rep->is_int32 (); }
+  int is_int32 () const { return m_rep->is_int32 (); }
 
-  int is_int64 (void) const { return m_rep->is_int64 (); }
+  int is_int64 () const { return m_rep->is_int64 (); }
 
-  int is_int8 (void) const { return m_rep->is_int8 (); }
+  int is_int8 () const { return m_rep->is_int8 (); }
 
-  int is_logical (void) const { return m_rep->is_logical (); }
+  int is_logical () const { return m_rep->is_logical (); }
 
-  int is_numeric (void) const { return m_rep->is_numeric (); }
+  int is_numeric () const { return m_rep->is_numeric (); }
 
-  int is_single (void) const { return m_rep->is_single (); }
+  int is_single () const { return m_rep->is_single (); }
 
-  int is_sparse (void) const { return m_rep->is_sparse (); }
+  int is_sparse () const { return m_rep->is_sparse (); }
 
-  int is_struct (void) const { return m_rep->is_struct (); }
+  int is_struct () const { return m_rep->is_struct (); }
 
-  int is_uint16 (void) const { return m_rep->is_uint16 (); }
+  int is_uint16 () const { return m_rep->is_uint16 (); }
 
-  int is_uint32 (void) const { return m_rep->is_uint32 (); }
+  int is_uint32 () const { return m_rep->is_uint32 (); }
 
-  int is_uint64 (void) const { return m_rep->is_uint64 (); }
+  int is_uint64 () const { return m_rep->is_uint64 (); }
 
-  int is_uint8 (void) const { return m_rep->is_uint8 (); }
+  int is_uint8 () const { return m_rep->is_uint8 (); }
 
-  int is_logical_scalar (void) const { return m_rep->is_logical_scalar (); }
+  int is_logical_scalar () const { return m_rep->is_logical_scalar (); }
 
-  int is_logical_scalar_true (void) const
+  int is_logical_scalar_true () const
   { return m_rep->is_logical_scalar_true (); }
 
-  mwSize get_m (void) const { return m_rep->get_m (); }
+  mwSize get_m () const { return m_rep->get_m (); }
 
-  mwSize get_n (void) const { return m_rep->get_n (); }
+  mwSize get_n () const { return m_rep->get_n (); }
 
-  mwSize * get_dimensions (void) const { return m_rep->get_dimensions (); }
+  mwSize * get_dimensions () const { return m_rep->get_dimensions (); }
 
-  mwSize get_number_of_dimensions (void) const
+  mwSize get_number_of_dimensions () const
   { return m_rep->get_number_of_dimensions (); }
 
   void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }
@@ -462,20 +438,20 @@
   int set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
   { DO_MUTABLE_METHOD (int, set_dimensions (dims_arg, ndims_arg)); }
 
-  mwSize get_number_of_elements (void) const
+  mwSize get_number_of_elements () const
   { return m_rep->get_number_of_elements (); }
 
-  int isempty (void) const { return get_number_of_elements () == 0; }
+  int isempty () const { return get_number_of_elements () == 0; }
 
-  bool is_scalar (void) const { return m_rep->is_scalar (); }
+  bool is_scalar () const { return m_rep->is_scalar (); }
 
-  const char * get_name (void) const { return m_name; }
+  const char * get_name () const { return m_name; }
 
   OCTINTERP_API void set_name (const char *name);
 
-  mxClassID get_class_id (void) const { return m_rep->get_class_id (); }
+  mxClassID get_class_id () const { return m_rep->get_class_id (); }
 
-  const char * get_class_name (void) const { return m_rep->get_class_name (); }
+  const char * get_class_name () const { return m_rep->get_class_name (); }
 
   mxArray * get_property (mwIndex idx, const char *pname) const
   { return m_rep->get_property (idx, pname); }
@@ -492,74 +468,47 @@
   void set_cell (mwIndex idx, mxArray *val)
   { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }
 
-  double get_scalar (void) const { return m_rep->get_scalar (); }
+  double get_scalar () const { return m_rep->get_scalar (); }
 
-  void * get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); }
+  void * get_data () const { DO_MUTABLE_METHOD (void *, get_data ()); }
 
-  mxDouble * get_doubles (void) const
+  mxDouble * get_doubles () const
   { DO_MUTABLE_METHOD (mxDouble *, get_doubles ()); }
 
-  mxSingle * get_singles (void) const
+  mxSingle * get_singles () const
   { DO_MUTABLE_METHOD (mxSingle *, get_singles ()); }
 
-  mxInt8 * get_int8s (void) const
+  mxInt8 * get_int8s () const
   { DO_MUTABLE_METHOD (mxInt8 *, get_int8s ()); }
 
-  mxInt16 * get_int16s (void) const
+  mxInt16 * get_int16s () const
   { DO_MUTABLE_METHOD (mxInt16 *, get_int16s ()); }
 
-  mxInt32 * get_int32s (void) const
+  mxInt32 * get_int32s () const
   { DO_MUTABLE_METHOD (mxInt32 *, get_int32s ()); }
 
-  mxInt64 * get_int64s (void) const
+  mxInt64 * get_int64s () const
   { DO_MUTABLE_METHOD (mxInt64 *, get_int64s ()); }
 
-  mxUint8 * get_uint8s (void) const
+  mxUint8 * get_uint8s () const
   { DO_MUTABLE_METHOD (mxUint8 *, get_uint8s ()); }
 
-  mxUint16 * get_uint16s (void) const
+  mxUint16 * get_uint16s () const
   { DO_MUTABLE_METHOD (mxUint16 *, get_uint16s ()); }
 
-  mxUint32 * get_uint32s (void) const
+  mxUint32 * get_uint32s () const
   { DO_MUTABLE_METHOD (mxUint32 *, get_uint32s ()); }
 
-  mxUint64 * get_uint64s (void) const
+  mxUint64 * get_uint64s () const
   { DO_MUTABLE_METHOD (mxUint64 *, get_uint64s ()); }
 
-  mxComplexDouble * get_complex_doubles (void) const
+  mxComplexDouble * get_complex_doubles () const
   { DO_MUTABLE_METHOD (mxComplexDouble *, get_complex_doubles ()); }
 
-  mxComplexSingle * get_complex_singles (void) const
+  mxComplexSingle * get_complex_singles () const
   { DO_MUTABLE_METHOD (mxComplexSingle *, get_complex_singles ()); }
 
-#if 0
-  /* We don't have these yet. */
-  mxComplexInt8 * get_complex_int8s (void) const
-  { DO_MUTABLE_METHOD (mxComplexInt8 *, get_complex_int8s ()); }
-
-  mxComplexInt16 * get_complex_int16s (void) const
-  { DO_MUTABLE_METHOD (mxComplexInt16 *, get_complex_int16s ()); }
-
-  mxComplexInt32 * get_complex_int32s (void) const
-  { DO_MUTABLE_METHOD (mxComplexInt32 *, get_complex_int32s ()); }
-
-  mxComplexInt64 * get_complex_int64s (void) const
-  { DO_MUTABLE_METHOD (mxComplexInt64 *, get_complex_int64s ()); }
-
-  mxComplexUint8 * get_complex_uint8s (void) const
-  { DO_MUTABLE_METHOD (mxComplexUint8 *, get_complex_uint8s ()); }
-
-  mxComplexUint16 * get_complex_uint16s (void) const
-  { DO_MUTABLE_METHOD (mxComplexUint16 *, get_complex_uint16s ()); }
-
-  mxComplexUint32 * get_complex_uint32s (void) const
-  { DO_MUTABLE_METHOD (mxComplexUint32 *, get_complex_uint32s ()); }
-
-  mxComplexUint64 * get_complex_uint64s (void) const
-  { DO_MUTABLE_METHOD (mxComplexUint64 *, get_complex_uint64s ()); }
-#endif
-
-  void * get_imag_data (void) const
+  void * get_imag_data () const
   { DO_MUTABLE_METHOD (void *, get_imag_data ()); }
 
   void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }
@@ -600,40 +549,13 @@
   int set_complex_singles (mxComplexSingle *data)
   { DO_MUTABLE_METHOD (int, set_complex_singles (data)); }
 
-#if 0
-  /* We don't have these yet. */
-  int set_complex_int8s (mxComplexInt8 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_int8s (data)); }
-
-  int set_complex_int16s (mxComplexInt16 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_int16s (data)); }
-
-  int set_complex_int32s (mxComplexInt32 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_int32s (data)); }
-
-  int set_complex_int64s (mxComplexInt64 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_int64s (data)); }
-
-  int set_complex_uint8s (mxComplexUint8 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_uint8s (data)); }
-
-  int set_complex_uint16s (mxComplexUint16 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_uint16s (data)); }
-
-  int set_complex_uint32s (mxComplexUint32 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_uint32s (data)); }
-
-  int set_complex_uint64s (mxComplexUint64 *data)
-  { DO_MUTABLE_METHOD (int, set_complex_uint64s (data)); }
-#endif
-
   void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }
 
-  mwIndex * get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
+  mwIndex * get_ir () const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
 
-  mwIndex * get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
+  mwIndex * get_jc () const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
 
-  mwSize get_nzmax (void) const { return m_rep->get_nzmax (); }
+  mwSize get_nzmax () const { return m_rep->get_nzmax (); }
 
   void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }
 
@@ -652,7 +574,7 @@
   void set_field_by_number (mwIndex index, int key_num, mxArray *val)
   { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }
 
-  int get_number_of_fields (void) const
+  int get_number_of_fields () const
   { return m_rep->get_number_of_fields (); }
 
   const char * get_field_name_by_number (int key_num) const
@@ -664,17 +586,17 @@
   int get_string (char *buf, mwSize buflen) const
   { return m_rep->get_string (buf, buflen); }
 
-  char * array_to_string (void) const { return m_rep->array_to_string (); }
+  char * array_to_string () const { return m_rep->array_to_string (); }
 
   mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
   { return m_rep->calc_single_subscript (nsubs, subs); }
 
-  std::size_t get_element_size (void) const
+  std::size_t get_element_size () const
   { return m_rep->get_element_size (); }
 
-  bool mutation_needed (void) const { return m_rep->mutation_needed (); }
+  bool mutation_needed () const { return m_rep->mutation_needed (); }
 
-  mxArray * mutate (void) const { return m_rep->mutate (); }
+  mxArray * mutate () const { return m_rep->mutate (); }
 
   static OCTINTERP_API void * malloc (std::size_t n);
 
@@ -702,7 +624,7 @@
   static OCTINTERP_API octave_value
   as_octave_value (const mxArray *ptr, bool null_is_empty = true);
 
-  OCTINTERP_API octave_value as_octave_value (void) const;
+  OCTINTERP_API octave_value as_octave_value () const;
 
 private:
 
@@ -740,7 +662,7 @@
   create_rep (bool interleaved, mxClassID id, mwSize m, mwSize n,
               mwSize nzmax, mxComplexity flag);
 
-  OCTINTERP_API void maybe_mutate (void) const;
+  OCTINTERP_API void maybe_mutate () const;
 
   //--------
 
--- a/libinterp/corefcn/oct-errno.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-errno.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,22 +39,24 @@
 {
 protected:
 
-  octave_errno (void);
+  octave_errno ();
 
 public:
 
-  ~octave_errno (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (octave_errno)
+
+  ~octave_errno () = default;
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   { delete s_instance; s_instance = nullptr; }
 
   static int lookup (const std::string& name);
 
-  static octave_scalar_map list (void);
+  static octave_scalar_map list ();
 
-  static int get (void) { return errno; }
+  static int get () { return errno; }
 
   static int set (int val)
   {
@@ -67,14 +69,13 @@
 
   int do_lookup (const std::string& name);
 
-  octave_scalar_map do_list (void);
+  octave_scalar_map do_list ();
 
   //--------
 
   std::map<std::string, int> m_errno_tbl;
 
   static octave_errno *s_instance;
-
 };
 
 #endif
--- a/libinterp/corefcn/oct-errno.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-errno.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 
 octave_errno *octave_errno::s_instance = nullptr;
 
-octave_errno::octave_errno (void)
+octave_errno::octave_errno ()
 {
   struct errno_struct
   {
@@ -293,7 +293,7 @@
 }
 
 bool
-octave_errno::instance_ok (void)
+octave_errno::instance_ok ()
 {
   bool retval = true;
 
@@ -313,7 +313,7 @@
 }
 
 octave_scalar_map
-octave_errno::list (void)
+octave_errno::list ()
 {
   return (instance_ok ()) ? s_instance->do_list () : octave_scalar_map ();
 }
@@ -326,7 +326,7 @@
 }
 
 octave_scalar_map
-octave_errno::do_list (void)
+octave_errno::do_list ()
 {
   octave_scalar_map retval;
 
--- a/libinterp/corefcn/oct-fstrm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-fstrm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -67,7 +67,7 @@
 // Return current stream position.
 
 off_t
-fstream::tell (void)
+fstream::tell ()
 {
   // Note: error is inherited from base_stream, not ::error.
   // This error function does not halt execution so "return ..." must exist.
@@ -78,19 +78,19 @@
 // Return nonzero if EOF has been reached on this stream.
 
 bool
-fstream::eof (void) const
+fstream::eof () const
 {
   return m_fstream.eof ();
 }
 
 void
-fstream::do_close (void)
+fstream::do_close ()
 {
   m_fstream.close ();
 }
 
 std::istream *
-fstream::input_stream (void)
+fstream::input_stream ()
 {
   std::istream *retval = nullptr;
 
@@ -101,7 +101,7 @@
 }
 
 std::ostream *
-fstream::output_stream (void)
+fstream::output_stream ()
 {
   std::ostream *retval = nullptr;
 
--- a/libinterp/corefcn/oct-fstrm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-fstrm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,11 +44,7 @@
            std::ios::openmode arg_md = std::ios::in | std::ios::out,
            mach_info::float_format flt_fmt = mach_info::native_float_format ());
 
-  // No copying!
-
-  fstream (const fstream&) = delete;
-
-  fstream& operator = (const fstream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fstream)
 
   static stream
   create (const std::string& nm_arg,
@@ -61,25 +57,25 @@
 
   // Return current stream position.
 
-  off_t tell (void);
+  off_t tell ();
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const;
+  bool eof () const;
 
-  void do_close (void);
+  void do_close ();
 
   // The name of the file.
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
-  std::istream * input_stream (void);
+  std::istream * input_stream ();
 
-  std::ostream * output_stream (void);
+  std::ostream * output_stream ();
 
 protected:
 
-  ~fstream (void) = default;
+  ~fstream () = default;
 
 private:
 
@@ -90,11 +86,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::fstream' instead")
-typedef octave::fstream octave_fstream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-handle.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-handle.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 class octave_handle
 {
 public:
-  octave_handle (void) : m_dval (octave::numeric_limits<double>::NaN ()) { }
+  octave_handle () : m_dval (octave::numeric_limits<double>::NaN ()) { }
 
   octave_handle (const octave_value& a)
     : m_dval (octave::numeric_limits<double>::NaN ())
@@ -73,23 +73,23 @@
     return *this;
   }
 
-  ~octave_handle (void) = default;
+  ~octave_handle () = default;
 
-  double value (void) const { return m_dval; }
+  double value () const { return m_dval; }
 
-  octave_value as_octave_value (void) const
+  octave_value as_octave_value () const
   {
     return ok () ? octave_value (m_dval) : octave_value (Matrix ());
   }
 
   // Prefix increment/decrement operators.
-  octave_handle& operator ++ (void)
+  octave_handle& operator ++ ()
   {
     ++m_dval;
     return *this;
   }
 
-  octave_handle& operator -- (void)
+  octave_handle& operator -- ()
   {
     --m_dval;
     return *this;
@@ -110,7 +110,7 @@
     return old_value;
   }
 
-  bool ok (void) const { return ! octave::math::isnan (m_dval); }
+  bool ok () const { return ! octave::math::isnan (m_dval); }
 
 private:
   double m_dval;
--- a/libinterp/corefcn/oct-hdf5-types.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-hdf5-types.h	Fri Jun 23 20:51:51 2023 +0200
@@ -38,16 +38,6 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::check_hdf5_types' instead")
-inline bool check_hdf5_types (bool warn = true)
-{
-  return octave::check_hdf5_types (warn);
-}
-
-#endif
-
 #endif
 
 // Available for C and C++.
--- a/libinterp/corefcn/oct-hist.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-hist.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -276,7 +276,7 @@
   evmgr.set_history (command_history::list ());
 }
 
-void history_system::write_timestamp (void)
+void history_system::write_timestamp ()
 {
   sys::localtime now;
 
@@ -524,7 +524,7 @@
   source_file (name);
 }
 
-std::string history_system::default_file (void)
+std::string history_system::default_file ()
 {
   std::string file;
 
@@ -550,7 +550,7 @@
   return file;
 }
 
-int history_system::default_size (void)
+int history_system::default_size ()
 {
   int size = 1000;
 
@@ -567,7 +567,7 @@
   return size;
 }
 
-std::string history_system::default_timestamp_format (void)
+std::string history_system::default_timestamp_format ()
 {
   return
     "# Octave " OCTAVE_VERSION ", %a %b %d %H:%M:%S %Y %Z <"
--- a/libinterp/corefcn/oct-hist.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-hist.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,20 +44,18 @@
 
   history_system (interpreter& interp);
 
-  history_system (const history_system&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (history_system)
 
-  history_system& operator = (const history_system&) = delete;
-
-  ~history_system (void) = default;
+  ~history_system () = default;
 
   void initialize (bool read_history_file = false);
 
-  void write_timestamp (void);
+  void write_timestamp ();
 
   octave_value input_from_tmp_file (const octave_value_list& args,
                                     int nargout);
 
-  bool input_from_tmp_file (void) const
+  bool input_from_tmp_file () const
   {
     return m_input_from_tmp_file;
   }
@@ -70,7 +68,7 @@
   octave_value timestamp_format_string (const octave_value_list& args,
                                         int nargout);
 
-  std::string timestamp_format_string (void) const
+  std::string timestamp_format_string () const
   {
     return m_timestamp_format_string;
   }
@@ -99,11 +97,11 @@
   // Octave exits.
   std::string m_timestamp_format_string;
 
-  static std::string default_file (void);
+  static std::string default_file ();
 
-  static int default_size (void);
+  static int default_size ();
 
-  static std::string default_timestamp_format (void);
+  static std::string default_timestamp_format ();
 
   template <typename T>
   T set (T& var, const T& new_val)
--- a/libinterp/corefcn/oct-iostrm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-iostrm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 // Return current stream position.
 
 off_t
-base_iostream::tell (void)
+base_iostream::tell ()
 {
   invalid_operation ();
   return -1;
@@ -56,14 +56,14 @@
 // Return nonzero if EOF has been reached on this stream.
 
 bool
-base_iostream::eof (void) const
+base_iostream::eof () const
 {
   invalid_operation ();
   return false;
 }
 
 void
-base_iostream::invalid_operation (void) const
+base_iostream::invalid_operation () const
 {
   // Note: use ::error to get error from error.h which halts operation.
   ::error ("%s: invalid operation", stream_type ());
@@ -72,7 +72,7 @@
 // Return nonzero if EOF has been reached on this stream.
 
 bool
-istream::eof (void) const
+istream::eof () const
 {
   return m_istream && m_istream->eof ();
 }
@@ -86,7 +86,7 @@
 // Return nonzero if EOF has been reached on this stream.
 
 bool
-ostream::eof (void) const
+ostream::eof () const
 {
   return m_ostream && m_ostream->eof ();
 }
--- a/libinterp/corefcn/oct-iostrm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-iostrm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,15 +44,11 @@
                  mach_info::float_format ff = mach_info::native_float_format ())
     : base_stream (m, ff), m_name (n) { }
 
-  // No copying!
-
-  base_iostream (const base_iostream&) = delete;
-
-  base_iostream& operator = (const base_iostream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_iostream)
 
 protected:
 
-  ~base_iostream (void) = default;
+  ~base_iostream () = default;
 
 public:
 
@@ -62,25 +58,25 @@
 
   // Return current stream position.
 
-  off_t tell (void);
+  off_t tell ();
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const;
+  bool eof () const;
 
   // The name of the file.
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
 protected:
 
-  void invalid_operation (void) const;
+  void invalid_operation () const;
 
 private:
 
   std::string m_name;
 
-  virtual const char * stream_type (void) const = 0;
+  virtual const char * stream_type () const = 0;
 };
 
 class
@@ -93,32 +89,28 @@
       m_istream (arg)
   { }
 
+  OCTAVE_DISABLE_COPY_MOVE (istream)
+
   static stream
   create (std::istream *arg = nullptr, const std::string& n = "");
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const;
+  bool eof () const;
 
-  std::istream * input_stream (void) { return m_istream; }
+  std::istream * input_stream () { return m_istream; }
 
-  std::ostream * output_stream (void) { return nullptr; }
+  std::ostream * output_stream () { return nullptr; }
 
 protected:
 
-  ~istream (void) = default;
+  ~istream () = default;
 
 private:
 
   std::istream *m_istream;
 
-  const char * stream_type (void) const { return "istream"; }
-
-  // No copying!
-
-  istream (const istream&) = delete;
-
-  istream& operator = (const istream&) = delete;
+  const char * stream_type () const { return "istream"; }
 };
 
 class
@@ -131,47 +123,30 @@
       m_ostream (arg)
   { }
 
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (ostream)
+
   static stream
   create (std::ostream *arg, const std::string& n = "");
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const;
+  bool eof () const;
 
-  std::istream * input_stream (void) { return nullptr; }
+  std::istream * input_stream () { return nullptr; }
 
-  std::ostream * output_stream (void) { return m_ostream; }
+  std::ostream * output_stream () { return m_ostream; }
 
 protected:
 
-  ~ostream (void) = default;
+  ~ostream () = default;
 
 private:
 
   std::ostream *m_ostream;
 
-  const char * stream_type (void) const { return "ostream"; }
-
-  // No copying!
-
-  ostream (const ostream&) = delete;
-
-  ostream& operator = (const ostream&) = delete;
+  const char * stream_type () const { return "ostream"; }
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_iostream' instead")
-typedef octave::base_iostream octave_base_iostream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::istream' instead")
-typedef octave::istream octave_istream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::ostream' instead")
-typedef octave::ostream octave_ostream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-map.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-map.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 #include "utils.h"
 
 octave_fields::fields_rep *
-octave_fields::nil_rep (void)
+octave_fields::nil_rep ()
 {
   static fields_rep nr;
   return &nr;
@@ -155,7 +155,7 @@
 }
 
 string_vector
-octave_fields::fieldnames (void) const
+octave_fields::fieldnames () const
 {
   octave_idx_type n = nfields ();
   string_vector retval(n);
@@ -205,7 +205,7 @@
 }
 
 octave_scalar_map
-octave_scalar_map::orderfields (void) const
+octave_scalar_map::orderfields () const
 {
   Array<octave_idx_type> perm;
   return orderfields (perm);
@@ -303,7 +303,7 @@
 }
 
 octave_map
-octave_map::orderfields (void) const
+octave_map::orderfields () const
 {
   Array<octave_idx_type> perm;
   return orderfields (perm);
@@ -439,7 +439,7 @@
 }
 
 octave_map
-octave_map::squeeze (void) const
+octave_map::squeeze () const
 {
   octave_map retval (*this);
   octave_idx_type nf = nfields ();
@@ -496,7 +496,7 @@
 */
 
 octave_map
-octave_map::transpose (void) const
+octave_map::transpose () const
 {
   octave_map retval (m_keys);
 
@@ -1344,7 +1344,7 @@
 }
 
 void
-octave_map::optimize_dimensions (void)
+octave_map::optimize_dimensions ()
 {
   octave_idx_type nf = nfields ();
 
--- a/libinterp/corefcn/oct-map.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-map.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,38 +40,41 @@
 
 // A class holding a map field->index.  Supports reference-counting.
 class OCTINTERP_API
-  octave_fields
+octave_fields
 {
   class fields_rep : public std::map<std::string, octave_idx_type>
   {
   public:
-    fields_rep (void) : std::map<std::string, octave_idx_type> (), m_count (1) { }
+
+    fields_rep () : std::map<std::string, octave_idx_type> (), m_count (1) { }
+
     fields_rep (const fields_rep& other)
       : std::map<std::string, octave_idx_type> (other), m_count (1) { }
 
-    octave::refcount<octave_idx_type> m_count;
+    fields_rep& operator = (const fields_rep&) = delete;
 
-  private:
-    fields_rep& operator = (const fields_rep&); // no assignment!
+    ~fields_rep () = default;
+
+    octave::refcount<octave_idx_type> m_count;
   };
 
   fields_rep *m_rep;
 
-  static fields_rep * nil_rep (void);
+  static fields_rep * nil_rep ();
 
 public:
 
-  octave_fields (void) : m_rep (nil_rep ()) { m_rep->m_count++; }
+  octave_fields () : m_rep (nil_rep ()) { m_rep->m_count++; }
   octave_fields (const string_vector&);
   octave_fields (const char *const *);
 
-  ~octave_fields (void)
+  ~octave_fields ()
   {
     if (--m_rep->m_count == 0)
       delete m_rep;
   }
 
-  void make_unique (void)
+  void make_unique ()
   {
     if (m_rep->m_count > 1)
       {
@@ -105,11 +108,11 @@
   typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;
   typedef const_iterator iterator;
 
-  const_iterator begin (void) const { return m_rep->begin (); }
-  const_iterator end (void) const { return m_rep->end (); }
+  const_iterator begin () const { return m_rep->begin (); }
+  const_iterator end () const { return m_rep->end (); }
 
-  const_iterator cbegin (void) const { return m_rep->cbegin (); }
-  const_iterator cend (void) const { return m_rep->cend (); }
+  const_iterator cbegin () const { return m_rep->cbegin (); }
+  const_iterator cend () const { return m_rep->cend (); }
 
   std::string key (const_iterator p) const { return p->first; }
   octave_idx_type index (const_iterator p) const { return p->second; }
@@ -120,7 +123,7 @@
   // high-level methods.
 
   // number of fields.
-  octave_idx_type nfields (void) const { return m_rep->size (); }
+  octave_idx_type nfields () const { return m_rep->size (); }
 
   // check whether a field exists.
   bool isfield (const std::string& name) const;
@@ -149,39 +152,28 @@
   { return m_rep == other.m_rep; }
 
   // Returns the fields as a vector of strings.
-  string_vector fieldnames (void) const;
+  string_vector fieldnames () const;
 
-  void clear (void)
+  void clear ()
   {
     *this = octave_fields ();
   }
 };
 
 class OCTINTERP_API
-  octave_scalar_map
+octave_scalar_map
 {
 public:
 
   octave_scalar_map (const octave_fields& k)
     : m_keys (k), m_vals (k.nfields ()) { }
 
-  octave_scalar_map (void) : m_keys (), m_vals () { }
-
   octave_scalar_map (const string_vector& k)
     : m_keys (k), m_vals (k.numel ()) { }
 
-  octave_scalar_map (const octave_scalar_map& m)
-    : m_keys (m.m_keys), m_vals (m.m_vals) { }
-
   octave_scalar_map (const std::map<std::string, octave_value>& m);
 
-  octave_scalar_map& operator = (const octave_scalar_map& m)
-  {
-    m_keys = m.m_keys;
-    m_vals = m.m_vals;
-
-    return *this;
-  }
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_scalar_map)
 
   // iteration support.
   // note that both const and non-const iterators are the same.
@@ -189,11 +181,11 @@
   typedef octave_fields::const_iterator const_iterator;
   typedef const_iterator iterator;
 
-  const_iterator begin (void) const { return m_keys.begin (); }
-  const_iterator end (void) const { return m_keys.end (); }
+  const_iterator begin () const { return m_keys.begin (); }
+  const_iterator end () const { return m_keys.end (); }
 
-  const_iterator cbegin (void) const { return m_keys.cbegin (); }
-  const_iterator cend (void) const { return m_keys.cend (); }
+  const_iterator cbegin () const { return m_keys.cbegin (); }
+  const_iterator cend () const { return m_keys.cend (); }
 
   const_iterator seek (const std::string& k) const { return m_keys.seek (k); }
 
@@ -215,7 +207,7 @@
   { return m_vals[i]; }
 
   // number of fields.
-  octave_idx_type nfields (void) const { return m_keys.nfields (); }
+  octave_idx_type nfields () const { return m_keys.nfields (); }
 
   // check whether a field exists.
   bool isfield (const std::string& name) const
@@ -224,10 +216,10 @@
   bool contains (const std::string& name) const
   { return isfield (name); }
 
-  string_vector fieldnames (void) const
+  string_vector fieldnames () const
   { return m_keys.fieldnames (); }
 
-  string_vector keys (void) const
+  string_vector keys () const
   { return fieldnames (); }
 
   // get contents of a given field.  empty value if not exist.
@@ -243,7 +235,7 @@
   void del (const std::string& k) { rmfield (k); }
 
   // return a copy with fields ordered, optionally along with permutation.
-  octave_scalar_map orderfields (void) const;
+  octave_scalar_map orderfields () const;
   octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;
   octave_scalar_map orderfields (const octave_scalar_map& other,
                                  Array<octave_idx_type>& perm) const;
@@ -252,7 +244,7 @@
   octave_value contents (const std::string& k) const;
   octave_value& contents (const std::string& k);
 
-  void clear (void)
+  void clear ()
   {
     m_keys.clear ();
     m_vals.clear ();
@@ -264,7 +256,6 @@
 
   octave_fields m_keys;
   std::vector<octave_value> m_vals;
-
 };
 
 template <>
@@ -273,7 +264,7 @@
 { return v.scalar_map_value (); }
 
 class OCTINTERP_API
-  octave_map
+octave_map
 {
 public:
 
@@ -285,8 +276,6 @@
 
   typedef octave_scalar_map element_type;
 
-  octave_map (void) : m_keys (), m_vals (), m_dimensions () { }
-
   octave_map (const dim_vector& dv) : m_keys (), m_vals (), m_dimensions (dv) { }
 
   octave_map (const string_vector& k)
@@ -295,19 +284,9 @@
   octave_map (const dim_vector& dv, const string_vector& k)
     : m_keys (k), m_vals (k.numel (), Cell (dv)), m_dimensions (dv) { }
 
-  octave_map (const octave_map& m)
-    : m_keys (m.m_keys), m_vals (m.m_vals), m_dimensions (m.m_dimensions) { }
-
   octave_map (const octave_scalar_map& m);
 
-  octave_map& operator = (const octave_map& m)
-  {
-    m_keys = m.m_keys;
-    m_vals = m.m_vals;
-    m_dimensions = m.m_dimensions;
-
-    return *this;
-  }
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_map)
 
   // iteration support.
   // note that both const and non-const iterators are the same.
@@ -315,11 +294,11 @@
   typedef octave_fields::const_iterator const_iterator;
   typedef const_iterator iterator;
 
-  const_iterator begin (void) const { return m_keys.begin (); }
-  const_iterator end (void) const { return m_keys.end (); }
+  const_iterator begin () const { return m_keys.begin (); }
+  const_iterator end () const { return m_keys.end (); }
 
-  const_iterator cbegin (void) const { return m_keys.cbegin (); }
-  const_iterator cend (void) const { return m_keys.cend (); }
+  const_iterator cbegin () const { return m_keys.cbegin (); }
+  const_iterator cend () const { return m_keys.cend (); }
 
   const_iterator seek (const std::string& k) const { return m_keys.seek (k); }
 
@@ -341,7 +320,7 @@
   { return m_vals[i]; }
 
   // number of fields.
-  octave_idx_type nfields (void) const { return m_keys.nfields (); }
+  octave_idx_type nfields () const { return m_keys.nfields (); }
 
   // check whether a field exists.
   bool isfield (const std::string& name) const
@@ -350,10 +329,10 @@
   bool contains (const std::string& name) const
   { return isfield (name); }
 
-  string_vector fieldnames (void) const
+  string_vector fieldnames () const
   { return m_keys.fieldnames (); }
 
-  string_vector keys (void) const
+  string_vector keys () const
   { return fieldnames (); }
 
   // get contents of a given field.  empty value if not exist.
@@ -370,7 +349,7 @@
   void del (const std::string& k) { rmfield (k); }
 
   // return a copy with fields ordered, optionally along with permutation.
-  octave_map orderfields (void) const;
+  octave_map orderfields () const;
   octave_map orderfields (Array<octave_idx_type>& perm) const;
   octave_map orderfields (const octave_map& other,
                           Array<octave_idx_type>& perm) const;
@@ -379,20 +358,20 @@
   Cell contents (const std::string& k) const;
   Cell& contents (const std::string& k);
 
-  void clear (void)
+  void clear ()
   {
     m_keys.clear ();
     m_vals.clear ();
   }
 
   // The Array-like methods.
-  octave_idx_type numel (void) const { return m_dimensions.numel (); }
-  octave_idx_type length (void) const { return numel (); }
-  bool isempty (void) const { return m_dimensions.any_zero (); }
+  octave_idx_type numel () const { return m_dimensions.numel (); }
+  octave_idx_type length () const { return numel (); }
+  bool isempty () const { return m_dimensions.any_zero (); }
 
-  octave_idx_type rows (void) const { return m_dimensions(0); }
-  octave_idx_type cols (void) const { return m_dimensions(1); }
-  octave_idx_type columns (void) const { return m_dimensions(1); }
+  octave_idx_type rows () const { return m_dimensions(0); }
+  octave_idx_type cols () const { return m_dimensions(1); }
+  octave_idx_type columns () const { return m_dimensions(1); }
 
   // Extract a scalar substructure.
   // FIXME: actually check something.
@@ -423,15 +402,15 @@
   operator () (const Array<octave_idx_type>& ra_idx) const
   { return elem (ra_idx); }
 
-  octave_map squeeze (void) const;
+  octave_map squeeze () const;
 
   octave_map permute (const Array<int>& vec, bool inv = false) const;
 
-  dim_vector dims (void) const { return m_dimensions; }
+  dim_vector dims () const { return m_dimensions; }
 
-  int ndims (void) const { return m_dimensions.ndims (); }
+  int ndims () const { return m_dimensions.ndims (); }
 
-  octave_map transpose (void) const;
+  octave_map transpose () const;
 
   octave_map reshape (const dim_vector& dv) const;
 
@@ -491,7 +470,7 @@
   std::vector<Cell> m_vals;
   dim_vector m_dimensions;
 
-  void optimize_dimensions (void);
+  void optimize_dimensions ();
   void extract_scalar (octave_scalar_map& dest,
                        octave_idx_type index) const;
   static void do_cat (int dim, octave_idx_type n,
--- a/libinterp/corefcn/oct-opengl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-opengl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,13 +56,13 @@
 {
 public:
 
-  opengl_functions (void) { }
+  opengl_functions () { }
 
   opengl_functions (const opengl_functions&) = default;
 
   opengl_functions& operator = (const opengl_functions&) = default;
 
-  virtual ~opengl_functions (void) = default;
+  virtual ~opengl_functions () = default;
 
 #if defined (HAVE_OPENGL)
 
@@ -186,17 +186,17 @@
     ::glEnable (cap);
   }
 
-  virtual void glEndList (void)
+  virtual void glEndList ()
   {
     ::glEndList ();
   }
 
-  virtual void glEnd (void)
+  virtual void glEnd ()
   {
     ::glEnd ();
   }
 
-  virtual void glFinish (void)
+  virtual void glFinish ()
   {
     ::glFinish ();
   }
@@ -221,7 +221,7 @@
     ::glGetDoublev (pname, data);
   }
 
-  virtual GLenum glGetError (void)
+  virtual GLenum glGetError ()
   {
     return ::glGetError ();
   }
@@ -246,7 +246,7 @@
     ::glHint (target, mode);
   }
 
-  virtual void glInitNames (void)
+  virtual void glInitNames ()
   {
     ::glInitNames ();
   }
@@ -271,7 +271,7 @@
     ::glLineWidth (width);
   }
 
-  virtual void glLoadIdentity (void)
+  virtual void glLoadIdentity ()
   {
     ::glLoadIdentity ();
   }
@@ -337,17 +337,17 @@
     ::glPolygonOffset (factor, units);
   }
 
-  virtual void glPopAttrib (void)
+  virtual void glPopAttrib ()
   {
     ::glPopAttrib ();
   }
 
-  virtual void glPopMatrix (void)
+  virtual void glPopMatrix ()
   {
     ::glPopMatrix ();
   }
 
-  virtual void glPopName (void)
+  virtual void glPopName ()
   {
     ::glPopName ();
   }
@@ -357,7 +357,7 @@
     ::glPushAttrib (mask);
   }
 
-  virtual void glPushMatrix (void)
+  virtual void glPushMatrix ()
   {
     ::glPushMatrix ();
   }
--- a/libinterp/corefcn/oct-prcstrm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-prcstrm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
                          arg_md, ff, encoding, octave::pclose)
 { }
 
-octave_iprocstream::~octave_iprocstream (void)
+octave_iprocstream::~octave_iprocstream ()
 {
   do_close ();
 }
@@ -71,7 +71,7 @@
                          arg_md, ff, encoding, octave::pclose)
 { }
 
-octave_oprocstream::~octave_oprocstream (void)
+octave_oprocstream::~octave_oprocstream ()
 {
   do_close ();
 }
--- a/libinterp/corefcn/oct-prcstrm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-prcstrm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,11 +51,7 @@
                       = octave::mach_info::native_float_format (),
                       const std::string& encoding = "utf-8");
 
-  // No copying!
-
-  octave_iprocstream (const octave_iprocstream&) = delete;
-
-  octave_iprocstream& operator = (const octave_iprocstream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_iprocstream)
 
   static octave::stream
   create (const std::string& n, std::ios::openmode arg_md = std::ios::in,
@@ -65,7 +61,7 @@
 
 protected:
 
-  ~octave_iprocstream (void);
+  ~octave_iprocstream ();
 };
 
 class
@@ -79,11 +75,7 @@
                       = octave::mach_info::native_float_format (),
                       const std::string& encoding = "utf-8");
 
-  // No copying!
-
-  octave_oprocstream (const octave_oprocstream&) = delete;
-
-  octave_oprocstream& operator = (const octave_oprocstream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_oprocstream)
 
   static octave::stream
   create (const std::string& n, std::ios::openmode arg_md = std::ios::out,
@@ -93,19 +85,9 @@
 
 protected:
 
-  ~octave_oprocstream (void);
+  ~octave_oprocstream ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::octave_iprocstream' instead")
-typedef octave::octave_iprocstream octave_iprocstream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::octave_oprocstream' instead")
-typedef octave::octave_oprocstream octave_oprocstream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-procbuf.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-procbuf.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -182,7 +182,7 @@
 }
 
 procbuf *
-procbuf::close (void)
+procbuf::close ()
 {
 #if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
 
--- a/libinterp/corefcn/oct-procbuf.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-procbuf.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  procbuf (void)
+  procbuf ()
     : c_file_ptr_buf (nullptr), m_wstatus (-1), m_open_p (false),
       m_proc_pid (-1), m_next (nullptr)
   { }
@@ -52,23 +52,19 @@
       m_proc_pid (-1), m_next (nullptr)
   { open (command, mode); }
 
-  // No copying!
-
-  procbuf (const procbuf&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (procbuf)
 
-  procbuf& operator = (const procbuf&) = delete;
-
-  ~procbuf (void) { close (); }
+  ~procbuf () { close (); }
 
   procbuf * open (const char *command, int mode);
 
-  procbuf * close (void);
+  procbuf * close ();
 
-  int wait_status (void) const { return m_wstatus; }
+  int wait_status () const { return m_wstatus; }
 
-  bool is_open (void) const { return m_open_p; }
+  bool is_open () const { return m_open_p; }
 
-  pid_t pid (void) const { return m_proc_pid; }
+  pid_t pid () const { return m_proc_pid; }
 
 protected:
 
@@ -83,11 +79,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use octave::procbuf' instead")
-typedef octave::procbuf procbuf;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-process.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-process.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  process_execution_result (void)
+  process_execution_result ()
     : m_status (-1), m_err_msg (), m_exit_status (-1), m_stdout_output ()
   { }
 
@@ -48,19 +48,21 @@
       m_stdout_output (stdout_output)
   { }
 
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (process_execution_result)
+
   static OCTINTERP_API process_execution_result
   of_success (int exit_status, const std::string& stdout_output);
 
   static OCTINTERP_API process_execution_result
   of_error (int status, const std::string& err_msg);
 
-  int status (void) const { return m_status; }
+  int status () const { return m_status; }
 
-  int exit_status (void) const { return m_exit_status; }
+  int exit_status () const { return m_exit_status; }
 
-  std::string err_msg (void) const { return m_err_msg; }
+  std::string err_msg () const { return m_err_msg; }
 
-  std::string stdout_output (void) const { return m_stdout_output; }
+  std::string stdout_output () const { return m_stdout_output; }
 
 private:
 
--- a/libinterp/corefcn/oct-stdstrm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-stdstrm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,11 +50,7 @@
       m_stream (f ? new STREAM_T (f, cf) : nullptr), m_fnum (fid)
   { }
 
-  // No copying!
-
-  tstdiostream (const tstdiostream&) = delete;
-
-  tstdiostream& operator = (const tstdiostream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tstdiostream)
 
   // Position a stream at OFFSET relative to ORIGIN.
 
@@ -65,43 +61,43 @@
 
   // Return current stream position.
 
-  off_t tell (void) { return m_stream ? m_stream->tell () : -1; }
+  off_t tell () { return m_stream ? m_stream->tell () : -1; }
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return m_stream ? m_stream->eof () : true; }
+  bool eof () const { return m_stream ? m_stream->eof () : true; }
 
   // The name of the file.
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
-  std::istream * input_stream (void)
+  std::istream * input_stream ()
   {
     return (m_mode & std::ios::in) ? m_stream : nullptr;
   }
 
-  std::ostream * output_stream (void)
+  std::ostream * output_stream ()
   {
     return (m_mode & std::ios::out) ? m_stream : nullptr;
   }
 
   // FIXME: should not have to cast away const here.
-  BUF_T * rdbuf (void) const
+  BUF_T * rdbuf () const
   {
     return m_stream ? (const_cast<STREAM_T *> (m_stream))->rdbuf () : nullptr;
   }
 
-  int file_number (void) const { return m_fnum; }
+  int file_number () const { return m_fnum; }
 
-  bool bad (void) const { return m_stream ? m_stream->bad () : true; }
+  bool bad () const { return m_stream ? m_stream->bad () : true; }
 
-  void clear (void)
+  void clear ()
   {
     if (m_stream)
       m_stream->clear ();
   }
 
-  void do_close (void)
+  void do_close ()
   {
     if (m_stream)
       m_stream->stream_close ();
@@ -109,7 +105,7 @@
 
 protected:
 
-  ~tstdiostream (void) { delete m_stream; }
+  ~tstdiostream () { delete m_stream; }
 
   //--------
 
@@ -147,15 +143,11 @@
     return stream (new stdiostream (n, f, m, ff, encoding, cf));
   }
 
-  // No copying!
-
-  stdiostream (const stdiostream&) = delete;
-
-  stdiostream& operator = (const stdiostream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (stdiostream)
 
 protected:
 
-  ~stdiostream (void) = default;
+  ~stdiostream () = default;
 };
 
 #if defined (HAVE_ZLIB)
@@ -184,29 +176,15 @@
     return stream (new zstdiostream (n, f, fid, m, ff, encoding, cf));
   }
 
-  // No copying!
-
-  zstdiostream (const zstdiostream&) = delete;
-
-  zstdiostream& operator = (const zstdiostream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (zstdiostream)
 
 protected:
 
-  ~zstdiostream (void) = default;
+  ~zstdiostream () = default;
 };
 
 #endif
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::stdiostream' instead")
-typedef octave::stdiostream octave_stdiostream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::zstdiostream' instead")
-typedef octave::zstdiostream octave_zstdiostream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-stream.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-stream.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,6 +39,7 @@
 #include <iostream>
 #include <sstream>
 #include <string>
+#include <vector>
 
 #include "Array.h"
 #include "Cell.h"
@@ -262,7 +263,7 @@
 
   scanf_format_elt& operator = (const scanf_format_elt&) = default;
 
-  ~scanf_format_elt (void) = default;
+  ~scanf_format_elt () = default;
 
   // The C-style format string.
   std::string text;
@@ -291,30 +292,26 @@
 
   scanf_format_list (const std::string& fmt = "");
 
-  // No copying!
-
-  scanf_format_list (const scanf_format_list&) = delete;
-
-  scanf_format_list& operator = (const scanf_format_list&) = delete;
-
-  ~scanf_format_list (void);
-
-  octave_idx_type num_conversions (void) { return m_nconv; }
+  OCTAVE_DISABLE_COPY_MOVE (scanf_format_list)
+
+  ~scanf_format_list ();
+
+  octave_idx_type num_conversions () { return m_nconv; }
 
   // The length can be different than the number of conversions.
   // For example, "x %d y %d z" has 2 conversions but the length of
   // the list is 3 because of the characters that appear after the
   // last conversion.
 
-  std::size_t length (void) const { return m_fmt_elts.size (); }
-
-  const scanf_format_elt * first (void)
+  std::size_t length () const { return m_fmt_elts.size (); }
+
+  const scanf_format_elt * first ()
   {
     m_curr_idx = 0;
     return current ();
   }
 
-  const scanf_format_elt * current (void) const
+  const scanf_format_elt * current () const
   {
     return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;
   }
@@ -337,15 +334,15 @@
     return current ();
   }
 
-  void printme (void) const;
-
-  bool ok (void) const { return (m_nconv >= 0); }
+  void printme () const;
+
+  bool ok () const { return (m_nconv >= 0); }
 
   operator bool () const { return ok (); }
 
-  bool all_character_conversions (void);
-
-  bool all_numeric_conversions (void);
+  bool all_character_conversions ();
+
+  bool all_numeric_conversions ();
 
 private:
 
@@ -449,7 +446,7 @@
   m_buf.str ("");
 }
 
-scanf_format_list::~scanf_format_list (void)
+scanf_format_list::~scanf_format_list ()
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -665,7 +662,7 @@
 }
 
 void
-scanf_format_list::printme (void) const
+scanf_format_list::printme () const
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -693,7 +690,7 @@
 }
 
 bool
-scanf_format_list::all_character_conversions (void)
+scanf_format_list::all_character_conversions ()
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -723,7 +720,7 @@
 }
 
 bool
-scanf_format_list::all_numeric_conversions (void)
+scanf_format_list::all_numeric_conversions ()
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -767,7 +764,7 @@
 
   printf_format_elt& operator = (const printf_format_elt&) = default;
 
-  ~printf_format_elt (void) = default;
+  ~printf_format_elt () = default;
 
   // The C-style format string.
   std::string text;
@@ -799,28 +796,24 @@
 
   printf_format_list (const std::string& fmt = "");
 
-  // No copying!
-
-  printf_format_list (const printf_format_list&) = delete;
-
-  printf_format_list& operator = (const printf_format_list&) = delete;
-
-  ~printf_format_list (void);
-
-  octave_idx_type num_conversions (void) { return m_nconv; }
-
-  const printf_format_elt * first (void)
+  OCTAVE_DISABLE_COPY_MOVE (printf_format_list)
+
+  ~printf_format_list ();
+
+  octave_idx_type num_conversions () { return m_nconv; }
+
+  const printf_format_elt * first ()
   {
     m_curr_idx = 0;
     return current ();
   }
 
-  const printf_format_elt * current (void) const
+  const printf_format_elt * current () const
   {
     return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;
   }
 
-  std::size_t length (void) const { return m_fmt_elts.size (); }
+  std::size_t length () const { return m_fmt_elts.size (); }
 
   const printf_format_elt * next (bool cycle = true)
   {
@@ -837,11 +830,11 @@
     return current ();
   }
 
-  bool last_elt_p (void) { return (m_curr_idx + 1 == length ()); }
-
-  void printme (void) const;
-
-  bool ok (void) const { return (m_nconv >= 0); }
+  bool last_elt_p () { return (m_curr_idx + 1 == length ()); }
+
+  void printme () const;
+
+  bool ok () const { return (m_nconv >= 0); }
 
   operator bool () const { return ok (); }
 
@@ -958,7 +951,7 @@
     }
 }
 
-printf_format_list::~printf_format_list (void)
+printf_format_list::~printf_format_list ()
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -1160,7 +1153,7 @@
 }
 
 void
-printf_format_list::printme (void) const
+printf_format_list::printme () const
 {
   std::size_t n = m_fmt_elts.size ();
 
@@ -1198,7 +1191,7 @@
 }
 
 static Cell
-init_inf_nan (void)
+init_inf_nan ()
 {
   Cell retval (dim_vector (1, 2));
 
@@ -1231,17 +1224,13 @@
 
   delimited_stream (std::istream& is, const delimited_stream& ds);
 
-  // No copying!
-
-  delimited_stream (const delimited_stream&) = delete;
-
-  delimited_stream& operator = (const delimited_stream&) = delete;
-
-  ~delimited_stream (void);
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (delimited_stream)
+
+  ~delimited_stream ();
 
   // Called when optimized sequence of get is finished.  Ensures that
   // there is a remaining delimiter in buf, or loads more data in.
-  void field_done (void)
+  void field_done ()
   {
     if (m_idx >= m_last)
       refresh_buf ();
@@ -1253,7 +1242,7 @@
 
   // Get a character, relying on caller to call field_done if
   // a delimiter has been reached.
-  int get (void)
+  int get ()
   {
     if (m_delimited)
       return eof () ? std::istream::traits_type::eof () : *m_idx++;
@@ -1262,17 +1251,17 @@
   }
 
   // Get a character, checking for underrun of the buffer.
-  int get_undelim (void);
+  int get_undelim ();
 
   // Read character that will be got by the next get.
   // FIXME: This will not set EOF if delimited stream is at EOF and a peek
   // is attempted.  This does *NOT* behave like C++ input stream.
   // For a compatible peek function, use peek_undelim.  See bug #56917.
-  int peek (void)
+  int peek ()
   { return eof () ? std::istream::traits_type::eof () : *m_idx; }
 
   // Read character that will be got by the next get.
-  int peek_undelim (void);
+  int peek_undelim ();
 
   // Undo a 'get' or 'get_undelim'.  It is the caller's responsibility
   // to avoid overflow by calling putbacks only for a character got by
@@ -1288,22 +1277,22 @@
 
   // Return a position suitable to "seekg", valid only within this
   // block between calls to field_done.
-  char * tellg (void) { return m_idx; }
+  char * tellg () { return m_idx; }
 
   void seekg (char *old_idx) { m_idx = old_idx; }
 
-  bool eof (void)
+  bool eof ()
   {
     return (m_eob == m_buf + m_overlap && m_i_stream.eof ())
            || (m_flags & std::ios_base::eofbit);
   }
 
-  operator const void *(void)
+  operator const void *()
   { return (! eof () && ! m_flags) ? this : nullptr; }
 
-  bool fail (void) { return m_flags & std::ios_base::failbit; }
-
-  std::ios_base::iostate rdstate (void) { return m_flags; }
+  bool fail () { return m_flags & std::ios_base::failbit; }
+
+  std::ios_base::iostate rdstate () { return m_flags; }
 
   void setstate (std::ios_base::iostate m) { m_flags = m_flags | m; }
 
@@ -1316,14 +1305,14 @@
   // Report if any characters have been consumed.
   // (get, read, etc. not cancelled by putback or seekg)
 
-  void progress_benchmark (void) { m_progress_marker = m_idx; }
-
-  bool no_progress (void) { return m_progress_marker == m_idx; }
+  void progress_benchmark () { m_progress_marker = m_idx; }
+
+  bool no_progress () { return m_progress_marker == m_idx; }
 
   // Number of characters remaining until end of stream if it is already
   // buffered. int_max otherwise.
 
-  std::ptrdiff_t remaining (void)
+  std::ptrdiff_t remaining ()
   {
     if (m_eob < m_buf + m_bufsize)
       return m_eob - m_idx;
@@ -1398,7 +1387,7 @@
   : delimited_stream (is, ds.m_delims, ds.m_longest, ds.m_bufsize)
 { }
 
-delimited_stream::~delimited_stream (void)
+delimited_stream::~delimited_stream ()
 {
   // Seek to the correct position in i_stream.
   if (! eof ())
@@ -1415,7 +1404,7 @@
 // if necessary.
 
 int
-delimited_stream::get_undelim (void)
+delimited_stream::get_undelim ()
 {
   int retval;
   if (eof ())
@@ -1449,7 +1438,7 @@
 // pointer, refilling the buffer from the file if necessary.
 
 int
-delimited_stream::peek_undelim (void)
+delimited_stream::peek_undelim ()
 {
   int retval = get_undelim ();
   putback ();
@@ -1659,6 +1648,8 @@
     literal_conversion = 2
   };
 
+  textscan_format_elt () = delete;
+
   textscan_format_elt (const std::string& txt, int w = 0, int p = -1,
                        int bw = 0, bool dis = false, char typ = '\0',
                        const std::string& ch_class = std::string ())
@@ -1667,28 +1658,7 @@
       numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n')
   { }
 
-  textscan_format_elt (const textscan_format_elt& e)
-    : text (e.text), width (e.width), prec (e.prec),
-      bitwidth (e.bitwidth), char_class (e.char_class), type (e.type),
-      discard (e.discard), numeric (e.numeric)
-  { }
-
-  textscan_format_elt& operator = (const textscan_format_elt& e)
-  {
-    if (this != &e)
-      {
-        text = e.text;
-        width = e.width;
-        prec = e.prec;
-        bitwidth = e.bitwidth;
-        discard = e.discard;
-        type = e.type;
-        numeric = e.numeric;
-        char_class = e.char_class;
-      }
-
-    return *this;
-  }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (textscan_format_elt)
 
   // The C-style format string.
   std::string text;
@@ -1729,30 +1699,26 @@
 
   textscan_format_list (const std::string& fmt = std::string (),
                         const std::string& who = "textscan");
-  // No copying!
-
-  textscan_format_list (const textscan_format_list&) = delete;
-
-  textscan_format_list& operator = (const textscan_format_list&) = delete;
-
-  ~textscan_format_list (void);
-
-  octave_idx_type num_conversions (void) const { return m_nconv; }
+  OCTAVE_DISABLE_COPY_MOVE (textscan_format_list)
+
+  ~textscan_format_list ();
+
+  octave_idx_type num_conversions () const { return m_nconv; }
 
   // The length can be different than the number of conversions.
   // For example, "x %d y %d z" has 2 conversions but the length of
   // the list is 3 because of the characters that appear after the
   // last conversion.
 
-  std::size_t numel (void) const { return m_fmt_elts.size (); }
-
-  const textscan_format_elt * first (void)
+  std::size_t numel () const { return m_fmt_elts.size (); }
+
+  const textscan_format_elt * first ()
   {
     m_curr_idx = 0;
     return current ();
   }
 
-  const textscan_format_elt * current (void) const
+  const textscan_format_elt * current () const
   {
     return numel () > 0 ? m_fmt_elts[m_curr_idx] : nullptr;
   }
@@ -1772,11 +1738,11 @@
     return current ();
   }
 
-  void printme (void) const;
-
-  bool ok (void) const { return (m_nconv >= 0); }
-
-  operator const void *(void) const { return ok () ? this : nullptr; }
+  void printme () const;
+
+  bool ok () const { return (m_nconv >= 0); }
+
+  operator const void *() const { return ok () ? this : nullptr; }
 
   // What function name should be shown when reporting errors.
   std::string who;
@@ -1789,7 +1755,7 @@
 
   int read_first_row (delimited_stream& is, textscan& ts);
 
-  std::list<octave_value> out_buf (void) const
+  std::list<octave_value> out_buf () const
   { return (m_output_container); }
 
 private:
@@ -1846,13 +1812,9 @@
   textscan (const std::string& who_arg = "textscan",
             const std::string& encoding = "utf-8");
 
-  // No copying!
-
-  textscan (const textscan&) = delete;
-
-  textscan& operator = (const textscan&) = delete;
-
-  ~textscan (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (textscan)
+
+  ~textscan () = default;
 
   octave_value scan (std::istream& isp, const std::string& fmt,
                      octave_idx_type ntimes,
@@ -1922,7 +1884,7 @@
   { return m_whitespace_table[ch & 0xff]; }
 
   // True if the only delimiter is whitespace.
-  bool whitespace_delim (void) const { return m_delim_table.empty (); }
+  bool whitespace_delim () const { return m_delim_table.empty (); }
 
   //--------
 
@@ -1982,7 +1944,7 @@
   short m_return_on_error;
 
   bool m_collect_output;
-  bool multiple_delims_as_one;
+  bool m_multiple_delims_as_one;
   bool m_default_exp;
 
   octave_idx_type m_lines;
@@ -2088,7 +2050,7 @@
   m_buf.str ("");
 }
 
-textscan_format_list::~textscan_format_list (void)
+textscan_format_list::~textscan_format_list ()
 {
   std::size_t n = numel ();
 
@@ -2474,7 +2436,7 @@
 }
 
 void
-textscan_format_list::printme (void) const
+textscan_format_list::printme () const
 {
   std::size_t n = numel ();
 
@@ -2590,7 +2552,7 @@
     m_exp_chars ("edED"), m_header_lines (0), m_treat_as_empty (),
     m_treat_as_empty_len (0), m_whitespace (" \b\t"), m_eol1 ('\r'),
     m_eol2 ('\n'), m_return_on_error (1), m_collect_output (false),
-    multiple_delims_as_one (false), m_default_exp (true), m_lines (0)
+    m_multiple_delims_as_one (false), m_default_exp (true), m_lines (0)
 { }
 
 octave_value
@@ -2664,7 +2626,7 @@
   int err = 0;
   octave_idx_type row = 0;
 
-  if (multiple_delims_as_one)           // bug #44750?
+  if (m_multiple_delims_as_one)           // bug #44750?
     skip_delim (is);
 
   int done_after;  // Number of columns read when EOF seen.
@@ -2690,7 +2652,7 @@
   // after reading in data.
   // If the format was "", that conversion may already have happened,
   // so force all to be merged (as all are %f).
-  bool merge_with_prev[fmt_list.numel ()];
+  std::vector<bool> merge_with_prev (fmt_list.numel ());
   int conv = 0;
   if (m_collect_output)
     {
@@ -3748,7 +3710,7 @@
         }
       else if (param == "multipledelimsasone")
         {
-          multiple_delims_as_one = args(i
+          m_multiple_delims_as_one = args(i
                                         +1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", m_who.c_str ());
         }
       else if (param == "returnonerror")
@@ -3983,7 +3945,7 @@
           if (c1 == m_eol1 && is.peek_undelim () == m_eol2)
             is.get ();          // if \r\n, skip the \n too.
 
-          if (multiple_delims_as_one)
+          if (m_multiple_delims_as_one)
             {
               int prev = -1;
               // skip multiple delims.
@@ -4021,7 +3983,7 @@
               is.get_undelim ();
             }
 
-          if (multiple_delims_as_one)
+          if (m_multiple_delims_as_one)
             {
               int prev = -1;
               // skip multiple delims.
@@ -4084,14 +4046,14 @@
 }
 
 void
-base_stream::clear (void)
+base_stream::clear ()
 {
   m_fail = false;
   m_errmsg = "";
 }
 
 void
-base_stream::clearerr (void)
+base_stream::clearerr ()
 {
   std::istream *is = input_stream ();
   std::ostream *os = preferred_output_stream ();
@@ -4288,6 +4250,9 @@
 {
   T value = T ();
 
+    is >> std::ws;  // skip through whitespace and advance stream pointer
+    std::streampos pos = is.tellg ();
+
   switch (fmt.type)
     {
     case 'o':
@@ -4301,11 +4266,7 @@
 
     case 'i':
       {
-        int c1 = std::istream::traits_type::eof ();
-
-        while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
-               && isspace (c1))
-          ; // skip whitespace
+          int c1 = is.get ();
 
         if (c1 != std::istream::traits_type::eof ())
           {
@@ -4354,18 +4315,33 @@
       break;
     }
 
-  // If conversion produces an integer that overflows, failbit is set but
-  // value is non-zero.  We want to treat this case as success, so clear
-  // failbit from the stream state to keep going.
-  // FIXME: Maybe set error state on octave stream as above? Matlab does
-  // *not* indicate an error message on overflow.
-  if ((is.rdstate () & std::ios::failbit) && value != T ())
-    is.clear (is.rdstate () & ~std::ios::failbit);
-
-  // Only copy the converted value if the stream is in a state where we
-  // want to continue reading.
-  if (! (is.rdstate () & std::ios::failbit))
-    *valptr = value;
+    std::ios::iostate status = is.rdstate ();
+    if (! (status & std::ios::failbit))
+      {
+        // Copy the converted value if the stream is in a good state
+        *valptr = value;
+      }
+    else
+      {
+        if (value != T ())
+          {
+            // If conversion produces an integer that overflows, failbit is set
+            // but value is nonzero.  We want to treat this case as success,
+            // so clear  failbit from the stream state to keep going.
+            // FIXME: Maybe set error state on octave stream?  Matlab does
+            // *not* indicate an error message on overflow.
+            is.clear (status & ~std::ios::failbit);
+            *valptr = value;
+          }
+        else
+          {
+            // True error.
+            // Reset stream to original position, clear eof bit, pass status on.
+            is.clear ();
+            is.seekg (pos);
+            is.setstate (status & ~std::ios_base::eofbit);
+          }
+      }
 
   return is;
 }
@@ -4433,17 +4409,20 @@
     case 'E':
     case 'G':
       {
-        int c1 = std::istream::traits_type::eof ();
-
-        while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
-               && isspace (c1))
-          ; // skip whitespace
-
-        if (c1 != std::istream::traits_type::eof ())
+          is >> std::ws;  // skip through whitespace and advance stream pointer
+          if (is.good ())
           {
-            is.putback (c1);
+              std::streampos pos = is.tellg ();
 
             ref = read_value<double> (is);
+
+              std::ios::iostate status = is.rdstate ();
+              if (status & std::ios::failbit)
+                {
+                  is.clear ();
+                  is.seekg (pos);
+                  is.setstate (status & ~std::ios_base::eofbit);
+                }
           }
       }
       break;
@@ -4497,11 +4476,16 @@
     {                                                                   \
       int c = std::istream::traits_type::eof ();                        \
                                                                         \
+      /* get all whitespace characters */                               \
       while (is && (c = is.get ()) != std::istream::traits_type::eof () \
              && isspace (c))                                            \
         { /* skip whitespace */ }                                       \
                                                                         \
-      if (c != std::istream::traits_type::eof ())                       \
+      if (c == std::istream::traits_type::eof ())                       \
+        /* reset failbit at eof */                                      \
+        is.clear (is.rdstate () & (~std::ios::failbit));                \
+      else                                                              \
+        /* put back non-whitespace character */                         \
         is.putback (c);                                                 \
     }                                                                   \
   while (0)
@@ -4566,8 +4550,8 @@
          && (c = is.get ()) != std::istream::traits_type::eof ())       \
     tmp[n++] = static_cast<char> (c);                                   \
                                                                         \
-  if (n > 0 && c == std::istream::traits_type::eof ())                  \
-    is.clear ();                                                        \
+  if (c == std::istream::traits_type::eof ())                           \
+    is.clear (is.rdstate () & (~std::ios::failbit));                    \
                                                                         \
   tmp.resize (n)
 
@@ -4609,8 +4593,8 @@
                 tmp[n++] = static_cast<char> (c);                       \
             }                                                           \
                                                                         \
-          if (n > 0 && c == std::istream::traits_type::eof ())          \
-            is.clear ();                                                \
+          if (c == std::istream::traits_type::eof ())                   \
+            is.clear (is.rdstate () & (~std::ios::failbit));            \
                                                                         \
           tmp.resize (n);                                               \
         }                                                               \
@@ -4623,15 +4607,13 @@
 
 // This format must match a nonempty sequence of characters.
 #define BEGIN_CHAR_CLASS_CONVERSION()                                   \
-  int width = elt->width;                                               \
+  int width = (elt->width ? elt->width                                  \
+                          : std::numeric_limits<int>::max ());          \
                                                                         \
   std::string tmp;                                                      \
                                                                         \
   do                                                                    \
     {                                                                   \
-      if (! width)                                                      \
-        width = std::numeric_limits<int>::max ();                       \
-                                                                        \
       std::ostringstream buf;                                           \
                                                                         \
       std::string char_class = elt->char_class;                         \
@@ -4642,29 +4624,39 @@
         {                                                               \
           int chars_read = 0;                                           \
           while (is && chars_read++ < width                             \
-                 && (c = is.get ()) != std::istream::traits_type::eof () \
-                 && char_class.find (c) != std::string::npos)           \
-            buf << static_cast<char> (c);                               \
+                 && (c = is.get ()) != std::istream::traits_type::eof ()) \
+            {                                                           \
+              if (char_class.find (c) != std::string::npos)             \
+                buf << static_cast<char> (c);                           \
+              else                                                      \
+                {                                                       \
+                  is.putback (c);                                       \
+                  break;                                                \
+                }                                                       \
+            }                                                           \
         }                                                               \
       else                                                              \
         {                                                               \
           int chars_read = 0;                                           \
           while (is && chars_read++ < width                             \
-                 && (c = is.get ()) != std::istream::traits_type::eof () \
-                 && char_class.find (c) == std::string::npos)           \
-            buf << static_cast<char> (c);                               \
+                 && (c = is.get ()) != std::istream::traits_type::eof ()) \
+            {                                                           \
+              if (char_class.find (c) == std::string::npos)             \
+                buf << static_cast<char> (c);                           \
+              else                                                      \
+                {                                                       \
+                  is.putback (c);                                       \
+                  break;                                                \
+                }                                                       \
+            }                                                           \
         }                                                               \
                                                                         \
-      if (width == std::numeric_limits<int>::max ()                     \
-          && c != std::istream::traits_type::eof ())                    \
-        is.putback (c);                                                 \
-                                                                        \
       tmp = buf.str ();                                                 \
                                                                         \
       if (tmp.empty ())                                                 \
         is.setstate (std::ios::failbit);                                \
       else if (c == std::istream::traits_type::eof ())                  \
-        is.clear ();                                                    \
+        is.clear (is.rdstate () & (~std::ios::failbit));                \
                                                                         \
     }                                                                   \
   while (0)
@@ -4676,7 +4668,7 @@
         tmp = string::u8_from_encoding (who, tmp, encoding ());         \
       width = tmp.length ();                                            \
                                                                         \
-      if (is)                                                           \
+      if (is && width > 0)                                              \
         {                                                               \
           int i = 0;                                                    \
                                                                         \
@@ -5048,10 +5040,10 @@
 
                   // If it looks like we have a matching failure, then
                   // reset the failbit in the stream state.
-                  if (! is.eof () && is.rdstate () & std::ios::failbit)
+                    if (is.rdstate () & std::ios::failbit)
                     {
-                      error (who, "format failed to match");
                       is.clear (is.rdstate () & (~std::ios::failbit));
+                        error (who, "format failed to match");
                     }
 
                   // FIXME: is this the right thing to do?
@@ -5470,7 +5462,7 @@
 // (output streams are those that define os).
 
 int
-base_stream::flush (void)
+base_stream::flush ()
 {
   int retval = -1;
 
@@ -5510,13 +5502,9 @@
       }
   }
 
-  // No copying!
-
-  printf_value_cache (const printf_value_cache&) = delete;
-
-  printf_value_cache& operator = (const printf_value_cache&) = delete;
-
-  ~printf_value_cache (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (printf_value_cache)
+
+  ~printf_value_cache () = default;
 
   // Get the current value as a double and advance the internal pointer.
   octave_value get_next_value (char type = 0);
@@ -5525,16 +5513,16 @@
   // pointer.  Value before conversion to int must be >= 0 and less
   // than std::numeric_limits<int>::max ().
 
-  int int_value (void);
+  int int_value ();
 
   operator bool () const { return (m_curr_state == ok); }
 
-  bool exhausted (void) { return (m_val_idx >= m_n_vals); }
+  bool exhausted () { return (m_val_idx >= m_n_vals); }
 
 private:
 
   // Must create value cache with values!
-  printf_value_cache (void);
+  printf_value_cache ();
 
   //--------
 
@@ -5664,7 +5652,7 @@
 }
 
 int
-printf_value_cache::int_value (void)
+printf_value_cache::int_value ()
 {
   octave_value val = get_next_value ();
 
@@ -6132,7 +6120,7 @@
 }
 
 int
-stream::flush (void)
+stream::flush ()
 {
   int retval = -1;
 
@@ -6372,7 +6360,7 @@
 }
 
 off_t
-stream::tell (void)
+stream::tell ()
 {
   off_t retval = -1;
 
@@ -6383,13 +6371,13 @@
 }
 
 int
-stream::rewind (void)
+stream::rewind ()
 {
   return seek (0, SEEK_SET);
 }
 
 bool
-stream::is_open (void) const
+stream::is_open () const
 {
   bool retval = false;
 
@@ -6400,7 +6388,7 @@
 }
 
 void
-stream::close (void)
+stream::close ()
 {
   if (stream_ok ())
     {
@@ -7297,7 +7285,7 @@
 }
 
 bool
-stream::eof (void) const
+stream::eof () const
 {
   int retval = -1;
 
@@ -7319,7 +7307,7 @@
 }
 
 std::string
-stream::name (void) const
+stream::name () const
 {
   std::string retval;
 
@@ -7330,7 +7318,7 @@
 }
 
 int
-stream::mode (void) const
+stream::mode () const
 {
   int retval = 0;
 
@@ -7341,7 +7329,7 @@
 }
 
 mach_info::float_format
-stream::float_format (void) const
+stream::float_format () const
 {
   mach_info::float_format retval = mach_info::flt_fmt_unknown;
 
@@ -7412,7 +7400,7 @@
   m_stderr_file = insert (stderr_stream);
 }
 
-stream_list::~stream_list (void)
+stream_list::~stream_list ()
 {
   clear ();
 }
@@ -7620,7 +7608,7 @@
   return get_info (int_fid);
 }
 
-std::string stream_list::list_open_files (void) const
+std::string stream_list::list_open_files () const
 {
   std::ostringstream buf;
 
@@ -7652,7 +7640,7 @@
   return buf.str ();
 }
 
-octave_value stream_list::open_file_numbers (void) const
+octave_value stream_list::open_file_numbers () const
 {
   Matrix retval (1, m_list.size (), 0.0);
 
@@ -7710,17 +7698,17 @@
   return retval;
 }
 
-octave_value stream_list::stdin_file (void) const
+octave_value stream_list::stdin_file () const
 {
   return octave_value (m_stdin_file);
 }
 
-octave_value stream_list::stdout_file (void) const
+octave_value stream_list::stdout_file () const
 {
   return octave_value (m_stdout_file);
 }
 
-octave_value stream_list::stderr_file (void) const
+octave_value stream_list::stderr_file () const
 {
   return octave_value (m_stderr_file);
 }
--- a/libinterp/corefcn/oct-stream.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-stream.h	Fri Jun 23 20:51:51 2023 +0200
@@ -79,13 +79,9 @@
       m_errmsg ()
   { }
 
-  // No copying!
-
-  base_stream (const base_stream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_stream)
 
-  base_stream& operator = (const base_stream&) = delete;
-
-  virtual ~base_stream (void) = default;
+  virtual ~base_stream () = default;
 
   // The remaining functions are not specific to input or output only,
   // and must be provided by the derived classes.
@@ -96,32 +92,32 @@
 
   // Return current stream position.
 
-  virtual off_t tell (void) = 0;
+  virtual off_t tell () = 0;
 
   // Return TRUE if EOF has been reached on this stream.
 
-  virtual bool eof (void) const = 0;
+  virtual bool eof () const = 0;
 
   // The name of the file.
 
-  virtual std::string name (void) const = 0;
+  virtual std::string name () const = 0;
 
   // If the derived class provides this function and it returns a
   // pointer to a valid istream, scanf(), read(), getl(), and gets()
   // will automatically work for this stream.
 
-  virtual std::istream * input_stream (void) { return nullptr; }
+  virtual std::istream * input_stream () { return nullptr; }
 
   // If the derived class provides this function and it returns a
   // pointer to a valid ostream, flush(), write(), and printf() will
   // automatically work for this stream.
 
-  virtual std::ostream * output_stream (void) { return nullptr; }
+  virtual std::ostream * output_stream () { return nullptr; }
 
   // Return either the original output stream or one wrapped with the
   // encoding facet.
 
-  std::ostream * preferred_output_stream (void)
+  std::ostream * preferred_output_stream ()
   {
     if (! m_encoding.compare ("utf-8"))
       return output_stream ();
@@ -145,11 +141,11 @@
 
   // Return TRUE if this stream is open.
 
-  bool is_open (void) const { return m_open_state; }
+  bool is_open () const { return m_open_state; }
 
-  virtual void do_close (void) { }
+  virtual void do_close () { }
 
-  void close (void)
+  void close ()
   {
     if (is_open ())
       {
@@ -158,7 +154,7 @@
       }
   }
 
-  virtual int file_number (void) const
+  virtual int file_number () const
   {
     // Kluge alert!
 
@@ -172,7 +168,7 @@
       return -1;
   }
 
-  bool ok (void) const { return ! m_fail; }
+  bool ok () const { return ! m_fail; }
 
   // Return current error message for this stream.
 
@@ -180,11 +176,11 @@
 
 protected:
 
-  int mode (void) const { return m_mode; }
+  int mode () const { return m_mode; }
 
-  mach_info::float_format float_format (void) const { return m_flt_fmt; }
+  mach_info::float_format float_format () const { return m_flt_fmt; }
 
-  std::string encoding (void) const { return m_encoding; }
+  std::string encoding () const { return m_encoding; }
 
   // Set current error state and set fail to TRUE.
 
@@ -193,11 +189,11 @@
 
   // Clear any error message and set fail to FALSE.
 
-  OCTINTERP_API void clear (void);
+  OCTINTERP_API void clear ();
 
   // Clear stream state.
 
-  OCTINTERP_API void clearerr (void);
+  OCTINTERP_API void clearerr ();
 
 private:
 
@@ -273,7 +269,7 @@
   // Functions that are defined for all output streams (output streams
   // are those that define os).
 
-  OCTINTERP_API int flush (void);
+  OCTINTERP_API int flush ();
 
   OCTINTERP_API int
   do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
@@ -314,9 +310,9 @@
 
   stream& operator = (const stream&) = default;
 
-  ~stream (void) = default;
+  ~stream () = default;
 
-  OCTINTERP_API int flush (void);
+  OCTINTERP_API int flush ();
 
   OCTINTERP_API std::string
   getl (octave_idx_type max_len, bool& err,
@@ -346,13 +342,13 @@
   OCTINTERP_API int
   seek (const octave_value& offset, const octave_value& origin);
 
-  OCTINTERP_API off_t tell (void);
+  OCTINTERP_API off_t tell ();
 
-  OCTINTERP_API int rewind (void);
+  OCTINTERP_API int rewind ();
 
-  OCTINTERP_API bool is_open (void) const;
+  OCTINTERP_API bool is_open () const;
 
-  OCTINTERP_API void close (void);
+  OCTINTERP_API void close ();
 
   OCTINTERP_API octave_value
   read (const Array<double>& size, octave_idx_type block_size,
@@ -408,7 +404,7 @@
   OCTINTERP_API int
   puts (const octave_value& s, const std::string& who /* = "puts" */);
 
-  OCTINTERP_API bool eof (void) const;
+  OCTINTERP_API bool eof () const;
 
   OCTINTERP_API std::string error (bool clear, int& err_num);
 
@@ -428,33 +424,33 @@
 
   void error (const char *msg) { error (std::string (msg)); }
 
-  int file_number (void) { return m_rep ? m_rep->file_number () : -1; }
+  int file_number () { return m_rep ? m_rep->file_number () : -1; }
 
-  bool is_valid (void) const { return bool (m_rep); }
+  bool is_valid () const { return bool (m_rep); }
 
-  bool ok (void) const { return m_rep && m_rep->ok (); }
+  bool ok () const { return m_rep && m_rep->ok (); }
 
   operator bool () const { return ok (); }
 
-  OCTINTERP_API std::string name (void) const;
+  OCTINTERP_API std::string name () const;
 
-  OCTINTERP_API int mode (void) const;
+  OCTINTERP_API int mode () const;
 
-  OCTINTERP_API mach_info::float_format float_format (void) const;
+  OCTINTERP_API mach_info::float_format float_format () const;
 
   OCTINTERP_API static std::string mode_as_string (int mode);
 
-  std::string encoding (void)
+  std::string encoding ()
   {
     return m_rep ? m_rep->encoding () : std::string ();
   }
 
-  std::istream * input_stream (void)
+  std::istream * input_stream ()
   {
     return m_rep ? m_rep->input_stream () : nullptr;
   }
 
-  std::ostream * output_stream (void)
+  std::ostream * output_stream ()
   {
     return (m_rep ? m_rep->output_stream () : nullptr);
   }
@@ -465,7 +461,7 @@
     return (m_rep ? m_rep->preferred_output_stream () : nullptr);
   }
 
-  void clearerr (void) { if (m_rep) m_rep->clearerr (); }
+  void clearerr () { if (m_rep) m_rep->clearerr (); }
 
 private:
 
@@ -511,10 +507,9 @@
 
   OCTINTERP_API stream_list (interpreter& interp);
 
-  stream_list (const stream_list&) = delete;
-  stream_list& operator = (const stream_list&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (stream_list)
 
-  OCTINTERP_API ~stream_list (void);
+  OCTINTERP_API ~stream_list ();
 
   OCTINTERP_API int insert (stream& os);
 
@@ -531,15 +526,15 @@
   OCTINTERP_API string_vector get_info (int fid) const;
   OCTINTERP_API string_vector get_info (const octave_value& fid) const;
 
-  OCTINTERP_API std::string list_open_files (void) const;
+  OCTINTERP_API std::string list_open_files () const;
 
-  OCTINTERP_API octave_value open_file_numbers (void) const;
+  OCTINTERP_API octave_value open_file_numbers () const;
 
   OCTINTERP_API int get_file_number (const octave_value& fid) const;
 
-  OCTINTERP_API octave_value stdin_file (void) const;
-  OCTINTERP_API octave_value stdout_file (void) const;
-  OCTINTERP_API octave_value stderr_file (void) const;
+  OCTINTERP_API octave_value stdin_file () const;
+  OCTINTERP_API octave_value stdout_file () const;
+  OCTINTERP_API octave_value stderr_file () const;
 
 private:
 
--- a/libinterp/corefcn/oct-strstrm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-strstrm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -45,7 +45,7 @@
 // Return current stream position.
 
 off_t
-base_strstream::tell (void)
+base_strstream::tell ()
 {
   // Note: error is inherited from base_stream, not ::error.
   // This error function does not halt execution so "return ..." must exist.
--- a/libinterp/corefcn/oct-strstrm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-strstrm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,15 +46,11 @@
                   const std::string& encoding = "utf-8")
     : base_stream (m, ff, encoding) { }
 
-  // No copying!
-
-  base_strstream (const base_strstream&) = delete;
-
-  base_strstream& operator = (const base_strstream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_strstream)
 
 protected:
 
-  ~base_strstream (void) = default;
+  ~base_strstream () = default;
 
 public:
 
@@ -64,17 +60,17 @@
 
   // Return current stream position.
 
-  virtual off_t tell (void);
+  virtual off_t tell ();
 
   // The name of the file.
 
-  std::string name (void) const { return ""; }
+  std::string name () const { return ""; }
 
-  virtual std::streambuf * rdbuf (void) = 0;
+  virtual std::streambuf * rdbuf () = 0;
 
-  virtual bool bad (void) const = 0;
+  virtual bool bad () const = 0;
 
-  virtual void clear (void) = 0;
+  virtual void clear () = 0;
 };
 
 class
@@ -94,15 +90,11 @@
               const std::string& encoding = "utf-8")
     : base_strstream (arg_md, ff, encoding), m_istream (data) { }
 
-  // No copying!
-
-  istrstream (const istrstream&) = delete;
-
-  istrstream& operator = (const istrstream&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (istrstream)
 
 protected:
 
-  ~istrstream (void) = default;
+  ~istrstream () = default;
 
 public:
 
@@ -119,22 +111,22 @@
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return m_istream.eof (); }
+  bool eof () const { return m_istream.eof (); }
 
-  std::istream * input_stream (void) { return &m_istream; }
+  std::istream * input_stream () { return &m_istream; }
 
-  std::ostream * output_stream (void) { return nullptr; }
+  std::ostream * output_stream () { return nullptr; }
 
-  off_t tell (void) { return m_istream.tellg (); }
+  off_t tell () { return m_istream.tellg (); }
 
-  std::streambuf * rdbuf (void)
+  std::streambuf * rdbuf ()
   {
     return m_istream ? m_istream.rdbuf () : nullptr;
   }
 
-  bool bad (void) const { return m_istream.bad (); }
+  bool bad () const { return m_istream.bad (); }
 
-  void clear (void) { m_istream.clear (); }
+  void clear () { m_istream.clear (); }
 
 private:
 
@@ -151,15 +143,11 @@
               const std::string& encoding = "utf-8")
     : base_strstream (arg_md, ff, encoding), m_ostream () { }
 
-  // No copying!
-
-  ostrstream (const ostrstream&) = delete;
-
-  ostrstream& operator = (const ostrstream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (ostrstream)
 
 protected:
 
-  ~ostrstream (void) = default;
+  ~ostrstream () = default;
 
 public:
 
@@ -170,22 +158,22 @@
 
   // Return nonzero if EOF has been reached on this stream.
 
-  bool eof (void) const { return m_ostream.eof (); }
+  bool eof () const { return m_ostream.eof (); }
 
-  std::istream * input_stream (void) { return nullptr; }
+  std::istream * input_stream () { return nullptr; }
 
-  std::ostream * output_stream (void) { return &m_ostream; }
+  std::ostream * output_stream () { return &m_ostream; }
 
-  std::string str (void) { return m_ostream.str (); }
+  std::string str () { return m_ostream.str (); }
 
-  std::streambuf * rdbuf (void)
+  std::streambuf * rdbuf ()
   {
     return m_ostream ? m_ostream.rdbuf () : nullptr;
   }
 
-  bool bad (void) const { return m_ostream.bad (); }
+  bool bad () const { return m_ostream.bad (); }
 
-  void clear (void) { m_ostream.clear (); }
+  void clear () { m_ostream.clear (); }
 
 private:
 
@@ -194,17 +182,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::base_strstream' instead")
-typedef octave::base_strstream octave_base_strstream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::istrstream' instead")
-typedef octave::istrstream octave_istrstream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::ostrstream' instead")
-typedef octave::ostrstream octave_ostrstream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/oct-tex-lexer.in.ll	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/oct-tex-lexer.in.ll	Fri Jun 23 20:51:51 2023 +0200
@@ -237,7 +237,7 @@
     return (m_scanner && m_buffer_state);
   }
 
-  void text_parser_tex::destroy_lexer (void)
+  void text_parser_tex::destroy_lexer ()
   {
     if (m_buffer_state)
       {
--- a/libinterp/corefcn/ordschur.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/ordschur.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -82,8 +82,7 @@
   if (args.length () != 3)
     print_usage ();
 
-  const Array<octave_idx_type> sel_arg = args(
-      2).xoctave_idx_type_vector_value ("ordschur: SELECT must be an array of integers");
+  const Array<octave_idx_type> sel_arg = args(2).xoctave_idx_type_vector_value ("ordschur: SELECT must be an array of integers");
 
   const octave_idx_type sel_n = sel_arg.numel ();
 
@@ -98,10 +97,8 @@
 
   octave_value_list retval;
 
-  const bool double_type  = args(0).is_double_type ()
-                            || args(1).is_double_type ();
-  const bool complex_type = args(0).iscomplex ()
-                            || args(1).iscomplex ();
+  const bool double_type = args(0).is_double_type () || args(1).is_double_type ();
+  const bool complex_type = args(0).iscomplex () || args(1).iscomplex ();
 
 #define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND)                           \
   TYPE ## Matrix U = args(0).x ## TYPE_M ## _value                      \
--- a/libinterp/corefcn/pager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pager.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -114,7 +114,7 @@
   return false;
 }
 
-static std::string default_pager (void)
+static std::string default_pager ()
 {
   std::string pager_binary = sys::env::getenv ("PAGER");
 
@@ -125,7 +125,7 @@
 }
 
 int
-pager_buf::sync (void)
+pager_buf::sync ()
 {
   output_system& output_sys = __get_output_system__ ();
 
@@ -144,7 +144,7 @@
 }
 
 void
-pager_buf::flush_current_contents_to_diary (void)
+pager_buf::flush_current_contents_to_diary ()
 {
   char *buf = pbase () + m_diary_skip;
 
@@ -156,13 +156,13 @@
 }
 
 void
-pager_buf::set_diary_skip (void)
+pager_buf::set_diary_skip ()
 {
   m_diary_skip = pptr () - pbase ();
 }
 
 int
-diary_buf::sync (void)
+diary_buf::sync ()
 {
   output_system& output_sys = __get_output_system__ ();
 
@@ -183,31 +183,31 @@
   return 0;
 }
 
-pager_stream::pager_stream (void) : std::ostream (nullptr), m_pb (nullptr)
+pager_stream::pager_stream () : std::ostream (nullptr), m_pb (nullptr)
 {
   m_pb = new pager_buf ();
   rdbuf (m_pb);
   setf (unitbuf);
 }
 
-pager_stream::~pager_stream (void)
+pager_stream::~pager_stream ()
 {
   flush ();
   delete m_pb;
 }
 
-std::ostream& pager_stream::stream (void)
+std::ostream& pager_stream::stream ()
 {
   return *this;
 }
 
-void pager_stream::flush_current_contents_to_diary (void)
+void pager_stream::flush_current_contents_to_diary ()
 {
   if (m_pb)
     m_pb->flush_current_contents_to_diary ();
 }
 
-void pager_stream::set_diary_skip (void)
+void pager_stream::set_diary_skip ()
 {
   if (m_pb)
     m_pb->set_diary_skip ();
@@ -218,7 +218,7 @@
 // called when the pager is not in use.  For example, just before
 // getting command-line input.
 
-void pager_stream::reset (void)
+void pager_stream::reset ()
 {
   delete m_pb;
   m_pb = new pager_buf ();
@@ -226,20 +226,20 @@
   setf (unitbuf);
 }
 
-diary_stream::diary_stream (void) : std::ostream (nullptr), m_db (nullptr)
+diary_stream::diary_stream () : std::ostream (nullptr), m_db (nullptr)
 {
   m_db = new diary_buf ();
   rdbuf (m_db);
   setf (unitbuf);
 }
 
-diary_stream::~diary_stream (void)
+diary_stream::~diary_stream ()
 {
   flush ();
   delete m_db;
 }
 
-std::ostream& diary_stream::stream (void)
+std::ostream& diary_stream::stream ()
 {
   return *this;
 }
@@ -249,7 +249,7 @@
 // called when the pager is not in use.  For example, just before
 // getting command-line input.
 
-void diary_stream::reset (void)
+void diary_stream::reset ()
 {
   delete m_db;
   m_db = new diary_buf ();
@@ -257,7 +257,7 @@
   setf (unitbuf);
 }
 
-void flush_stdout (void)
+void flush_stdout ()
 {
   output_system& output_sys = __get_output_system__ ();
 
@@ -302,7 +302,7 @@
                                 "page_screen_output");
 }
 
-std::string output_system::pager_command (void) const
+std::string output_system::pager_command () const
 {
   std::string cmd = m_PAGER;
 
@@ -312,7 +312,7 @@
   return cmd;
 }
 
-void output_system::reset (void)
+void output_system::reset ()
 {
   flush_stdout ();
 
@@ -320,7 +320,7 @@
   m_diary_stream.reset ();
 }
 
-void output_system::flush_stdout (void)
+void output_system::flush_stdout ()
 {
   if (! m_flushing_output_to_pager)
     {
@@ -338,7 +338,7 @@
     }
 }
 
-void output_system::close_diary (void)
+void output_system::close_diary ()
 {
   // Try to flush the current buffer to the diary now, so that things
   // like
@@ -360,7 +360,7 @@
     }
 }
 
-void output_system::open_diary (void)
+void output_system::open_diary ()
 {
   close_diary ();
 
@@ -406,7 +406,7 @@
   return false;
 }
 
-void output_system::clear_external_pager (void)
+void output_system::clear_external_pager ()
 {
   if (m_external_pager)
     {
@@ -419,7 +419,7 @@
     }
 }
 
-void output_system::start_external_pager (void)
+void output_system::start_external_pager ()
 {
   if (m_external_pager)
     return;
@@ -489,14 +489,14 @@
     }
 }
 
-std::ostream& __stdout__ (void)
+std::ostream& __stdout__ ()
 {
   output_system& output_sys = __get_output_system__ ();
 
   return output_sys.__stdout__ ();
 }
 
-std::ostream& __diary__ (void)
+std::ostream& __diary__ ()
 {
   output_system& output_sys = __get_output_system__ ();
 
--- a/libinterp/corefcn/pager.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,15 +47,19 @@
 {
 public:
 
-  pager_buf (void) : std::stringbuf (), m_diary_skip (0) { }
+  pager_buf () : std::stringbuf (), m_diary_skip (0) { }
+
+  OCTAVE_DISABLE_COPY_MOVE (pager_buf)
 
-  void flush_current_contents_to_diary (void);
+  ~pager_buf () = default;
 
-  void set_diary_skip (void);
+  void flush_current_contents_to_diary ();
+
+  void set_diary_skip ();
 
 protected:
 
-  int sync (void);
+  int sync ();
 
 private:
 
@@ -68,23 +72,19 @@
 {
 public:
 
-  pager_stream (void);
-
-  // No copying!
+  pager_stream ();
 
-  pager_stream (const pager_stream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (pager_stream)
 
-  pager_stream& operator = (const pager_stream&) = delete;
+  ~pager_stream ();
 
-  ~pager_stream (void);
+  void flush_current_contents_to_diary ();
 
-  void flush_current_contents_to_diary (void);
+  void set_diary_skip ();
 
-  void set_diary_skip (void);
+  std::ostream& stream ();
 
-  std::ostream& stream (void);
-
-  void reset (void);
+  void reset ();
 
 private:
 
@@ -97,11 +97,12 @@
 {
 public:
 
-  diary_buf (void) : std::stringbuf () { }
+  OCTAVE_DEFAULT_CONSTRUCT_DELETE (diary_buf)
+  OCTAVE_DISABLE_COPY_MOVE (diary_buf)
 
 protected:
 
-  int sync (void);
+  int sync ();
 };
 
 class
@@ -110,26 +111,22 @@
 {
 public:
 
-  diary_stream (void);
+  diary_stream ();
 
-  // No copying!
-
-  diary_stream (const diary_stream&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (diary_stream)
 
-  diary_stream& operator = (const diary_stream&) = delete;
-
-  ~diary_stream (void);
+  ~diary_stream ();
 
-  std::ostream& stream (void);
+  std::ostream& stream ();
 
-  void reset (void);
+  void reset ();
 
 private:
 
   diary_buf *m_db;
 };
 
-extern OCTINTERP_API void flush_stdout (void);
+extern OCTINTERP_API void flush_stdout ();
 
 class output_system
 {
@@ -137,17 +134,15 @@
 
   output_system (interpreter& interp);
 
-  output_system (const output_system&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (output_system)
 
-  output_system& operator = (const output_system&) = delete;
-
-  ~output_system (void) = default;
+  ~output_system () = default;
 
-  pager_stream& pager (void) { return m_pager_stream; }
+  pager_stream& pager () { return m_pager_stream; }
 
-  diary_stream& diary (void) { return m_diary_stream; }
+  diary_stream& diary () { return m_diary_stream; }
 
-  std::string diary_file_name (void) const { return m_diary_file_name; }
+  std::string diary_file_name () const { return m_diary_file_name; }
 
   std::string diary_file_name (const std::string& nm)
   {
@@ -158,7 +153,7 @@
 
   octave_value PAGER (const octave_value_list& args, int nargout);
 
-  std::string PAGER (void) const { return m_PAGER; }
+  std::string PAGER () const { return m_PAGER; }
 
   std::string PAGER (const std::string& s)
   {
@@ -169,7 +164,7 @@
 
   octave_value PAGER_FLAGS (const octave_value_list& args, int nargout);
 
-  std::string PAGER_FLAGS (void) const { return m_PAGER_FLAGS; }
+  std::string PAGER_FLAGS () const { return m_PAGER_FLAGS; }
 
   std::string PAGER_FLAGS (const std::string& s)
   {
@@ -181,7 +176,7 @@
   octave_value page_output_immediately (const octave_value_list& args,
                                         int nargout);
 
-  bool page_output_immediately (void) const
+  bool page_output_immediately () const
   {
     return m_page_output_immediately;
   }
@@ -196,7 +191,7 @@
   octave_value page_screen_output (const octave_value_list& args,
                                    int nargout);
 
-  bool page_screen_output (void) const { return m_page_screen_output; }
+  bool page_screen_output () const { return m_page_screen_output; }
 
   bool page_screen_output (bool flag)
   {
@@ -205,7 +200,7 @@
     return val;
   }
 
-  bool write_to_diary_file (void) const
+  bool write_to_diary_file () const
   {
     return m_write_to_diary_file;
   }
@@ -217,7 +212,7 @@
     return val;
   }
 
-  bool really_flush_to_pager (void) const
+  bool really_flush_to_pager () const
   {
     return m_really_flush_to_pager;
   }
@@ -229,7 +224,7 @@
     return val;
   }
 
-  bool flushing_output_to_pager (void) const
+  bool flushing_output_to_pager () const
   {
     return m_flushing_output_to_pager;
   }
@@ -241,25 +236,25 @@
     return val;
   }
 
-  std::string pager_command (void) const;
+  std::string pager_command () const;
 
-  std::ofstream& external_diary_file (void) { return m_external_diary_file; }
+  std::ofstream& external_diary_file () { return m_external_diary_file; }
 
-  void reset (void);
+  void reset ();
 
-  void flush_stdout (void);
+  void flush_stdout ();
 
   bool sync (const char *msg, int len);
 
-  void clear_external_pager (void);
+  void clear_external_pager ();
 
-  void open_diary (void);
+  void open_diary ();
 
-  void close_diary (void);
+  void close_diary ();
 
-  std::ostream& __stdout__ (void) { return m_pager_stream.stream (); }
+  std::ostream& __stdout__ () { return m_pager_stream.stream (); }
 
-  std::ostream& __diary__ (void) { return m_diary_stream.stream (); }
+  std::ostream& __diary__ () { return m_diary_stream.stream (); }
 
 private:
 
@@ -300,14 +295,14 @@
 
   bool m_flushing_output_to_pager;
 
-  void start_external_pager (void);
+  void start_external_pager ();
 
   void do_sync (const char *msg, int len, bool bypass_pager);
 };
 
-extern OCTINTERP_API std::ostream& __stdout__ (void);
+extern OCTINTERP_API std::ostream& __stdout__ ();
 
-extern OCTINTERP_API std::ostream& __diary__ (void);
+extern OCTINTERP_API std::ostream& __diary__ ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/perms.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,398 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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 "defun.h"
+#include "error.h"
+#include "errwarn.h"
+#include "ovl.h"
+
+OCTAVE_BEGIN_NAMESPACE (octave)
+
+static inline double
+Factorial (octave_idx_type n)
+{
+  double ret = 1;
+  for (octave_idx_type i = 2; i <= n; i++)
+    ret *= i;
+  return ret;
+}
+
+//
+// Use C++ template to cater for the different octave array classes.
+//
+template <typename T>
+static inline Array<T>
+GetPerms (const Array<T> &ar_in, bool uniq_v, bool do_sort = false)
+{
+  octave_idx_type m = ar_in.numel ();
+  double nr = Factorial (m);
+
+  // Setup index vector filled from 0..m-1
+  int myvidx[m];
+  for (int i = 0; i < m; i++)
+    myvidx[i] = i;
+
+  // Interim array to sort ar_in for octave sort order and to implement
+  // "unique".
+  Array<T> ar (ar_in);
+
+  if (uniq_v)
+    {
+      ar = ar.sort (ar.dims () (1) > ar.dims () (0) ? 1 : 0, ASCENDING);
+      const T *Ar = ar.data ();
+      int ctr = 0;
+      int N_el = 1;
+
+      // Number of same elements where we need to remove permutations
+      // Number of unique permutations is n! / (n_el1! * n_el2! * ...)
+      for (octave_idx_type i = 0; i < m - 1; i++)
+        {
+          myvidx[i] = ctr;
+          if (Ar[i + 1] != Ar[i])
+            {
+              nr /= Factorial (N_el);
+              ctr = i + 1;  // index of next different element
+              N_el = 1;
+            }
+          else
+            N_el++;
+        }
+      myvidx[m - 1] = ctr;
+      nr /= Factorial (N_el);
+    }
+  else if (do_sort)
+    {
+      ar = ar.sort (ar.dims () (1) > ar.dims () (0) ? 1 : 0, ASCENDING);
+    }
+
+  // Sort vector indices for inverse lexicographic order later.
+  std::sort (myvidx, myvidx + m, std::greater<int> ());
+
+  const T *Ar = ar.data ();
+
+  // Set up result array
+  octave_idx_type n = static_cast<octave_idx_type> (nr);
+  Array<T> res (dim_vector (n, m));
+  T *Res = res.fortran_vec ();
+
+  // Do the actual job
+  octave_idx_type i = 0;
+  std::sort (myvidx, myvidx + m, std::greater<int> ());
+  do
+    {
+      for (octave_idx_type j = 0; j < m; j++)
+        Res[i + j * n] = Ar[myvidx[j]];
+      i++;
+    }
+  while (std::next_permutation (myvidx, myvidx + m, std::greater<int> ()));
+
+  return res;
+}
+
+// Template for non-numerical types (e.g. Cell) without sorting.
+// The C++ compiler complains as the provided type octave_value does not
+// support the test of equality via '==' in the above template.
+
+template <typename T>
+static inline Array<T>
+GetPermsNoSort (const Array<T> &ar_in, bool uniq_v = false)
+{
+  octave_idx_type m = ar_in.numel ();
+  double nr = Factorial (m);
+
+  // Setup index vector filled from 0..m-1
+  int myvidx[m];
+  for (int i = 0; i < m; i++)
+    myvidx[i] = i;
+
+  const T *Ar = ar_in.data ();
+
+  if (uniq_v)
+    {
+      // Mutual Comparison using is_equal to detect duplicated values
+      int N_el = 1;
+      // Number of unique permutations is n! / (n_el1! * n_el2! * ...)
+      for (octave_idx_type i = 0; i < m - 1; i++)
+        {
+          for (octave_idx_type j = i + 1; j < m; j++)
+            {
+              if (myvidx[j] > myvidx[i] && Ar[i].is_equal (Ar[j]))
+                {
+                  myvidx[j] = myvidx[i];  // not yet processed...
+                  N_el++;
+                }
+              else
+                {
+                  nr /= Factorial (N_el);
+                  N_el = 1;
+                }
+            }
+        }
+      nr /= Factorial (N_el);
+    }
+
+  // Sort vector indices for inverse lexicographic order later.
+  std::sort (myvidx, myvidx + m, std::greater<int> ());
+
+  // Set up result array
+  octave_idx_type n = static_cast<octave_idx_type> (nr);
+  Array<T> res (dim_vector (n, m));
+  T *Res = res.fortran_vec ();
+
+  // Do the actual job
+  octave_idx_type i = 0;
+  do
+    {
+      for (octave_idx_type j = 0; j < m; j++)
+        Res[i + j * n] = Ar[myvidx[j]];
+      i++;
+    }
+  while (std::next_permutation (myvidx, myvidx + m, std::greater<int> ()));
+  return res;
+}
+
+DEFUN (perms, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{P} =} perms (@var{v})
+@deftypefnx {} {@var{P} =} perms (@var{v}, "unique")
+Generate all permutations of vector @var{v} with one row per permutation.
+
+Results are returned in reverse lexicographic order if @var{v} is in ascending
+order.  If @var{v} is in a different permutation, then the result is permuted
+that way too.  Consequently, an input in descending order yields a result in
+normal lexicographic order.  The result has size
+@code{factorial (@var{n}) * @var{n}}, where @var{n} is the length of @var{v}.
+Any repeated elements are included in the output.
+
+If the optional argument @qcode{"unique"} is given then only unique
+permutations are returned, using less memory and taking less time than calling
+@code{unique (perms (@var{v}), "rows")}.
+
+Example 1
+
+@example
+@group
+perms ([1, 2, 3])
+@result{}
+3   2   1
+3   1   2
+2   3   1
+2   1   3
+1   3   2
+1   2   3
+@end group
+@end example
+
+Example 2
+
+@example
+@group
+perms ([1, 1, 2, 2], "unique")
+@result{}
+2   2   1   1
+2   1   2   1
+2   1   1   2
+1   2   2   1
+1   2   1   2
+1   1   2   2
+@end group
+@end example
+
+Programming Note: If the @qcode{"unique"} option is not used, the length of
+@var{v} should be no more than 10-12 to limit memory consumption.  Even with
+@qcode{"unique"}, there should be no more than 10-12 unique elements in
+@var{v}.
+@seealso{permute, randperm, nchoosek}
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+
+  octave_value retval;
+
+  // Parameter check "unique"
+  bool uniq_v = false;
+  if (nargin == 2)
+    {
+      const charMatrix opt = args (1).char_matrix_value ();
+      const char *str = opt.data ();
+      if (std::string (str, opt.cols ()) != "unique")
+        {
+          error ("perms: option must be the string \"unique\".");
+        }
+      uniq_v = true;
+    }
+
+  if (! (args (0).is_matrix_type () || args (0).is_range ()
+      || args (0).iscell () || args (0).is_scalar_type ()
+      || args (0).isstruct ()))
+    {
+      error ("perms: INPUT must be a matrix, a range, a cell array, "
+             "a struct or a scalar.");
+    }
+
+  std::string clname = args (0).class_name ();
+
+  // Execute main permutation code for the different classes
+  if (clname == "double")
+    retval = GetPerms<double> (args (0).array_value (), uniq_v);
+  else if (clname == "single")
+    retval = GetPerms<float> (args (0).float_array_value (), uniq_v);
+  else if (clname == "logical")
+    retval = GetPerms<bool> (args (0).bool_array_value (), uniq_v);
+  else if (clname == "char")
+    retval = GetPerms<char> (args (0).char_array_value (), uniq_v);
+  else if (clname == "int8")
+    retval = GetPerms<octave_int8> (args (0).int8_array_value (), uniq_v);
+  else if (clname == "int16")
+    retval = GetPerms<octave_int16> (args (0).int16_array_value (), uniq_v);
+  else if (clname == "int32")
+    retval = GetPerms<octave_int32> (args (0).int32_array_value (), uniq_v);
+  else if (clname == "int64")
+    retval = GetPerms<octave_int64> (args (0).int64_array_value (), uniq_v);
+  else if (clname == "uint8")
+    retval = GetPerms<octave_uint8> (args (0).uint8_array_value (), uniq_v);
+  else if (clname == "uint16")
+    retval = GetPerms<octave_uint16> (args (0).uint16_array_value (), uniq_v);
+  else if (clname == "uint32")
+    retval = GetPerms<octave_uint32> (args (0).uint32_array_value (), uniq_v);
+  else if (clname == "uint64")
+    retval = GetPerms<octave_uint64> (args (0).uint64_array_value (), uniq_v);
+  else if (clname == "cell")
+    retval = GetPermsNoSort<octave_value> (args (0).cell_value (), uniq_v);
+  else if (clname == "struct")
+    {
+      const octave_map map_in (args (0).map_value ());
+      string_vector fn = map_in.fieldnames ();
+      if (fn.numel () == 0 && map_in.numel () != 0)
+        {
+          octave_scalar_map out;
+          retval = out;
+        }
+      else
+        {
+          octave_map out;
+          if (fn.numel () == 0)
+            {
+              out = octave_map (dim_vector (1, 0));
+            }
+          else
+            {
+              for (octave_idx_type i = 0; i < fn.numel (); i++)
+                {
+                  out.assign (fn (i), GetPermsNoSort<octave_value>
+                                      (map_in.contents (fn (i)), uniq_v));
+                }
+            }
+          retval = out;
+        }
+    }
+  else  // none of the above class criteria were met
+    {
+      warning ("perms: unable to permute for class %s", clname.c_str ());
+      // retval stays empty
+    }
+  return ovl (retval);
+}
+
+/*
+
+%!assert (rows (perms (1:6)), factorial (6))
+%!assert (perms (pi), pi)
+%!assert (perms ([e, pi]), [pi, e; e, pi])
+%!assert (perms ([pi, e]), [e, pi; pi, e])
+%!assert (perms ([1 2 3]), [3 2 1; 3 1 2; 2 3 1; 2 1 3; 1 3 2; 1 2 3])
+%!assert (sortrows (perms (1:5)), sortrows (perms ([2 5 4 1 3]')))
+%!assert (perms ("abc"), char ("cba", "cab", "bca", "bac", "acb", "abc"))
+%!assert (sortrows (perms ("fobar")), unique (perms ("fobar"), "rows"))
+%!assert (unique (perms (1:5)(:))', 1:5)
+%!assert (perms (int8 (1:4)), int8 (perms (1:4)))
+
+%!assert (sortrows (perms ("abb", "unique")), ["abb"; "bab"; "bba"])
+%!assert (size (perms ([1 1 1 1 2 2 2 3 3], "unique")), [1260 9])
+%!assert (size (perms (int8([1 1 1 1 1 2 2 2 2 3 3 3]), "unique")), [27720 12])
+
+## 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 (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})),
+%!                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])),
+%!                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])),
+%!                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))
+
+%!test <*52432>
+%! s = struct ();
+%! s(1) = [];
+%! assert (perms (reshape (s, 0, 0)), reshape (s, 1, 0));
+%! assert (perms (reshape (s, 0, 1)), reshape (s, 1, 0));
+
+## test if "unique" works also for cell arrays
+%!assert <*63965> (perms ({"foo"; "foo"}, "unique"), {"foo", "foo"})
+%!assert <*63965> (perms ({"foo", "foo", "bar"}, "unique"), ...
+%!                        {"bar", "foo", "foo";
+%!                         "foo", "bar", "foo";
+%!                         "foo", "foo", "bar"})
+
+## Test input validation
+%!error <Invalid call> perms ()
+%!error <option must be the string "unique"> perms (1:5, "foobar")
+%!error <option must be the string "unique"> perms (1:5, {"foo"})
+
+*/
+
+OCTAVE_END_NAMESPACE (octave)
--- a/libinterp/corefcn/pr-flt-fmt.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pr-flt-fmt.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 static int Voutput_precision = 5;
 
 int
-output_precision (void)
+output_precision ()
 {
   return Voutput_precision;
 }
--- a/libinterp/corefcn/pr-flt-fmt.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pr-flt-fmt.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 template <typename T>
 class pr_rational_float;
 
-extern OCTINTERP_API int output_precision (void);
+extern OCTINTERP_API int output_precision ();
 
 extern OCTINTERP_API void set_output_prec (int prec);
 
@@ -60,33 +60,33 @@
 
   float_format& operator = (const float_format&) = default;
 
-  ~float_format (void) = default;
+  ~float_format () = default;
 
-  float_format& scientific (void)
+  float_format& scientific ()
   {
     m_fmt = std::ios::scientific;
     return *this;
   }
 
-  float_format& fixed (void)
+  float_format& fixed ()
   {
     m_fmt = std::ios::fixed;
     return *this;
   }
 
-  float_format& general (void)
+  float_format& general ()
   {
     m_fmt = 0;
     return *this;
   }
 
-  float_format& uppercase (void)
+  float_format& uppercase ()
   {
     m_up = std::ios::uppercase;
     return *this;
   }
 
-  float_format& lowercase (void)
+  float_format& lowercase ()
   {
     m_up = 0;
     return *this;
@@ -117,57 +117,57 @@
     return *this;
   }
 
-  std::ios::fmtflags format_flags (void) const
+  std::ios::fmtflags format_flags () const
   {
     return static_cast<std::ios::fmtflags> (m_fmt | m_up | m_sp);
   }
 
-  int format (void) const
+  int format () const
   {
     return m_fmt;
   }
 
-  bool is_scientific (void) const
+  bool is_scientific () const
   {
     return m_fmt == std::ios::scientific;
   }
 
-  bool is_fixed (void) const
+  bool is_fixed () const
   {
     return m_fmt == std::ios::fixed;
   }
 
-  bool is_general (void) const
+  bool is_general () const
   {
     return m_fmt == 0;
   }
 
-  bool is_uppercase (void) const
+  bool is_uppercase () const
   {
     return m_up == std::ios::uppercase;
   }
 
-  bool is_lowercase (void) const
+  bool is_lowercase () const
   {
     return m_up == 0;
   }
 
-  int precision (void) const
+  int precision () const
   {
     return m_prec;
   }
 
-  int width (void) const
+  int width () const
   {
     return m_fw;
   }
 
-  int exponent_width (void) const
+  int exponent_width () const
   {
     return m_ex;
   }
 
-  bool show_trailing_zeros (void) const
+  bool show_trailing_zeros () const
   {
     return m_sp == std::ios::showpoint;
   }
@@ -211,7 +211,7 @@
 {
 public:
 
-  float_display_format (void) = default;
+  float_display_format () = default;
 
   float_display_format (double scale, const float_format& real_fmt,
                         const float_format& imag_fmt = float_format ())
@@ -227,13 +227,13 @@
 
   float_display_format& operator = (const float_display_format&) = default;
 
-  ~float_display_format (void) = default;
+  ~float_display_format () = default;
 
-  double scale_factor (void) const { return m_scale; }
+  double scale_factor () const { return m_scale; }
 
-  float_format real_format (void) const { return m_real_fmt; }
+  float_format real_format () const { return m_real_fmt; }
 
-  float_format imag_format (void) const { return m_imag_fmt; }
+  float_format imag_format () const { return m_imag_fmt; }
 
   void set_precision (int prec)
   {
--- a/libinterp/corefcn/pr-output.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pr-output.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,11 +50,11 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter.h"
 #include "ovl.h"
 #include "oct-stream.h"
 #include "octave-preserve-stream-state.h"
 #include "pager.h"
-#include "parse.h"
 #include "pr-flt-fmt.h"
 #include "pr-output.h"
 #include "sysdep.h"
@@ -170,14 +170,14 @@
 
 template <typename T>
 int
-pr_engineering_float<T>::exponent (void) const
+pr_engineering_float<T>::exponent () const
 {
   return engineering_exponent (m_val);
 }
 
 template <typename T>
 T
-pr_engineering_float<T>::mantissa (void) const
+pr_engineering_float<T>::mantissa () const
 {
   return m_val / std::pow (static_cast<T> (10), exponent ());
 }
@@ -896,10 +896,12 @@
   T rp = c.real ();
   T ip = c.imag ();
 
-  bool inf_or_nan = (octave::math::isinf (c) || octave::math::isnan (c));
-
-  bool int_only = (octave::math::x_nint (rp) == rp
-                   && octave::math::x_nint (ip) == ip);
+  bool r_inf_or_nan = (octave::math::isinf (rp) || octave::math::isnan (rp));
+  bool i_inf_or_nan = (octave::math::isinf (ip) || octave::math::isnan (ip));
+  bool inf_or_nan = r_inf_or_nan || i_inf_or_nan;
+
+  bool int_only = ((r_inf_or_nan || octave::math::x_nint (rp) == rp)
+                   && (i_inf_or_nan || octave::math::x_nint (ip) == ip));
 
   T r_abs = (rp < 0 ? -rp : rp);
   T i_abs = (ip < 0 ? -ip : ip);
@@ -3445,8 +3447,8 @@
 %! end_unwind_protect
 */
 
-DEFUN (display, args, ,
-       classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64
+DEFMETHOD (display, interp, args, ,
+           classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64
        doc: /* -*- texinfo -*-
 @deftypefn {} {} display (@var{obj})
 Display the contents of the object @var{obj} prepended by its name.
@@ -3518,7 +3520,7 @@
 
   // Use feval so that dispatch will also work for disp.
 
-  feval ("disp", ovl (value));
+  interp.feval ("disp", ovl (value));
 
   if (print_newlines)
     octave_stdout << std::endl;
@@ -3555,7 +3557,7 @@
 */
 
 static inline void
-init_format_state (void)
+init_format_state ()
 {
   free_format = false;
   plus_format = false;
@@ -3603,7 +3605,7 @@
   frame.protect_var (Vcompact_format);
   frame.protect_var (uppercase_format);
   int prec = output_precision ();
-  frame.add ([=] (void) { set_output_prec (prec); });
+  frame.add ([=] () { set_output_prec (prec); });
 
   format = format_string;   // Initialize with existing value
   while (argc-- > 0)
--- a/libinterp/corefcn/pr-output.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/pr-output.h	Fri Jun 23 20:51:51 2023 +0200
@@ -517,9 +517,9 @@
 
   T m_val;
 
-  int exponent (void) const;
+  int exponent () const;
 
-  T mantissa (void) const;
+  T mantissa () const;
 
   pr_engineering_float (const float_format& ff, T val)
     : m_ff (ff), m_val (val) { }
--- a/libinterp/corefcn/procstream.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/procstream.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -59,7 +59,7 @@
 }
 
 int
-procstreambase::close (void)
+procstreambase::close ()
 {
   int status = 0;
 
--- a/libinterp/corefcn/procstream.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/procstream.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,13 +43,15 @@
 {
 public:
 
-  procstreambase (void) : m_pb () { pb_init (); }
+  procstreambase () : m_pb () { pb_init (); }
 
   procstreambase (const std::string& name, int mode);
 
   procstreambase (const char *name, int mode);
 
-  ~procstreambase (void) { close (); }
+  OCTAVE_DISABLE_COPY_MOVE (procstreambase)
+
+  ~procstreambase () { close (); }
 
   void open (const std::string& name, int mode)
   {
@@ -58,28 +60,24 @@
 
   void open (const char *name, int mode);
 
-  int is_open (void) const { return m_pb.is_open (); }
+  int is_open () const { return m_pb.is_open (); }
 
-  int close (void);
+  int close ();
 
-  pid_t pid (void) const { return m_pb.pid (); }
+  pid_t pid () const { return m_pb.pid (); }
 
-  int file_number (void) const { return m_pb.file_number (); }
+  int file_number () const { return m_pb.file_number (); }
 
 private:
 
   procbuf m_pb;
 
-  void pb_init (void)
+  void pb_init ()
   {
     // Explicit initialization of the std::ios object is needed.
     // FIXME: is there a better way to organize these classes?
     init (&m_pb);
   }
-
-  procstreambase (const procstreambase&);
-
-  procstreambase& operator = (const procstreambase&);
 };
 
 class
@@ -88,7 +86,7 @@
 {
 public:
 
-  iprocstream (void) : std::istream (nullptr), procstreambase () { }
+  iprocstream () : std::istream (nullptr), procstreambase () { }
 
   iprocstream (const std::string& name, int mode = std::ios::in)
     : std::istream (nullptr), procstreambase (name, mode)
@@ -98,7 +96,9 @@
     : std::istream (nullptr), procstreambase (name, mode)
   { }
 
-  ~iprocstream (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (iprocstream)
+
+  ~iprocstream () = default;
 
   void open (const std::string& name, int mode = std::ios::in)
   {
@@ -109,12 +109,6 @@
   {
     procstreambase::open (name, mode);
   }
-
-private:
-
-  iprocstream (const iprocstream&);
-
-  iprocstream& operator = (const iprocstream&);
 };
 
 class
@@ -123,7 +117,7 @@
 {
 public:
 
-  oprocstream (void) : std::ostream (nullptr), procstreambase () { }
+  oprocstream () : std::ostream (nullptr), procstreambase () { }
 
   oprocstream (const std::string& name, int mode = std::ios::out)
     : std::ostream (nullptr), procstreambase (name, mode) { }
@@ -131,7 +125,9 @@
   oprocstream (const char *name, int mode = std::ios::out)
     : std::ostream (nullptr), procstreambase (name, mode) { }
 
-  ~oprocstream (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (oprocstream)
+
+  ~oprocstream () = default;
 
   void open (const std::string& name, int mode = std::ios::out)
   {
@@ -142,12 +138,6 @@
   {
     procstreambase::open (name, mode);
   }
-
-private:
-
-  oprocstream (const oprocstream&);
-
-  oprocstream& operator = (const oprocstream&);
 };
 
 class
@@ -156,7 +146,7 @@
 {
 public:
 
-  procstream (void) : std::iostream (nullptr), procstreambase () { }
+  procstream () : std::iostream (nullptr), procstreambase () { }
 
   procstream (const std::string& name, int mode)
     : std::iostream (nullptr), procstreambase (name, mode)
@@ -166,7 +156,9 @@
     : std::iostream (nullptr), procstreambase (name, mode)
   { }
 
-  ~procstream (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (procstream)
+
+  ~procstream () = default;
 
   void open (const std::string& name, int mode)
   {
@@ -177,30 +169,8 @@
   {
     procstreambase::open (name, mode);
   }
-
-private:
-
-  procstream (const procstream&);
-
-  procstream& operator = (const procstream&);
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::procstreambase' instead")
-typedef octave::procstreambase procstreambase;
-
-OCTAVE_DEPRECATED (7, "use 'octave::iprocstream' instead")
-typedef octave::iprocstream iprocstream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::oprocstream' instead")
-typedef octave::oprocstream oprocstream;
-
-OCTAVE_DEPRECATED (7, "use 'octave::procstream' instead")
-typedef octave::procstream procstream;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/quad.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/quad.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,8 +36,8 @@
 #include "error.h"
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "pager.h"
-#include "parse.h"
 #include "ov.h"
 #include "ovl.h"
 #include "unwind-prot.h"
@@ -71,7 +71,9 @@
 
       try
         {
-          tmp = feval (quad_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (quad_fcn, args, 1);
         }
       catch (execution_exception& ee)
         {
@@ -107,7 +109,9 @@
 
       try
         {
-          tmp = feval (quad_fcn, args, 1);
+          interpreter& interp = __get_interpreter__ ();
+
+          tmp = interp.feval (quad_fcn, args, 1);
         }
       catch (execution_exception& ee)
         {
--- a/libinterp/corefcn/quadcc.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/quadcc.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,8 +37,8 @@
 #include "defun.h"
 #include "error.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "ovl.h"
-#include "parse.h"
 #include "utils.h"
 #include "variables.h"
 
@@ -1715,7 +1715,7 @@
             ex(i) = m + xi[i]*h;
         }
       fargs(0) = ex;
-      fvals = feval (fcn, fargs, 1);
+      fvals = interp.feval (fcn, fargs, 1);
       if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
         error ("quadcc: integrand F must return a single, real-valued vector");
 
@@ -1825,7 +1825,7 @@
                   ex(i) = m + xi[(2*i + 1) * skip[d]] * h;
               }
             fargs(0) = ex;
-            fvals = feval (fcn, fargs, 1);
+            fvals = interp.feval (fcn, fargs, 1);
             if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
               error ("quadcc: integrand F must return a single, real-valued vector");
 
@@ -1958,7 +1958,7 @@
                   ex(i) = ml + xi[(i + 1) * skip[0]] * hl;
               }
             fargs(0) = ex;
-            fvals = feval (fcn, fargs, 1);
+            fvals = interp.feval (fcn, fargs, 1);
             if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
               error ("quadcc: integrand F must return a single, real-valued vector");
 
@@ -2049,7 +2049,7 @@
                   ex(i) = mr + xi[(i + 1) * skip[0]] * hr;
               }
             fargs(0) = ex;
-            fvals = feval (fcn, fargs, 1);
+            fvals = interp.feval (fcn, fargs, 1);
             if (fvals.length () != 1 || ! fvals(0).is_real_matrix ())
               error ("quadcc: integrand F must return a single, real-valued vector");
 
--- a/libinterp/corefcn/qz.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/qz.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -59,15 +59,10 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-// FIXME: Matlab does not produce lambda as the first output argument.
-// Compatibility problem?
-
 DEFUN (qz, args, nargout,
        doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{lambda} =} qz (@var{A}, @var{B})
-@deftypefnx {} {[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}, @var{lambda}] =} qz (@var{A}, @var{B})
-@deftypefnx {} {[@var{AA}, @var{BB}, @var{Z}] =} qz (@var{A}, @var{B}, @var{opt})
-@deftypefnx {} {[@var{AA}, @var{BB}, @var{Z}, @var{lambda}] =} qz (@var{A}, @var{B}, @var{opt})
+@deftypefn {} {[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] =} qz (@var{A}, @var{B})
+@deftypefnx {} {[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}] =} qz (@var{A}, @var{B}, @var{opt})
 Compute the QZ@tie{}decomposition of a generalized eigenvalue problem.
 
 The generalized eigenvalue problem is defined as
@@ -81,27 +76,17 @@
 
 @end ifnottex
 
-There are three calling forms of the function:
+There are two calling forms of the function:
 
 @enumerate
-@item @code{@var{lambda} = qz (@var{A}, @var{B})}
-
-Compute the generalized eigenvalues
-@tex
-$\lambda.$
-@end tex
-@ifnottex
-@var{lambda}.
-@end ifnottex
-
 @item @code{[@var{AA}, @var{BB}, @var{Q}, @var{Z}, @var{V}, @var{W}, @var{lambda}] = qz (@var{A}, @var{B})}
 
-Compute QZ@tie{}decomposition, generalized eigenvectors, and generalized
+Compute the complex QZ@tie{}decomposition, generalized eigenvectors, and generalized
 eigenvalues.
 @tex
 $$ AA = Q^T AZ, BB = Q^T BZ $$
-$$ AV = BV{ \rm diag }(\lambda) $$
-$$ W^T A = { \rm diag }(\lambda)W^T B $$
+$$ { \rm diag }(BB)AV = BV{ \rm diag }(AA) $$
+$$ { \rm diag }(BB) W^T A = { \rm diag }(AA) W^T B $$
 @end tex
 @ifnottex
 
@@ -109,58 +94,32 @@
 @group
 
 @var{AA} = @var{Q} * @var{A} * @var{Z}, @var{BB} = @var{Q} * @var{B} * @var{Z}
-@var{A} * @var{V} = @var{B} * @var{V} * diag (@var{lambda})
-@var{W}' * @var{A} = diag (@var{lambda}) * @var{W}' * @var{B}
+@var{A} * @var{V} * diag (diag (@var{BB})) = @var{B} * @var{V} * diag (diag (@var{AA}))
+diag (diag (@var{BB})) * @var{W}' * @var{A} = diag (diag (@var{AA})) * @var{W}' * @var{B}
 
 @end group
 @end example
 
 @end ifnottex
-with @var{Q} and @var{Z} orthogonal (unitary for complex case).
+with @var{AA} and @var{BB} upper triangular, and @var{Q} and @var{Z}
+unitary. The matrices @var{V} and @var{W} respectively contain the right
+and left generalized eigenvectors.
 
 @item @code{[@var{AA}, @var{BB}, @var{Z} @{, @var{lambda}@}] = qz (@var{A}, @var{B}, @var{opt})}
 
-As in form 2 above, but allows ordering of generalized eigenpairs for, e.g.,
-solution of discrete time algebraic @nospell{Riccati} equations.  Form 3 is not
-available for complex matrices, and does not compute the generalized
-eigenvectors @var{V}, @var{W}, nor the orthogonal matrix @var{Q}.
-
-@table @var
-@item opt
-for ordering eigenvalues of the @nospell{GEP} pencil.  The leading block of
-the revised pencil contains all eigenvalues that satisfy:
-
-@table @asis
-@item @qcode{"N"}
-unordered (default)
+The @var{opt} argument must be equal to either @qcode{"real"} or
+@qcode{"complex"}. If it is equal to @qcode{"complex"}, then this
+calling form is equivalent to the first one with only two input
+arguments.
 
-@item @qcode{"S"}
-small: leading block has all
-@tex
-$|\lambda| < 1$
-@end tex
-@ifnottex
-|@var{lambda}| < 1
-@end ifnottex
+If @var{opt} is equal to @qcode{"real"}, then the real QZ decomposition
+is computed. In particular, @var{AA} is only guaranteed to be
+quasi-upper triangular with 1-by-1 and 2-by-2 blocks on the diagonal,
+and @var{Q} and @var{Z} are orthogonal. The identities mentioned above
+for right and left generalized eigenvectors are only verified if
+@var{AA} is upper triangular (i.e., when all the generalized eigenvalues
+are real, in which case the real and complex QZ coincide).
 
-@item @qcode{"B"}
-big: leading block has all
-@tex
-$|\lambda| \geq 1$
-@end tex
-@ifnottex
-|@var{lambda}| @geq{} 1
-@end ifnottex
-
-@item @qcode{"-"}
-negative real part: leading block has all eigenvalues in the open left
-half-plane
-
-@item @qcode{"+"}
-non-negative real part: leading block has all eigenvalues in the closed right
-half-plane
-@end table
-@end table
 @end enumerate
 
 Note: @code{qz} performs permutation balancing, but not scaling
@@ -177,65 +136,29 @@
                 << ", nargout = " << nargout << std::endl;
 #endif
 
-  if (nargin < 2 || nargin > 3 || nargout > 7)
+  if (nargin < 2 || nargin > 3 || nargout > 6)
     print_usage ();
 
-  if (nargin == 3 && (nargout < 3 || nargout > 4))
-    error ("qz: invalid number of output arguments for form 3 call");
-
-#if defined (DEBUG)
-  octave_stdout << "qz: determine ordering option" << std::endl;
-#endif
-
-  // Determine ordering option.
-
-  char ord_job = 'N';
-  double safmin = 0.0;
+  bool complex_case = true;
 
   if (nargin == 3)
     {
       std::string opt = args(2).xstring_value ("qz: OPT must be a string");
 
-      if (opt.empty ())
-        error ("qz: OPT must be a non-empty string");
-
-      ord_job = std::toupper (opt[0]);
-
-      std::string valid_opts = "NSB+-";
-
-      if (valid_opts.find_first_of (ord_job) == std::string::npos)
-        error ("qz: invalid order option '%c'", ord_job);
-
-      // overflow constant required by dlag2
-      F77_FUNC (xdlamch, XDLAMCH) (F77_CONST_CHAR_ARG2 ("S", 1),
-                                   safmin
-                                   F77_CHAR_ARG_LEN (1));
-
-#if defined (DEBUG_EIG)
-      octave_stdout << "qz: initial value of safmin="
-                    << setiosflags (std::ios::scientific)
-                    << safmin << std::endl;
-#endif
-
-      // Some machines (e.g., DEC alpha) get safmin = 0;
-      // for these, use eps instead to avoid problems in dlag2.
-      if (safmin == 0)
+      if (opt == "real")
         {
-#if defined (DEBUG_EIG)
-          octave_stdout << "qz: DANGER WILL ROBINSON: safmin is 0!"
-                        << std::endl;
-#endif
-
-          F77_FUNC (xdlamch, XDLAMCH) (F77_CONST_CHAR_ARG2 ("E", 1),
-                                       safmin
-                                       F77_CHAR_ARG_LEN (1));
-
-#if defined (DEBUG_EIG)
-          octave_stdout << "qz: safmin set to "
-                        << setiosflags (std::ios::scientific)
-                        << safmin << std::endl;
-#endif
+          if (args(0).iscomplex () || args(1).iscomplex ())
+            {
+              warning ("qz: ignoring 'real' option with complex matrices");
+              complex_case = true;
+            }
+          else
+            complex_case = false;
         }
+      else if (opt == "complex")
+        complex_case = true;
+      else
+        error ("qz: OPT must be 'real' or 'complex'");
     }
 
 #if defined (DEBUG)
@@ -251,12 +174,7 @@
                 << std::endl;
 #endif
 
-  if (args(0).isempty ())
-    {
-      warn_empty_arg ("qz: A");
-      return octave_value_list (2, Matrix ());
-    }
-  else if (nc != nn)
+  if (nc != nn)
     err_square_matrix_required ("qz", "A");
 
   // Matrix A: get value.
@@ -287,13 +205,6 @@
   else
     bb = args(1).matrix_value ();
 
-  // Both matrices loaded, now check whether to calculate complex or real val.
-
-  bool complex_case = (args(0).iscomplex () || args(1).iscomplex ());
-
-  if (nargin == 3 && complex_case)
-    error ("qz: cannot re-order complex qz decomposition");
-
   // First, declare variables used in both the real and complex cases.
   // FIXME: There are a lot of excess variables declared.
   //        Probably a better way to handle this.
@@ -303,7 +214,7 @@
   ComplexMatrix CQ (nn, nn), CZ (nn, nn), CVR (nn, nn), CVL (nn, nn);
   F77_INT ilo, ihi, info;
   char comp_q = (nargout >= 3 ? 'V' : 'N');
-  char comp_z = ((nargout >= 4 || nargin == 3)? 'V' : 'N');
+  char comp_z = (nargout >= 4 ? 'V' : 'N');
 
   // Initialize Q, Z to identity matrix if either is needed
   if (comp_q == 'V' || comp_z == 'V')
@@ -366,44 +277,6 @@
 
   // Only permutation balance above is done.  Skip scaling balance.
 
-#if 0
-  // Since we just want the balancing matrices, we can use dggbal
-  // for both the real and complex cases; left first
-
-  if (comp_q == 'V')
-    {
-      F77_XFCN (dggbak, DGGBAK,
-                (F77_CONST_CHAR_ARG2 (&bal_job, 1),
-                 F77_CONST_CHAR_ARG2 ("L", 1),
-                 nn, ilo, ihi, lscale.data (), rscale.data (),
-                 nn, QQ.fortran_vec (), nn, info
-                 F77_CHAR_ARG_LEN (1)
-                 F77_CHAR_ARG_LEN (1)));
-
-#if defined (DEBUG)
-      if (comp_q == 'V')
-        octave_stdout << "qz: balancing done; QQ =\n" << QQ << std::endl;
-#endif
-    }
-
-  // then right
-  if (comp_z == 'V')
-    {
-      F77_XFCN (dggbak, DGGBAK,
-                (F77_CONST_CHAR_ARG2 (&bal_job, 1),
-                 F77_CONST_CHAR_ARG2 ("R", 1),
-                 nn, ilo, ihi, lscale.data (), rscale.data (),
-                 nn, ZZ.fortran_vec (), nn, info
-                 F77_CHAR_ARG_LEN (1)
-                 F77_CHAR_ARG_LEN (1)));
-
-#if defined (DEBUG)
-      if (comp_z == 'V')
-        octave_stdout << "qz: balancing done; ZZ=\n" << ZZ << std::endl;
-#endif
-    }
-#endif
-
   char qz_job = (nargout < 2 ? 'E' : 'S');
 
   if (complex_case)
@@ -575,127 +448,6 @@
 
     }
 
-  // Order the QZ decomposition?
-  if (ord_job != 'N')
-    {
-      if (complex_case)
-        // Probably not needed, but better be safe.
-        error ("qz: cannot re-order complex QZ decomposition");
-
-#if defined (DEBUG_SORT)
-      octave_stdout << "qz: ordering eigenvalues: ord_job = "
-                    << ord_job << std::endl;
-#endif
-
-      Array<F77_LOGICAL> select (dim_vector (nn, 1));
-
-      for (int j = 0; j < nn; j++)
-        {
-          switch (ord_job)
-            {
-            case 'S':
-              select(j) = alphar(j)*alphar(j) + alphai(j)*alphai(j) < betar(j)*betar(j);
-              break;
-
-            case 'B':
-              select(j) = alphar(j)*alphar(j) + alphai(j)*alphai(j) >= betar(j)*betar(j);
-              break;
-
-            case '+':
-              select(j) = alphar(j) * betar(j) >= 0;
-              break;
-
-            case '-':
-              select(j) = alphar(j) * betar(j) < 0;
-              break;
-
-            default:
-              // Invalid order option
-              // (should never happen since options were checked at the top).
-              panic_impossible ();
-              break;
-            }
-        }
-
-      F77_LOGICAL wantq = 0, wantz = (comp_z == 'V');
-      F77_INT ijob = 0, mm, lrwork3 = 4*nn+16, liwork = nn;
-      F77_DBLE pl, pr;
-      RowVector rwork3(lrwork3);
-      Array<F77_INT> iwork (dim_vector (liwork, 1));
-
-      F77_XFCN (dtgsen, DTGSEN,
-                (ijob, wantq, wantz,
-                 select.fortran_vec (), nn,
-                 aa.fortran_vec (), nn,
-                 bb.fortran_vec (), nn,
-                 alphar.fortran_vec (),
-                 alphai.fortran_vec (),
-                 betar.fortran_vec (),
-                 nullptr, nn,
-                 ZZ.fortran_vec (), nn,
-                 mm,
-                 pl, pr,
-                 nullptr,
-                 rwork3.fortran_vec (), lrwork3,
-                 iwork.fortran_vec (), liwork,
-                 info));
-
-#if defined (DEBUG_SORT)
-      octave_stdout << "qz: back from dtgsen: aa =\n";
-      octave_print_internal (octave_stdout, aa);
-      octave_stdout << "\nbb =\n";
-      octave_print_internal (octave_stdout, bb);
-      if (comp_z == 'V')
-        {
-          octave_stdout << "\nZZ =\n";
-          octave_print_internal (octave_stdout, ZZ);
-        }
-      octave_stdout << "\nqz: info=" << info;
-      octave_stdout << "\nalphar =\n";
-      octave_print_internal (octave_stdout, Matrix (alphar));
-      octave_stdout << "\nalphai =\n";
-      octave_print_internal (octave_stdout, Matrix (alphai));
-      octave_stdout << "\nbeta =\n";
-      octave_print_internal (octave_stdout, Matrix (betar));
-      octave_stdout << std::endl;
-#endif
-    }
-
-  // Compute the generalized eigenvalues as well?
-  ComplexColumnVector gev;
-
-  if (nargout < 2 || nargout == 7 || (nargin == 3 && nargout == 4))
-    {
-      if (complex_case)
-        {
-          ComplexColumnVector tmp (nn);
-
-          for (F77_INT i = 0; i < nn; i++)
-            tmp(i) = xalpha(i) / xbeta(i);
-
-          gev = tmp;
-        }
-      else
-        {
-#if defined (DEBUG)
-          octave_stdout << "qz: computing generalized eigenvalues" << std::endl;
-#endif
-
-          // Return finite generalized eigenvalues.
-          ComplexColumnVector tmp (nn);
-
-          for (F77_INT i = 0; i < nn; i++)
-            {
-              if (betar(i) != 0)
-                tmp(i) = Complex (alphar(i), alphai(i)) / betar(i);
-              else
-                tmp(i) = numeric_limits<double>::Inf ();
-            }
-
-          gev = tmp;
-        }
-    }
-
   // Right, left eigenvector matrices.
   if (nargout >= 5)
     {
@@ -744,56 +496,6 @@
                      m, work.fortran_vec (), info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
-
-          // Now construct the complex form of VV, WW.
-          F77_INT j = 0;
-
-          while (j < nn)
-            {
-              octave_quit ();
-
-              // See if real or complex eigenvalue.
-
-              // Column increment; assume complex eigenvalue.
-              int cinc = 2;
-
-              if (j == (nn-1))
-                // Single column.
-                cinc = 1;
-              else if (aa(j+1, j) == 0)
-                cinc = 1;
-
-              // Now copy the eigenvector (s) to CVR, CVL.
-              if (cinc == 1)
-                {
-                  for (F77_INT i = 0; i < nn; i++)
-                    CVR(i, j) = VR(i, j);
-
-                  if (side == 'B')
-                    for (F77_INT i = 0; i < nn; i++)
-                      CVL(i, j) = VL(i, j);
-                }
-              else
-                {
-                  // Double column; complex vector.
-
-                  for (F77_INT i = 0; i < nn; i++)
-                    {
-                      CVR(i, j) = Complex (VR(i, j), VR(i, j+1));
-                      CVR(i, j+1) = Complex (VR(i, j), -VR(i, j+1));
-                    }
-
-                  if (side == 'B')
-                    for (F77_INT i = 0; i < nn; i++)
-                      {
-                        CVL(i, j) = Complex (VL(i, j), VL(i, j+1));
-                        CVL(i, j+1) = Complex (VL(i, j), -VL(i, j+1));
-                      }
-                }
-
-              // Advance to next eigenvectors (if any).
-              j += cinc;
-            }
         }
     }
 
@@ -801,57 +503,39 @@
 
   switch (nargout)
     {
-    case 7:
-      retval(6) = gev;
-      OCTAVE_FALLTHROUGH;
-
     case 6:
       // Return left eigenvectors.
-      retval(5) = CVL;
+      if (complex_case)
+        retval(5) = CVL;
+      else
+        retval(5) = VL;
       OCTAVE_FALLTHROUGH;
 
     case 5:
       // Return right eigenvectors.
-      retval(4) = CVR;
+      if (complex_case)
+        retval(4) = CVR;
+      else
+        retval(4) = VR;
       OCTAVE_FALLTHROUGH;
 
     case 4:
-      if (nargin == 3)
-        {
-#if defined (DEBUG)
-          octave_stdout << "qz: sort: retval(3) = gev =\n";
-          octave_print_internal (octave_stdout, ComplexMatrix (gev));
-          octave_stdout << std::endl;
-#endif
-          retval(3) = gev;
-        }
+      if (complex_case)
+        retval(3) = CZ;
       else
-        {
-          if (complex_case)
-            retval(3) = CZ;
-          else
-            retval(3) = ZZ;
-        }
+        retval(3) = ZZ;
       OCTAVE_FALLTHROUGH;
 
     case 3:
-      if (nargin == 3)
-        {
-          if (complex_case)
-            retval(2) = CZ;
-          else
-            retval(2) = ZZ;
-        }
+      if (complex_case)
+        retval(2) = CQ.hermitian ();
       else
-        {
-          if (complex_case)
-            retval(2) = CQ.hermitian ();
-          else
-            retval(2) = QQ.transpose ();
-        }
+        retval(2) = QQ.transpose ();
       OCTAVE_FALLTHROUGH;
 
     case 2:
+    case 1:
+    case 0:
       {
         if (complex_case)
           {
@@ -880,17 +564,23 @@
       }
       break;
 
-    case 1:
-    case 0:
-#if defined (DEBUG)
-      octave_stdout << "qz: retval(0) = gev = " << gev << std::endl;
-#endif
-      retval(0) = gev;
-      break;
+    }
 
-    default:
-      error ("qz: too many return arguments");
-      break;
+  // FIXME: The API for qz changed in version 9.
+  // These warnings can be removed in Octave version 11.
+  if (nargout == 1)
+    {
+      warning_with_id ("Octave:qz:single-arg-out",
+                       "qz: requesting a single output argument no longer returns eigenvalues since version 9");
+      disable_warning ("Octave:qz:single-arg-out");
+    }
+
+  if (nargin == 2 && args(0).isreal () && args(1).isreal ()
+      && retval(0).iscomplex ())
+    {
+      warning_with_id ("Octave:qz:complex-default",
+                       "qz: returns the complex QZ by default on real matrices since version 9");
+      disable_warning ("Octave:qz:complex-default");
     }
 
 #if defined (DEBUG)
@@ -901,35 +591,26 @@
 }
 
 /*
-%!test
-%! A = [1 2; 0 3];
-%! B = [1 0; 0 0];
-%! C = [0 1; 0 0];
-%! assert (qz (A,B), [1; Inf]);
-%! assert (qz (A,C), [Inf; Inf]);
-
-## Example 7.7.3 in Golub & Van Loan
+## Example 7.7.3 in Golub & Van Loan (3rd ed.; not present in 4th ed.)
+## The generalized eigenvalues are real, so the real and complex QZ coincide.
 %!test
 %! a = [ 10  1  2;
 %!        1  2 -1;
 %!        1  1  2 ];
 %! b = reshape (1:9, 3,3);
-%! [aa, bb, q, z, v, w, lambda] = qz (a, b);
+%! [aa, bb, q, z, v, w] = qz (a, b);
+%! assert (isreal (aa) && isreal (bb) && isreal (q) && isreal (z) ...
+%!         && isreal (v) && isreal (w));
+%! assert (istriu (aa) && istriu (bb));
+%! assert (q * q', eye(3), 1e-15);
+%! assert (z * z', eye(3), 1e-15);
 %! assert (q * a * z, aa, norm (aa) * 1e-14);
 %! assert (q * b * z, bb, norm (bb) * 1e-14);
-%! is_finite = abs (lambda) < 1 / eps (max (a(:)));
-%! observed = (b * v * diag (lambda))(:,is_finite);
-%! assert (observed, (a*v)(:,is_finite), norm (observed) * 1e-14);
-%! observed = (diag (lambda) * w' * b)(is_finite,:);
-%! assert (observed, (w'*a)(is_finite,:), norm (observed) * 1e-13);
+%! assert (a * v * diag (diag (bb)), b * v * diag (diag (aa)), 1e-13);
+%! assert (diag (diag (bb)) * w' * a, diag (diag (aa)) * w' * b, 1e-13);
 
-%!test
-%! A = [0, 0, -1, 0; 1, 0, 0, 0; -1, 0, -2, -1; 0, -1, 1, 0];
-%! B = [0, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1];
-%! [AA, BB, Q, Z1] = qz (A, B);
-%! [AA, BB, Z2] = qz (A, B, "-");
-%! assert (Z1, Z2);
-
+## An example with real matrices where some generalized eigenvalues are
+## complex, so the real and complex QZ differ.
 %!test
 %! A = [ -1.03428  0.24929  0.43205 -0.12860;
 %!        1.16228  0.27870  2.12954  0.69250;
@@ -939,18 +620,35 @@
 %!        0.149898  0.298248  0.991777  0.023652;
 %!        0.169281 -0.405205 -1.775834  1.511730;
 %!        0.717770  1.291390 -1.766607 -0.531352 ];
-%! [AA, BB, Z, lambda] = qz (A, B, "+");
-%! assert (all (real (lambda(1:3)) >= 0));
-%! assert (real (lambda(4) < 0));
-%! [AA, BB, Z, lambda] = qz (A, B, "-");
-%! assert (real (lambda(1) < 0));
-%! assert (all (real (lambda(2:4)) >= 0));
-%! [AA, BB, Z, lambda] = qz (A, B, "B");
-%! assert (all (abs (lambda(1:3)) >= 1));
-%! assert (abs (lambda(4) < 1));
-%! [AA, BB, Z, lambda] = qz (A, B, "S");
-%! assert (abs (lambda(1) < 1));
-%! assert (all (abs (lambda(2:4)) >= 1));
+%! [CAA, CBB, CQ, CZ, CV, CW] = qz (A, B, 'complex');
+%! assert (iscomplex (CAA) && iscomplex (CBB) && iscomplex (CQ) ...
+%!         && iscomplex (CZ) && iscomplex (CV) && iscomplex (CW));
+%! assert (istriu (CAA) && istriu (CBB));
+%! assert (CQ * CQ', eye(4), 1e-14);
+%! assert (CZ * CZ', eye(4), 1e-14);
+%! assert (CQ * A * CZ, CAA, norm (CAA) * 1e-14);
+%! assert (CQ * B * CZ, CBB, norm (CBB) * 1e-14);
+%! assert (A * CV * diag (diag (CBB)), B * CV * diag (diag (CAA)), 1e-13);
+%! assert (diag (diag (CBB)) * CW' * A, diag (diag (CAA)) * CW' * B, 1e-13);
+%! [AA, BB, Q, Z, V, W] = qz (A, B, 'real');
+%! assert (isreal (AA) && isreal (BB) && isreal (Q) && isreal (Z) ...
+%!         && isreal (V) && isreal (W));
+%! assert (istriu (BB));
+%! assert (Q * Q', eye(4), 1e-14);
+%! assert (Z * Z', eye(4), 1e-14);
+%! assert (Q * A * Z, AA, norm (AA) * 1e-14);
+%! assert (Q * B * Z, BB, norm (BB) * 1e-14);
+
+## Test input validation
+%!error <Invalid call> qz ()
+%!error <Invalid call> qz (1)
+%!error <Invalid call> qz (1,2,3,4)
+%!error <Invalid call> [r1,r2,r3,r4,r5,r6,r7] = qz (1,2)
+%!error <OPT must be a string> qz (1,2, 3)
+%!error <OPT must be 'real' or 'complex'> qz (1,2, 'foobar')
+%!warning <ignoring 'real' option with complex matrices> qz (2i, 3, 'real');
+%!warning <ignoring 'real' option with complex matrices> qz (2, 3i, 'real');
+
 */
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/rand.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/rand.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -538,7 +538,7 @@
 */
 
 /*
-## Check that negative dimensions are treated as zero for Matlab compatibility
+## Note: Matlab compatibility requires using 0 for negative dimensions.
 %!assert (size (rand (1, -1, 2)), [1, 0, 2])
 
 ## Test input validation
--- a/libinterp/corefcn/settings.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/settings.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-settings::settings (void)
+settings::settings ()
   : m_display_tokens (false), m_token_count (0),
     m_lexer_debug_flag (false)
 { }
--- a/libinterp/corefcn/settings.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/settings.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,17 +45,15 @@
 {
 public:
 
-  settings (void);
-
-  settings (const settings&) = delete;
+  settings ();
 
-  settings& operator = (const settings&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (settings)
 
-  ~settings (void) = default;
+  ~settings () = default;
 
   octave_value display_tokens (const octave_value_list& args, int nargout);
 
-  bool display_tokens (void) const { return m_display_tokens; }
+  bool display_tokens () const { return m_display_tokens; }
 
   bool display_tokens (bool flag)
   {
@@ -65,13 +63,13 @@
   }
 
   // Read only.
-  std::size_t token_count (void) const { return m_token_count; }
+  std::size_t token_count () const { return m_token_count; }
 
-  void increment_token_count (void) { ++m_token_count; }
+  void increment_token_count () { ++m_token_count; }
 
   octave_value lexer_debug_flag (const octave_value_list& args, int nargout);
 
-  bool lexer_debug_flag (void) const { return m_lexer_debug_flag; }
+  bool lexer_debug_flag () const { return m_lexer_debug_flag; }
 
   bool lexer_debug_flag (bool flag)
   {
--- a/libinterp/corefcn/sighandlers.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sighandlers.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include <atomic>
 #include <csignal>
 #include <cstdlib>
 
@@ -65,7 +66,7 @@
 int pipe_handler_error_count = 0;
 
 // TRUE means we can be interrupted.
-bool can_interrupt = false;
+std::atomic<bool> can_interrupt{false};
 
 // TRUE means we should try to enter the debugger on SIGINT.
 bool Vdebug_on_interrupt = false;
@@ -82,7 +83,7 @@
 static bool Vsigterm_dumps_octave_core = true;
 
 // List of signals we have caught since last call to signal_handler.
-static bool *signals_caught = nullptr;
+static std::atomic<bool> *signals_caught = nullptr;
 
 static void
 my_friendly_exit (int sig, bool save_vars = true)
@@ -107,7 +108,7 @@
 // we have caught.
 
 void
-respond_to_pending_signals (void)
+respond_to_pending_signals ()
 {
   // The list of signals is relatively short, so we will just go
   // linearly through the list.
@@ -194,10 +195,10 @@
 
   for (int sig = 0; sig < octave_num_signals (); sig++)
     {
-      if (signals_caught[sig])
+      bool expected = true;
+
+      if (signals_caught[sig].compare_exchange_strong (expected, false))
         {
-          signals_caught[sig] = false;
-
           if ((have_sigchld && sig == sigchld)
               || (have_sigcld && sig == sigcld))
             {
@@ -276,7 +277,7 @@
   // signal watcher thread so it should probably be more careful about
   // how it accesses global objects.
 
-  octave_signal_caught = 1;
+  octave_signal_caught = true;
 
   signals_caught[sig] = true;
 
@@ -296,7 +297,7 @@
 
       if (can_interrupt)
         {
-          octave_signal_caught = 1;
+          octave_signal_caught = true;
           octave_interrupt_state++;
         }
     }
@@ -323,7 +324,7 @@
 }
 
 interrupt_handler
-catch_interrupts (void)
+catch_interrupts ()
 {
   interrupt_handler retval;
 
@@ -334,7 +335,7 @@
 }
 
 interrupt_handler
-ignore_interrupts (void)
+ignore_interrupts ()
 {
   interrupt_handler retval;
 
@@ -362,10 +363,10 @@
 // Install all the handlers for the signals we might care about.
 
 void
-install_signal_handlers (void)
+install_signal_handlers ()
 {
   if (! signals_caught)
-    signals_caught = new bool [octave_num_signals ()];
+    signals_caught = new std::atomic<bool> [octave_num_signals ()];
 
   for (int i = 0; i < octave_num_signals (); i++)
     signals_caught[i] = false;
@@ -445,7 +446,7 @@
 }
 
 static octave_scalar_map
-make_sig_struct (void)
+make_sig_struct ()
 {
   octave_scalar_map m;
 
--- a/libinterp/corefcn/sighandlers.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sighandlers.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,6 +36,8 @@
 #if ! defined (octave_sighandlers_h)
 #define octave_sighandlers_h 1
 
+#include <atomic>
+
 #include "octave-config.h"
 
 #include "child-list.h"
@@ -56,7 +58,7 @@
 extern int pipe_handler_error_count;
 
 // TRUE means we can be interrupted.
-extern OCTINTERP_API bool can_interrupt;
+extern OCTINTERP_API std::atomic<bool> can_interrupt;
 
 extern OCTINTERP_API sig_handler *
 set_signal_handler (int sig, sig_handler *h,
@@ -66,13 +68,13 @@
 set_signal_handler (const char *signame, sig_handler *h,
                     bool restart_syscalls = true);
 
-extern OCTINTERP_API void install_signal_handlers (void);
+extern OCTINTERP_API void install_signal_handlers ();
 
-extern OCTINTERP_API void respond_to_pending_signals (void);
+extern OCTINTERP_API void respond_to_pending_signals ();
 
-extern OCTINTERP_API interrupt_handler catch_interrupts (void);
+extern OCTINTERP_API interrupt_handler catch_interrupts ();
 
-extern OCTINTERP_API interrupt_handler ignore_interrupts (void);
+extern OCTINTERP_API interrupt_handler ignore_interrupts ();
 
 extern OCTINTERP_API interrupt_handler
 set_interrupt_handler (const volatile interrupt_handler& h,
--- a/libinterp/corefcn/sparse-xdiv.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sparse-xdiv.h	Fri Jun 23 20:51:51 2023 +0200
@@ -104,207 +104,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline Matrix
-xdiv (const Matrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseMatrix
-xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
-      MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseMatrix
-xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline Matrix
-x_el_div (double a, const SparseMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (double a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (const Complex& a, const SparseMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (const Complex& a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline Matrix
-xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseMatrix
-xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
-          MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseMatrix
-xleftdiv (const DiagMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const ComplexDiagMatrix& a, const SparseMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const DiagMatrix& a, const SparseComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline SparseComplexMatrix
-xleftdiv (const ComplexDiagMatrix& a, const SparseComplexMatrix& b,
-          MatrixType& typ)
-{
-  return octave::xleftdiv (a, b, typ);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/sparse-xpow.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sparse-xpow.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,106 +62,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const SparseMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const SparseComplexMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const SparseMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseMatrix& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseMatrix& a, const SparseMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseMatrix& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const SparseMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseComplexMatrix& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseComplexMatrix& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,9 @@
 %!assert (issparse (1), false)
 %!assert (issparse (sparse (false)), true)
 %!assert (issparse (true), false)
-%!assert (issparse (sparse (single ([1 2]))), true)
+%!test
+%! warning ("off", "Octave:sparse:double-conversion", "local");
+%! assert (issparse (sparse (single ([1 2]))), true);
 %!assert (issparse (single ([1, 2])), false)
 %!assert (issparse (sparse ([1+i, 2]')), true)
 %!assert (issparse ([1+i, 2]'), false)
@@ -81,10 +83,10 @@
 DEFUN (sparse, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{S} =} sparse (@var{A})
-@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n})
+@deftypefnx {} {@var{S} =} sparse (@var{m}, @var{n})
 @deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv})
-@deftypefnx {} {@var{S} =} sparse (@var{m}, @var{n})
-@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{s}, @var{m}, @var{n}, "unique")
+@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n})
+@deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, "unique")
 @deftypefnx {} {@var{S} =} sparse (@var{i}, @var{j}, @var{sv}, @var{m}, @var{n}, @var{nzmax})
 Create a sparse matrix from a full matrix @var{A} or row, column, value
 triplets.
@@ -93,6 +95,9 @@
 removing all zero values in the process.  The matrix @var{A} should be of type
 logical or double.
 
+If two inputs @var{m} (rows) and @var{n} (columns) are specified then create
+an empty sparse matrix with the specified dimensions.
+
 Given the integer index vectors @var{i} and @var{j}, and a 1-by-@code{nnz}
 vector of real or complex values @var{sv}, construct the sparse matrix
 @code{S(@var{i}(@var{k}),@var{j}(@var{k})) = @var{sv}(@var{k})} with overall
@@ -111,7 +116,8 @@
 
 If the option @qcode{"unique"} is given, and more than one value is specified
 at the same @var{i}, @var{j} indices, then only the last specified value will
-be used.
+be used.  For completeness, the option @qcode{"sum"} can be given and will
+be ignored as the default behavior is to sum values at repeated locations.
 
 @code{sparse (@var{m}, @var{n})} will create an empty @var{m}x@var{n} sparse
 matrix and is equivalent to @code{sparse ([], [], [], @var{m}, @var{n})}
@@ -176,24 +182,28 @@
   if (nargin == 1)
     {
       octave_value arg = args(0);
-      if (arg.islogical ())
+      if (arg.isfloat ())
+        {
+          if (arg.is_single_type ())
+            warning_with_id ("Octave:sparse:double-conversion",
+                             "sparse: input array cast to double");
+          if (arg.iscomplex ())
+            retval = arg.sparse_complex_matrix_value ();
+          else
+            retval = arg.sparse_matrix_value ();
+        }
+      else if (arg.islogical ())
         retval = arg.sparse_bool_matrix_value ();
-      else if (arg.iscomplex ())
-        retval = arg.sparse_complex_matrix_value ();
-      else if (arg.isnumeric ())
-        retval = arg.sparse_matrix_value ();
       else
         err_wrong_type_arg ("sparse", arg);
     }
   else if (nargin == 2)
     {
-      octave_idx_type m = 0;
-      octave_idx_type n = 0;
-
-      get_dimensions (args(0), args(1), "sparse", m, n);
+      octave_idx_type m = args(0).xidx_type_value ("sparse: M must be a non-negative integer");
+      octave_idx_type n = args(1).xidx_type_value ("sparse: N must be a non-negative integer");
 
       if (m < 0 || n < 0)
-        error ("sparse: dimensions must be non-negative");
+        error ("sparse: dimensions M and N must be non-negative");
 
       retval = SparseMatrix (m, n);
     }
@@ -223,35 +233,43 @@
 
       if (nargin == 5)
         {
-          get_dimensions (args(3), args(4), "sparse", m, n);
+          m = args(3).xidx_type_value ("sparse: M must be a non-negative integer");
+          n = args(4).xidx_type_value ("sparse: N must be a non-negative integer");
 
           if (m < 0 || n < 0)
-            error ("sparse: dimensions must be non-negative");
+            error ("sparse: dimensions M and N must be non-negative");
         }
 
-      int k = 0;    // index we're checking when index_vector throws
+      int argidx = 0;    // index being checked when index_vector throws
       try
         {
           idx_vector i = args(0).index_vector ();
-          k = 1;
+          argidx = 1;
           idx_vector j = args(1).index_vector ();
 
-          if (args(2).islogical ())
-            retval = SparseBoolMatrix (args(2).bool_array_value (), i, j,
-                                       m, n, summation, nzmax);
-          else if (args(2).iscomplex ())
-            retval = SparseComplexMatrix (args(2).complex_array_value(),
-                                          i, j, m, n, summation, nzmax);
-          else if (args(2).isnumeric ())
-            retval = SparseMatrix (args(2).array_value (), i, j,
-                                   m, n, summation, nzmax);
+          octave_value arg = args(2);  // temp var for code readability
+          if (arg.isfloat ())
+            {
+              if (arg.is_single_type ())
+                warning_with_id ("Octave:sparse:double-conversion",
+                                 "sparse: input array cast to double");
+              if (arg.iscomplex ())
+                retval = SparseComplexMatrix (arg.complex_array_value (),
+                                              i, j, m, n, summation, nzmax);
+              else
+                retval = SparseMatrix (arg.array_value (),
+                                       i, j, m, n, summation, nzmax);
+            }
+          else if (arg.islogical ())
+            retval = SparseBoolMatrix (arg.bool_array_value (),
+                                       i, j, m, n, summation, nzmax);
           else
-            err_wrong_type_arg ("sparse", args(2));
+            err_wrong_type_arg ("sparse", arg);
         }
       catch (index_exception& ie)
         {
           // Rethrow to allow more info to be reported later.
-          ie.set_pos_if_unset (2, k+1);
+          ie.set_pos_if_unset (2, argidx+1);
           throw;
         }
     }
--- a/libinterp/corefcn/stack-frame.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/stack-frame.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include "lo-regexp.h"
 #include "str-vec.h"
 
@@ -47,14 +49,893 @@
 #include "symrec.h"
 #include "symscope.h"
 #include "variables.h"
+#include <array>
+#include "ov-ref.h"
+
+#include "pt-bytecode-vm.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+
+// bytecode_fcn_stack_frame is for the VM.
+//
+// The VM stack does not directly translate to the tree walker's stack,
+// so there is a translation table to make accessing the VM stack opaque
+// for non-VM use.
+//
+// The octave_values are not acctually stored in the bytecode_fcn_stack_frame
+// object, but on the VM stack. Extra values created by eg. 'eval ("e = 3;")'
+// are stored in this frame object though.
+class bytecode_fcn_stack_frame : public stack_frame
+{
+public:
+
+  enum class bytecode_offsets
+  {
+    DATA_NLOCALS = 2,
+  };
+
+  bytecode_fcn_stack_frame (void) = delete;
+
+  bytecode_fcn_stack_frame (tree_evaluator& tw,
+                            octave_user_function *fcn,
+                            std::size_t index,
+                            const std::shared_ptr<stack_frame>& parent_link,
+                            const std::shared_ptr<stack_frame>& static_link,
+                            vm &vm,
+                            int nargout, int nargin)
+    : stack_frame (tw, index, parent_link, static_link,
+                   nullptr),
+      m_fcn (fcn),
+      m_unwind_data (vm.m_unwind_data),
+      m_name_data (vm.m_name_data),
+      m_stack_start (vm.m_sp),
+      m_code (vm.m_code),
+      m_size (m_unwind_data->m_ids_size),
+      // The above fields in vm change during execution so we need to store them in the frame
+      m_vm (&vm),
+      m_nargin (nargin),
+      m_nargout (nargout)
+  {
+    // If the function scope has more variables now due to something adding e.g.
+    // a global too it after the compilation of the function was done we need
+    // to resize the bytecode frame size.
+    std::size_t n_syms =  fcn->scope_num_symbols ();
+
+    m_orig_size = m_unwind_data->m_external_frame_offset_to_internal.size ();
+
+    if (n_syms > m_orig_size)
+      {
+        int n_to_add = m_orig_size - n_syms;
+        internal_resize (m_size + n_to_add);
+      }
+  }
+
+  bytecode_fcn_stack_frame (const bytecode_fcn_stack_frame& elt)
+    : stack_frame(elt.m_evaluator, elt.m_index, elt.m_parent_link,
+                  elt.m_static_link, elt.m_access_link)
+  {
+    // A copy of a bytecode frame has no pointers to the actual VM stack or VM itself.
+    m_nargin = elt.m_nargin;
+    m_nargout = elt.m_nargout;
+    m_name_data = elt.m_name_data;
+    m_size = elt.m_size;
+    m_orig_size = elt.m_orig_size;
+    m_ip = elt.m_ip;
+    m_unwind_data = elt.m_unwind_data; // TODO: Ownership?
+    m_size = m_unwind_data->m_ids_size;
+
+    if (elt.m_lazy_data)
+      {
+        auto &lazy = lazy_data ();
+
+        lazy.m_extra_slots = elt.m_lazy_data->m_extra_slots;
+        lazy.m_extra_flags = elt.m_lazy_data->m_extra_flags;
+        lazy.m_extra_names = elt.m_lazy_data->m_extra_names;
+      }
+  }
+
+  bytecode_fcn_stack_frame&
+  operator = (const bytecode_fcn_stack_frame& elt) = delete;
+
+  bytecode_fcn_stack_frame&
+  operator = (bytecode_fcn_stack_frame&& elt)
+  {
+    if (m_lazy_data)
+      {
+        if (m_lazy_data->m_stack_cpy)
+          {
+            // Note: int nargout at offset 0
+            for (unsigned i = 1; i < m_size; i++)
+              m_lazy_data->m_stack_cpy[i].ov.~octave_value ();
+            delete m_lazy_data->m_stack_cpy;
+          }
+        delete m_lazy_data->m_unwind_protect_frame;
+        delete m_lazy_data;
+      }
+
+    *this = std::move (elt);
+    elt.m_lazy_data = nullptr;
+
+    return *this;
+  }
+
+  // vm_clear_for_cache () and the dtor need to mirror eachother
+  // so they both call dispose()
+  void dispose ()
+  {
+    if (m_lazy_data)
+      {
+        if (m_lazy_data->m_stack_cpy)
+          {
+            // Note: int nargout at offset 0
+            for (unsigned i = 1; i < m_size; i++)
+              m_lazy_data->m_stack_cpy[i].ov.~octave_value ();
+            delete m_lazy_data->m_stack_cpy;
+          }
+        delete m_lazy_data->m_unwind_protect_frame;
+        delete m_lazy_data;
+        m_lazy_data = nullptr;
+      }
+  }
+
+  ~bytecode_fcn_stack_frame ()
+  {
+    // vm_clear_for_cache () need to mirror the dtor
+    dispose ();
+  }
+
+
+  size_t local_to_external_offset (size_t local_offset) const
+  {
+    for (auto it : m_unwind_data->m_external_frame_offset_to_internal)
+      {
+        size_t local_tmp = it.second;
+        if (local_tmp != local_offset)
+          continue;
+
+        return it.first; // external offset
+      }
+
+    if (local_offset < m_size)
+      error ("VM internal error: Invalid internal offset. Smaller than original size and not in table");
+
+    return local_offset - m_size + m_orig_size;
+  }
+
+  std::size_t external_to_local_offset (std::size_t external_offset) const
+  {
+    auto it = m_unwind_data->m_external_frame_offset_to_internal.find (external_offset);
+    if (it == m_unwind_data->m_external_frame_offset_to_internal.end ())
+    {
+      if (external_offset < m_orig_size)
+        error ("VM internal error: Invalid external offset. Smaller than original size and not in table");
+      // The offsets that are not in the original translation table are in the extra slots added dynamically
+      return m_size + (external_offset - m_orig_size);
+    }
+
+    return it->second;
+  }
+
+  // Do an expensive check if the stack is in order. Call only during debugging.
+  void vm_dbg_check_scope ()
+  {
+    symbol_scope scope = __get_interpreter__().get_current_scope ();
+    auto symbols = scope.symbol_list ();
+
+    for (symbol_record sym_scope : symbols)
+      {
+        if (sym_scope.frame_offset ()) // Don't check nested function stuff becouse it aint working anyways
+          continue;
+
+        std::size_t scope_offset = sym_scope.data_offset ();
+        std::string scope_name = sym_scope.name ();
+
+        std::size_t internal_offset = external_to_local_offset (scope_offset);
+        if (internal_offset >= m_size)
+          continue; // We don't check the "extra" slots since these can change with eval and evalin:s etc
+
+        symbol_record sym_frame = lookup_symbol (scope_name);
+
+        std::size_t frame_offset = sym_frame.data_offset ();
+        std::string frame_name = sym_frame.name ();
+
+        if (scope_name != frame_name && frame_name != "")
+          error ("VM stack check failed: %s != %s\n", scope_name.c_str (), frame_name.c_str ());
+        if (scope_offset != frame_offset && frame_name != "")
+          error ("VM stack check failed: %zu != %zu\n", scope_offset, frame_offset);
+
+        if (internal_offset >= internal_size ())
+          internal_resize (internal_offset + 1);
+
+        auto flag = get_scope_flag (scope_offset);
+        if (flag == PERSISTENT || flag == GLOBAL)
+          continue;
+
+        octave_value ov1 = varval (sym_scope);
+        octave_value ov2 = varval (scope_name);
+        octave_value ov3 = varval (scope_offset);
+        octave_value ov4 = varref (sym_scope);
+        octave_value ov5 = varref (scope_offset);
+
+        if (!ov1.same_rep (ov2))
+          error ("VM stack check failed: Same object differs 2\n");
+        if (!ov1.same_rep (ov3))
+          error ("VM stack check failed: Same object differs 3\n");
+        if (!ov1.same_rep (ov4))
+          error ("VM stack check failed: Same object differs 4\n");
+        if (!ov1.same_rep (ov5))
+          error ("VM stack check failed: Same object differs 5\n");
+      }
+
+  }
+
+  void vm_clear_for_cache ()
+  {
+    m_parent_link = nullptr;
+    m_static_link = nullptr;
+    m_access_link = nullptr;
+    m_dispatch_class.clear ();
+
+    dispose ();
+  }
+
+  // Since a reference to the stackframe can be saved somewhere
+  // we need to check at stack unwind in the VM if that is the case
+  // and save the variables on the VM stack in this frame object so
+  // they can be accessed.
+  void vm_unwinds ()
+  {
+    //vm_dbg_check_scope ();
+    bool is_alone = m_weak_ptr_to_self.use_count () <= 2; // Two seems about right
+
+    if (m_lazy_data)
+      {
+        delete m_lazy_data->m_unwind_protect_frame;
+        m_lazy_data->m_unwind_protect_frame = nullptr;
+
+        // Restore warningstates
+        if (m_fcn)
+          {
+            auto usr_fn_p = m_fcn->user_function_value ();
+            if (usr_fn_p)
+              usr_fn_p->restore_warning_states (); // TODO: octave_user_function::restore_warning_states() could be static.
+          }
+      }
+
+    if (is_alone)
+      {
+        if (m_lazy_data)
+          delete m_lazy_data;
+
+        // Zero these so it is easier to find a "use-after-unwind"
+        // error
+        m_lazy_data = nullptr;
+        m_stack_start = nullptr;
+        m_code = nullptr;
+        m_name_data = nullptr;
+        m_unwind_data = nullptr;
+        m_vm = nullptr;
+
+        return;
+      }
+
+    // These pointers might become invalid
+    m_vm = nullptr;
+    m_unwind_data = nullptr;
+
+    // Copy the stack to the frame
+    size_t stack_slots = m_size;
+
+    lazy_data ();
+
+    m_lazy_data->m_stack_cpy = new octave::stack_element[stack_slots];
+    for (unsigned i = 1; i < m_size; i++)
+      new (&m_lazy_data->m_stack_cpy[i].ov) octave_value {};
+
+    // Note: int nargout at offset 0
+    m_lazy_data->m_stack_cpy[0].i = m_stack_start[0].i;
+    for (unsigned i = 1; i < m_size; i++)
+      m_lazy_data->m_stack_cpy[i].ov = m_stack_start[i].ov;
+
+    m_stack_start = m_lazy_data->m_stack_cpy;
+  }
+
+  std::size_t size (void) const
+  {
+    return m_orig_size +
+      (m_lazy_data ? m_lazy_data->m_extra_slots.size () : 0);
+  }
+
+  std::size_t internal_size (void) const
+  {
+    return m_size +
+      (m_lazy_data ? m_lazy_data->m_extra_slots.size () : 0);
+  }
+
+  void resize (std::size_t arg)
+  {
+    int diff = static_cast<int> (arg) - static_cast<int>(size ());
+
+    if (diff > 0)
+      internal_resize (internal_size () + diff);
+  }
+
+  void internal_resize (std::size_t arg)
+  {
+    int diff = static_cast<int> (arg) - static_cast<int>(internal_size ());
+
+    if (diff > 0)
+      {
+        auto &lazy = lazy_data ();
+        lazy.m_extra_slots.resize (lazy.m_extra_slots.size () + diff);
+
+        lazy.m_extra_flags.resize (lazy.m_extra_flags.size () + diff);
+
+        lazy.m_extra_names.resize (lazy.m_extra_names.size () + diff);
+      }
+  }
+
+  bool slot_is_global (std::size_t local_offset) const
+  {
+    if (local_offset >= m_size)
+      {
+        if (!m_lazy_data)
+          panic ("bytecode_fcn_stack_frame::slot_is_global(%zu): Bad request", local_offset);
+        scope_flags flag = m_lazy_data->m_extra_flags.at (local_offset - m_size);
+        return flag == GLOBAL;
+      }
+
+    octave_value &ov = m_stack_start [local_offset].ov;
+    if (!ov.is_ref ())
+      return false;
+    if (ov.ref_rep ()->is_global_ref ())
+      return true;
+
+    return false;
+  }
+
+  bool slot_is_persistent (std::size_t local_offset) const
+  {
+    if (local_offset >= m_size)
+      {
+        if (!m_lazy_data)
+          panic ("bytecode_fcn_stack_frame::slot_is_global(%zu): Bad request", local_offset);
+        scope_flags flag = m_lazy_data->m_extra_flags.at (local_offset - m_size);
+        return flag == PERSISTENT;
+      }
+
+    octave_value &ov = m_stack_start [local_offset].ov;
+    if (!ov.is_ref ())
+      return false;
+    if (ov.ref_rep ()->is_persistent_ref ())
+      return true;
+    return false;
+  }
+
+  stack_frame::scope_flags get_scope_flag (std::size_t external_offset) const
+  {
+    std::size_t local_offset = external_to_local_offset (external_offset);
+    // Is the slot on the original bytecode stack frame?
+    if (local_offset < m_size)
+      {
+        octave_value &ov = m_stack_start [local_offset].ov;
+        if (!ov.is_ref ())
+          return LOCAL;
+        if (ov.ref_rep ()->is_global_ref ())
+          return GLOBAL;
+        if (ov.ref_rep ()->is_persistent_ref ())
+          return PERSISTENT;
+        return LOCAL;
+      }
+
+    size_t extra_offset = local_offset - m_size;
+    if (m_lazy_data && extra_offset < m_lazy_data->m_extra_flags.size ())
+      return m_lazy_data->m_extra_flags.at (local_offset - m_size);
+
+    return LOCAL;
+  }
+
+  void set_scope_flag (std::size_t external_offset, scope_flags flag)
+  {
+    std::size_t local_offset = external_to_local_offset (external_offset);
+    if (local_offset >= m_size)
+      {
+        if (!m_lazy_data)
+          error ("VM internal error: Trying to set scope flag on invalid offset");
+        m_lazy_data->m_extra_flags.at (local_offset - m_size) = flag;
+        return;
+      }
+
+    scope_flags current_flag = get_scope_flag (external_offset);
+
+    bool is_global = current_flag == GLOBAL;
+    bool is_pers = current_flag == PERSISTENT;
+
+    if (flag == GLOBAL)
+      {
+        if (is_global)
+          return;
+        if (is_pers)
+          error ("VM internal error: Trying to make persistent variable global");
+
+        octave_value &ov = m_stack_start [local_offset].ov;
+        ov = octave_value {new octave_value_ref_global {m_name_data [local_offset]}};
+
+        return;
+      }
+
+    if (flag == PERSISTENT)
+      {
+        if (is_pers)
+          return;
+        if (is_global)
+          error ("VM internal error: Trying to make global variable persistent");
+
+        octave_value &ov = m_stack_start [local_offset].ov;
+        ov = octave_value {new octave_value_ref_persistent {get_scope (), static_cast<int> (external_offset)}};
+
+        return;
+      }
+
+    if (flag == LOCAL)
+      {
+        if (!is_global && !is_pers)
+          return;
+
+        // Clear the global or persistent ref on the stack
+        if (is_global || is_pers)
+          {
+            // Clear the ref in its slot
+            octave_value& ov_ref = m_stack_start [local_offset].ov;
+            ov_ref = octave_value {};
+          }
+
+        return;
+      }
+
+    panic ("VM internal error: Strange state: %d", flag);
+  }
+
+  stack_frame::scope_flags scope_flag (const symbol_record& sym) const
+  {
+    std::size_t external_offset = sym.data_offset ();
+
+    if (sym.frame_offset())
+      error ("TODO: Frame offset %d", __LINE__);
+
+    return get_scope_flag (external_offset);
+  }
+
+  virtual octave_value get_active_bytecode_call_arg_names ()
+  {
+
+    // Handle ARG_NAMES
+    if (!m_unwind_data || !m_vm)
+      return Cell {};
+
+    int best_match = -1;
+    int best_start = -1;
+
+    auto &entries = m_unwind_data->m_argname_entries;
+    for (unsigned i = 0; i < entries.size (); i++)
+      {
+        int start = entries[i].m_ip_start;
+        int end = entries[i].m_ip_end;
+
+        if (start > m_ip || end < m_ip)
+          continue;
+
+        if (best_match != -1)
+          {
+            if (best_start > start)
+              continue;
+          }
+
+        best_match = i;
+        best_start = start;
+      }
+
+    if (best_match == -1)
+      return Cell {};
+
+    Cell c = entries[best_match].m_arg_names;
+    return c;
+  }
+
+  virtual void set_active_bytecode_ip (int ip)
+  {
+    m_ip = ip;
+  }
+
+  octave_value get_auto_fcn_var (auto_var_type avt) const
+  {
+    switch (avt)
+      {
+        case stack_frame::NARGIN:
+          return octave_value {m_nargin};
+        case stack_frame::NARGOUT:
+          return octave_value {m_nargout};
+        case stack_frame::SAVED_WARNING_STATES:
+          if (!m_lazy_data)
+            return {};
+          else
+            return m_lazy_data->m_saved_warnings_states;
+        case stack_frame::IGNORED:
+          if (!m_lazy_data)
+            return {};
+          else
+            return m_lazy_data->m_ignored;
+        case stack_frame::ARG_NAMES:
+        {
+          // If the current bytecode stack frame is the root one in the VM, the caller
+          // sets ARG_NAMES in the root bytecode stack frame
+          if (m_lazy_data)
+            {
+              octave_value ov = m_lazy_data->m_arg_names;
+              if (ov.is_defined ())
+                return ov;
+            }
+          // In bytecode stack frames, the arg names are stored in the caller frame.
+          return m_parent_link->get_active_bytecode_call_arg_names ();
+        }
+        default:
+          panic ("bytecode_fcn_stack_frame::get_auto_fcn_var() : Invalid call idx=%d", static_cast<int> (avt));
+      }
+  }
+
+  void set_nargin (int nargin) { m_nargin = nargin; }
+  void set_nargout (int nargout) { m_nargout = nargout; }
+
+  void set_auto_fcn_var (auto_var_type avt, const octave_value& val)
+  {
+    switch (avt)
+      {
+        case stack_frame::NARGIN:
+          m_nargin = val.int_value ();
+          return;
+        case stack_frame::NARGOUT:
+          m_nargout = val.int_value ();
+          return;
+        case stack_frame::SAVED_WARNING_STATES:
+          lazy_data ().m_saved_warnings_states = val;
+          return;
+        case stack_frame::IGNORED:
+          lazy_data ().m_ignored = val;
+          return;
+        case stack_frame::ARG_NAMES:
+          lazy_data ().m_arg_names = val;
+          return;
+        default:
+          panic ("bytecode_fcn_stack_frame::set_auto_fcn_var() : Invalid call idx=%d", static_cast<int> (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 (std::size_t external_offset) const
+  {
+    size_t extra_size = (m_lazy_data ? m_lazy_data->m_extra_slots.size () : 0);
+    size_t stack_slots = m_size;
+
+    std::size_t local_offset = external_to_local_offset (external_offset);
+
+    if (local_offset == 0) // Handle native int %nargout specially
+      return octave_value {m_stack_start [0].i};
+    if (local_offset < stack_slots)
+      {
+        octave_value ov = m_stack_start [local_offset].ov;
+        if (ov.is_ref ())
+          return ov.ref_rep ()->deref ();
+        return ov;
+      }
+    else
+      {
+        std::size_t extra_offset = local_offset - stack_slots;
+        if (!m_lazy_data || extra_offset >= extra_size)
+          error ("VM internal error: Trying to access extra slot out of range, %zu", extra_offset);
+        return m_lazy_data->m_extra_slots.at (extra_offset);
+      }
+  }
+
+  octave_value varval (const symbol_record& sym) const
+  {
+    // We don't use frame offsets. Just return nil
+    if (sym.frame_offset())
+      return octave_value {};
+
+    std::size_t external_offset = sym.data_offset ();
+    std::size_t local_offset = external_to_local_offset (external_offset);
+
+    // If the offset is out of range we return a nil ov
+    if (local_offset >= internal_size ())
+      return {};
+    if (local_offset >= m_size)
+      {
+        std::string nm_src = sym.name ();
+        if (!m_lazy_data)
+          panic ("bytecode_fcn_stack_frame::varval() Invalid request");
+        std::string &nm = m_lazy_data->m_extra_names.at (local_offset - m_size);
+        if (nm == "")
+          nm = nm_src;
+        else if (nm != nm_src && nm_src != "")
+          error ("VM internal error: Trying to access extra slot with the wrong name. Current: %s, New: %s\n",
+            nm.c_str (), nm_src.c_str ());
+      }
+
+    bool is_global = slot_is_global (local_offset);
+    bool is_pers = slot_is_persistent (local_offset);
+
+    if (is_global)
+      return m_evaluator.global_varval (sym.name ());
+    if (is_pers)
+      return get_scope ().persistent_varval (external_offset);
+
+    return varval (external_offset);
+  }
+
+  octave_value& varref (std::size_t external_offset)
+  {
+    static octave_value fake_dummy_nargout{0};
+
+    std::size_t extra_size = (m_lazy_data ? m_lazy_data->m_extra_slots.size () : 0);
+    std::size_t stack_slots = m_size;
+
+    std::size_t local_offset = external_to_local_offset (external_offset);
+
+    // Handle native int %nargout specially. Note that changing
+    // the value of %nargout via the this ref wont work.
+    if (local_offset == 0)
+      return fake_dummy_nargout = octave_value {m_stack_start [0].i};
+    if (local_offset < stack_slots)
+      {
+        octave_value &ov = m_stack_start [local_offset].ov;
+        if (ov.is_ref ())
+          return ov.ref_rep ()->ref ();
+        return ov;
+      }
+    else
+      {
+        std::size_t extra_offset = local_offset - stack_slots;
+        if (!m_lazy_data || extra_offset >= extra_size)
+          error ("VM internal error: Trying to access extra slot out of range, %zu", extra_offset);
+        return m_lazy_data->m_extra_slots.at (extra_offset);
+      }
+  }
+
+  octave_value& varref (const symbol_record& sym)
+  {
+    std::size_t external_offset = sym.data_offset ();
+    std::size_t local_offset = external_to_local_offset (external_offset);
+
+    if (sym.frame_offset())
+      error ("TODO: Frame offset");
+
+    // If the offset is out of range we make room for it
+    if (local_offset >= internal_size ())
+      internal_resize (local_offset + 1);
+    if (local_offset >= m_size)
+      {
+        std::string nm_src = sym.name ();
+        if (!m_lazy_data)
+          panic ("bytecode_fcn_stack_frame::varval() Invalid request");
+        std::string &nm = m_lazy_data->m_extra_names.at (local_offset - m_size);
+        if (nm == "")
+          nm = nm_src;
+        else if (nm != nm_src && nm_src != "")
+          error ("VM internal error: Trying to access extra slot with wrong name. Current: %s, New: %s\n",
+            nm.c_str (), nm_src.c_str ());
+      }
+
+    bool is_global = slot_is_global (local_offset);
+    bool is_pers = slot_is_persistent (local_offset);
+
+    if (is_global)
+      return m_evaluator.global_varref (sym.name ());
+    if (is_pers)
+      return get_scope ().persistent_varref(external_offset);
+
+    return varref (external_offset);
+  }
+
+  void mark_scope (const symbol_record& sym,
+                   scope_flags flag)
+  {
+    std::size_t external_offset = sym.data_offset ();
+    std::size_t local_offset = external_to_local_offset (external_offset);
+
+    if (local_offset >= internal_size ())
+      internal_resize (local_offset + 1);
+
+    set_scope_flag (external_offset, flag);
+  }
+
+  bool is_bytecode_fcn_frame (void) const { return true; }
+
+  symbol_record lookup_symbol (const std::string& name) const
+  {
+    int local_offset = -1;
+    scope_flags flag = LOCAL;
+
+    for (int i = 0; i < static_cast<int> (m_size); i++)
+      {
+        if (m_name_data [i] == name)
+          {
+            local_offset = i;
+
+            bool is_global = slot_is_global (local_offset);
+            bool is_pers = slot_is_persistent (local_offset);
+
+            if (is_global)
+              flag = GLOBAL;
+            else if (is_pers)
+              flag = PERSISTENT;
+
+            break;
+          }
+      }
+
+    if (local_offset >= 0)
+      {
+        symbol_record ret (name, flag);
+        ret.set_data_offset (local_to_external_offset (static_cast<std::size_t> (local_offset)));
+        // Check if the symbol is an argument or return symbol. Note: Negative count for vararg and varargin
+        int n_returns = abs (static_cast<signed char> (m_code[0]));
+        int n_args = abs (static_cast<signed char> (m_code[1]));
+        if (local_offset < n_returns + n_args)
+          ret.mark_formal ();
+
+        return ret;
+      }
+
+    if (m_lazy_data)
+      {
+        for (unsigned i = 0; i < m_lazy_data->m_extra_slots.size (); i++)
+          {
+            if (m_lazy_data->m_extra_names.at (i) == name)
+              {
+                symbol_record ret (name, m_lazy_data->m_extra_flags.at (i));
+                ret.set_data_offset (m_orig_size + i);
+                return ret;
+              }
+          }
+      }
+
+    // Search the "scope" object of this and any nested frame
+    // The scope object will have e.g. variables added by scripts
+    const stack_frame *frame = this;
+    while (frame)
+      {
+        symbol_scope scope = frame->get_scope ();
+
+        symbol_record sym = scope.lookup_symbol (name);
+
+        if (sym)
+          return sym;
+
+        std::shared_ptr<stack_frame> nxt = frame->access_link ();
+        frame = nxt.get ();
+      }
+
+    return symbol_record ();
+  }
+
+  symbol_record 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;
+
+    // If we have not created the extra slots, now is the time
+    auto &lazy = lazy_data ();
+    lazy.m_extra_names.push_back (name);
+    lazy.m_extra_slots.push_back ({});
+    lazy.m_extra_flags.push_back (LOCAL);
+
+    sym = scope.find_symbol (name);
+
+    panic_unless (sym.is_valid ());
+
+    return sym;
+  }
+
+  symbol_scope get_scope (void) const
+  {
+    return m_fcn->scope ();
+  }
+
+  octave_function * function () const { return m_fcn; }
+
+  void accept (stack_frame_walker& sfw);
+
+  void display (bool follow = true) const;
+
+  int line () const
+  {
+    if (! m_vm)
+      return -1;
+
+    loc_entry loc = vm::find_loc (m_ip, m_vm->m_unwind_data->m_loc_entry); // TODO: Does not work in nested bytecode stack frames
+    return loc.m_line;
+  }
+
+  int column () const
+  {
+    if (! m_vm)
+      return -1;
+
+    loc_entry loc = m_vm->find_loc (m_ip, m_vm->m_unwind_data->m_loc_entry);
+    return loc.m_col;
+  }
+
+  unwind_protect *unwind_protect_frame ()
+  {
+    if (! lazy_data ().m_unwind_protect_frame)
+      lazy_data ().m_unwind_protect_frame = new unwind_protect ();
+
+    return lazy_data ().m_unwind_protect_frame;
+  }
+
+  std::weak_ptr<stack_frame> m_weak_ptr_to_self;
+
+private:
+  // To keep down the footprint of the frame some seldom used
+  // variables are lazy initialized and stored in *m_lazy_data
+  struct lazy_data_struct
+  {
+    octave_value m_ignored;
+    octave_value m_arg_names;
+    octave_value m_saved_warnings_states;
+
+    std::vector<octave_value> m_extra_slots;
+    std::vector<std::string> m_extra_names;
+    std::vector<scope_flags> m_extra_flags;
+
+    unwind_protect *m_unwind_protect_frame = nullptr;
+    stack_element *m_stack_cpy = nullptr;
+  };
+
+  lazy_data_struct & lazy_data ()
+  {
+    if (!m_lazy_data)
+      m_lazy_data = new lazy_data_struct {};
+    return *m_lazy_data;
+  }
+
+  lazy_data_struct *m_lazy_data = nullptr;
+
+  octave_function *m_fcn;
+
+  unwind_data *m_unwind_data;
+
+  std::string *m_name_data;
+  stack_element *m_stack_start;
+
+  unsigned char *m_code;
+  unsigned m_size;
+  unsigned m_orig_size;
+  vm *m_vm;
+  int m_ip;
+
+  int m_nargin;
+  int m_nargout;
+};
+
 class compiled_fcn_stack_frame : public stack_frame
 {
 public:
 
-  compiled_fcn_stack_frame (void) = delete;
+  compiled_fcn_stack_frame () = delete;
 
   compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn,
                             std::size_t index,
@@ -70,16 +951,16 @@
   compiled_fcn_stack_frame&
   operator = (const compiled_fcn_stack_frame& elt) = delete;
 
-  ~compiled_fcn_stack_frame (void) = default;
-
-  bool is_compiled_fcn_frame (void) const { return true; }
-
-  symbol_scope get_scope (void) const
+  ~compiled_fcn_stack_frame () = default;
+
+  bool is_compiled_fcn_frame () const { return true; }
+
+  symbol_scope get_scope () const
   {
     return m_static_link->get_scope ();
   }
 
-  octave_function * function (void) const { return m_fcn; }
+  octave_function * function () const { return m_fcn; }
 
   symbol_record lookup_symbol (const std::string& name) const
   {
@@ -175,7 +1056,7 @@
 {
 public:
 
-  script_stack_frame (void) = delete;
+  script_stack_frame () = delete;
 
   script_stack_frame (tree_evaluator& tw, octave_user_script *script,
                       std::size_t index,
@@ -186,36 +1067,36 @@
 
   script_stack_frame& operator = (const script_stack_frame& elt) = delete;
 
-  ~script_stack_frame (void)
+  ~script_stack_frame ()
   {
     delete m_unwind_protect_frame;
   }
 
-  bool is_user_script_frame (void) const { return true; }
+  bool is_user_script_frame () const { return true; }
 
   static std::shared_ptr<stack_frame>
   get_access_link (const std::shared_ptr<stack_frame>& static_link);
 
   static std::size_t get_num_symbols (octave_user_script *script);
 
-  void set_script_offsets (void);
+  void set_script_offsets ();
 
   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);
+  symbol_scope get_scope () const { return m_script->scope (); }
+
+  octave_function * function () const { return m_script; }
+
+  unwind_protect * unwind_protect_frame ();
 
   symbol_record lookup_symbol (const std::string& name) const;
 
   symbol_record insert_symbol (const std::string&);
 
-  std::size_t size (void) const { return m_lexical_frame_offsets.size (); }
+  std::size_t size () const { return m_lexical_frame_offsets.size (); }
 
   void resize (std::size_t size)
   {
@@ -288,7 +1169,7 @@
 {
 public:
 
-  base_value_stack_frame (void) = delete;
+  base_value_stack_frame () = delete;
 
   base_value_stack_frame (tree_evaluator& tw, std::size_t num_symbols,
                           std::size_t index,
@@ -306,9 +1187,9 @@
   base_value_stack_frame&
   operator = (const base_value_stack_frame& elt) = delete;
 
-  ~base_value_stack_frame (void) = default;
-
-  std::size_t size (void) const
+  ~base_value_stack_frame () = default;
+
+  std::size_t size () const
   {
     return m_values.size ();
   }
@@ -331,6 +1212,10 @@
 
   octave_value get_auto_fcn_var (auto_var_type avt) const
   {
+    if (avt != stack_frame::auto_var_type::ARG_NAMES)
+      return m_auto_vars.at (avt);
+    if (m_parent_link->is_bytecode_fcn_frame ())
+      return m_parent_link->get_active_bytecode_call_arg_names ();
     return m_auto_vars.at (avt);
   }
 
@@ -394,7 +1279,7 @@
 {
 public:
 
-  user_fcn_stack_frame (void) = delete;
+  user_fcn_stack_frame () = delete;
 
   user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn,
                         std::size_t index,
@@ -433,12 +1318,12 @@
   user_fcn_stack_frame&
   operator = (const user_fcn_stack_frame& elt) = delete;
 
-  ~user_fcn_stack_frame (void)
+  ~user_fcn_stack_frame ()
   {
     delete m_unwind_protect_frame;
   }
 
-  bool is_user_fcn_frame (void) const { return true; }
+  bool is_user_fcn_frame () const { return true; }
 
   static std::shared_ptr<stack_frame>
   get_access_link (octave_user_function *fcn,
@@ -451,13 +1336,13 @@
     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);
+  void clear_values ();
+
+  symbol_scope get_scope () const { return m_fcn->scope (); }
+
+  octave_function * function () const { return m_fcn; }
+
+  unwind_protect * unwind_protect_frame ();
 
   symbol_record lookup_symbol (const std::string& name) const;
 
@@ -505,7 +1390,7 @@
 {
 public:
 
-  scope_stack_frame (void) = delete;
+  scope_stack_frame () = delete;
 
   scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope,
                      std::size_t index,
@@ -520,11 +1405,11 @@
 
   scope_stack_frame& operator = (const scope_stack_frame& elt) = delete;
 
-  ~scope_stack_frame (void) = default;
-
-  bool is_scope_frame (void) const { return true; }
-
-  symbol_scope get_scope (void) const { return m_scope; }
+  ~scope_stack_frame () = default;
+
+  bool is_scope_frame () const { return true; }
+
+  symbol_scope get_scope () const { return m_scope; }
 
   symbol_record lookup_symbol (const std::string& name) const
   {
@@ -588,17 +1473,13 @@
 {
 protected:
 
-  stack_frame_walker (void) { }
-
-  virtual ~stack_frame_walker (void) = default;
+  stack_frame_walker () { }
+
+  virtual ~stack_frame_walker () = default;
 
 public:
 
-  // No copying!
-
-  stack_frame_walker (const stack_frame_walker&) = delete;
-
-  stack_frame_walker& operator = (const stack_frame_walker&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (stack_frame_walker)
 
   virtual void
   visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame&) = 0;
@@ -611,6 +1492,9 @@
 
   virtual void
   visit_scope_stack_frame (scope_stack_frame&) = 0;
+
+  virtual void
+  visit_bytecode_fcn_stack_frame (bytecode_fcn_stack_frame&) = 0;
 };
 
 class symbol_cleaner : public stack_frame_walker
@@ -635,11 +1519,9 @@
       m_have_regexp (false), m_cleared_names ()
   { }
 
-  symbol_cleaner (const symbol_cleaner&) = delete;
-
-  symbol_cleaner& operator = (const symbol_cleaner&) = delete;
-
-  ~symbol_cleaner (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (symbol_cleaner)
+
+  ~symbol_cleaner () = default;
 
   void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame)
   {
@@ -681,6 +1563,16 @@
       alink->accept (*this);
   }
 
+  void visit_bytecode_fcn_stack_frame (bytecode_fcn_stack_frame& frame)
+  {
+    clean_frame (frame);
+
+    std::shared_ptr<stack_frame> alink = frame.access_link ();
+
+    if (alink)
+      alink->accept (*this);
+  }
+
 private:
 
   void maybe_clear_symbol (stack_frame& frame, const symbol_record& sym)
@@ -796,13 +1688,11 @@
       m_sym_inf_list (), m_found_names ()
   { }
 
-  symbol_info_accumulator (const symbol_info_accumulator&) = delete;
-
-  symbol_info_accumulator& operator = (const symbol_info_accumulator&) = delete;
-
-  ~symbol_info_accumulator (void) = default;
-
-  bool is_empty  (void) const
+  OCTAVE_DISABLE_COPY_MOVE (symbol_info_accumulator)
+
+  ~symbol_info_accumulator () = default;
+
+  bool is_empty  () const
   {
     for (const auto& nm_sil : m_sym_inf_list)
       {
@@ -815,7 +1705,7 @@
     return true;
   }
 
-  std::list<std::string> names (void) const
+  std::list<std::string> names () const
   {
     std::list<std::string> retval;
 
@@ -832,7 +1722,7 @@
     return retval;
   }
 
-  symbol_info_list symbol_info (void) const
+  symbol_info_list symbol_info () const
   {
     symbol_info_list retval;
 
@@ -847,7 +1737,7 @@
     return retval;
   }
 
-  octave_map map_value (void) const
+  octave_map map_value () const
   {
     octave_map retval;
 
@@ -923,6 +1813,16 @@
       alink->accept (*this);
   }
 
+  void visit_bytecode_fcn_stack_frame (bytecode_fcn_stack_frame& frame)
+  {
+    append_list (frame);
+
+    std::shared_ptr<stack_frame> alink = frame.access_link ();
+
+    if (alink)
+      alink->accept (*this);
+  }
+
 private:
 
   typedef std::pair<std::string, symbol_info_list> syminf_list_elt;
@@ -1085,11 +1985,50 @@
   return new scope_stack_frame (tw, scope, index, parent_link, static_link);
 }
 
+std::shared_ptr<stack_frame>
+stack_frame::create_bytecode (tree_evaluator& tw, octave_user_function *fcn,
+                              vm &vm, std::size_t index,
+                              const std::shared_ptr<stack_frame>& parent_link,
+                              const std::shared_ptr<stack_frame>& static_link,
+                              int nargout, int nargin)
+{
+  // If we have any cached shared_ptr to empty bytecode_fcn_stack_frame objects
+  // we use on of those
+  if (vm.m_frame_ptr_cache.size ())
+    {
+      std::shared_ptr<stack_frame> sp = std::move (vm.m_frame_ptr_cache.back ());
+      vm.m_frame_ptr_cache.pop_back ();
+
+      bytecode_fcn_stack_frame *p = static_cast<bytecode_fcn_stack_frame*> (sp.get ());
+      // Most objects where cleared when the shared_ptr was put into the cache but call the
+      // dtor anyways to be sure.
+      p->~bytecode_fcn_stack_frame ();
+      // Placement new into the storage managed by the shared_ptr
+      new (p) bytecode_fcn_stack_frame (tw, fcn, index, parent_link, static_link, vm, nargout, nargin);
+
+      p->m_weak_ptr_to_self = sp;
+
+      return sp;
+    }
+
+  bytecode_fcn_stack_frame *new_frame_raw
+    = new bytecode_fcn_stack_frame (tw, fcn, index, parent_link, static_link,
+                                    vm, nargout, nargin);
+  std::shared_ptr<stack_frame> new_frame (new_frame_raw);
+
+  // The bytecode stackframe needs to know if it needs to save away
+  // all the stack variables. So it need to keep track of if it is saved
+  // somewhere outsite the VM
+  new_frame_raw->m_weak_ptr_to_self = new_frame;
+
+  return new_frame;
+}
+
 // This function is only implemented and should only be called for
 // user_fcn stack frames.  Anything else indicates an error in the
 // implementation, but we'll simply warn if that happens.
 
-void stack_frame::clear_values (void)
+void stack_frame::clear_values ()
 {
   warning ("invalid call to stack_frame::clear_values; please report");
 }
@@ -1158,7 +2097,7 @@
 // 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_list stack_frame::all_variables ()
 {
   symbol_info_accumulator sia (true, true);
 
@@ -1167,7 +2106,7 @@
   return sia.symbol_info ();
 }
 
-octave_value stack_frame::workspace (void)
+octave_value stack_frame::workspace ()
 {
   std::list<octave_scalar_map> ws_list;
 
@@ -1205,7 +2144,7 @@
 // FIXME: Should this function also find any variables in parent
 // scopes accessible through access_links?
 
-std::list<std::string> stack_frame::variable_names (void) const
+std::list<std::string> stack_frame::variable_names () const
 {
   std::list<std::string> retval;
 
@@ -1242,7 +2181,7 @@
   return sia.symbol_info ();
 }
 
-std::size_t stack_frame::size (void) const
+std::size_t stack_frame::size () const
 {
   // This function should only be called for user_fcn_stack_frame or
   // scope_stack_frame objects.  Anything else indicates an error in
@@ -1342,7 +2281,7 @@
   panic_impossible ();
 }
 
-void stack_frame::clear_objects (void)
+void stack_frame::clear_objects ()
 {
   symbol_cleaner sc (true, true);
 
@@ -1384,7 +2323,7 @@
   accept (sc);
 }
 
-void stack_frame::clear_variables (void)
+void stack_frame::clear_variables ()
 {
   symbol_cleaner sc;
 
@@ -1491,7 +2430,7 @@
   return script_scope.num_symbols ();
 }
 
-void script_stack_frame::set_script_offsets (void)
+void script_stack_frame::set_script_offsets ()
 {
   // Set frame and data offsets inside stack frame based on enclosing
   // scope(s).
@@ -1639,7 +2578,7 @@
   return alink;
 }
 
-unwind_protect *script_stack_frame::unwind_protect_frame (void)
+unwind_protect *script_stack_frame::unwind_protect_frame ()
 {
   if (! m_unwind_protect_frame)
     m_unwind_protect_frame = new unwind_protect ();
@@ -2131,7 +3070,7 @@
   return alink;
 }
 
-void user_fcn_stack_frame::clear_values (void)
+void user_fcn_stack_frame::clear_values ()
 {
   symbol_scope fcn_scope = m_fcn->scope ();
 
@@ -2165,7 +3104,7 @@
     }
 }
 
-unwind_protect *user_fcn_stack_frame::unwind_protect_frame (void)
+unwind_protect *user_fcn_stack_frame::unwind_protect_frame ()
 {
   if (! m_unwind_protect_frame)
     m_unwind_protect_frame = new unwind_protect ();
@@ -2351,6 +3290,18 @@
   set_scope_flag (data_offset, flag);
 }
 
+void bytecode_fcn_stack_frame::display (bool) const
+{
+  std::ostream& os = octave_stdout;
+
+  os << "-- [bytecode_fcn_stack_frame] (" << this << ") --" << std::endl;
+
+  os << "fcn: " << m_fcn->name ()
+     << " (" << m_fcn->type_name () << ")" << std::endl;
+
+  display_scope (os, get_scope ());
+}
+
 void user_fcn_stack_frame::display (bool follow) const
 {
   std::ostream& os = octave_stdout;
@@ -2491,4 +3442,10 @@
   sfw.visit_scope_stack_frame (*this);
 }
 
+void bytecode_fcn_stack_frame::accept (stack_frame_walker& sfw)
+{
+  sfw.visit_bytecode_fcn_stack_frame (*this);
+}
+
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/stack-frame.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/stack-frame.h	Fri Jun 23 20:51:51 2023 +0200
@@ -104,6 +104,7 @@
 class unwind_protect;
 
 class stack_frame_walker;
+class vm;
 
 class stack_frame
 {
@@ -137,7 +138,7 @@
     NUM_AUTO_VARS
   };
 
-  stack_frame (void) = delete;
+  stack_frame () = delete;
 
   stack_frame (tree_evaluator& tw, std::size_t index,
                const std::shared_ptr<stack_frame>& parent_link,
@@ -182,32 +183,43 @@
           const std::shared_ptr<stack_frame>& parent_link,
           const std::shared_ptr<stack_frame>& static_link);
 
+  // Bytecode function stackframe
+  static std::shared_ptr<stack_frame>
+  create_bytecode (tree_evaluator& tw,
+                   octave_user_function *fcn,
+                   vm &vm,
+                   std::size_t index,
+                   const std::shared_ptr<stack_frame>& parent_link,
+                   const std::shared_ptr<stack_frame>& static_link,
+                   int nargout, int nargin);
+
   stack_frame (const stack_frame& elt) = default;
 
   stack_frame& operator = (const stack_frame& elt) = delete;
 
-  virtual ~stack_frame (void) = default;
+  virtual ~stack_frame () = default;
 
   // 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 bool is_compiled_fcn_frame () const { return false; }
+  virtual bool is_user_script_frame () const { return false; }
+  virtual bool is_user_fcn_frame () const { return false; }
+  virtual bool is_scope_frame () const { return false; }
+  virtual bool is_bytecode_fcn_frame (void) const { return false; }
 
-  virtual void clear_values (void);
+  virtual void clear_values ();
 
-  std::size_t index (void) const { return m_index; }
+  std::size_t index () const { return m_index; }
 
   void line (int l) { m_line = l; }
-  int line (void) const { return m_line; }
+  virtual int line () const { return m_line; }
 
   void column (int c) { m_column = c; }
-  int column (void) const { return m_column; }
+  virtual int column () const { return m_column; }
 
-  std::string fcn_file_name (void) const
+  std::string fcn_file_name () const
   {
     octave_function *fcn = function ();
 
@@ -238,11 +250,11 @@
     return retval;
   }
 
-  virtual symbol_scope get_scope (void) const = 0;
+  virtual symbol_scope get_scope () const = 0;
 
-  virtual octave_function * function (void) const { return nullptr; }
+  virtual octave_function * function () const { return nullptr; }
 
-  virtual unwind_protect * unwind_protect_frame (void) { return nullptr; }
+  virtual unwind_protect * unwind_protect_frame () { return nullptr; }
 
   symbol_info_list
   make_symbol_info_list (const std::list<symbol_record>& symrec_list) const;
@@ -252,11 +264,11 @@
                     const std::string& whos_line_fmt,
                     const std::string& msg);
 
-  symbol_info_list all_variables (void);
+  symbol_info_list all_variables ();
 
-  octave_value workspace (void);
+  octave_value workspace ();
 
-  std::list<std::string> variable_names (void) const;
+  std::list<std::string> variable_names () const;
 
   // Look for named symbol visible from current scope.  Don't
   // attempt to insert if missing.
@@ -270,7 +282,7 @@
 
   symbol_info_list regexp_symbol_info (const std::string& pattern);
 
-  symbol_info_list get_symbol_info (void)
+  symbol_info_list get_symbol_info ()
   {
     return all_variables ();
   }
@@ -307,16 +319,19 @@
     mark_global (sym);
   }
 
+  std::size_t
+  parent_frame_index () const { return m_parent_link->index (); }
+
   std::shared_ptr<stack_frame>
-  parent_link (void) const {return m_parent_link; }
+  parent_link () const {return m_parent_link; }
 
   std::shared_ptr<stack_frame>
-  static_link (void) const {return m_static_link; }
+  static_link () const {return m_static_link; }
 
   std::shared_ptr<stack_frame>
-  access_link (void) const {return m_access_link; }
+  access_link () const {return m_access_link; }
 
-  virtual std::size_t size (void) const;
+  virtual std::size_t size () const;
 
   virtual void resize (std::size_t);
 
@@ -423,10 +438,23 @@
     install_variable (sym, value, global);
   }
 
+  virtual octave_value get_active_bytecode_call_arg_names ()
+  {
+    panic_impossible (); // Only bytecode frame need to implement this
+  }
+
+  virtual void set_active_bytecode_ip (int)
+  {
+    panic_impossible (); // Only bytecode frame need to implement this
+  }
+
   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 void set_nargin (int nargin) { set_auto_fcn_var (NARGIN, nargin); }
+  virtual void set_nargout (int nargout) { set_auto_fcn_var (NARGOUT, nargout); }
+
   virtual octave_value varval (const symbol_record& sym) const = 0;
 
   virtual octave_value varval (std::size_t data_offset) const;
@@ -525,7 +553,7 @@
       unmark_persistent (sym);
   }
 
-  void clear_objects (void);
+  void clear_objects ();
 
   void clear_variable (const std::string& name);
 
@@ -535,9 +563,9 @@
   void clear_variable_regexp (const std::string& pattern);
   void clear_variable_regexp (const string_vector& patterns);
 
-  void clear_variables (void);
+  void clear_variables ();
 
-  std::string get_dispatch_class (void) const { return m_dispatch_class; }
+  std::string get_dispatch_class () const { return m_dispatch_class; }
 
   void set_dispatch_class (const std::string& class_name)
   {
@@ -554,8 +582,14 @@
 
   virtual void break_closure_cycles (const std::shared_ptr<stack_frame>&) { }
 
-  void mark_closure_context (void) { m_is_closure_context = true; }
-  bool is_closure_context (void) const { return m_is_closure_context; }
+  void mark_closure_context () { m_is_closure_context = true; }
+  bool is_closure_context () const { return m_is_closure_context; }
+
+  // The VM needs to tell the bytecode stackframe that it unwinds so
+  // that it can check whether to save the stack.
+  virtual void vm_unwinds () {}
+  virtual void vm_dbg_check_scope () {}
+  virtual void vm_clear_for_cache () {}
 
 protected:
 
--- a/libinterp/corefcn/strfns.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/strfns.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -1216,8 +1216,7 @@
   if (nargin < 1 || nargin > 3)
     print_usage ();
 
-  string_vector s = args(
-                      0).xstring_vector_value ("list_in_columns: ARG must be a cellstr or char array");
+  string_vector s = args(0).xstring_vector_value ("list_in_columns: ARG must be a cellstr or char array");
 
   int width = -1;
 
--- a/libinterp/corefcn/svd.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/svd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,7 @@
 
 template <typename T>
 static typename math::svd<T>::Driver
-svd_driver (void)
+svd_driver ()
 {
   if (Vsvd_driver == "gejsv")
     return math::svd<T>::Driver::GEJSV;
--- a/libinterp/corefcn/syminfo.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/syminfo.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -177,7 +177,7 @@
   return octave_value ();
 }
 
-std::list<std::string> symbol_info_list::names (void) const
+std::list<std::string> symbol_info_list::names () const
 {
   std::list<std::string> retval;
 
--- a/libinterp/corefcn/syminfo.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/syminfo.h	Fri Jun 23 20:51:51 2023 +0200
@@ -63,19 +63,19 @@
       m_is_global (is_global), m_is_persistent (is_persistent)
   { }
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
-  octave_value value (void) const { return m_value; }
+  octave_value value () const { return m_value; }
 
-  bool is_complex (void) const { return m_is_complex; }
+  bool is_complex () const { return m_is_complex; }
 
-  bool is_sparse (void) const { return m_is_sparse; }
+  bool is_sparse () const { return m_is_sparse; }
 
-  bool is_formal (void) const { return m_is_formal; }
+  bool is_formal () const { return m_is_formal; }
 
-  bool is_global (void) const { return m_is_global; }
+  bool is_global () const { return m_is_global; }
 
-  bool is_persistent (void) const { return m_is_persistent; }
+  bool is_persistent () const { return m_is_persistent; }
 
   void display_line (std::ostream& os,
                      const std::list<whos_parameter>& params) const;
@@ -96,17 +96,17 @@
 {
 public:
 
-  symbol_info_list (void) = default;
+  symbol_info_list () = default;
 
   symbol_info_list (const symbol_info_list&) = default;
 
   symbol_info_list& operator = (const symbol_info_list&) = default;
 
-  ~symbol_info_list (void) = default;
+  ~symbol_info_list () = default;
 
   octave_value varval (const std::string& name) const;
 
-  std::list<std::string> names (void) const;
+  std::list<std::string> names () const;
 
   octave_map map_value (const std::string& caller_function_name,
                         int nesting_level) const;
--- a/libinterp/corefcn/symrec.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symrec.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,13 +42,13 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 std::shared_ptr<symbol_record::symbol_record_rep>
-symbol_record::symbol_record_rep::dup (void) const
+symbol_record::symbol_record_rep::dup () const
 {
   return std::shared_ptr<symbol_record::symbol_record_rep> (new symbol_record_rep (*this));
 }
 
 octave_value
-symbol_record::symbol_record_rep::dump (void) const
+symbol_record::symbol_record_rep::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "frame_offset", m_frame_offset },
--- a/libinterp/corefcn/symrec.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symrec.h	Fri Jun 23 20:51:51 2023 +0200
@@ -67,99 +67,97 @@
   {
   public:
 
+    symbol_record_rep () = delete;
+
     symbol_record_rep (const std::string& nm, symrec_t sc)
       : m_frame_offset (0), m_data_offset (0), m_storage_class (sc),
         m_name (nm)
     { }
 
-    symbol_record_rep (const symbol_record_rep&) = default;
-
-    symbol_record_rep& operator = (const symbol_record_rep&) = default;
-
-    ~symbol_record_rep (void) = default;
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (symbol_record_rep)
 
     // FIXME: use special storage class instead?
-    bool is_valid (void) const { return ! m_name.empty (); }
+    bool is_valid () const { return ! m_name.empty (); }
 
     void set_frame_offset (std::size_t offset) { m_frame_offset = offset; }
 
-    std::size_t frame_offset (void) const { return m_frame_offset; }
+    std::size_t frame_offset () const { return m_frame_offset; }
 
     void set_data_offset (std::size_t offset) { m_data_offset = offset; }
 
-    std::size_t data_offset (void) const { return m_data_offset; }
+    std::size_t data_offset () const { return m_data_offset; }
 
-    bool is_local (void) const
+    bool is_local () const
     {
       return m_storage_class & LOCAL;
     }
 
-    bool is_formal (void) const
+    bool is_formal () const
     {
       return m_storage_class & FORMAL;
     }
 
-    bool is_added_static (void) const
+    bool is_added_static () const
     {
       return m_storage_class & ADDED_STATIC;
     }
 
-    bool is_variable (void) const
+    bool is_variable () const
     {
       return m_storage_class & VARIABLE;
     }
 
-    void mark_local (void)
+    void mark_local ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class | LOCAL);
     }
 
-    void mark_formal (void)
+    void mark_formal ()
     {
       // Formal parameters are also variables.
       m_storage_class = static_cast<symrec_t> (m_storage_class
                         | FORMAL | VARIABLE);
     }
 
-    void mark_added_static (void)
+    void mark_added_static ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class
                         | ADDED_STATIC);
     }
 
-    void mark_as_variable (void)
+    void mark_as_variable ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class | VARIABLE);
     }
 
-    void unmark_local (void)
+    void unmark_local ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class & ~LOCAL);
     }
 
-    void unmark_formal (void)
+    void unmark_formal ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class & ~FORMAL);
     }
 
-    void unmark_added_static (void)
+    void unmark_added_static ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class
                         & ~ADDED_STATIC);
     }
 
-    void unmark_as_variable (void)
+    void unmark_as_variable ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class & ~VARIABLE);
     }
 
-    unsigned int storage_class (void) const { return m_storage_class; }
+    unsigned int storage_class () const { return m_storage_class; }
 
-    std::shared_ptr<symbol_record_rep> dup (void) const;
+    std::shared_ptr<symbol_record_rep> dup () const;
 
-    octave_value dump (void) const;
+    octave_value dump () const;
 
-    std::string name (void) const { return m_name; }
+    std::string name () const { return m_name; }
 
     void rename (const std::string& new_name) { m_name = new_name; }
 
@@ -188,46 +186,46 @@
 
   symbol_record& operator = (const symbol_record&) = default;
 
-  ~symbol_record (void) = default;
+  ~symbol_record () = default;
 
-  bool is_valid (void) const { return m_rep->is_valid (); }
+  bool is_valid () const { return m_rep->is_valid (); }
 
   explicit operator bool () const { return is_valid (); }
 
   void set_frame_offset (std::size_t offset)
   { m_rep->set_frame_offset (offset); }
 
-  std::size_t frame_offset (void) const { return m_rep->frame_offset (); }
+  std::size_t frame_offset () const { return m_rep->frame_offset (); }
 
   void set_data_offset (std::size_t offset)
   { m_rep->set_data_offset (offset); }
 
-  std::size_t data_offset (void) const { return m_rep->data_offset (); }
+  std::size_t data_offset () const { return m_rep->data_offset (); }
 
-  symbol_record dup (void) const { return symbol_record (m_rep->dup ()); }
+  symbol_record dup () const { return symbol_record (m_rep->dup ()); }
 
-  std::string name (void) const { return m_rep->name (); }
+  std::string name () const { return m_rep->name (); }
 
   void rename (const std::string& new_name) { m_rep->rename (new_name); }
 
-  bool is_local (void) const { return m_rep->is_local (); }
-  bool is_formal (void) const { return m_rep->is_formal (); }
-  bool is_added_static (void) const { return m_rep->is_added_static (); }
-  bool is_variable (void) const { return m_rep->is_variable (); }
+  bool is_local () const { return m_rep->is_local (); }
+  bool is_formal () const { return m_rep->is_formal (); }
+  bool is_added_static () const { return m_rep->is_added_static (); }
+  bool is_variable () const { return m_rep->is_variable (); }
 
-  void mark_local (void) { m_rep->mark_local (); }
-  void mark_formal (void) { m_rep->mark_formal (); }
-  void mark_added_static (void) { m_rep->mark_added_static (); }
-  void mark_as_variable (void) { m_rep->mark_as_variable (); }
+  void mark_local () { m_rep->mark_local (); }
+  void mark_formal () { m_rep->mark_formal (); }
+  void mark_added_static () { m_rep->mark_added_static (); }
+  void mark_as_variable () { m_rep->mark_as_variable (); }
 
-  void unmark_local (void) { m_rep->unmark_local (); }
-  void unmark_formal (void) { m_rep->unmark_formal (); }
-  void unmark_added_static (void) { m_rep->unmark_added_static (); }
-  void unmark_as_variable (void) { m_rep->unmark_as_variable (); }
+  void unmark_local () { m_rep->unmark_local (); }
+  void unmark_formal () { m_rep->unmark_formal (); }
+  void unmark_added_static () { m_rep->unmark_added_static (); }
+  void unmark_as_variable () { m_rep->unmark_as_variable (); }
 
-  unsigned int storage_class (void) const { return m_rep->storage_class (); }
+  unsigned int storage_class () const { return m_rep->storage_class (); }
 
-  octave_value dump (void) const { return m_rep->dump (); }
+  octave_value dump () const { return m_rep->dump (); }
 
 private:
 
--- a/libinterp/corefcn/symscope.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symscope.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -92,7 +92,7 @@
     return p->second;
 }
 
-std::list<octave_value> symbol_scope_rep::localfunctions (void) const
+std::list<octave_value> symbol_scope_rep::localfunctions () const
 {
   std::list<octave_value> retval;
 
@@ -130,7 +130,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump (void) const
+symbol_scope_rep::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "name", m_name },
@@ -145,7 +145,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump_symbols_map (void) const
+symbol_scope_rep::dump_symbols_map () const
 {
   std::map<std::string, octave_value> info_map;
 
@@ -159,7 +159,7 @@
   return octave_value (info_map);
 }
 
-std::list<symbol_record> symbol_scope_rep::symbol_list (void) const
+std::list<symbol_record> symbol_scope_rep::symbol_list () const
 {
   std::list<symbol_record> retval;
 
@@ -198,7 +198,7 @@
 }
 
 std::list<std::string>
-symbol_scope_rep::parent_fcn_names (void) const
+symbol_scope_rep::parent_fcn_names () const
 {
   std::list<std::string> retval;
 
@@ -304,7 +304,7 @@
   return false;
 }
 
-void symbol_scope_rep::update_nest (void)
+void symbol_scope_rep::update_nest ()
 {
   auto t_parent = m_parent.lock ();
 
@@ -370,7 +370,7 @@
   return false;
 }
 
-std::list<octave_value> symbol_scope::localfunctions (void) const
+std::list<octave_value> symbol_scope::localfunctions () const
 {
   if (! m_rep)
     return std::list<octave_value> ();
--- a/libinterp/corefcn/symscope.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symscope.h	Fri Jun 23 20:51:51 2023 +0200
@@ -65,27 +65,23 @@
   typedef std::map<std::string, octave_value>::iterator
     subfunctions_iterator;
 
-  symbol_scope_rep (const std::string& name = "")
+  symbol_scope_rep (const std::string& name = "", bool add_ans = true)
     : m_name (name), m_symbols (), m_subfunctions (),
       m_persistent_values (), m_code (nullptr), m_fcn_name (),
       m_fcn_file_name (), m_dir_name (), m_parent (),
       m_primary_parent (), m_children (), m_nesting_depth (0),
       m_is_static (false), m_is_primary_fcn_scope (false)
   {
-    // All scopes have ans as the first symbol, initially undefined.
-
-    insert_local ("ans");
+    // Most scopes have ans as the first symbol, initially undefined.
+    if (add_ans)
+      insert_local ("ans");
   }
 
-  // No copying!
-
-  symbol_scope_rep (const symbol_scope&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)
 
-  symbol_scope_rep& operator = (const symbol_scope&) = delete;
+  ~symbol_scope_rep () = default;
 
-  ~symbol_scope_rep (void) = default;
-
-  std::size_t num_symbols (void) const { return m_symbols.size (); }
+  std::size_t num_symbols () const { return m_symbols.size (); }
 
   // Simply inserts symbol.  No non-local searching.
 
@@ -93,29 +89,29 @@
 
   void insert_symbol_record (symbol_record& sr);
 
-  bool is_nested (void) const { return m_nesting_depth > 0; }
+  bool is_nested () const { return m_nesting_depth > 0; }
 
-  std::size_t nesting_depth (void) const { return m_nesting_depth; }
+  std::size_t nesting_depth () const { return m_nesting_depth; }
 
   void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; }
 
-  bool is_parent (void) const { return ! m_children.empty (); }
+  bool is_parent () const { return ! m_children.empty (); }
 
-  bool is_static (void) const { return m_is_static; }
+  bool is_static () const { return m_is_static; }
 
-  void mark_static (void) { m_is_static = true; }
+  void mark_static () { m_is_static = true; }
 
-  std::shared_ptr<symbol_scope_rep> parent_scope_rep (void) const
+  std::shared_ptr<symbol_scope_rep> parent_scope_rep () const
   {
     return m_parent.lock ();
   }
 
-  std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep (void) const
+  std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const
   {
     return m_primary_parent.lock ();
   }
 
-  std::shared_ptr<symbol_scope_rep> dup (void) const
+  std::shared_ptr<symbol_scope_rep> dup () const
   {
     std::shared_ptr<symbol_scope_rep> new_sid
       = std::shared_ptr<symbol_scope_rep> (new symbol_scope_rep (m_name));
@@ -204,32 +200,32 @@
 
   octave_value find_subfunction (const std::string& name) const;
 
-  void lock_subfunctions (void)
+  void lock_subfunctions ()
   {
     for (auto& nm_sf : m_subfunctions)
       nm_sf.second.lock ();
   }
 
-  void unlock_subfunctions (void)
+  void unlock_subfunctions ()
   {
     for (auto& nm_sf : m_subfunctions)
       nm_sf.second.unlock ();
   }
 
   // Pairs of name, function objects.
-  std::map<std::string, octave_value> subfunctions (void) const
+  std::map<std::string, octave_value> subfunctions () const
   {
     return m_subfunctions;
   }
 
-  void erase_subfunctions (void)
+  void erase_subfunctions ()
   {
     m_subfunctions.clear ();
   }
 
   void mark_subfunctions_in_scope_as_private (const std::string& class_name);
 
-  bool has_subfunctions (void) const
+  bool has_subfunctions () const
   {
     return ! m_subfunction_names.empty ();
   }
@@ -239,26 +235,26 @@
     m_subfunction_names = names;
   }
 
-  std::list<std::string> subfunction_names (void) const
+  std::list<std::string> subfunction_names () const
   {
     return m_subfunction_names;
   }
 
-  std::list<octave_value> localfunctions (void) const;
+  std::list<octave_value> localfunctions () const;
 
-  octave_value dump (void) const;
+  octave_value dump () const;
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
   void cache_name (const std::string& name) { m_name = name; }
 
-  std::string fcn_name (void) const { return m_fcn_name; }
+  std::string fcn_name () const { return m_fcn_name; }
 
   void cache_fcn_name (const std::string& name) { m_fcn_name = name; }
 
-  std::list<std::string> parent_fcn_names (void) const;
+  std::list<std::string> parent_fcn_names () const;
 
-  octave_user_code * user_code (void) const { return m_code; }
+  octave_user_code * user_code () const { return m_code; }
 
   void set_user_code (octave_user_code *code) { m_code = code; }
 
@@ -271,15 +267,15 @@
     m_fcn_file_name = name;
   }
 
-  std::string fcn_file_name (void) const { return m_fcn_file_name; }
+  std::string fcn_file_name () const { return m_fcn_file_name; }
 
   void cache_dir_name (const std::string& name);
 
-  std::string dir_name (void) const { return m_dir_name; }
+  std::string dir_name () const { return m_dir_name; }
 
-  void mark_primary_fcn_scope (void) { m_is_primary_fcn_scope = true; }
+  void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }
 
-  bool is_primary_fcn_scope (void) const { return m_is_primary_fcn_scope; }
+  bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }
 
   bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;
 
@@ -288,24 +284,24 @@
 
   bool is_variable (const std::string& nm) const;
 
-  void update_nest (void);
+  void update_nest ();
 
   bool look_nonlocal (const std::string& name, std::size_t offset,
                       symbol_record& result);
 
-  octave_value dump_symbols_map (void) const;
+  octave_value dump_symbols_map () const;
 
-  const std::map<std::string, symbol_record>& symbols (void) const
+  const std::map<std::string, symbol_record>& symbols () const
   {
     return m_symbols;
   }
 
-  std::map<std::string, symbol_record>& symbols (void)
+  std::map<std::string, symbol_record>& symbols ()
   {
     return m_symbols;
   }
 
-  std::list<symbol_record> symbol_list (void) const;
+  std::list<symbol_record> symbol_list () const;
 
 private:
 
@@ -390,13 +386,13 @@
 
   symbol_scope& operator = (const symbol_scope&) = default;
 
-  ~symbol_scope (void) = default;
+  ~symbol_scope () = default;
 
-  bool is_valid (void) const { return bool (m_rep); }
+  bool is_valid () const { return bool (m_rep); }
 
   explicit operator bool () const { return bool (m_rep); }
 
-  std::size_t num_symbols (void) const
+  std::size_t num_symbols () const
   {
     return m_rep ? m_rep->num_symbols () : 0;
   }
@@ -412,12 +408,12 @@
       m_rep->insert_symbol_record (sr);
   }
 
-  bool is_nested (void) const
+  bool is_nested () const
   {
     return m_rep ? m_rep->is_nested () : false;
   }
 
-  bool is_parent (void) const
+  bool is_parent () const
   {
     return m_rep ? m_rep->is_parent () : false;
   }
@@ -428,33 +424,33 @@
       m_rep->set_nesting_depth (depth);
   }
 
-  std::size_t nesting_depth (void) const
+  std::size_t nesting_depth () const
   {
     return m_rep ? m_rep->nesting_depth () : 0;
   }
 
-  bool is_static (void) const
+  bool is_static () const
   {
     return m_rep ? m_rep->is_static () : false;
   }
 
-  void mark_static (void)
+  void mark_static ()
   {
     if (m_rep)
       m_rep->mark_static ();
   }
 
-  std::shared_ptr<symbol_scope_rep> parent_scope (void) const
+  std::shared_ptr<symbol_scope_rep> parent_scope () const
   {
     return m_rep ? m_rep->parent_scope_rep () : nullptr;
   }
 
-  std::shared_ptr<symbol_scope_rep> primary_parent_scope (void) const
+  std::shared_ptr<symbol_scope_rep> primary_parent_scope () const
   {
     return m_rep ? m_rep->primary_parent_scope_rep () : nullptr;
   }
 
-  symbol_scope dup (void) const
+  symbol_scope dup () const
   {
     return symbol_scope (m_rep ? m_rep->dup () : nullptr);
   }
@@ -513,26 +509,26 @@
     return m_rep ? m_rep->find_subfunction (name) : octave_value ();
   }
 
-  void lock_subfunctions (void)
+  void lock_subfunctions ()
   {
     if (m_rep)
       m_rep->lock_subfunctions ();
   }
 
-  void unlock_subfunctions (void)
+  void unlock_subfunctions ()
   {
     if (m_rep)
       m_rep->unlock_subfunctions ();
   }
 
-  std::map<std::string, octave_value> subfunctions (void) const
+  std::map<std::string, octave_value> subfunctions () const
   {
     return (m_rep
             ? m_rep->subfunctions ()
             : std::map<std::string, octave_value> ());
   }
 
-  void erase_subfunctions (void)
+  void erase_subfunctions ()
   {
     if (m_rep)
       m_rep->erase_subfunctions ();
@@ -544,7 +540,7 @@
       m_rep->mark_subfunctions_in_scope_as_private (class_name);
   }
 
-  bool has_subfunctions (void) const
+  bool has_subfunctions () const
   {
     return m_rep ? m_rep->has_subfunctions () : false;
   }
@@ -555,20 +551,20 @@
       m_rep->stash_subfunction_names (names);
   }
 
-  std::list<std::string> subfunction_names (void) const
+  std::list<std::string> subfunction_names () const
   {
     return m_rep ? m_rep->subfunction_names () : std::list<std::string> ();
   }
 
   // List of function handle objects.
-  std::list<octave_value> localfunctions (void) const;
+  std::list<octave_value> localfunctions () const;
 
-  octave_value dump (void) const
+  octave_value dump () const
   {
     return m_rep ? m_rep->dump () : octave_value ();
   }
 
-  std::string name (void) const
+  std::string name () const
   {
     return m_rep ? m_rep->name () : "";
   }
@@ -579,7 +575,7 @@
       m_rep->cache_name (name);
   }
 
-  std::string fcn_name (void) const
+  std::string fcn_name () const
   {
     return m_rep ? m_rep->fcn_name () : "";
   }
@@ -590,12 +586,12 @@
       m_rep->cache_fcn_name (name);
   }
 
-  std::list<std::string> parent_fcn_names (void) const
+  std::list<std::string> parent_fcn_names () const
   {
     return m_rep ? m_rep->parent_fcn_names () : std::list<std::string> ();
   }
 
-  octave_user_code * user_code (void) const
+  octave_user_code * user_code () const
   {
     return m_rep ? m_rep->user_code () : nullptr;
   }
@@ -630,23 +626,23 @@
       m_rep->cache_dir_name (name);
   }
 
-  std::string fcn_file_name (void) const
+  std::string fcn_file_name () const
   {
     return m_rep ? m_rep->fcn_file_name () : "";
   }
 
-  std::string dir_name (void) const
+  std::string dir_name () const
   {
     return m_rep ? m_rep->dir_name () : "";
   }
 
-  void mark_primary_fcn_scope (void)
+  void mark_primary_fcn_scope ()
   {
     if (m_rep)
       m_rep->mark_primary_fcn_scope ();
   }
 
-  bool is_primary_fcn_scope (void) const
+  bool is_primary_fcn_scope () const
   {
     return m_rep ? m_rep->is_primary_fcn_scope () : false;
   }
@@ -673,7 +669,7 @@
     return m_rep ? m_rep->is_variable (nm) : false;
   }
 
-  void update_nest (void)
+  void update_nest ()
   {
     if (m_rep)
       m_rep->update_nest ();
@@ -685,7 +681,7 @@
     return m_rep ? m_rep->look_nonlocal (name, offset, result) : false;
   }
 
-  std::shared_ptr<symbol_scope_rep> get_rep (void) const
+  std::shared_ptr<symbol_scope_rep> get_rep () const
   {
     return m_rep;
   }
@@ -700,21 +696,21 @@
     return a.m_rep != b.m_rep;
   }
 
-  const std::map<std::string, symbol_record>& symbols (void) const
+  const std::map<std::string, symbol_record>& symbols () 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)
+  std::map<std::string, symbol_record>& symbols ()
   {
     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
+  std::list<symbol_record> symbol_list () const
   {
     static const std::list<symbol_record> empty_list;
 
--- a/libinterp/corefcn/symtab.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symtab.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,7 +57,7 @@
   install_builtins ();
 }
 
-symbol_scope symbol_table::current_scope (void) const
+symbol_scope symbol_table::current_scope () const
 {
   tree_evaluator& tw = m_interpreter.get_evaluator ();
 
@@ -495,7 +495,7 @@
     }
 }
 
-void symbol_table::clear_mex_functions (void)
+void symbol_table::clear_mex_functions ()
 {
   auto p = m_fcn_table.begin ();
 
@@ -578,7 +578,7 @@
     error ("install_built_in_dispatch: '%s' is undefined", name.c_str ());
 }
 
-std::list<std::string> symbol_table::user_function_names (void)
+std::list<std::string> symbol_table::user_function_names ()
 {
   std::list<std::string> retval;
 
@@ -594,7 +594,7 @@
   return retval;
 }
 
-std::list<std::string> symbol_table::built_in_function_names (void)
+std::list<std::string> symbol_table::built_in_function_names ()
 {
   std::list<std::string> retval;
 
@@ -612,7 +612,7 @@
   return retval;
 }
 
-std::list<std::string> symbol_table::cmdline_function_names (void)
+std::list<std::string> symbol_table::cmdline_function_names ()
 {
   std::list<std::string> retval;
 
@@ -650,7 +650,7 @@
   return octave_value (info_map);
 }
 
-octave_value symbol_table::dump (void) const
+octave_value symbol_table::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "function_info", dump_fcn_table_map () },
@@ -691,7 +691,7 @@
   return retval;
 }
 
-void symbol_table::cleanup (void)
+void symbol_table::cleanup ()
 {
   clear_functions ();
 
@@ -706,7 +706,7 @@
   return p != m_fcn_table.end () ? &p->second : nullptr;
 }
 
-octave_value symbol_table::dump_fcn_table_map (void) const
+octave_value symbol_table::dump_fcn_table_map () const
 {
   if (m_fcn_table.empty ())
     return octave_value (Matrix ());
@@ -741,8 +741,7 @@
     return symtab.dump ();
   else
     {
-      std::string fname = args(
-                            0).xstring_value ("__dump_symtab_info__: argument must be a function name");
+      std::string fname = args(0).xstring_value ("__dump_symtab_info__: argument must be a function name");
 
       fcn_info *finfo = symtab.get_fcn_info (fname);
 
@@ -762,8 +761,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  std::string name = args(
-                       0).xstring_value ("__get_cmdline_fcn_txt__: first argument must be function name");
+  std::string name = args(0).xstring_value ("__get_cmdline_fcn_txt__: first argument must be function name");
 
   symbol_table& symtab = interp.get_symbol_table ();
 
--- a/libinterp/corefcn/symtab.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/symtab.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,15 +60,11 @@
 
   symbol_table (interpreter& interp);
 
-  // No copying!
-
-  symbol_table (const symbol_table&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (symbol_table)
 
-  symbol_table& operator = (const symbol_table&) = delete;
+  ~symbol_table () = default;
 
-  ~symbol_table (void) = default;
-
-  symbol_scope current_scope (void) const;
+  symbol_scope current_scope () const;
 
   bool is_built_in_function_name (const std::string& name);
 
@@ -155,7 +151,7 @@
   // This clears oct and mex files, including autoloads.
   void clear_dld_function (const std::string& name);
 
-  void clear_mex_functions (void);
+  void clear_mex_functions ();
 
   bool set_class_relationship (const std::string& sup_class,
                                const std::string& inf_class);
@@ -168,20 +164,20 @@
   void install_built_in_dispatch (const std::string& name,
                                   const std::string& klass);
 
-  std::list<std::string> user_function_names (void);
+  std::list<std::string> user_function_names ();
 
-  std::list<std::string> built_in_function_names (void);
+  std::list<std::string> built_in_function_names ();
 
-  std::list<std::string> cmdline_function_names (void);
+  std::list<std::string> cmdline_function_names ();
 
-  octave_value dump (void) const;
+  octave_value dump () const;
 
   void add_to_parent_map (const std::string& classname,
                           const std::list<std::string>& parent_list);
 
   std::list<std::string> parent_classes (const std::string& dispatch_type);
 
-  void cleanup (void);
+  void cleanup ();
 
   fcn_info * get_fcn_info (const std::string& name);
 
@@ -222,10 +218,10 @@
   typedef std::map<std::string, std::list<std::string>>::iterator
       parent_map_iterator;
 
-  octave_value dump_fcn_table_map (void) const;
+  octave_value dump_fcn_table_map () const;
 
   // This function is generated automatically by mk-builtins.pl.
-  void install_builtins (void);
+  void install_builtins ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/sysdep.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sysdep.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -108,7 +108,7 @@
 #if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
 
 static void
-BSD_init (void)
+BSD_init ()
 {
 #  if defined (HAVE_FLOATINGPOINT_H)
   // Disable trapping on common exceptions.
@@ -124,7 +124,7 @@
 #if defined (__MINGW32__) || defined (_MSC_VER)
 
 static void
-w32_set_octave_home (void)
+w32_set_octave_home ()
 {
   std::string bin_dir;
 
@@ -171,7 +171,7 @@
 }
 
 static void
-w32_init (void)
+w32_init ()
 {
   w32_set_octave_home ();
 
@@ -180,7 +180,7 @@
 
 #endif
 
-void set_application_id (void)
+void set_application_id ()
 {
 #if defined (__MINGW32__) || defined (_MSC_VER)
 
@@ -363,7 +363,7 @@
 #if defined (__MINGW32__)
 
 static void
-MINGW_init (void)
+MINGW_init ()
 {
   w32_init ();
 }
@@ -373,88 +373,13 @@
 #if defined (_MSC_VER)
 
 static void
-MSVC_init (void)
+MSVC_init ()
 {
   w32_init ();
 }
 
 #endif
 
-// Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
-
-bool same_file_internal (const std::string& file1, const std::string& file2)
-{
-#if defined (OCTAVE_USE_WINDOWS_API)
-
-  // FIXME: When Octave switches to C++17, consider replacing this function
-  //        by https://en.cppreference.com/w/cpp/filesystem/equivalent.
-
-  bool retval = false;
-
-  std::wstring file1w = sys::u8_to_wstring (file1);
-  std::wstring file2w = sys::u8_to_wstring (file2);
-  const wchar_t *f1 = file1w.c_str ();
-  const wchar_t *f2 = file2w.c_str ();
-
-  bool f1_is_dir = GetFileAttributesW (f1) & FILE_ATTRIBUTE_DIRECTORY;
-  bool f2_is_dir = GetFileAttributesW (f2) & FILE_ATTRIBUTE_DIRECTORY;
-
-  // Windows native code
-  // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx
-
-  DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-
-  HANDLE hfile1
-    = CreateFileW (f1, 0, share, 0, OPEN_EXISTING,
-                   f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
-
-  if (hfile1 != INVALID_HANDLE_VALUE)
-    {
-      HANDLE hfile2
-        = CreateFileW (f2, 0, share, 0, OPEN_EXISTING,
-                       f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
-
-      if (hfile2 != INVALID_HANDLE_VALUE)
-        {
-          BY_HANDLE_FILE_INFORMATION hfi1;
-          BY_HANDLE_FILE_INFORMATION hfi2;
-
-          if (GetFileInformationByHandle (hfile1, &hfi1)
-              && GetFileInformationByHandle (hfile2, &hfi2))
-            {
-              retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber
-                        && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh
-                        && hfi1.nFileIndexLow == hfi2.nFileIndexLow
-                        && hfi1.nFileSizeHigh == hfi2.nFileSizeHigh
-                        && hfi1.nFileSizeLow == hfi2.nFileSizeLow
-                        && hfi1.ftLastWriteTime.dwLowDateTime
-                        == hfi2.ftLastWriteTime.dwLowDateTime
-                        && hfi1.ftLastWriteTime.dwHighDateTime
-                        == hfi2.ftLastWriteTime.dwHighDateTime);
-            }
-
-          CloseHandle (hfile2);
-        }
-
-      CloseHandle (hfile1);
-    }
-
-  return retval;
-
-#else
-
-  // POSIX Code
-
-  sys::file_stat fs_file1 (file1);
-  sys::file_stat fs_file2 (file2);
-
-  return (fs_file1 && fs_file2
-          && fs_file1.ino () == fs_file2.ino ()
-          && fs_file1.dev () == fs_file2.dev ());
-
-#endif
-}
-
 // Return TRUE if NAME refers to an existing drive letter or UNC share
 
 bool drive_or_unc_share (const std::string& name)
@@ -506,7 +431,7 @@
 #endif
 }
 
-void sysdep_init (void)
+void sysdep_init ()
 {
   // Use a function from libgomp to force loading of OpenMP library.
   // Otherwise, a dynamically loaded library making use of OpenMP such
@@ -524,7 +449,7 @@
 #endif
 }
 
-void sysdep_cleanup (void)
+void sysdep_cleanup ()
 {
 #if defined (OCTAVE_USE_WINDOWS_API)
   // Let us fail immediately without displaying any dialog.
@@ -763,7 +688,7 @@
   return c;
 }
 
-std::string get_P_tmpdir (void)
+std::string get_P_tmpdir ()
 {
 #if defined (OCTAVE_USE_WINDOWS_API)
 
@@ -1134,10 +1059,9 @@
         error ("winqueryreg: error %ld reading names from registry", retval);
 
       Cell fieldnames (dim_vector (1, fields.size ()));
-      std::size_t i;
-      std::list<std::string>::const_iterator it;
-      for (i = 0, it = fields.begin (); it != fields.end (); ++it, ++i)
-        fieldnames(i) = *it;
+      std::size_t i = 0;
+      for (const auto& it : fields)
+        fieldnames(i++) = it;
 
       return ovl (fieldnames);
     }
--- a/libinterp/corefcn/sysdep.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/sysdep.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,11 +37,11 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-extern OCTINTERP_API void sysdep_init (void);
+extern OCTINTERP_API void sysdep_init ();
 
-extern OCTINTERP_API void set_application_id (void);
+extern OCTINTERP_API void set_application_id ();
 
-extern OCTINTERP_API void sysdep_cleanup (void);
+extern OCTINTERP_API void sysdep_cleanup ();
 
 extern OCTINTERP_API void raw_mode (bool, bool wait = true);
 
@@ -51,10 +51,7 @@
 
 extern OCTINTERP_API int kbhit (bool wait = true);
 
-extern OCTINTERP_API std::string get_P_tmpdir (void);
-
-extern OCTINTERP_API bool same_file_internal (const std::string&,
-                                              const std::string&);
+extern OCTINTERP_API std::string get_P_tmpdir ();
 
 extern OCTINTERP_API bool drive_or_unc_share (const std::string&);
 
--- a/libinterp/corefcn/text-engine.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/text-engine.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 uint32_t
-text_element_symbol::get_symbol_code (void) const
+text_element_symbol::get_symbol_code () const
 {
   uint32_t code = invalid_code;
 
--- a/libinterp/corefcn/text-engine.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/text-engine.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,14 +56,12 @@
 text_element
 {
 public:
-  text_element (void) { }
 
-  virtual ~text_element (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_element)
+
+  virtual ~text_element () = default;
 
   virtual void accept (text_processor& p) = 0;
-
-private:
-  text_element (const text_element&);
 };
 
 class
@@ -71,19 +69,17 @@
 text_element_string : public text_element
 {
 public:
+
   text_element_string (const std::string& s = "")
     : text_element (), m_str (s) { }
 
-  ~text_element_string (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_string)
 
-  std::string string_value (void) const { return m_str; }
+  std::string string_value () const { return m_str; }
 
   void accept (text_processor& p);
 
 private:
-  text_element_string (const text_element_string&);
-
-  //--------
 
   std::string m_str;
 };
@@ -93,16 +89,19 @@
 text_element_symbol : public text_element
 {
 public:
+
   enum { invalid_code = 0xFFFFFFFFU };
 
+  text_element_symbol () = delete;
+
   text_element_symbol (int sym)
     : text_element (), m_symbol (sym) { }
 
-  ~text_element_symbol (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_symbol)
 
-  int get_symbol (void) const { return m_symbol; }
+  int get_symbol () const { return m_symbol; }
 
-  uint32_t get_symbol_code (void) const;
+  uint32_t get_symbol_code () const;
 
   void accept (text_processor& p);
 
@@ -116,8 +115,8 @@
   : public text_element, public base_list<text_element *>
 {
 public:
-  text_element_list (void)
-    : text_element (), base_list<text_element*> () { }
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_element_list)
 
   text_element_list (text_element *e)
     : text_element (), base_list<text_element*> ()
@@ -125,7 +124,7 @@
     push_back (e);
   }
 
-  ~text_element_list (void)
+  ~text_element_list ()
   {
     while (! empty ())
       {
@@ -143,6 +142,9 @@
 text_element_subscript : public text_element
 {
 public:
+
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text_element_subscript)
+
   text_element_subscript (text_element *e)
     : text_element (), m_elem (e) { }
 
@@ -150,20 +152,16 @@
     : text_element ()
   { m_elem = new text_element_string (std::string (1, c)); }
 
-  ~text_element_subscript (void)
+  ~text_element_subscript ()
   { delete m_elem; }
 
   void accept (text_processor& p);
 
-  text_element * get_element (void) { return m_elem; }
+  text_element * get_element () { return m_elem; }
 
 private:
-  text_element_subscript (void);
-
-  //--------
 
   text_element *m_elem;
-
 };
 
 class
@@ -171,6 +169,9 @@
 text_element_superscript : public text_element
 {
 public:
+
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (text_element_superscript)
+
   text_element_superscript (text_element *e)
     : text_element (), m_elem (e) { }
 
@@ -178,20 +179,16 @@
     : text_element ()
   { m_elem = new text_element_string (std::string (1, c)); }
 
-  ~text_element_superscript (void)
+  ~text_element_superscript ()
   { delete m_elem; }
 
   void accept (text_processor& p);
 
-  text_element * get_element (void) { return m_elem; }
+  text_element * get_element () { return m_elem; }
 
 private:
-  text_element_superscript (void);
-
-  //--------
 
   text_element *m_elem;
-
 };
 
 class
@@ -199,6 +196,9 @@
 text_element_combined : public text_element_list
 {
 public:
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (text_element_combined)
+
   text_element_combined (text_element *e)
     : text_element_list (e) { }
 
@@ -214,6 +214,7 @@
 text_element_fontstyle : public text_element
 {
 public:
+
   enum fontstyle
   {
     normal,
@@ -222,22 +223,20 @@
     oblique
   };
 
+  text_element_fontstyle () = delete;
+
   text_element_fontstyle (fontstyle st)
     : text_element (), m_style (st) { }
 
-  ~text_element_fontstyle (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontstyle)
 
-  fontstyle get_fontstyle (void) const { return m_style; }
+  fontstyle get_fontstyle () const { return m_style; }
 
   void accept (text_processor& p);
 
 private:
-  text_element_fontstyle (void);
-
-  //--------
 
   fontstyle m_style;
-
 };
 
 class
@@ -245,22 +244,21 @@
 text_element_fontname : public text_element
 {
 public:
+
+  text_element_fontname () = delete;
+
   text_element_fontname (const std::string& fname)
     : text_element (), m_name (fname) { }
 
-  ~text_element_fontname (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontname)
 
-  const std::string& get_fontname (void) const { return m_name; }
+  const std::string& get_fontname () const { return m_name; }
 
   void accept (text_processor& p);
 
 private:
-  text_element_fontname (void);
-
-  //--------
 
   std::string m_name;
-
 };
 
 class
@@ -268,22 +266,21 @@
 text_element_fontsize : public text_element
 {
 public:
+
+  text_element_fontsize () = delete;
+
   text_element_fontsize (double fsize)
     : text_element (), m_size (fsize) { }
 
-  ~text_element_fontsize (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_fontsize)
 
-  double get_fontsize (void) const { return m_size; }
+  double get_fontsize () const { return m_size; }
 
   void accept (text_processor& p);
 
 private:
-  text_element_fontsize (void);
-
-  //--------
 
   double m_size;
-
 };
 
 class
@@ -291,6 +288,9 @@
 text_element_color : public text_element
 {
 public:
+
+  text_element_color () = delete;
+
   text_element_color (double r, double g, double b)
     : text_element (), m_rgb (1, 3, 0.0)
   {
@@ -317,13 +317,14 @@
 #undef ASSIGN_COLOR
                         }
 
-  ~text_element_color (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (text_element_color)
 
-  Matrix get_color (void) { return m_rgb; }
+  Matrix get_color () { return m_rgb; }
 
   void accept (text_processor& p);
 
 private:
+
   Matrix m_rgb;
 };
 
@@ -332,6 +333,7 @@
 text_processor
 {
 public:
+
   virtual void visit (text_element_string&) { }
 
   virtual void visit (text_element_symbol&) { }
@@ -360,12 +362,13 @@
 
   virtual void visit (text_element_color&) { }
 
-  virtual void reset (void) { }
+  virtual void reset () { }
 
 protected:
-  text_processor (void) { }
 
-  virtual ~text_processor (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_processor)
+
+  virtual ~text_processor () = default;
 };
 
 #define TEXT_ELEMENT_ACCEPT(cls)                \
@@ -391,9 +394,10 @@
 text_parser
 {
 public:
-  text_parser (void) { }
 
-  virtual ~text_parser (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_parser)
+
+  virtual ~text_parser () = default;
 
   virtual text_element * parse (const std::string& s) = 0;
 
@@ -407,9 +411,8 @@
 text_parser_none : public text_parser
 {
 public:
-  text_parser_none (void) : text_parser () { }
 
-  ~text_parser_none (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (text_parser_none)
 
   // FIXME: is it possible to use reference counting to manage the
   // memory for the object returned by the text parser?  That would be
@@ -427,26 +430,29 @@
 text_parser_tex : public text_parser
 {
 public:
-  text_parser_tex (void)
+
+  text_parser_tex ()
     : text_parser (), m_scanner (nullptr), m_buffer_state (nullptr),
       m_result (nullptr)
   { }
 
-  ~text_parser_tex (void)
+  OCTAVE_DISABLE_COPY_MOVE (text_parser_tex)
+
+  ~text_parser_tex ()
   { destroy_lexer (); }
 
   text_element * parse (const std::string& s);
 
-  void * get_scanner (void) { return m_scanner; }
+  void * get_scanner () { return m_scanner; }
 
   void set_parse_result (text_element *e) { m_result = e; }
 
-  text_element * get_parse_result (void) { return m_result; }
+  text_element * get_parse_result () { return m_result; }
 
 private:
   bool init_lexer (const std::string& s);
 
-  void destroy_lexer (void);
+  void destroy_lexer ();
 
   //--------
 
--- a/libinterp/corefcn/text-renderer.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/text-renderer.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,19 +36,19 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-text_renderer::text_renderer (void)
+text_renderer::text_renderer ()
   : m_rep (make_ft_text_renderer ()),
     m_latex_rep (make_latex_text_renderer ())
 { }
 
-text_renderer::~text_renderer (void)
+text_renderer::~text_renderer ()
 {
   delete m_rep;
   delete m_latex_rep;
 }
 
 bool
-text_renderer::ok (void) const
+text_renderer::ok () const
 {
   static bool warned = false;
 
@@ -96,7 +96,7 @@
 }
 
 octave_map
-text_renderer::get_system_fonts (void)
+text_renderer::get_system_fonts ()
 {
   octave_map retval;
 
--- a/libinterp/corefcn/text-renderer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/text-renderer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,17 +47,13 @@
 {
 public:
 
-  text_renderer (void);
+  text_renderer ();
 
-  // No copying!
-
-  text_renderer (const text_renderer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (text_renderer)
 
-  text_renderer& operator = (const text_renderer&) = delete;
+  ~text_renderer ();
 
-  ~text_renderer (void);
-
-  bool ok (void) const;
+  bool ok () const;
 
   Matrix get_extent (text_element *elt, double rotation = 0.0);
 
@@ -69,7 +65,7 @@
   void set_font (const std::string& name, const std::string& weight,
                  const std::string& angle, double size);
 
-  octave_map get_system_fonts (void);
+  octave_map get_system_fonts ();
 
   void set_color (const Matrix& c);
 
@@ -83,7 +79,7 @@
   {
   public:
 
-    font (void)
+    font ()
       : m_name (), m_weight (), m_angle (), m_size (0)
     { }
 
@@ -97,7 +93,7 @@
         m_size (ft.m_size)
     { }
 
-    ~font (void) = default;
+    ~font () = default;
 
     font& operator = (const font& ft)
     {
@@ -112,13 +108,13 @@
       return *this;
     }
 
-    std::string get_name (void) const { return m_name; }
+    std::string get_name () const { return m_name; }
 
-    std::string get_weight (void) const { return m_weight; }
+    std::string get_weight () const { return m_weight; }
 
-    std::string get_angle (void) const { return m_angle; }
+    std::string get_angle () const { return m_angle; }
 
-    double get_size (void) const { return m_size; }
+    double get_size () const { return m_size; }
 
   protected:
 
@@ -134,77 +130,55 @@
   {
   public:
 
-    string (const std::string& s, font& f, const double x, const double y)
+    string () = delete;
+
+    string (const std::string& s, const font& f, double x, double y)
       : m_str (s), m_family (f.get_name ()), m_fnt (f), m_x (x), m_y (y),
         m_z (0.0), m_xdata (), m_code (0), m_color (Matrix (1, 3, 0.0)),
         m_svg_element ()
     { }
 
-    string (const string& s)
-      : m_str (s.m_str), m_family (s.m_family), m_fnt (s.m_fnt), m_x (s.m_x),
-        m_y (s.m_y), m_z (s.m_z), m_xdata (s.m_xdata), m_code (s.m_code),
-        m_color (s.m_color), m_svg_element (s.m_svg_element)
-    { }
-
-    ~string (void) = default;
-
-    string& operator = (const string& s)
-    {
-      if (&s != this)
-        {
-          m_str = s.m_str;
-          m_family = s.m_family;
-          m_fnt = s.m_fnt;
-          m_x = s.m_x;
-          m_y = s.m_y;
-          m_z = s.m_z;
-          m_xdata = s.m_xdata;
-          m_code = s.m_code;
-          m_color = s.m_color;
-        }
-
-      return *this;
-    }
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (string)
 
     void set_string (const std::string& s) { m_str = s; }
 
-    std::string get_string (void) const { return m_str; }
+    std::string get_string () const { return m_str; }
 
-    std::string get_name (void) const { return m_fnt.get_name (); }
+    std::string get_name () const { return m_fnt.get_name (); }
 
-    std::string get_family (void) const { return m_family; }
+    std::string get_family () const { return m_family; }
 
     void set_family (const std::string& nm) { m_family = nm; }
 
-    std::string get_weight (void) const { return m_fnt.get_weight (); }
+    std::string get_weight () const { return m_fnt.get_weight (); }
 
-    std::string get_angle (void) const { return m_fnt.get_angle (); }
+    std::string get_angle () const { return m_fnt.get_angle (); }
 
-    double get_size (void) const { return m_fnt.get_size (); }
+    double get_size () const { return m_fnt.get_size (); }
 
     void set_x (const double x) { m_x = x; }
 
-    double get_x (void) const { return m_x; }
+    double get_x () const { return m_x; }
 
     void set_xdata (const std::vector<double>& x) { m_xdata = x; }
 
-    std::vector<double> get_xdata (void) const { return m_xdata; }
+    std::vector<double> get_xdata () const { return m_xdata; }
 
     void set_y (const double y) { m_y = y; }
 
-    double get_y (void) const { return m_y; }
+    double get_y () const { return m_y; }
 
     void set_z (const double z) { m_z = z; }
 
-    double get_z (void) const { return m_z; }
+    double get_z () const { return m_z; }
 
     void set_code (const uint32_t code) { m_code = code; }
 
-    uint32_t get_code (void) const { return m_code; }
+    uint32_t get_code () const { return m_code; }
 
     void set_svg_element (const std::string& svg) { m_svg_element = svg; }
 
-    std::string get_svg_element (void) const { return m_svg_element; }
+    std::string get_svg_element () const { return m_svg_element; }
 
     void set_color (const uint8NDArray& c)
     {
@@ -213,7 +187,7 @@
       m_color(2) = static_cast<double> (c(2)) / 255;
     }
 
-    Matrix get_color (void) const { return m_color; }
+    Matrix get_color () const { return m_color; }
 
   private:
 
--- a/libinterp/corefcn/time.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/time.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -267,8 +267,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  octave_scalar_map map = args(
-                            0).xscalar_map_value ("mktime: TM_STRUCT argument must be a structure");
+  octave_scalar_map map = args(0).xscalar_map_value ("mktime: TM_STRUCT argument must be a structure");
 
   sys::base_tm tm = extract_tm (map, "mktime");
 
--- a/libinterp/corefcn/toplev.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/toplev.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -158,7 +158,7 @@
 // Combine alloc+get in one action.
 
 static void *
-get_signal_mask (void)
+get_signal_mask ()
 {
   void *mask = octave_alloc_signal_mask ();
 
@@ -540,7 +540,6 @@
         { "QT_CPPFLAGS", build_env::QT_CPPFLAGS },
         { "QT_LDFLAGS", build_env::QT_LDFLAGS },
         { "QT_LIBS", build_env::QT_LIBS },
-        { "QT_OPENGL_LIBS", build_env::QT_OPENGL_LIBS },
         { "RANLIB", build_env::RANLIB },
         { "RDYNAMIC_FLAG", build_env::RDYNAMIC_FLAG },
         { "READLINE_LIBS", build_env::READLINE_LIBS },
@@ -614,8 +613,7 @@
 
   if (nargin == 1)
     {
-      std::string arg = args(
-                          0).xstring_value ("__octave_config_info__: OPTION argument must be a string");
+      std::string arg = args(0).xstring_value ("__octave_config_info__: OPTION argument must be a string");
 
       octave_value info = find_config_info (config, arg);
 
@@ -654,7 +652,7 @@
 
 int debug_new_delete = 0;
 
-typedef void (*vfp)(void);
+typedef void (*vfp)();
 extern vfp __new_handler;
 
 void *
--- a/libinterp/corefcn/url-handle-manager.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/url-handle-manager.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,14 +36,14 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static double
-make_handle_fraction (void)
+make_handle_fraction ()
 {
   static double maxrand = RAND_MAX + 2.0;
 
   return (rand () + 1.0) / maxrand;
 }
 
-url_handle url_handle_manager::get_handle (void)
+url_handle url_handle_manager::get_handle ()
 {
   url_handle retval;
 
--- a/libinterp/corefcn/url-handle-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/url-handle-manager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,17 +48,15 @@
 {
 public:
 
-  url_handle_manager (void)
+  url_handle_manager ()
     : m_handle_map (), m_handle_free_list (),
       m_next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)) { }
 
-  url_handle_manager (const url_handle_manager&) = delete;
-
-  url_handle_manager& operator = (const url_handle_manager&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (url_handle_manager)
 
-  ~url_handle_manager (void) = default;
+  ~url_handle_manager () = default;
 
-  url_handle get_handle (void);
+  url_handle get_handle ();
 
   void free (const url_handle& h);
 
@@ -110,7 +108,7 @@
     return h;
   }
 
-  Matrix handle_list (void)
+  Matrix handle_list ()
   {
     Matrix retval (1, m_handle_map.size ());
 
--- a/libinterp/corefcn/urlwrite.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/urlwrite.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -126,8 +126,7 @@
       if (method != "get" && method != "post")
         error (R"(urlwrite: METHOD must be "get" or "post")");
 
-      param = args(
-                3).xcellstr_value ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of strings");
+      param = args(3).xcellstr_value ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of strings");
 
       if (param.numel () % 2 == 1)
         error ("urlwrite: number of elements in PARAM must be even");
@@ -137,8 +136,6 @@
   // create it, and the download fails.  We use unwind_protect to do
   // it so that the deletion happens no matter how we exit the function.
 
-  sys::file_stat fs (filename);
-
   std::ofstream ofile =
     sys::ofstream (filename.c_str (), std::ios::out | std::ios::binary);
 
@@ -238,8 +235,7 @@
       if (method != "get" && method != "post")
         error (R"(urlread: METHOD must be "get" or "post")");
 
-      param = args(
-                2).xcellstr_value ("urlread: parameters (PARAM) for get and post requests must be given as a cell array of strings");
+      param = args(2).xcellstr_value ("urlread: parameters (PARAM) for get and post requests must be given as a cell array of strings");
 
       if (param.numel () % 2 == 1)
         error ("urlread: number of elements in PARAM must be even");
@@ -254,18 +250,17 @@
 
   url_xfer.http_action (param, method);
 
-  octave_value_list retval;
-
-  if (nargout > 0)
-    {
-      // Return empty string if no error occurred.
-      retval = ovl (buf.str (), url_xfer.good (),
-                    url_xfer.good () ? "" : url_xfer.lasterror ());
-    }
-
   if (nargout < 2 && ! url_xfer.good ())
     error ("urlread: %s", url_xfer.lasterror ().c_str ());
 
+  octave_value_list retval (std::max (1, std::min (nargout, 3)));
+
+  retval(0) = buf.str ();
+  if (nargout > 1)
+    retval(1) = url_xfer.good ();
+  if (nargout > 2)
+    retval(2) = url_xfer.good () ? "" : url_xfer.lasterror ();
+
   return retval;
 }
 
--- a/libinterp/corefcn/utils.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/utils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,6 +39,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "lo-mappers.h"
+#include "lo-sysdep.h"
 #include "lo-utils.h"
 #include "nanosleep-wrapper.h"
 #include "oct-cmplx.h"
@@ -293,7 +294,7 @@
 
 bool same_file (const std::string& f, const std::string& g)
 {
-  return same_file_internal (f, g);
+  return sys::same_file (f, g);
 }
 
 DEFUN (is_same_file, args, ,
@@ -336,7 +337,7 @@
       std::string file1 = args(0).string_value ();
       std::string file2 = args(1).string_value ();
 
-      retval = same_file (file1, file2);
+      retval = sys::same_file (file1, file2);
     }
   else if ((s1_string && s2_cellstr) || (s1_cellstr && s2_string))
     {
@@ -359,7 +360,7 @@
       boolNDArray output (cellstr.dims (), false);
 
       for (octave_idx_type idx = 0; idx < cellstr.numel (); idx++)
-        output(idx) = same_file (str, cellstr(idx));
+        output(idx) = sys::same_file (str, cellstr(idx));
 
       retval = output;
     }
@@ -377,7 +378,7 @@
       boolNDArray output (size1, false);
 
       for (octave_idx_type idx = 0; idx < cellstr1.numel (); idx++)
-        output(idx) = same_file (cellstr1(idx), cellstr2(idx));
+        output(idx) = sys::same_file (cellstr1(idx), cellstr2(idx));
 
       retval = output;
     }
@@ -391,7 +392,7 @@
 %!testif ; ! ispc ()
 %! assert (is_same_file ("~", tilde_expand ("~")));
 %!testif ; ispc ()
-%! assert (is_same_file (tolower (tempdir ()), toupper (tempdir ())), true);
+%! assert (is_same_file (lower (tempdir ()), upper (tempdir ())), true);
 %!assert (is_same_file ({pwd(), ".", tempdir()}, canonicalize_file_name (".")),
 %!        [true, true, false])
 
@@ -573,8 +574,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  string_vector names = args(
-                          0).xstring_vector_value ("file_in_loadpath: FILE argument must be a string");
+  string_vector names = args(0).xstring_vector_value ("file_in_loadpath: FILE argument must be a string");
 
   if (names.empty ())
     error ("file_in_loadpath: FILE argument must not be empty");
@@ -585,8 +585,7 @@
     return ovl (sys::env::make_absolute (lp.find_first_of (names)));
   else
     {
-      std::string opt = args(
-                          1).xstring_value ("file_in_loadpath: optional second argument must be a string");
+      std::string opt = args(1).xstring_value ("file_in_loadpath: optional second argument must be a string");
 
       if (opt != "all")
         error (R"(file_in_loadpath: "all" is only valid second argument)");
@@ -712,10 +711,8 @@
       // Load path will also search "." first, but we don't want to
       // issue a warning if the file is found in the current directory,
       // so do an explicit check for that.
-      sys::file_stat fs (fname);
-
       bool local_file_ok
-        = fs.exists () && (fs.is_reg () || ! require_regular_file);
+        = sys::file_exists (fname, ! require_regular_file);
 
       if (! local_file_ok)
         {
@@ -736,7 +733,7 @@
   return fname;
 }
 
-// See if there is an function file in the path.
+// See if there is a function file in the path.
 // If so, return the full path to the file.
 
 std::string fcn_file_in_path (const std::string& name)
@@ -749,9 +746,7 @@
     {
       if (sys::env::absolute_pathname (name))
         {
-          sys::file_stat fs (name);
-
-          if (fs.exists () && ! fs.is_dir ())
+          if (sys::file_exists (name, false))
             retval = name;
         }
       else if (len > 2 && name[len - 2] == '.' && name[len - 1] == 'm')
@@ -790,9 +785,7 @@
       std::string tcontents
         = sys::file_ops::concat (lp.find_dir (dir), "Contents.m");
 
-      sys::file_stat fs (tcontents);
-
-      if (fs.exists ())
+      if (sys::file_exists (tcontents))
         retval = sys::env::make_absolute (tcontents);
     }
 
@@ -940,8 +933,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  std::string str = args(
-                      0).xstring_value ("do_string_escapes: STRING argument must be of type string");
+  std::string str = args(0).xstring_value ("do_string_escapes: STRING argument must be of type string");
 
   return ovl (do_string_escapes (str));
 }
--- a/libinterp/corefcn/utils.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/utils.h	Fri Jun 23 20:51:51 2023 +0200
@@ -68,6 +68,8 @@
 
   make_valid_name_options () = default;
 
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (make_valid_name_options)
+
   //! Extract attribute-value-pairs from an octave_value_list of strings.
   //!
   //! If attributes occur multiple times, the rightmost pair is chosen.
@@ -103,6 +105,7 @@
 extern OCTINTERP_API bool
 make_valid_name (std::string& str, const make_valid_name_options& options);
 
+OCTAVE_DEPRECATED (9, "octave::same_file is obsolete, use octave::sys::same_file")
 extern OCTINTERP_API bool
 same_file (const std::string& f, const std::string& g);
 
--- a/libinterp/corefcn/variables.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/variables.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -60,7 +60,6 @@
 #include "ov-class.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
-#include "parse.h"
 #include "pt-eval.h"
 #include "syminfo.h"
 #include "symtab.h"
@@ -558,7 +557,7 @@
 }
 
 static octave::unwind_protect *
-curr_fcn_unwind_protect_frame (void)
+curr_fcn_unwind_protect_frame ()
 {
   octave::tree_evaluator& tw = octave::__get_evaluator__ ();
 
@@ -1236,6 +1235,11 @@
 
   string_vector argv = args.make_argv ("clear");
 
+  // FIXME: This action should probably happen in the functions that
+  // are called below, not here.
+  // Mark any function cache in use by the VM as invalid
+  octave::load_path::signal_clear_fcn_cache ();
+
   if (argc == 1)
     {
       do_clear_variables (interp, argv, argc, true);
@@ -1430,7 +1434,7 @@
       Vmissing_function_hook.clear ();
 
       // Call.
-      octave_value_list tmp = octave::feval (fcn_name, octave_value (name), 1);
+      octave_value_list tmp = interp.feval (fcn_name, octave_value (name), 1);
 
       if (tmp.length () == 1 && tmp(0).is_string ())
         return tmp(0).string_value ();
--- a/libinterp/corefcn/variables.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/variables.h	Fri Jun 23 20:51:51 2023 +0200
@@ -107,91 +107,6 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::symbol_exist' instead")
-inline int
-symbol_exist (const std::string& name, const std::string& type = "any")
-{
-  return octave::symbol_exist (name, type);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::unique_symbol_name' instead")
-inline std::string
-unique_symbol_name (const std::string& basename)
-{
-  return octave::unique_symbol_name (basename);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (bool& var, const octave_value_list& args, int nargout,
-                       const char *nm)
-{
-  return octave::set_internal_variable (var, args, nargout, nm);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (char& var, const octave_value_list& args, int nargout,
-                       const char *nm)
-{
-  return octave::set_internal_variable (var, args, nargout, nm);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (int& var, const octave_value_list& args, int nargout,
-                       const char *nm,
-                       int minval = std::numeric_limits<int>::min (),
-                       int maxval = std::numeric_limits<int>::max ())
-{
-  return octave::set_internal_variable (var, args, nargout, nm, minval, maxval);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (double& var, const octave_value_list& args, int nargout,
-                       const char *nm,
-                       double minval = -octave::numeric_limits<double>::Inf (),
-                       double maxval = octave::numeric_limits<double>::Inf ())
-{
-  return octave::set_internal_variable (var, args, nargout, nm, minval, maxval);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (std::string& var, const octave_value_list& args,
-                       int nargout, const char *nm, bool empty_ok = true)
-{
-  return octave::set_internal_variable (var, args, nargout, nm, empty_ok);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (std::string& var, const octave_value_list& args,
-                       int nargout, const char *nm, const char **choices)
-{
-  return octave::set_internal_variable (var, args, nargout, nm, choices);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead")
-inline octave_value
-set_internal_variable (int& var, const octave_value_list& args, int nargout,
-                       const char *nm, const char **choices)
-{
-  return octave::set_internal_variable (var, args, nargout, nm, choices);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::maybe_missing_function_hook' instead")
-inline std::string
-maybe_missing_function_hook (const std::string& name)
-{
-  return octave::maybe_missing_function_hook (name);
-}
-
-#endif
-
 // The following macros should also be considered obsolete.
 
 #define SET_INTERNAL_VARIABLE(NM)                       \
--- a/libinterp/corefcn/xdiv.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/xdiv.h	Fri Jun 23 20:51:51 2023 +0200
@@ -156,415 +156,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline Matrix
-xdiv (const Matrix& a, const Matrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline Matrix
-x_el_div (double a, const Matrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (double a, const ComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (const Complex a, const Matrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexMatrix
-x_el_div (const Complex a, const ComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline NDArray
-x_el_div (double a, const NDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexNDArray
-x_el_div (double a, const ComplexNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexNDArray
-x_el_div (const Complex a, const NDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline ComplexNDArray
-x_el_div (const Complex a, const ComplexNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline Matrix
-xleftdiv (const Matrix& a, const Matrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const Matrix& a, const ComplexMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const ComplexMatrix& a, const Matrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatMatrix
-xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType& typ)
-{
-  return octave::xdiv (a, b, typ);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatMatrix
-x_el_div (float a, const FloatMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexMatrix
-x_el_div (float a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexMatrix
-x_el_div (const FloatComplex a, const FloatMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexMatrix
-x_el_div (const FloatComplex a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatNDArray
-x_el_div (float a, const FloatNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexNDArray
-x_el_div (float a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexNDArray
-x_el_div (const FloatComplex a, const FloatNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead")
-inline FloatComplexNDArray
-x_el_div (const FloatComplex a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatMatrix
-xleftdiv (const FloatMatrix& a, const FloatMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexMatrix
-xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexMatrix
-xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexMatrix
-xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
-          MatrixType& typ, blas_trans_type transt = blas_no_trans)
-{
-  return octave::xleftdiv (a, b, typ, transt);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline Matrix
-xdiv (const Matrix& a, const DiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const DiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexMatrix
-xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline DiagMatrix
-xdiv (const DiagMatrix& a, const DiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexDiagMatrix
-xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline ComplexDiagMatrix
-xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatMatrix
-xdiv (const FloatMatrix& a, const FloatDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatMatrix& a, const FloatComplexDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatDiagMatrix
-xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexDiagMatrix
-xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead")
-inline FloatComplexDiagMatrix
-xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{
-  return octave::xdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline Matrix
-xleftdiv (const DiagMatrix& a, const Matrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const DiagMatrix& a, const ComplexMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexMatrix
-xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline DiagMatrix
-xleftdiv (const DiagMatrix& a, const DiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexDiagMatrix
-xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline ComplexDiagMatrix
-xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexMatrix
-xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatDiagMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexDiagMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead")
-inline FloatComplexDiagMatrix
-xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{
-  return octave::xleftdiv (a, b);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/xnorm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/xnorm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,36 +48,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline octave_value
-xnorm (const octave_value& x, const octave_value& p)
-{
-  return octave::xnorm (x, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline octave_value
-xcolnorms (const octave_value& x, const octave_value& p)
-{
-  return octave::xcolnorms (x, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline octave_value
-xrownorms (const octave_value& x, const octave_value& p)
-{
-  return octave::xrownorms (x, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline octave_value
-xfrobnorm (const octave_value& x)
-{
-  return octave::xfrobnorm (x);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/xpow.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/xpow.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -59,13 +59,13 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static void
-err_failed_diagonalization (void)
+err_failed_diagonalization ()
 {
   error ("Failed to diagonalize matrix while calculating matrix exponential");
 }
 
 static void
-err_nonsquare_matrix (void)
+err_nonsquare_matrix ()
 {
   error ("for x^y, only square matrix arguments are permitted and one " \
          "argument must be scalar.  Use .^ for elementwise power.");
--- a/libinterp/corefcn/xpow.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/corefcn/xpow.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,6 @@
 class ComplexNDArray;
 class FloatComplexNDArray;
 class octave_value;
-class Range;
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -209,589 +208,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (double a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (double a, const Matrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (double a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (double a, const ComplexMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Matrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Matrix& a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const DiagMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const DiagMatrix& a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const PermMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Complex& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Complex& a, const Matrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Complex& a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const Complex& a, const ComplexMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const ComplexMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const ComplexMatrix& a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const ComplexDiagMatrix& a, double b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const ComplexDiagMatrix& a, const Complex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const Matrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const ComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const octave::range<double>& r)
-{
-  return octave::elem_xpow (a, r);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Matrix& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Matrix& a, const Matrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Matrix& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Matrix& a, const ComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const Matrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const ComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const octave::range<double>& r)
-{
-  return octave::elem_xpow (a, r);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexMatrix& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexMatrix& a, const Matrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexMatrix& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const NDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (double a, const ComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const NDArray& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const NDArray& a, const NDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const NDArray& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const NDArray& a, const ComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const NDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const Complex& a, const ComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexNDArray& a, double b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexNDArray& a, const NDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexNDArray& a, const Complex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (float a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (float a, const FloatMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (float a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (float a, const FloatComplexMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatMatrix& a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatMatrix& a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatDiagMatrix& a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatDiagMatrix& a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplex& a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplex& a, const FloatMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplex& a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplex& a, const FloatComplexMatrix& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplexMatrix& a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplexMatrix& a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplexDiagMatrix& a, float b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead")
-inline octave_value
-xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b)
-{
-  return octave::xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (float a, const FloatMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (float a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatMatrix& a, float b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatMatrix& a, const FloatMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatMatrix& a, const FloatComplex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplex& a, const FloatMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexMatrix& a, float b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (float a, const FloatNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (float a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatNDArray& a, float b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatNDArray& a, const FloatNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatNDArray& a, const FloatComplex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplex& a, const FloatNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexNDArray& a, float b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead")
-inline octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b)
-{
-  return octave::elem_xpow (a, b);
-}
-
 #endif
-
-#endif
--- a/libinterp/dldfcn/__init_fltk__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/dldfcn/__init_fltk__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -102,7 +102,6 @@
 #include "ov-fcn-handle.h"
 #include "ov.h"
 #include "ovl.h"
-#include "parse.h"
 #include "variables.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -145,7 +144,9 @@
 #endif
   }
 
-  ~OpenGL_fltk (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (OpenGL_fltk)
+
+  ~OpenGL_fltk () = default;
 
   void zoom (bool z)
   {
@@ -154,7 +155,7 @@
       hide_overlay ();
   }
 
-  bool zoom (void) { return m_in_zoom; }
+  bool zoom () { return m_in_zoom; }
   void set_zoom_box (const Matrix& zb) { m_zoom_box = zb; }
 
   void print (const std::string& cmd, const std::string& term)
@@ -164,7 +165,7 @@
     octave::gl2ps_print (m_glfcns, gh_mgr.get_object (m_number), cmd, term);
   }
 
-  uint8NDArray get_pixels (void)
+  uint8NDArray get_pixels ()
   {
     gh_manager& gh_mgr = octave::__get_gh_manager__ ();
 
@@ -219,7 +220,7 @@
   // (x1,y1,x2,y2)
   Matrix m_zoom_box;
 
-  void draw (void)
+  void draw ()
   {
 #if defined (HAVE_OPENGL)
 
@@ -247,7 +248,7 @@
 #endif
   }
 
-  void overlay (void)
+  void overlay ()
   {
     Matrix overlaycolor (3, 1);
     overlaycolor(0) = 0.45;
@@ -308,7 +309,11 @@
     : m_menubar (new Fl_Menu_Bar (xx, yy, ww, hh))
   { }
 
-  int items_to_show (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fltk_uimenu)
+
+  ~fltk_uimenu () = default;
+
+  int items_to_show ()
   {
     //returns the number of visible menu items
     int len = m_menubar->size ();
@@ -325,19 +330,19 @@
     return n;
   }
 
-  void show (void)
+  void show ()
   {
     m_menubar->show ();
     m_menubar->redraw ();
   }
 
-  void hide (void)
+  void hide ()
   {
     m_menubar->hide ();
     m_menubar->redraw ();
   }
 
-  bool is_visible (void)
+  bool is_visible ()
   {
     return m_menubar->visible ();
   }
@@ -648,8 +653,8 @@
 
         if (kgo.valid_object ())
           {
-            uimenu::properties& kprop = dynamic_cast<uimenu::properties&>
-                                        (kgo.get_properties ());
+            uimenu::properties& kprop
+              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());
 
             // if no pos yet, delay adding menu until after other menus
             int pos = kprop.get_position ();
@@ -669,8 +674,8 @@
 
         if (kgo.valid_object ())
           {
-            uimenu::properties& kprop = dynamic_cast<uimenu::properties&>
-                                        (kgo.get_properties ());
+            uimenu::properties& kprop
+              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());
             add_to_menu (kprop);
             update_position (kprop, ++count);
           }
@@ -694,8 +699,8 @@
 
         if (kgo.valid_object ())
           {
-            uimenu::properties& kprop = dynamic_cast<uimenu::properties&>
-                                        (kgo.get_properties ());
+            uimenu::properties& kprop
+              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());
 
             // if no pos yet, delay adding menu until after other menus
             int pos = kprop.get_position ();
@@ -716,8 +721,8 @@
 
         if (kgo.valid_object ())
           {
-            uimenu::properties& kprop = dynamic_cast<uimenu::properties&>
-                                        (kgo.get_properties ());
+            uimenu::properties& kprop
+              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());
             add_to_menu (kprop);
             update_position (kprop, ++count);
           }
@@ -740,8 +745,8 @@
 
         if (kgo.valid_object ())
           {
-            uimenu::properties kprop = dynamic_cast<uimenu::properties&>
-                                       (kgo.get_properties ());
+            uimenu::properties& kprop
+              = dynamic_cast<uimenu::properties&> (kgo.get_properties ());
             remove_from_menu (kprop);
           }
       }
@@ -752,17 +757,6 @@
       m_menubar->clear ();
   }
 
-  // No copying!
-
-  fltk_uimenu (const fltk_uimenu&) = delete;
-
-  fltk_uimenu operator = (const fltk_uimenu&) = delete;
-
-  ~fltk_uimenu (void)
-  {
-    // FLTK is supposed to manage memory for widgets.
-  }
-
 private:
 
   Fl_Menu_Bar *m_menubar;
@@ -784,7 +778,7 @@
 
   plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp,
                bool internal)
-    : Fl_Window (xx, yy, ww, hh + m_menu_h + m_status_h + 2, "octave"),
+    : Fl_Window (xx, yy, ww, hh + MENU_H + STATUS_H + 2, "octave"),
       m_window_label (), m_fp (xfp), m_uimenu (nullptr), m_canvas (nullptr),
       m_autoscale (nullptr), m_togglegrid (nullptr), m_panzoom (nullptr),
       m_rotate (nullptr), m_help (nullptr), m_status (nullptr),
@@ -794,8 +788,8 @@
 
     // The size of the resize_dummy box also determines the minimum
     // window size.
-    m_resize_dummy = new Fl_Box (5 * m_status_h, m_menu_h,
-                                 ww - 5 * m_status_h, hh);
+    m_resize_dummy = new Fl_Box (5 * STATUS_H, MENU_H,
+                                 ww - 5 * STATUS_H, hh);
 
     // See http://fltk.org/articles.php?L415+I0+T+M1000+P1
                 // for how resizable works
@@ -809,16 +803,16 @@
     // windows.  Otherwise, the class is just "FLTK"
     //default_xclass ("Octave");
 
-    m_uimenu = new fltk_uimenu (0, 0, ww, m_menu_h);
-    m_canvas = new OpenGL_fltk (0, m_menu_h, ww, hh, number ());
+    m_uimenu = new fltk_uimenu (0, 0, ww, MENU_H);
+    m_canvas = new OpenGL_fltk (0, MENU_H, ww, hh, number ());
 
     // The bottom toolbar is a composite of "autoscale", "togglegrid",
     // "panzoom", "rotate", "help", and "status".
     // Only "status" should be resized.
 
-    int toolbar_y = m_menu_h + hh + 1;
-    m_status = new Fl_Output (5 * m_status_h, toolbar_y,
-                              ww - 5 * m_status_h, m_status_h, "");
+    int toolbar_y = MENU_H + hh + 1;
+    m_status = new Fl_Output (5 * STATUS_H, toolbar_y,
+                              ww - 5 * STATUS_H, STATUS_H, "");
 
     m_status->textcolor (FL_BLACK);
     m_status->color (FL_GRAY);
@@ -826,23 +820,23 @@
     m_status->textsize (10);
     m_status->box (FL_ENGRAVED_BOX);
 
-    m_autoscale = new Fl_Button (0, toolbar_y, m_status_h, m_status_h, "A");
+    m_autoscale = new Fl_Button (0, toolbar_y, STATUS_H, STATUS_H, "A");
     m_autoscale->callback (button_callback, static_cast<void *> (this));
     m_autoscale->tooltip ("Autoscale");
 
-    m_togglegrid = new Fl_Button (m_status_h, toolbar_y, m_status_h, m_status_h, "G");
+    m_togglegrid = new Fl_Button (STATUS_H, toolbar_y, STATUS_H, STATUS_H, "G");
     m_togglegrid->callback (button_callback, static_cast<void *> (this));
     m_togglegrid->tooltip ("Toggle Grid");
 
-    m_panzoom = new Fl_Button (2* m_status_h, toolbar_y, m_status_h, m_status_h, "P");
+    m_panzoom = new Fl_Button (2* STATUS_H, toolbar_y, STATUS_H, STATUS_H, "P");
     m_panzoom->callback (button_callback, static_cast<void *> (this));
     m_panzoom->tooltip ("Mouse Pan/Zoom");
 
-    m_rotate = new Fl_Button (3 * m_status_h, toolbar_y, m_status_h, m_status_h, "R");
+    m_rotate = new Fl_Button (3 * STATUS_H, toolbar_y, STATUS_H, STATUS_H, "R");
     m_rotate->callback (button_callback, static_cast<void *> (this));
     m_rotate->tooltip ("Mouse Rotate");
 
-    m_help = new Fl_Button (4 * m_status_h, toolbar_y, m_status_h, m_status_h, "?");
+    m_help = new Fl_Button (4 * STATUS_H, toolbar_y, STATUS_H, STATUS_H, "?");
     m_help->callback (button_callback, static_cast<void *> (this));
     m_help->tooltip ("Help");
 
@@ -883,13 +877,9 @@
       }
   }
 
-  // No copying!
-
-  plot_window (const plot_window&) = delete;
-
-  plot_window& operator = (const plot_window&) = delete;
-
-  ~plot_window (void)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (plot_window)
+
+  ~plot_window ()
   {
     this->hide ();
     Fl::check ();
@@ -899,7 +889,7 @@
     // FLTK is supposed to manage memory for widgets.
   }
 
-  double number (void) { return m_fp.get___myhandle__ ().value (); }
+  double number () { return m_fp.get___myhandle__ ().value (); }
 
   void renumber (double new_number)
   {
@@ -920,13 +910,13 @@
     return m_canvas->get_pixels ();
   }
 
-  void show_menubar (void)
+  void show_menubar ()
   {
     m_uimenu->show ();
     update_toolbar_position ();
   }
 
-  void hide_menubar (void)
+  void hide_menubar ()
   {
     m_uimenu->hide ();
     update_toolbar_position ();
@@ -997,7 +987,7 @@
       }
   }
 
-  void show_canvas (void)
+  void show_canvas ()
   {
     if (! m_canvas->can_do ())
       error ("unable to plot due to insufficient OpenGL support");
@@ -1008,7 +998,7 @@
       }
   }
 
-  void hide_canvas (void)
+  void hide_canvas ()
   {
     m_canvas->hide ();
   }
@@ -1027,12 +1017,12 @@
 
     int toolbar_y = m_canvas->h () + menu_dy () + 1;
     m_autoscale->position (0, toolbar_y);
-    m_togglegrid->position (m_status_h, toolbar_y);
-    m_panzoom->position (2 * m_status_h, toolbar_y);
-    m_rotate->position (3 * m_status_h, toolbar_y);
-    m_help->position (4 * m_status_h, toolbar_y);
-    m_status->resize (5 * m_status_h, toolbar_y,
-                      w () - 5 * m_status_h, m_status_h);
+    m_togglegrid->position (STATUS_H, toolbar_y);
+    m_panzoom->position (2 * STATUS_H, toolbar_y);
+    m_rotate->position (3 * STATUS_H, toolbar_y);
+    m_help->position (4 * STATUS_H, toolbar_y);
+    m_status->resize (5 * STATUS_H, toolbar_y,
+                      w () - 5 * STATUS_H, STATUS_H);
     init_sizes ();
     redraw ();
   }
@@ -1041,7 +1031,7 @@
   {
     Matrix pos = outerpos;
     pos(1) += menu_dy ();
-    pos(3) -= menu_dy () + m_status_h + 2;
+    pos(3) -= menu_dy () + STATUS_H + 2;
     return pos;
   }
 
@@ -1049,7 +1039,7 @@
   {
     Matrix outerpos = pos;
     outerpos(1) -= menu_dy ();
-    outerpos(3) += menu_dy () + m_status_h + 2;
+    outerpos(3) += menu_dy () + STATUS_H + 2;
     return outerpos;
   }
 
@@ -1066,12 +1056,12 @@
     resize (bb(0), bb(1), bb(2), bb(3));
   }
 
-  void mark_modified (void)
+  void mark_modified ()
   {
     m_canvas->redraw ();
   }
 
-  void set_name (void)
+  void set_name ()
   {
     m_window_label = m_fp.get_title ();
     label (m_window_label.c_str ());
@@ -1087,10 +1077,10 @@
   figure::properties& m_fp;
 
   // Status area height.
-  static const int m_status_h = 20;
+  static const int STATUS_H = 20;
 
   // Menu height
-  static const int m_menu_h = 25;
+  static const int MENU_H = 25;
 
   fltk_uimenu *m_uimenu;
 
@@ -1113,9 +1103,12 @@
   // Window callback.
   static void window_close (Fl_Widget *, void *data)
   {
+    interpreter& interp = __get_interpreter__ ();
+
     octave_value_list args;
     args(0) = static_cast<plot_window *> (data)->number ();
-    octave::feval ("close", args);
+
+    interp.feval ("close", args);
   }
 
   // Button callbacks.
@@ -1166,25 +1159,32 @@
       }
   }
 
-  void axis_auto (void)
+  void axis_auto ()
   {
     octave_value_list args;
     if (m_fp.get_currentaxes ().ok ())
       {
+        interpreter& interp = __get_interpreter__ ();
+
         args(0) = m_fp.get_currentaxes ().as_octave_value ();
         args(1) = "auto";
-        octave::feval ("axis", args);
+
+        interp.feval ("axis", args);
+
         mark_modified ();
       }
   }
 
-  void toggle_grid (void)
+  void toggle_grid ()
   {
+    interpreter& interp = __get_interpreter__ ();
+
     octave_value_list args;
     if (m_fp.get_currentaxes ().ok ())
       args(0) = m_fp.get_currentaxes ().as_octave_value ();
 
-    octave::feval ("grid", args);
+    interp.feval ("grid", args);
+
     mark_modified ();
   }
 
@@ -1332,7 +1332,7 @@
   int menu_dy ()
   {
     if (m_uimenu->is_visible ())
-      return m_menu_h;
+      return MENU_H;
     else
       return 0;
   }
@@ -1466,7 +1466,7 @@
     m_fp.set_boundingbox (outerposition2position (bb), true, false);
   }
 
-  bool pan_enabled (void)
+  bool pan_enabled ()
   {
     // Getting pan mode property:
     octave_value ov_pm = m_fp.get___pan_mode__ ();
@@ -1476,7 +1476,7 @@
     return pm.contents ("Enable").string_value () == "on";
   }
 
-  std::string pan_mode (void)
+  std::string pan_mode ()
   {
     // Getting pan mode property:
     octave_value ov_pm = m_fp.get___pan_mode__ ();
@@ -1486,7 +1486,7 @@
     return pm.contents ("Motion").string_value ();
   }
 
-  bool rotate_enabled (void)
+  bool rotate_enabled ()
   {
     // Getting rotate mode property:
     octave_value ov_rm = m_fp.get___rotate_mode__ ();
@@ -1871,47 +1871,43 @@
 {
 private:
 
-  figure_manager (void) = default;
+  figure_manager () = default;
 
 public:
 
-  // No copying!
-
-  figure_manager (const figure_manager&) = delete;
-
-  figure_manager& operator = (const figure_manager&) = delete;
-
-  ~figure_manager (void)
+  OCTAVE_DISABLE_COPY_MOVE (figure_manager)
+
+  ~figure_manager ()
   {
     close_all ();
   }
 
-  static bool instance_ok (void)
+  static bool instance_ok ()
   {
     bool retval = true;
 
-    if (! instance)
-      instance = new figure_manager ();
+    if (! s_instance)
+      s_instance = new figure_manager ();
 
     return retval;
   }
 
-  static void close_all (void)
+  static void close_all ()
   {
     if (instance_ok ())
-      instance->do_close_all ();
+      s_instance->do_close_all ();
   }
 
   static void new_window (figure::properties& fp)
   {
     if (instance_ok ())
-      instance->do_new_window (fp);
+      s_instance->do_new_window (fp);
   }
 
   static void delete_window (int idx)
   {
     if (instance_ok ())
-      instance->do_delete_window (idx);
+      s_instance->do_delete_window (idx);
   }
 
   static void delete_window (const std::string& idx_str)
@@ -1922,13 +1918,13 @@
   static void renumber_figure (const std::string& idx_str, double new_number)
   {
     if (instance_ok ())
-      instance->do_renumber_figure (str2idx (idx_str), new_number);
+      s_instance->do_renumber_figure (str2idx (idx_str), new_number);
   }
 
   static void toggle_window_visibility (int idx, bool is_visible)
   {
     if (instance_ok ())
-      instance->do_toggle_window_visibility (idx, is_visible);
+      s_instance->do_toggle_window_visibility (idx, is_visible);
   }
 
   static void toggle_window_visibility (const std::string& idx_str,
@@ -1940,7 +1936,7 @@
   static void mark_modified (int idx)
   {
     if (instance_ok ())
-      instance->do_mark_modified (idx);
+      s_instance->do_mark_modified (idx);
   }
 
   static void mark_modified (const graphics_handle& gh)
@@ -1951,7 +1947,7 @@
   static void set_name (int idx)
   {
     if (instance_ok ())
-      instance->do_set_name (idx);
+      s_instance->do_set_name (idx);
   }
 
   static void set_name (const std::string& idx_str)
@@ -1961,7 +1957,7 @@
 
   static Matrix get_size (int idx)
   {
-    return instance_ok () ? instance->do_get_size (idx) : Matrix ();
+    return instance_ok () ? s_instance->do_get_size (idx) : Matrix ();
   }
 
   static Matrix get_size (const graphics_handle& gh)
@@ -1973,14 +1969,14 @@
                      const std::string& term)
   {
     if (instance_ok ())
-      instance->do_print (hnd2idx (gh), cmd, term);
+      s_instance->do_print (hnd2idx (gh), cmd, term);
   }
 
   static uint8NDArray get_pixels (const graphics_handle& gh)
   {
     uint8NDArray retval;
     if (instance_ok ())
-      retval = instance->do_get_pixels (hnd2idx (gh));
+      retval = s_instance->do_get_pixels (hnd2idx (gh));
 
     return retval;
   }
@@ -1989,60 +1985,59 @@
                              const graphics_handle& uimenuh, int id)
   {
     if (instance_ok ())
-      instance->do_uimenu_update (hnd2idx (figh), uimenuh, id);
+      s_instance->do_uimenu_update (hnd2idx (figh), uimenuh, id);
   }
 
   static void update_canvas (const graphics_handle& gh,
                              const graphics_handle& ca)
   {
     if (instance_ok ())
-      instance->do_update_canvas (hnd2idx (gh), ca);
+      s_instance->do_update_canvas (hnd2idx (gh), ca);
   }
 
   static void update_boundingbox (const std::string& fig_idx_str,
                                   bool internal)
   {
     if (instance_ok ())
-      instance->do_update_boundingbox (str2idx (fig_idx_str), internal);
+      s_instance->do_update_boundingbox (str2idx (fig_idx_str), internal);
   }
 
   static void toggle_menubar_visibility (const std::string& fig_idx_str,
                                          bool menubar_is_figure)
   {
     if (instance_ok ())
-      instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),
+      s_instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),
                                               menubar_is_figure);
   }
 
 private:
 
-  static figure_manager *instance;
+  static figure_manager *s_instance;
 
   // Singleton -- hide all of the above.
 
-  static int curr_index;
+  static int s_curr_index;
 
   typedef std::map<int, plot_window *> window_map;
 
   typedef window_map::iterator wm_iterator;
 
-  window_map windows;
-
-  static std::string fltk_idx_header;
-
-  void do_close_all (void)
+  window_map m_windows;
+
+  static std::string s_fltk_idx_header;
+
+  void do_close_all ()
   {
-    wm_iterator win;
-    for (win = windows.begin (); win != windows.end (); win++)
-      delete win->second;
-    windows.clear ();
+    for (auto& win : m_windows)
+      delete win.second;
+    m_windows.clear ();
   }
 
   void do_new_window (figure::properties& fp)
   {
     int idx = figprops2idx (fp);
 
-    if (idx >= 0 && windows.find (idx) == windows.end ())
+    if (idx >= 0 && m_windows.find (idx) == m_windows.end ())
       {
         Matrix pos = fp.get_outerposition ().matrix_value ();
         bool internal = false;
@@ -2058,37 +2053,37 @@
             pos = fp.get_boundingbox (internal);
           }
 
-        idx2figprops (curr_index, fp);
-
-        windows[curr_index++] = new plot_window (pos(0), pos(1), pos(2), pos(3),
+        idx2figprops (s_curr_index, fp);
+
+        m_windows[s_curr_index++] = new plot_window (pos(0), pos(1), pos(2), pos(3),
             fp, internal);
       }
   }
 
   void do_delete_window (int idx)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       {
         delete win->second;
-        windows.erase (win);
+        m_windows.erase (win);
       }
   }
 
   void do_renumber_figure (int idx, double new_number)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       win->second->renumber (new_number);
   }
 
   void do_toggle_window_visibility (int idx, bool is_visible)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       {
         if (is_visible)
           {
@@ -2103,9 +2098,9 @@
 
   void do_toggle_menubar_visibility (int fig_idx, bool menubar_is_figure)
   {
-    wm_iterator win = windows.find (fig_idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (fig_idx);
+
+    if (win != m_windows.end ())
       {
         if (menubar_is_figure)
           win->second->show_menubar ();
@@ -2118,9 +2113,9 @@
 
   void do_mark_modified (int idx)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       {
         win->second->mark_modified ();
       }
@@ -2128,9 +2123,9 @@
 
   void do_set_name (int idx)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       win->second->set_name ();
   }
 
@@ -2138,9 +2133,9 @@
   {
     Matrix sz (1, 2, 0.0);
 
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       {
         sz(0) = win->second->w ();
         sz(1) = win->second->h ();
@@ -2151,18 +2146,18 @@
 
   void do_print (int idx, const std::string& cmd, const std::string& term)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       win->second->print (cmd, term);
   }
 
   uint8NDArray do_get_pixels (int idx)
   {
     uint8NDArray retval;
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       retval = win->second->get_pixels ();
 
     return retval;
@@ -2170,17 +2165,17 @@
 
   void do_uimenu_update (int idx, const graphics_handle& gh, int id)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       win->second->uimenu_update (gh, id);
   }
 
   void do_update_canvas (int idx, const graphics_handle& ca)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       {
         if (ca.ok ())
           win->second->show_canvas ();
@@ -2191,18 +2186,18 @@
 
   void do_update_boundingbox (int idx, bool internal)
   {
-    wm_iterator win = windows.find (idx);
-
-    if (win != windows.end ())
+    wm_iterator win = m_windows.find (idx);
+
+    if (win != m_windows.end ())
       win->second->update_boundingbox (internal);
   }
 
   static int str2idx (const caseless_str& clstr)
   {
     int ind;
-    if (clstr.find (fltk_idx_header, 0) == 0)
+    if (clstr.find (s_fltk_idx_header, 0) == 0)
       {
-        std::istringstream istr (clstr.substr (fltk_idx_header.size ()));
+        std::istringstream istr (clstr.substr (s_fltk_idx_header.size ()));
         if (istr >> ind)
           return ind;
       }
@@ -2213,7 +2208,7 @@
   void idx2figprops (int idx, figure::properties& fp)
   {
     std::ostringstream ind_str;
-    ind_str << fltk_idx_header << idx;
+    ind_str << s_fltk_idx_header << idx;
     fp.set___plot_stream__ (ind_str.str ());
   }
 
@@ -2253,10 +2248,10 @@
   }
 };
 
-figure_manager *figure_manager::instance = nullptr;
-
-std::string figure_manager::fltk_idx_header="fltk index=";
-int figure_manager::curr_index = 1;
+figure_manager *figure_manager::s_instance = nullptr;
+
+std::string figure_manager::s_fltk_idx_header="fltk index=";
+int figure_manager::s_curr_index = 1;
 
 static bool toolkit_loaded = false;
 
@@ -2266,14 +2261,16 @@
 
   fltk_graphics_toolkit (octave::interpreter& interp)
     : octave::base_graphics_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME),
-      m_interpreter (interp), input_event_hook_fcn_id ()
+      m_interpreter (interp), m_input_event_hook_fcn_id ()
   {
     Fl::visual (FL_RGB);
   }
 
-  ~fltk_graphics_toolkit (void) = default;
-
-  bool is_valid (void) const { return true; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (fltk_graphics_toolkit)
+
+  ~fltk_graphics_toolkit () = default;
+
+  bool is_valid () const { return true; }
 
   bool initialize (const graphics_object& go)
   {
@@ -2440,7 +2437,7 @@
   }
 
   /*
-    double get_screen_resolution (void) const
+    double get_screen_resolution () const
     {
       // FLTK doesn't give this info.
       return 72.0;
@@ -2450,7 +2447,7 @@
     }
   */
 
-  Matrix get_screen_size (void) const
+  Matrix get_screen_size () const
   {
     Matrix sz (1, 2, 0.0);
     sz(0) = Fl::w ();
@@ -2458,16 +2455,16 @@
     return sz;
   }
 
-  void close (void)
+  void close ()
   {
     if (toolkit_loaded)
       {
         m_interpreter.munlock ("__init_fltk__");
 
-        octave_value_list args = input_event_hook_fcn_id;
+        octave_value_list args = m_input_event_hook_fcn_id;
         args.append (false);
-        Fremove_input_event_hook (m_interpreter, args, 0);
-        input_event_hook_fcn_id = octave_value_list ();
+        Fremove_input_event_hook (m_interpreter, args);
+        m_input_event_hook_fcn_id = octave_value_list ();
 
         figure_manager::close_all ();
       }
@@ -2475,14 +2472,14 @@
 
   void set_input_event_hook_id (const octave_value_list& id)
   {
-    input_event_hook_fcn_id = id;
+    m_input_event_hook_fcn_id = id;
   }
 
 private:
 
   octave::interpreter& m_interpreter;
 
-  octave_value_list input_event_hook_fcn_id;
+  octave_value_list m_input_event_hook_fcn_id;
 };
 
 #endif
@@ -2534,7 +2531,8 @@
       octave_value fcn (new octave_builtin (F__fltk_check__));
       octave_value fcn_handle (new octave_fcn_handle (fcn));
 
-      octave_value_list id = Fadd_input_event_hook (interp, fcn_handle, 1);
+      octave_value_list id = Fadd_input_event_hook (interp,
+                                                    ovl (fcn_handle), 1);
 
       fltk->set_input_event_hook_id (id);
     }
--- a/libinterp/dldfcn/__init_gnuplot__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/dldfcn/__init_gnuplot__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,7 +51,6 @@
 #include "interpreter.h"
 #include "ov.h"
 #include "ovl.h"
-#include "parse.h"
 #include "utils.h"
 #include "variables.h"
 
@@ -62,6 +61,7 @@
 class gnuplot_graphics_toolkit : public octave::base_graphics_toolkit
 {
 public:
+
   gnuplot_graphics_toolkit (octave::interpreter& interp)
     : octave::base_graphics_toolkit ("gnuplot"), m_interpreter (interp)
   {
@@ -86,9 +86,11 @@
       }
   }
 
-  ~gnuplot_graphics_toolkit (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (gnuplot_graphics_toolkit)
 
-  bool is_valid (void) const { return true; }
+  ~gnuplot_graphics_toolkit () = default;
+
+  bool is_valid () const { return true; }
 
   bool initialize (const graphics_object& go)
   {
@@ -140,7 +142,7 @@
 
         octave_value_list args;
         args(0) = go.get_handle ().as_octave_value ();
-        octave::feval ("__gnuplot_drawnow__", args);
+        m_interpreter.feval ("__gnuplot_drawnow__", args);
       }
   }
 
@@ -154,7 +156,7 @@
     args(2) = file;
     args(1) = term;
     args(0) = go.get_handle ().as_octave_value ();
-    octave::feval ("__gnuplot_drawnow__", args);
+    m_interpreter.feval ("__gnuplot_drawnow__", args);
   }
 
   Matrix get_canvas_size (const graphics_handle&) const
@@ -163,13 +165,13 @@
     return sz;
   }
 
-  double get_screen_resolution (void) const
+  double get_screen_resolution () const
   { return 72.0; }
 
-  Matrix get_screen_size (void) const
+  Matrix get_screen_size () const
   { return Matrix (1, 2, 0.0); }
 
-  void close (void)
+  void close ()
   {
     if (m_interpreter.mislocked ("__init_gnuplot__"))
       m_interpreter.munlock ("__init_gnuplot__");
@@ -203,7 +205,7 @@
 };
 
 static bool
-have_gnuplot_binary (void)
+have_gnuplot_binary (interpreter& interp)
 {
   const std::string exeext = octave::build_env::EXEEXT;
   const std::string path = octave::sys::env::getenv ("PATH");
@@ -212,7 +214,7 @@
   try
     {
       octave_value_list tmp
-        = octave::feval ("gnuplot_binary", octave_value_list ());
+        = interp.feval ("gnuplot_binary", octave_value_list ());
 
       if (tmp(0).is_string () && ! tmp(0).isempty ())
         {
@@ -237,8 +239,6 @@
     }
   catch (const octave::execution_exception&)
     {
-      octave::interpreter& interp = octave::__get_interpreter__ ();
-
       interp.recover_from_exception ();
     }
 
@@ -253,7 +253,7 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  if (! have_gnuplot_binary ())
+  if (! have_gnuplot_binary (interp))
     error ("__init_gnuplot__: the gnuplot program is not available, see 'gnuplot_binary'");
   else if (! interp.mislocked ("__init_gnuplot__"))
     {
@@ -268,13 +268,13 @@
   return octave_value_list ();
 }
 
-DEFUN_DLD (__have_gnuplot__, , ,
-           doc: /* -*- texinfo -*-
+DEFMETHOD_DLD (__have_gnuplot__, interp, , ,
+               doc: /* -*- texinfo -*-
 @deftypefn {} {@var{gnuplot_available} =} __have_gnuplot__ ()
 Undocumented internal function.
 @end deftypefn */)
 {
-  return ovl (have_gnuplot_binary ());
+  return ovl (have_gnuplot_binary (interp));
 }
 
 /*
--- a/libinterp/dldfcn/__ode15__.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/dldfcn/__ode15__.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,11 +37,12 @@
 #include "defun-dld.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
 #include "oct-map.h"
 #include "ov.h"
 #include "ovl.h"
 #include "pager.h"
-#include "parse.h"
 
 #if defined (HAVE_SUNDIALS)
 
@@ -168,7 +169,7 @@
                                     SparseMatrix *dfdyp, realtype cj);
 
   //Default
-  IDA (void)
+  IDA ()
     : m_t0 (0.0), m_y0 (), m_yp0 (), m_havejac (false), m_havejacfcn (false),
       m_havejacsparse (false), m_mem (nullptr), m_num (), m_ida_fcn (),
       m_ida_jac (), m_dfdy (nullptr), m_dfdyp (nullptr), m_spdfdy (nullptr),
@@ -188,8 +189,9 @@
       m_sunJacMatrix (nullptr), m_sunLinearSolver (nullptr)
   { }
 
+  OCTAVE_DISABLE_COPY_MOVE (IDA)
 
-  ~IDA (void)
+  ~IDA ()
   {
     IDAFree (&m_mem);
     SUNLinSolFree (m_sunLinearSolver);
@@ -250,9 +252,9 @@
     return *this;
   }
 
-  void set_userdata (void);
+  void set_userdata ();
 
-  void initialize (void);
+  void initialize ();
 
   static ColumnVector NVecToCol (N_Vector& v, octave_f77_int_type n);
 
@@ -350,7 +352,7 @@
              const octave_value& event_fcn,
              const octave_idx_type num_event_args);
 
-  void print_stat (void);
+  void print_stat ();
 
 private:
 
@@ -521,7 +523,7 @@
     {
       // Allocate memory for sparse Jacobian defined in user function.
       // This will always be required at least once since we set the number
-      // of non-zero elements to zero initially.
+      // of nonzero elements to zero initially.
       if (SUNSparseMatrix_Reallocate (Jac, nnz))
         error ("Unable to allocate sufficient memory for IDA sparse matrix");
     }
@@ -571,7 +573,7 @@
 }
 
 void
-IDA::set_userdata (void)
+IDA::set_userdata ()
 {
   void *userdata = this;
 
@@ -580,7 +582,7 @@
 }
 
 void
-IDA::initialize (void)
+IDA::initialize ()
 {
   m_num = to_f77_int (m_y0.numel ());
 #  if defined (HAVE_SUNDIALS_SUNCONTEXT)
@@ -811,9 +813,11 @@
   // cont is the number of steps reached by the solver
   // temp is the number of events registered
 
+  interpreter& interp = __get_interpreter__ ();
+
   if (flag == "init")
     {
-      octave_value_list output = feval (event_fcn, args, 3);
+      octave_value_list output = interp.feval (event_fcn, args, 3);
       oldval = output(0).vector_value ();
       oldisterminal = output(1).vector_value ();
       olddir = output(2).vector_value ();
@@ -821,7 +825,7 @@
   else if (flag == "")
     {
       ColumnVector index (0);
-      octave_value_list output = feval (event_fcn, args, 3);
+      octave_value_list output = interp.feval (event_fcn, args, 3);
       ColumnVector val = output(0).vector_value ();
       ColumnVector isterminal = output(1).vector_value ();
       ColumnVector dir = output(2).vector_value ();
@@ -994,6 +998,8 @@
   else
     output(1) = yout;
 
+  interpreter& interp = __get_interpreter__ ();
+
   if (flag == "init")
     {
       ColumnVector toutput (2);
@@ -1001,19 +1007,19 @@
       toutput(1) = tend;
       output(0) = toutput;
 
-      feval (output_fcn, output, 0);
+      interp.feval (output_fcn, output, 0);
     }
   else if (flag == "")
     {
       output(0) = tsol;
-      octave_value_list val = feval (output_fcn, output, 1);
+      octave_value_list val = interp.feval (output_fcn, output, 1);
       status = val(0).bool_value ();
     }
   else
     {
       // Cleanup plotter
       output(0) = tend;
-      feval (output_fcn, output, 0);
+      interp.feval (output_fcn, output, 0);
     }
 
   return status;
@@ -1041,7 +1047,7 @@
 }
 
 void
-IDA::print_stat (void)
+IDA::print_stat ()
 {
   long int nsteps = 0, netfails = 0, nrevals = 0;
 
@@ -1070,7 +1076,9 @@
 
   try
     {
-      tmp = feval (ida_fc, ovl (t, x, xdot), 1);
+      interpreter& interp = __get_interpreter__ ();
+
+      tmp = interp.feval (ida_fc, ovl (t, x, xdot), 1);
     }
   catch (execution_exception& ee)
     {
@@ -1088,7 +1096,9 @@
 
   try
     {
-      tmp = feval (ida_jc, ovl (t, x, xdot), 2);
+      interpreter& interp = __get_interpreter__ ();
+
+      tmp = interp.feval (ida_jc, ovl (t, x, xdot), 2);
     }
   catch (execution_exception& ee)
     {
@@ -1106,7 +1116,9 @@
 
   try
     {
-      tmp = feval (ida_jc, ovl (t, x, xdot), 2);
+      interpreter& interp = __get_interpreter__ ();
+
+      tmp = interp.feval (ida_jc, ovl (t, x, xdot), 2);
     }
   catch (execution_exception& ee)
     {
--- a/libinterp/dldfcn/audiodevinfo.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/dldfcn/audiodevinfo.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,11 +44,12 @@
 #include "defun-dld.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
 #include "oct-map.h"
 #include "ov-int32.h"
 #include "ov.h"
 #include "ovl.h"
-#include "parse.h"
 
 #if defined (HAVE_PORTAUDIO)
 #  include <portaudio.h>
@@ -302,7 +303,7 @@
     {
       bool found = false;
       int outin = args(0).int_value ();
-      int id = args(1).int_value ();
+      int m_id = args(1).int_value ();
 
       std::string arg3 = args(2).string_value ();
       std::transform (arg3.begin (), arg3.end (), arg3.begin (), tolower);
@@ -313,7 +314,7 @@
         {
           for (int i = 0; i < numoutput; i++)
             {
-              if (output_id(i).int_value () == id)
+              if (output_id(i).int_value () == m_id)
                 {
                   found = true;
                   retval = output_driver_version(i);
@@ -325,7 +326,7 @@
         {
           for (int i = 0; i < numinput; i++)
             {
-              if (input_id(i).int_value () == id)
+              if (input_id(i).int_value () == m_id)
                 {
                   found = true;
                   retval = input_driver_version(i);
@@ -405,12 +406,12 @@
   else if (nargin == 5)
     {
       int io = args(0).int_value ();
-      int id = args(1).int_value ();
+      int m_id = args(1).int_value ();
       int rate = args(2).int_value ();
       int bits = args(3).int_value ();
       int chans = args(4).int_value ();
       PaStreamParameters stream_parameters;
-      stream_parameters.device = id;
+      stream_parameters.device = m_id;
       stream_parameters.channelCount = chans;
       PaSampleFormat format = bits_to_format (bits);
       if (format != 0)
@@ -418,10 +419,10 @@
       else
         error ("audiodevinfo: invalid bits per sample format");
 
-      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (id);
+      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (m_id);
 
       if (! device_info)
-        error ("audiodevinfo: invalid audio device ID = %d", id);
+        error ("audiodevinfo: invalid audio device ID = %d", m_id);
 
       stream_parameters.suggestedLatency
         = device_info->defaultLowInputLatency;
@@ -521,73 +522,77 @@
 class audioplayer : public octave_base_dld_value
 {
 public:
-  audioplayer (void);
-  ~audioplayer (void);
+
+  audioplayer ();
+
+  OCTAVE_DISABLE_COPY_MOVE (audioplayer)
+
+  ~audioplayer ();
 
   // Overloaded base functions
-  double player_value (void) const { return 0; }
+  double player_value () const { return 0; }
   virtual double scalar_value (bool = false) const { return 0; }
   void print (std::ostream& os, bool pr_as_read_syntax = false);
   void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
 
   // Properties
-  bool is_constant (void) const { return true; }
-  bool is_defined (void) const { return true; }
-  bool print_as_scalar (void) const { return true; }
-
-  void init (void);
-  void init_fn (void);
-  void set_y (const octave_value& y);
+  bool is_constant () const { return true; }
+  bool is_defined () const { return true; }
+  bool print_as_scalar () const { return true; }
+
+  void init ();
+  void init_fn ();
+  void set_y (const octave_value& m_y);
   void set_y (octave_function *fcn);
   void set_y (std::string fcn);
-  Matrix& get_y (void);
-  RowVector get_left (void) const;
-  RowVector get_right (void) const;
-  void set_fs (int fs);
-  int get_fs (void);
-  void set_nbits (int nbits);
-  int get_nbits (void);
-  void set_id (int id);
-  int get_id (void);
-  int get_channels (void);
-  audio_type get_type (void);
+  Matrix& get_y ();
+  RowVector get_left () const;
+  RowVector get_right () const;
+  void set_fs (int m_fs);
+  int get_fs ();
+  void set_nbits (int m_nbits);
+  int get_nbits ();
+  void set_id (int m_id);
+  int get_id ();
+  int get_channels ();
+  audio_type get_type ();
 
   void set_sample_number (unsigned int sample);
-  unsigned int get_sample_number (void);
-  unsigned int get_total_samples (void);
+  unsigned int get_sample_number ();
+  unsigned int get_total_samples ();
   void set_end_sample (unsigned int sample);
-  unsigned int get_end_sample (void);
-  void reset_end_sample (void);
-  void set_tag (const charMatrix& tag);
-  charMatrix get_tag (void);
-  void set_userdata (const octave_value& userdata);
-  octave_value get_userdata (void);
-  PaStream * get_stream (void);
-
-  void play (void);
-  void playblocking (void);
-  void pause (void);
-  void resume (void);
-  void stop (void);
-  bool isplaying (void);
+  unsigned int get_end_sample ();
+  void reset_end_sample ();
+  void set_tag (const charMatrix& m_tag);
+  charMatrix get_tag ();
+  void set_userdata (const octave_value& m_userdata);
+  octave_value get_userdata ();
+  PaStream * get_stream ();
+
+  void play ();
+  void playblocking ();
+  void pause ();
+  void resume ();
+  void stop ();
+  bool isplaying ();
 
   octave_function *octave_callback_function;
 
 private:
-  int id;
-  int fs;
-  int nbits;
-  int channels;
-  unsigned int sample_number;
-  unsigned int end_sample;
-  charMatrix tag;
-  Matrix y;
-  octave_value userdata;
-  RowVector left;
-  RowVector right;
-  PaStream *stream;
-  PaStreamParameters output_parameters;
-  audio_type type;
+  int m_id;
+  int m_fs;
+  int m_nbits;
+  int m_channels;
+  unsigned int m_sample_number;
+  unsigned int m_end_sample;
+  charMatrix m_tag;
+  Matrix m_y;
+  octave_value m_userdata;
+  RowVector m_left;
+  RowVector m_right;
+  PaStream *m_stream;
+  PaStreamParameters m_output_parameters;
+  audio_type m_type;
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
@@ -604,9 +609,11 @@
   if (! player)
     error ("audioplayer callback function called without player");
 
+  interpreter& interp = __get_interpreter__ ();
+
   octave_value_list retval
-    = feval (player->octave_callback_function,
-             ovl (static_cast<double> (frames)), 1);
+    = interp.feval (player->octave_callback_function,
+                    ovl (static_cast<double> (frames)), 1);
 
   if (retval.length () < 2)
     error ("audioplayer callback function failed");
@@ -731,17 +738,17 @@
 
             for (unsigned long j = 0; j < frames; j++)
               {
-                unsigned int sample_number = player->get_sample_number ();
-
-                if (sample_number >= player->get_end_sample ())
+                unsigned int m_sample_number = player->get_sample_number ();
+
+                if (m_sample_number >= player->get_end_sample ())
                   return paComplete;
 
                 unsigned long offset = j * 2;
 
-                buffer[offset+0] = pl[sample_number] * scale_factor;
-                buffer[offset+1] = pr[sample_number] * scale_factor;
-
-                player->set_sample_number (sample_number + 1);
+                buffer[offset+0] = pl[m_sample_number] * scale_factor;
+                buffer[offset+1] = pr[m_sample_number] * scale_factor;
+
+                player->set_sample_number (m_sample_number + 1);
               }
           }
           break;
@@ -754,17 +761,17 @@
 
             for (unsigned long j = 0; j < frames; j++)
               {
-                unsigned int sample_number = player->get_sample_number ();
-
-                if (sample_number >= player->get_end_sample ())
+                unsigned int m_sample_number = player->get_sample_number ();
+
+                if (m_sample_number >= player->get_end_sample ())
                   return paComplete;
 
                 unsigned long offset = j * 2;
 
-                buffer[offset+0] = pl[sample_number] * scale_factor;
-                buffer[offset+1] = pr[sample_number] * scale_factor;
-
-                player->set_sample_number (sample_number + 1);
+                buffer[offset+0] = pl[m_sample_number] * scale_factor;
+                buffer[offset+1] = pr[m_sample_number] * scale_factor;
+
+                player->set_sample_number (m_sample_number + 1);
               }
           }
           break;
@@ -779,13 +786,13 @@
 
             for (unsigned long j = 0; j < frames; j++)
               {
-                unsigned int sample_number = player->get_sample_number ();
-
-                if (sample_number >= player->get_end_sample ())
+                unsigned int m_sample_number = player->get_sample_number ();
+
+                if (m_sample_number >= player->get_end_sample ())
                   return paComplete;
 
-                int32_t sample_l = pl[sample_number] * scale_factor;
-                int32_t sample_r = pr[sample_number] * scale_factor;
+                int32_t sample_l = pl[m_sample_number] * scale_factor;
+                int32_t sample_r = pr[m_sample_number] * scale_factor;
 
                 sample_l &= 0x00ffffff;
                 sample_r &= 0x00ffffff;
@@ -803,7 +810,7 @@
                 buffer[offset+4] = _sample_r[1+big_endian];
                 buffer[offset+5] = _sample_r[2+big_endian];
 
-                player->set_sample_number (sample_number + 1);
+                player->set_sample_number (m_sample_number + 1);
               }
           }
           break;
@@ -818,17 +825,17 @@
 
       for (unsigned long j = 0; j < frames; j++)
         {
-          unsigned int sample_number = player->get_sample_number ();
-
-          if (sample_number >= player->get_end_sample ())
+          unsigned int m_sample_number = player->get_sample_number ();
+
+          if (m_sample_number >= player->get_end_sample ())
             return paComplete;
 
           unsigned long offset = j * 2;
 
-          buffer[offset+0] = pl[sample_number];
-          buffer[offset+1] = pr[sample_number];
-
-          player->set_sample_number (sample_number + 1);
+          buffer[offset+0] = pl[m_sample_number];
+          buffer[offset+1] = pr[m_sample_number];
+
+          player->set_sample_number (m_sample_number + 1);
         }
     }
   else if (player->get_type () == TYPE_UINT8)
@@ -837,17 +844,17 @@
 
       for (unsigned long j = 0; j < frames; j++)
         {
-          unsigned int sample_number = player->get_sample_number ();
-
-          if (sample_number >= player->get_end_sample ())
+          unsigned int m_sample_number = player->get_sample_number ();
+
+          if (m_sample_number >= player->get_end_sample ())
             return paComplete;
 
           unsigned long offset = j * 2;
 
-          buffer[offset+0] = pl[sample_number];
-          buffer[offset+1] = pr[sample_number];
-
-          player->set_sample_number (sample_number + 1);
+          buffer[offset+0] = pl[m_sample_number];
+          buffer[offset+1] = pr[m_sample_number];
+
+          player->set_sample_number (m_sample_number + 1);
         }
     }
   else if (player->get_type () == TYPE_UINT16)
@@ -856,31 +863,31 @@
 
       for (unsigned long j = 0; j < frames; j++)
         {
-          unsigned int sample_number = player->get_sample_number ();
-
-          if (sample_number >= player->get_end_sample ())
+          unsigned int m_sample_number = player->get_sample_number ();
+
+          if (m_sample_number >= player->get_end_sample ())
             return paComplete;
 
           unsigned long offset = j * 2;
 
-          buffer[offset+0] = pl[sample_number];
-          buffer[offset+1] = pr[sample_number];
-
-          player->set_sample_number (sample_number + 1);
+          buffer[offset+0] = pl[m_sample_number];
+          buffer[offset+1] = pr[m_sample_number];
+
+          player->set_sample_number (m_sample_number + 1);
         }
     }
 
   return paContinue;
 }
 
-audioplayer::audioplayer (void)
+audioplayer::audioplayer ()
   : octave_callback_function (nullptr),
-    id (-1), fs (0), nbits (16), channels (0), sample_number (0),
-    end_sample (-1), tag (""), y (), userdata (Matrix ()),
-    left (), right (), stream (nullptr), output_parameters (), type ()
+    m_id (-1), m_fs (0), m_nbits (16), m_channels (0), m_sample_number (0),
+    m_end_sample (-1), m_tag (""), m_y (), m_userdata (Matrix ()),
+    m_left (), m_right (), m_stream (nullptr), m_output_parameters (), m_type ()
 { }
 
-audioplayer::~audioplayer (void)
+audioplayer::~audioplayer ()
 {
   if (isplaying ())
     {
@@ -904,7 +911,7 @@
 }
 
 void
-audioplayer::init_fn (void)
+audioplayer::init_fn ()
 {
   if (Pa_Initialize () != paNoError)
     error ("audioplayer: initialization error");
@@ -917,9 +924,9 @@
   if (device == -1)
     device = Pa_GetDefaultOutputDevice ();
 
-  output_parameters.device = device;
-  output_parameters.channelCount = 2;
-  output_parameters.sampleFormat = bits_to_format (get_nbits ());
+  m_output_parameters.device = device;
+  m_output_parameters.channelCount = 2;
+  m_output_parameters.sampleFormat = bits_to_format (get_nbits ());
 
   const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
 
@@ -927,14 +934,14 @@
     warning_with_id ("Octave:invalid-default-audio-device",
                      "invalid default audio device ID = %d", device);
 
-  output_parameters.suggestedLatency
+  m_output_parameters.suggestedLatency
     = (device_info ? device_info->defaultHighOutputLatency : -1);
 
-  output_parameters.hostApiSpecificStreamInfo = nullptr;
+  m_output_parameters.hostApiSpecificStreamInfo = nullptr;
 }
 
 void
-audioplayer::init (void)
+audioplayer::init ()
 {
   // FIXME: Both of these variables are unused.
   // Should they be eliminated or is something not yet implemented?
@@ -953,17 +960,17 @@
   if (device == -1)
     device = Pa_GetDefaultOutputDevice ();
 
-  output_parameters.device = device;
-  output_parameters.channelCount = 2;
-
-  if (type == TYPE_DOUBLE)
-    output_parameters.sampleFormat = bits_to_format (get_nbits ());
-  else if (type == TYPE_INT8)
-    output_parameters.sampleFormat = paInt8;
-  else if (type == TYPE_UINT8)
-    output_parameters.sampleFormat = paUInt8;
-  else if (type == TYPE_UINT16)
-    output_parameters.sampleFormat = paInt16;
+  m_output_parameters.device = device;
+  m_output_parameters.channelCount = 2;
+
+  if (m_type == TYPE_DOUBLE)
+    m_output_parameters.sampleFormat = bits_to_format (get_nbits ());
+  else if (m_type == TYPE_INT8)
+    m_output_parameters.sampleFormat = paInt8;
+  else if (m_type == TYPE_UINT8)
+    m_output_parameters.sampleFormat = paUInt8;
+  else if (m_type == TYPE_UINT16)
+    m_output_parameters.sampleFormat = paInt16;
 
   const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
 
@@ -971,34 +978,34 @@
     warning_with_id ("Octave:invalid-default-audio-device",
                      "invalid default audio device ID = %d", device);
 
-  output_parameters.suggestedLatency
+  m_output_parameters.suggestedLatency
     = (device_info ? device_info->defaultHighOutputLatency : -1);
 
-  output_parameters.hostApiSpecificStreamInfo = nullptr;
+  m_output_parameters.hostApiSpecificStreamInfo = nullptr;
 }
 
 void
 audioplayer::set_y (const octave_value& y_arg)
 {
   if (y_arg.is_int8_type ())
-    type = TYPE_INT8;
+    m_type = TYPE_INT8;
   else if (y_arg.is_uint8_type ())
-    type = TYPE_UINT8;
+    m_type = TYPE_UINT8;
   else if (y_arg.is_int16_type ())
-    type = TYPE_UINT16;
+    m_type = TYPE_UINT16;
   else
-    type = TYPE_DOUBLE;
-
-  y = y_arg.matrix_value ();
-
-  if (y.rows () > 2)
-    y = y.transpose ();
-
-  channels = y.rows ();
-  left = y.row (0);
-
-  if (channels == 2)
-    right = y.row (1);
+    m_type = TYPE_DOUBLE;
+
+  m_y = y_arg.matrix_value ();
+
+  if (m_y.rows () > 2)
+    m_y = m_y.transpose ();
+
+  m_channels = m_y.rows ();
+  m_left = m_y.row (0);
+
+  if (m_channels == 2)
+    m_right = m_y.row (1);
 
   reset_end_sample ();
 }
@@ -1007,138 +1014,138 @@
 audioplayer::set_y (octave_function *fcn)
 {
   octave_callback_function = fcn;
-  channels = 2;
+  m_channels = 2;
   reset_end_sample ();
 }
 
 Matrix&
-audioplayer::get_y (void)
+audioplayer::get_y ()
 {
-  return y;
+  return m_y;
 }
 
 RowVector
-audioplayer::get_left (void) const
+audioplayer::get_left () const
 {
-  return left;
+  return m_left;
 }
 
 RowVector
-audioplayer::get_right (void) const
+audioplayer::get_right () const
 {
-  return channels == 1 ? left : right;
+  return m_channels == 1 ? m_left : m_right;
 }
 
 void
 audioplayer::set_fs (int fs_arg)
 {
-  fs = fs_arg;
+  m_fs = fs_arg;
 }
 
 int
-audioplayer::get_fs (void)
+audioplayer::get_fs ()
 {
-  return fs;
+  return m_fs;
 }
 
 void
 audioplayer::set_nbits (int nbits_arg)
 {
-  nbits = nbits_arg;
+  m_nbits = nbits_arg;
 }
 
 int
-audioplayer::get_nbits (void)
+audioplayer::get_nbits ()
 {
-  return nbits;
+  return m_nbits;
 }
 
 void
 audioplayer::set_id (int id_arg)
 {
-  id = id_arg;
+  m_id = id_arg;
 }
 
 int
-audioplayer::get_id (void)
+audioplayer::get_id ()
 {
-  return id;
+  return m_id;
 }
 
 int
-audioplayer::get_channels (void)
+audioplayer::get_channels ()
 {
-  return channels;
+  return m_channels;
 }
 
 audio_type
-audioplayer::get_type (void)
+audioplayer::get_type ()
 {
-  return type;
+  return m_type;
 }
 
 void
 audioplayer::set_sample_number (unsigned int sample_number_arg)
 {
-  sample_number = sample_number_arg;
+  m_sample_number = sample_number_arg;
 }
 
 unsigned int
-audioplayer::get_sample_number (void)
+audioplayer::get_sample_number ()
 {
-  return sample_number;
+  return m_sample_number;
 }
 
 unsigned int
-audioplayer::get_total_samples (void)
+audioplayer::get_total_samples ()
 {
-  return left.numel ();
+  return m_left.numel ();
 }
 
 void
 audioplayer::set_end_sample (unsigned int end_sample_arg)
 {
-  end_sample = end_sample_arg;
+  m_end_sample = end_sample_arg;
 }
 
 unsigned int
-audioplayer::get_end_sample (void)
+audioplayer::get_end_sample ()
 {
-  return end_sample;
+  return m_end_sample;
 }
 
 void
-audioplayer::reset_end_sample (void)
+audioplayer::reset_end_sample ()
 {
-  set_end_sample (left.numel ());
+  set_end_sample (m_left.numel ());
 }
 
 void
 audioplayer::set_tag (const charMatrix& tag_arg)
 {
-  tag = tag_arg;
+  m_tag = tag_arg;
 }
 
 charMatrix
-audioplayer::get_tag (void)
+audioplayer::get_tag ()
 {
-  return tag;
+  return m_tag;
 }
 
 void
 audioplayer::set_userdata (const octave_value& userdata_arg)
 {
-  userdata = userdata_arg;
+  m_userdata = userdata_arg;
 }
 
 octave_value
-audioplayer::get_userdata (void)
+audioplayer::get_userdata ()
 {
-  return userdata;
+  return m_userdata;
 }
 
 void
-audioplayer::playblocking (void)
+audioplayer::playblocking ()
 {
   if (get_stream ())
     stop ();
@@ -1147,12 +1154,12 @@
   OCTAVE_LOCAL_BUFFER (uint32_t, buffer, buffer_size * 2);
 
   PaError err;
-  err = Pa_OpenStream (&stream, nullptr, &(output_parameters), get_fs (),
+  err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters), get_fs (),
                        buffer_size, paClipOff, nullptr, nullptr);
   if (err != paNoError)
     error ("audioplayer: unable to open audio playback stream");
 
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audioplayer: unable to start audio playback stream");
 
@@ -1171,12 +1178,12 @@
       else
         portaudio_play_callback (nullptr, buffer, buffer_size, nullptr, 0, this);
 
-      err = Pa_WriteStream (stream, buffer, buffer_size);
+      err = Pa_WriteStream (m_stream, buffer, buffer_size);
     }
 }
 
 void
-audioplayer::play (void)
+audioplayer::play ()
 {
   if (get_stream ())
     stop ();
@@ -1185,54 +1192,54 @@
 
   PaError err;
   if (octave_callback_function != nullptr)
-    err = Pa_OpenStream (&stream, nullptr, &(output_parameters),
+    err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters),
                          get_fs (), buffer_size, paClipOff,
                          octave_play_callback, this);
   else
-    err = Pa_OpenStream (&stream, nullptr, &(output_parameters),
+    err = Pa_OpenStream (&m_stream, nullptr, &(m_output_parameters),
                          get_fs (), buffer_size, paClipOff,
                          portaudio_play_callback, this);
 
   if (err != paNoError)
     error ("audioplayer: failed to open audio playback stream");
 
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audioplayer: failed to start audio playback stream");
 }
 
 void
-audioplayer::pause (void)
+audioplayer::pause ()
 {
   if (get_stream () == nullptr)
     return;
 
   PaError err;
-  err = Pa_StopStream (stream);
+  err = Pa_StopStream (m_stream);
   if (err != paNoError)
     error ("audioplayer: failed to stop audio playback stream");
 }
 
 void
-audioplayer::resume (void)
+audioplayer::resume ()
 {
   if (get_stream () == nullptr)
     return;
 
   PaError err;
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audioplayer: failed to start audio playback stream");
 }
 
 PaStream *
-audioplayer::get_stream (void)
+audioplayer::get_stream ()
 {
-  return stream;
+  return m_stream;
 }
 
 void
-audioplayer::stop (void)
+audioplayer::stop ()
 {
   if (get_stream () == nullptr)
     return;
@@ -1251,17 +1258,17 @@
   if (err != paNoError)
     error ("audioplayer: failed to close audio playback stream");
 
-  stream = nullptr;
+  m_stream = nullptr;
 }
 
 bool
-audioplayer::isplaying (void)
+audioplayer::isplaying ()
 {
   if (get_stream () == nullptr)
     return false;
 
   PaError err;
-  err = Pa_IsStreamActive (stream);
+  err = Pa_IsStreamActive (m_stream);
   if (err != 0 && err != 1)
     error ("audioplayer: checking stream activity status failed");
 
@@ -1271,72 +1278,76 @@
 class audiorecorder : public octave_base_dld_value
 {
 public:
-  audiorecorder (void);
-  ~audiorecorder (void);
+
+  audiorecorder ();
+
+  OCTAVE_DISABLE_COPY_MOVE (audiorecorder)
+
+  ~audiorecorder ();
 
   // Overloaded base functions
-  double player_value (void) const { return 0; }
+  double player_value () const { return 0; }
   virtual double scalar_value (bool = false) const { return 0; }
   void print (std::ostream& os, bool pr_as_read_syntax = false);
   void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
 
   // Properties
-  bool is_constant (void) const { return true; }
-  bool is_defined (void) const { return true; }
-  bool print_as_scalar (void) const { return true; }
-
-  void init (void);
-  void set_fs (int fs);
-  int get_fs (void);
-  void set_nbits (int nbits);
-  int get_nbits (void);
-  PaSampleFormat get_sampleFormat (void);
-  void set_id (int id);
-  int get_id (void);
-  void set_channels (int channels);
-  int get_channels (void);
-  audio_type get_type (void);
+  bool is_constant () const { return true; }
+  bool is_defined () const { return true; }
+  bool print_as_scalar () const { return true; }
+
+  void init ();
+  void set_fs (int m_fs);
+  int get_fs ();
+  void set_nbits (int m_nbits);
+  int get_nbits ();
+  PaSampleFormat get_sampleFormat ();
+  void set_id (int m_id);
+  int get_id ();
+  void set_channels (int m_channels);
+  int get_channels ();
+  audio_type get_type ();
 
   void set_sample_number (unsigned int sample);
-  unsigned int get_sample_number (void);
-  unsigned int get_total_samples (void);
+  unsigned int get_sample_number ();
+  unsigned int get_total_samples ();
   void set_end_sample (unsigned int sample);
-  unsigned int get_end_sample (void);
-  void reset_end_sample (void);
-  void set_tag (const charMatrix& tag);
-  charMatrix get_tag (void);
-  void set_userdata (const octave_value& userdata);
-  octave_value get_userdata (void);
-  PaStream * get_stream (void);
-
-  octave_value getaudiodata (void);
-  audioplayer * getplayer (void);
-  bool isrecording (void);
-  audioplayer play (void);
-  void record (void);
+  unsigned int get_end_sample ();
+  void reset_end_sample ();
+  void set_tag (const charMatrix& m_tag);
+  charMatrix get_tag ();
+  void set_userdata (const octave_value& m_userdata);
+  octave_value get_userdata ();
+  PaStream * get_stream ();
+
+  octave_value getaudiodata ();
+  audioplayer * getplayer ();
+  bool isrecording ();
+  audioplayer play ();
+  void record ();
   void recordblocking (float seconds);
-  void pause (void);
-  void resume (void);
-  void stop (void);
+  void pause ();
+  void resume ();
+  void stop ();
   void append (float sample_l, float sample_r);
 
   octave_function *octave_callback_function;
 
 private:
-  int id;
-  int fs;
-  int nbits;
-  int channels;
-  unsigned int sample_number;
-  unsigned int end_sample;
-  charMatrix tag;
-  Matrix y;
-  octave_value userdata;
-  std::vector<float> left;
-  std::vector<float> right;
-  PaStream *stream;
-  PaStreamParameters input_parameters;
-  audio_type type;
+  int m_id;
+  int m_fs;
+  int m_nbits;
+  int m_channels;
+  unsigned int m_sample_number;
+  unsigned int m_end_sample;
+  charMatrix m_tag;
+  Matrix m_y;
+  octave_value m_userdata;
+  std::vector<float> m_left;
+  std::vector<float> m_right;
+  PaStream *m_stream;
+  PaStreamParameters m_input_parameters;
+  audio_type m_type;
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
@@ -1353,7 +1364,7 @@
   if (! recorder)
     error ("audiorecorder callback function called without recorder");
 
-  int channels = recorder->get_channels ();
+  int m_channels = recorder->get_channels ();
 
   Matrix sound (frames, 2);
   sound.resize (frames, 2);
@@ -1366,8 +1377,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = input8[i*channels] / scale_factor;
-          float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
+          float sample_l = input8[i*m_channels] / scale_factor;
+          float sample_r = input8[i*m_channels + (m_channels - 1)] / scale_factor;
 
           sound(i, 0) = sample_l;
           sound(i, 1) = sample_r;
@@ -1385,8 +1396,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = (input16[i*channels] >> 8) / scale_factor;
-          float sample_r = (input16[i*channels + (channels - 1)] >> 8)
+          float sample_l = (input16[i*m_channels] >> 8) / scale_factor;
+          float sample_r = (input16[i*m_channels + (m_channels - 1)] >> 8)
                            / scale_factor;
 
           sound(i, 0) = sample_l;
@@ -1401,8 +1412,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = input16[i*channels] / scale_factor;
-          float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
+          float sample_l = input16[i*m_channels] / scale_factor;
+          float sample_r = input16[i*m_channels + (m_channels - 1)] / scale_factor;
 
           sound(i, 0) = sample_l;
           sound(i, 1) = sample_r;
@@ -1426,8 +1437,8 @@
           sample_l32 = sample_r32 = 0;
           for (int j = 0; j < 3; j++)
             {
-              sample_l[j] = input24[i*channels*3 + j];
-              sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
+              sample_l[j] = input24[i*m_channels*3 + j];
+              sample_r[j] = input24[i*m_channels*3 + (m_channels - 1)*3 + j];
             }
 
           if (sample_l32 & 0x00800000)
@@ -1441,8 +1452,10 @@
         }
     }
 
+  interpreter& interp = __get_interpreter__ ();
+
   octave_value_list retval
-    = feval (recorder->octave_callback_function, ovl (sound), 1);
+    = interp.feval (recorder->octave_callback_function, ovl (sound), 1);
 
   return retval(0).int_value ();
 }
@@ -1457,7 +1470,7 @@
   if (! recorder)
     error ("audiorecorder callback function called without recorder");
 
-  int channels = recorder->get_channels ();
+  int m_channels = recorder->get_channels ();
 
   if (recorder->get_sampleFormat () == bits_to_format (8))
     {
@@ -1467,8 +1480,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = input8[i*channels] / scale_factor;
-          float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
+          float sample_l = input8[i*m_channels] / scale_factor;
+          float sample_r = input8[i*m_channels + (m_channels - 1)] / scale_factor;
 
           recorder->append (sample_l, sample_r);
         }
@@ -1485,8 +1498,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = (input16[i*channels] >> 8) / scale_factor;
-          float sample_r = (input16[i*channels + (channels - 1)] >> 8)
+          float sample_l = (input16[i*m_channels] >> 8) / scale_factor;
+          float sample_r = (input16[i*m_channels + (m_channels - 1)] >> 8)
                            / scale_factor;
 
           recorder->append (sample_l, sample_r);
@@ -1500,8 +1513,8 @@
 
       for (unsigned long i = 0; i < frames; i++)
         {
-          float sample_l = input16[i*channels] / scale_factor;
-          float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
+          float sample_l = input16[i*m_channels] / scale_factor;
+          float sample_r = input16[i*m_channels + (m_channels - 1)] / scale_factor;
 
           recorder->append (sample_l, sample_r);
         }
@@ -1524,8 +1537,8 @@
           sample_l32 = sample_r32 = 0;
           for (int j = 0; j < 3; j++)
             {
-              sample_l[j] = input24[i*channels*3 + j];
-              sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
+              sample_l[j] = input24[i*m_channels*3 + j];
+              sample_r[j] = input24[i*m_channels*3 + (m_channels - 1)*3 + j];
             }
 
           if (sample_l32 & 0x00800000)
@@ -1545,14 +1558,14 @@
   return paContinue;
 }
 
-audiorecorder::audiorecorder (void)
+audiorecorder::audiorecorder ()
   : octave_callback_function (nullptr),
-    id (-1), fs (8000), nbits (8), channels (1), sample_number (0),
-    end_sample (-1), tag (""), y (), userdata (Matrix ()),
-    left (), right (), stream (nullptr), input_parameters (), type ()
+    m_id (-1), m_fs (8000), m_nbits (8), m_channels (1), m_sample_number (0),
+    m_end_sample (-1), m_tag (""), m_y (), m_userdata (Matrix ()),
+    m_left (), m_right (), m_stream (nullptr), m_input_parameters (), m_type ()
 { }
 
-audiorecorder::~audiorecorder (void)
+audiorecorder::~audiorecorder ()
 {
   if (isrecording ())
     {
@@ -1576,7 +1589,7 @@
 }
 
 void
-audiorecorder::init (void)
+audiorecorder::init ()
 {
   if (Pa_Initialize () != paNoError)
     error ("audiorecorder: initialization error");
@@ -1589,15 +1602,15 @@
   if (device == -1)
     device = Pa_GetDefaultInputDevice ();
 
-  input_parameters.device = device;
-  input_parameters.channelCount = get_channels ();
-  input_parameters.sampleFormat = bits_to_format (get_nbits ());
+  m_input_parameters.device = device;
+  m_input_parameters.channelCount = get_channels ();
+  m_input_parameters.sampleFormat = bits_to_format (get_nbits ());
 
   // FIXME: This is a workaround for a bug in PortAudio affecting 8-Bit
   //        recording (see Octave bug #44305).
   //        Remove this clause once the bug in PortAudio has been fixed.
   if (get_nbits () == 8)
-    input_parameters.sampleFormat = bits_to_format (16);
+    m_input_parameters.sampleFormat = bits_to_format (16);
 
   const PaDeviceInfo *device_info = Pa_GetDeviceInfo (device);
 
@@ -1605,52 +1618,52 @@
     warning_with_id ("Octave:invalid-default-audio-device",
                      "invalid default audio device ID = %d", device);
 
-  input_parameters.suggestedLatency
+  m_input_parameters.suggestedLatency
     = (device_info ? device_info->defaultHighInputLatency : -1);
 
-  input_parameters.hostApiSpecificStreamInfo = nullptr;
+  m_input_parameters.hostApiSpecificStreamInfo = nullptr;
 }
 
 void
 audiorecorder::set_fs (int fs_arg)
 {
-  fs = fs_arg;
+  m_fs = fs_arg;
 }
 
 int
-audiorecorder::get_fs (void)
+audiorecorder::get_fs ()
 {
-  return fs;
+  return m_fs;
 }
 
 void
 audiorecorder::set_nbits (int nbits_arg)
 {
-  nbits = nbits_arg;
+  m_nbits = nbits_arg;
 }
 
 int
-audiorecorder::get_nbits (void)
+audiorecorder::get_nbits ()
 {
-  return nbits;
+  return m_nbits;
 }
 
 PaSampleFormat
-audiorecorder::get_sampleFormat (void)
+audiorecorder::get_sampleFormat ()
 {
-  return input_parameters.sampleFormat;
+  return m_input_parameters.sampleFormat;
 }
 
 void
 audiorecorder::set_id (int id_arg)
 {
-  id = id_arg;
+  m_id = id_arg;
 }
 
 int
-audiorecorder::get_id (void)
+audiorecorder::get_id ()
 {
-  return id;
+  return m_id;
 }
 
 void
@@ -1659,100 +1672,100 @@
   if (channels_arg != 1 && channels_arg != 2)
     error ("audiorecorder: number of channels must be 1 or 2");
 
-  channels = channels_arg;
+  m_channels = channels_arg;
 }
 
 int
-audiorecorder::get_channels (void)
+audiorecorder::get_channels ()
 {
-  return channels;
+  return m_channels;
 }
 
 audio_type
-audiorecorder::get_type (void)
+audiorecorder::get_type ()
 {
-  return type;
+  return m_type;
 }
 
 void
 audiorecorder::set_sample_number (unsigned int sample_number_arg)
 {
-  sample_number = sample_number_arg;
+  m_sample_number = sample_number_arg;
 }
 
 unsigned int
-audiorecorder::get_sample_number (void)
+audiorecorder::get_sample_number ()
 {
-  return sample_number;
+  return m_sample_number;
 }
 
 unsigned int
-audiorecorder::get_total_samples (void)
+audiorecorder::get_total_samples ()
 {
-  return left.size ();
+  return m_left.size ();
 }
 
 void
 audiorecorder::set_end_sample (unsigned int end_sample_arg)
 {
-  end_sample = end_sample_arg;
+  m_end_sample = end_sample_arg;
 }
 
 unsigned int
-audiorecorder::get_end_sample (void)
+audiorecorder::get_end_sample ()
 {
-  return end_sample;
+  return m_end_sample;
 }
 
 void
-audiorecorder::reset_end_sample (void)
+audiorecorder::reset_end_sample ()
 {
-  set_end_sample (left.size ());
+  set_end_sample (m_left.size ());
 }
 
 void
 audiorecorder::set_tag (const charMatrix& tag_arg)
 {
-  tag = tag_arg;
+  m_tag = tag_arg;
 }
 
 charMatrix
-audiorecorder::get_tag (void)
+audiorecorder::get_tag ()
 {
-  return tag;
+  return m_tag;
 }
 
 void
 audiorecorder::set_userdata (const octave_value& userdata_arg)
 {
-  userdata = userdata_arg;
+  m_userdata = userdata_arg;
 }
 
 octave_value
-audiorecorder::get_userdata (void)
+audiorecorder::get_userdata ()
 {
-  return userdata;
+  return m_userdata;
 }
 
 octave_value
-audiorecorder::getaudiodata (void)
+audiorecorder::getaudiodata ()
 {
   // Must get size before entering loop as the value of left.size() may change
   // during loop with simultaneous recording and playback (bug #50674).
-  unsigned int ls = left.size ();
+  unsigned int ls = m_left.size ();
   Matrix audio (2, ls);
 
   for (unsigned int i = 0; i < ls; i++)
     {
-      audio(0, i) = left[i];
-      audio(1, i) = right[i];
+      audio(0, i) = m_left[i];
+      audio(1, i) = m_right[i];
     }
 
   return audio;
 }
 
 audioplayer *
-audiorecorder::getplayer (void)
+audiorecorder::getplayer ()
 {
   audioplayer *player = new audioplayer ();
 
@@ -1765,13 +1778,13 @@
 }
 
 bool
-audiorecorder::isrecording (void)
+audiorecorder::isrecording ()
 {
   if (get_stream () == nullptr)
     return false;
 
   PaError err;
-  err = Pa_IsStreamActive (stream);
+  err = Pa_IsStreamActive (m_stream);
   if (err != 0 && err != 1)
     error ("audiorecorder: checking stream activity status failed");
 
@@ -1779,33 +1792,33 @@
 }
 
 void
-audiorecorder::record (void)
+audiorecorder::record ()
 {
   if (get_stream ())
     stop ();
 
-  left.clear ();
-  right.clear ();
+  m_left.clear ();
+  m_right.clear ();
 
   const unsigned int buffer_size = get_fs () / 20;
 
   PaError err;
   if (octave_callback_function != nullptr)
     {
-      err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
+      err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,
                            get_fs (), buffer_size, paClipOff,
                            octave_record_callback, this);
     }
   else
     {
-      err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
+      err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,
                            get_fs (), buffer_size, paClipOff,
                            portaudio_record_callback, this);
     }
   if (err != paNoError)
     error ("audiorecorder: unable to open audio recording stream");
 
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audiorecorder: unable to start audio recording stream");
 }
@@ -1816,19 +1829,19 @@
   if (get_stream ())
     stop ();
 
-  left.clear ();
-  right.clear ();
+  m_left.clear ();
+  m_right.clear ();
 
   const unsigned int buffer_size = get_fs () / 20;
   OCTAVE_LOCAL_BUFFER (uint8_t, buffer, buffer_size * 2 * 3);
 
   PaError err;
-  err = Pa_OpenStream (&stream, &(input_parameters), nullptr,
+  err = Pa_OpenStream (&m_stream, &(m_input_parameters), nullptr,
                        get_fs (), buffer_size, paClipOff, nullptr, this);
   if (err != paNoError)
     error ("audiorecorder: unable to open audio recording stream");
 
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audiorecorder: unable to start audio recording stream");
 
@@ -1850,31 +1863,31 @@
 }
 
 void
-audiorecorder::pause (void)
+audiorecorder::pause ()
 {
   if (get_stream () == nullptr)
     return;
 
   PaError err;
-  err = Pa_StopStream (stream);
+  err = Pa_StopStream (m_stream);
   if (err != paNoError)
     error ("audiorecorder: unable to stop audio recording stream");
 }
 
 void
-audiorecorder::resume (void)
+audiorecorder::resume ()
 {
   if (get_stream () == nullptr)
     return;
 
   PaError err;
-  err = Pa_StartStream (stream);
+  err = Pa_StartStream (m_stream);
   if (err != paNoError)
     error ("audiorecorder: unable to start audio recording stream");
 }
 
 void
-audiorecorder::stop (void)
+audiorecorder::stop ()
 {
   if (get_stream () == nullptr)
     return;
@@ -1887,27 +1900,27 @@
         error ("audioplayer: unable to stop audio playback stream");
     }
 
-  err = Pa_CloseStream (stream);
+  err = Pa_CloseStream (m_stream);
   if (err != paNoError)
     error ("audiorecorder: unable to close audio recording stream");
 
   set_sample_number (0);
   reset_end_sample ();
-  stream = nullptr;
+  m_stream = nullptr;
 }
 
 void
 audiorecorder::append (float sample_l, float sample_r)
 {
-  left.push_back (sample_l);
-  right.push_back (sample_r);
+  m_left.push_back (sample_l);
+  m_right.push_back (sample_r);
   set_sample_number (get_sample_number () + 1);
 }
 
 PaStream *
-audiorecorder::get_stream (void)
+audiorecorder::get_stream ()
 {
-  return stream;
+  return m_stream;
 }
 
 #endif
@@ -2354,18 +2367,18 @@
   if (args.length () > 2)
     {
       // FIXME: Should be able to support 32-bit streams (bug #57939)
-      int nbits = args(2).int_value ();
-      if (nbits != 8 && nbits != 16 && nbits != 24)
+      int m_nbits = args(2).int_value ();
+      if (m_nbits != 8 && m_nbits != 16 && m_nbits != 24)
         error ("audioplayer: NBITS must be 8, 16, or 24");
 
       switch (args.length ())
         {
         case 3:
-          recorder->set_nbits (nbits);
+          recorder->set_nbits (m_nbits);
           break;
 
         case 4:
-          recorder->set_nbits (nbits);
+          recorder->set_nbits (m_nbits);
           recorder->set_id (args(3).int_value ());
           break;
         }
--- a/libinterp/dldfcn/gzip.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/dldfcn/gzip.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -98,7 +98,7 @@
 {
 public:
 
-  CFile (void) = delete;
+  CFile () = delete;
 
   CFile (const std::string& path, const std::string& mode)
     : m_fp (sys::fopen (path, mode))
@@ -107,17 +107,15 @@
       throw std::runtime_error ("unable to open file");
   }
 
-  CFile (const CFile&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (CFile)
 
-  CFile& operator = (const CFile&) = delete;
-
-  ~CFile (void)
+  ~CFile ()
   {
     if (m_fp)
       std::fclose (m_fp);
   }
 
-  void close (void)
+  void close ()
   {
     if (std::fclose (m_fp))
       throw std::runtime_error ("unable to close file");
@@ -150,7 +148,7 @@
   {
   public:
 
-    zipper (void) = delete;
+    zipper () = delete;
 
     zipper (const std::string& source_path, const std::string& dest_path)
       : m_status (BZ_OK), m_source (source_path, "rb"),
@@ -161,17 +159,15 @@
         throw std::runtime_error ("failed to open bzip2 stream");
     }
 
-    zipper (const zipper&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (zipper)
 
-    zipper& operator = (const zipper&) = delete;
-
-    ~zipper (void)
+    ~zipper ()
     {
       if (m_bz != nullptr)
         BZ2_bzWriteClose (&m_status, m_bz, 1, nullptr, nullptr);
     }
 
-    void deflate (void)
+    void deflate ()
     {
       const std::size_t buf_len = 8192;
       char buf[buf_len];
@@ -188,7 +184,7 @@
         throw std::runtime_error ("failed to read from source file");
     }
 
-    void close (void)
+    void close ()
     {
       int abandon = (m_status == BZ_IO_ERROR) ? 1 : 0;
       BZ2_bzWriteClose (&m_status, m_bz, abandon, nullptr, nullptr);
@@ -265,7 +261,7 @@
     // Bytef is a typedef for unsigned char
     unsigned char *p;
 
-    uchar_array (void) = delete;
+    uchar_array () = delete;
 
     uchar_array (const std::string& str)
     {
@@ -273,18 +269,16 @@
       std::strcpy (reinterpret_cast<char *> (p), str.c_str ());
     }
 
-    uchar_array (const uchar_array&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (uchar_array)
 
-    uchar_array& operator = (const uchar_array&) = delete;
-
-    ~uchar_array (void) { delete[] p; }
+    ~uchar_array () { delete[] p; }
   };
 
   class gzip_header : public gz_header
   {
   public:
 
-    gzip_header (void) = delete;
+    gzip_header () = delete;
 
     gzip_header (const std::string& source_path)
       : m_basename (sys::env::base_pathname (source_path))
@@ -353,11 +347,9 @@
 #endif
     }
 
-    gzip_header (const gzip_header&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (gzip_header)
 
-    gzip_header& operator = (const gzip_header&) = delete;
-
-    ~gzip_header (void) = default;
+    ~gzip_header () = default;
 
   private:
 
@@ -369,7 +361,7 @@
   {
   public:
 
-    zipper (void) = delete;
+    zipper () = delete;
 
     zipper (const std::string& source_path, const std::string& dest_path)
       : m_source (source_path, "rb"), m_dest (dest_path, "wb"),
@@ -380,18 +372,16 @@
       m_strm->opaque = Z_NULL;
     }
 
-    zipper (const zipper&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (zipper)
 
-    zipper& operator = (const zipper&) = delete;
-
-    ~zipper (void)
+    ~zipper ()
     {
       if (m_strm)
         deflateEnd (m_strm);
       delete m_strm;
     }
 
-    void deflate (void)
+    void deflate ()
     {
       // int deflateInit2 (z_streamp m_strm,
       //                   int  level,      // compression level (default is 8)
@@ -451,7 +441,7 @@
         throw std::runtime_error ("failed to write file");
     }
 
-    void close (void)
+    void close ()
     {
       if (deflateEnd (m_strm) != Z_OK)
         throw std::runtime_error ("failed to close zlib stream");
--- a/libinterp/liboctinterp-build-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/liboctinterp-build-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,6 +30,6 @@
 
 #include <string>
 
-extern OCTINTERP_API std::string liboctinterp_hg_id (void);
+extern OCTINTERP_API std::string liboctinterp_hg_id ();
 
 #endif
--- a/libinterp/liboctinterp-build-info.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/liboctinterp-build-info.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 #include "liboctinterp-build-info.h"
 
 std::string
-liboctinterp_hg_id (void)
+liboctinterp_hg_id ()
 {
   return "%OCTAVE_HG_ID%";
 }
--- a/libinterp/mk-build-env-features.sh	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/mk-build-env-features.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 OCTAVE_BEGIN_NAMESPACE(build_env)
 
     octave_scalar_map
-    features (void)
+    features ()
     {
       static bool initialized = false;
 
--- a/libinterp/mk-builtins.pl	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/mk-builtins.pl	Fri Jun 23 20:51:51 2023 +0200
@@ -150,23 +150,6 @@
 
   print "\nOCTAVE_END_NAMESPACE(octave)\n";
 
-  print "\n#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)\n\n";
-
-  foreach $name (sort (@fcn_names))
-  {
-    print "OCTAVE_DEPRECATED (7, \"use 'octave::$name' instead\")
-inline octave_value_list
-$name (const octave_value_list& args = octave_value_list (), int nargout = 0)
-{
-  return octave::$name (args, nargout);
-}
-
-";
-  }
-
-  ## end OCTAVE_PROVIDE_DEPRECATED_SYMBOLS block
-  print "\n\n#endif\n";
-
   print "\n#endif\n";
 }
 elsif ($make_source)
@@ -314,7 +297,7 @@
 
   print "
   void
-  symbol_table::install_builtins (void)
+  symbol_table::install_builtins ()
   {
 ";
 
--- a/libinterp/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -169,21 +169,16 @@
   $(ULT_PARSER_SRC)
 
 LIBINTERP_FOUND_DEFUN_FILES := \
-  $(shell $(SHELL) $(srcdir)/build-aux/find-defun-files.sh "$(srcdir)" $(ULT_DIST_SRC))
+  $(shell $(SHELL) build-aux/find-defun-files.sh "$(srcdir)" $(ULT_DIST_SRC))
 
 BUILT_IN_DEFUN_FILES := $(OPT_HANDLERS) $(LIBINTERP_FOUND_DEFUN_FILES)
 
 LIBINTERP_DEFUN_FILES += \
   $(BUILT_IN_DEFUN_FILES)
 
-## FIXME: The following two variables are deprecated and should be removed
-##        in Octave version 3.12.
-DLL_CDEFS = @OCTINTERP_DLL_DEFS@
-DLL_CXXDEFS = @OCTINTERP_DLL_DEFS@
-
 ## Rules to build test files
 
-LIBINTERP_TST_FILES_SRC := $(shell $(SHELL) $(srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(ULT_DIST_SRC) $(DLDFCN_SRC))
+LIBINTERP_TST_FILES_SRC := $(shell $(SHELL) build-aux/find-files-with-tests.sh "$(srcdir)" $(ULT_DIST_SRC) $(DLDFCN_SRC))
 
 LIBINTERP_TST_FILES := $(addsuffix -tst,$(LIBINTERP_TST_FILES_SRC))
 
--- a/libinterp/octave-value/cdef-class.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-class.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -131,16 +131,14 @@
 {
 public:
 
-  ctor_analyzer (void) = delete;
+  ctor_analyzer () = delete;
 
   ctor_analyzer (const std::string& ctor, const std::string& obj)
     : tree_walker (), m_who (ctor), m_obj_name (obj) { }
 
-  ctor_analyzer (const ctor_analyzer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (ctor_analyzer)
 
-  ctor_analyzer& operator = (const ctor_analyzer&) = delete;
-
-  ~ctor_analyzer (void) = default;
+  ~ctor_analyzer () = default;
 
   void visit_statement (tree_statement& t)
   {
@@ -163,7 +161,7 @@
     t.expression ()->accept (*this);
   }
 
-  std::list<cdef_class> get_constructor_list (void) const
+  std::list<cdef_class> get_constructor_list () const
   { return m_ctor_list; }
 
   // NO-OP
@@ -278,7 +276,7 @@
 }
 
 void
-cdef_class::cdef_class_rep::load_all_methods (void)
+cdef_class::cdef_class_rep::load_all_methods ()
 {
   // FIXME: re-scan class directory
 }
@@ -319,26 +317,24 @@
 {
   load_all_methods ();
 
-  method_const_iterator it;
-
-  for (it = m_method_map.begin (); it != m_method_map.end (); ++it)
+  for (const auto& it : m_method_map)
     {
-      if (include_ctor || ! it->second.is_constructor ())
+      if (include_ctor || ! it.second.is_constructor ())
         {
-          std::string nm = it->second.get_name ();
+          std::string nm = it.second.get_name ();
 
           if (meths.find (nm) == meths.end ())
             {
               if (only_inherited)
                 {
-                  octave_value acc = it->second.get ("Access");
+                  octave_value acc = it.second.get ("Access");
 
                   if (! acc.is_string ()
                       || acc.string_value () == "private")
                     continue;
                 }
 
-              meths[nm] = it->second;
+              meths[nm] = it.second;
             }
         }
     }
@@ -425,24 +421,22 @@
     cdef_property>& props,
     int mode)
 {
-  property_const_iterator it;
-
-  for (it = m_property_map.begin (); it != m_property_map.end (); ++it)
+  for (const auto& it : m_property_map)
     {
-      std::string nm = it->second.get_name ();
+      std::string nm = it.second.get_name ();
 
       if (props.find (nm) == props.end ())
         {
           if (mode == property_inherited)
             {
-              octave_value acc = it->second.get ("GetAccess");
+              octave_value acc = it.second.get ("GetAccess");
 
               if (! acc.is_string ()
                   || acc.string_value () == "private")
                 continue;
             }
 
-          props[nm] = it->second;
+          props[nm] = it.second;
         }
     }
 
@@ -515,7 +509,7 @@
 }
 
 string_vector
-cdef_class::cdef_class_rep::get_names (void)
+cdef_class::cdef_class_rep::get_names ()
 {
   std::set<std::string> names;
 
@@ -584,8 +578,7 @@
         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");
+        std::string nm = idx.front ()(0).xstring_value ("invalid meta.class indexing, expected a method or property name");
 
         cdef_method meth = find_method (nm);
 
@@ -633,7 +626,7 @@
 }
 
 void
-cdef_class::cdef_class_rep::meta_release (void)
+cdef_class::cdef_class_rep::meta_release ()
 {
   cdef_manager& cdm = __get_cdef_manager__ ();
 
--- a/libinterp/octave-value/cdef-class.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-class.h	Fri Jun 23 20:51:51 2023 +0200
@@ -58,7 +58,7 @@
   cdef_class_rep : public cdef_meta_object_rep
   {
   public:
-    cdef_class_rep (void)
+    cdef_class_rep ()
       : cdef_meta_object_rep (), m_member_count (0), m_handle_class (false),
         m_meta (false)
     { }
@@ -67,20 +67,20 @@
 
     cdef_class_rep& operator = (const cdef_class_rep&) = delete;
 
-    ~cdef_class_rep (void) = default;
+    ~cdef_class_rep () = default;
 
-    cdef_object_rep * copy (void) const { return new cdef_class_rep (*this); }
+    cdef_object_rep * copy () const { return new cdef_class_rep (*this); }
 
-    bool is_class (void) const { return true; }
+    bool is_class () const { return true; }
 
-    std::string get_name (void) const
+    std::string get_name () 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_abstract () const { return get ("Abstract").bool_value (); }
 
-    bool is_sealed (void) const { return get ("Sealed").bool_value (); }
+    bool is_sealed () const { return get ("Sealed").bool_value (); }
 
     OCTINTERP_API cdef_method
     find_method (const std::string& nm, bool local = false);
@@ -103,11 +103,11 @@
     OCTINTERP_API std::map<std::string, cdef_property>
     get_property_map (int mode);
 
-    OCTINTERP_API string_vector get_names (void);
+    OCTINTERP_API string_vector get_names ();
 
     void set_directory (const std::string& dir) { m_directory = dir; }
 
-    std::string get_directory (void) const { return m_directory; }
+    std::string get_directory () const { return m_directory; }
 
     OCTINTERP_API void delete_object (const cdef_object& obj);
 
@@ -115,7 +115,7 @@
     meta_subsref (const std::string& type,
                   const std::list<octave_value_list>& idx, int nargout);
 
-    OCTINTERP_API void meta_release (void);
+    OCTINTERP_API void meta_release ();
 
     bool meta_accepts_postfix_index (char type) const
     {
@@ -134,13 +134,13 @@
     OCTINTERP_API void
     run_constructor (cdef_object& obj, const octave_value_list& args);
 
-    void mark_as_handle_class (void) { m_handle_class = true; }
+    void mark_as_handle_class () { m_handle_class = true; }
 
-    bool is_handle_class (void) const { return m_handle_class; }
+    bool is_handle_class () const { return m_handle_class; }
 
-    octave_idx_type static_count (void) const { return m_member_count; }
+    octave_idx_type static_count () const { return m_member_count; }
 
-    void destroy (void)
+    void destroy ()
     {
       if (m_member_count)
         {
@@ -155,21 +155,21 @@
         delete this;
     }
 
-    void mark_as_meta_class (void) { m_meta = true; }
+    void mark_as_meta_class () { m_meta = true; }
 
-    bool is_meta_class (void) const { return m_meta; }
+    bool is_meta_class () const { return m_meta; }
 
     void doc_string (const std::string& txt) { m_doc_string = txt; }
 
-    std::string doc_string (void) const { return m_doc_string; }
+    std::string doc_string () const { return m_doc_string; }
 
     void file_name (const std::string& nm) { m_file_name = nm; }
 
-    std::string file_name (void) const { return m_file_name; }
+    std::string file_name () const { return m_file_name; }
 
   private:
 
-    OCTINTERP_API void load_all_methods (void);
+    OCTINTERP_API void load_all_methods ();
 
     OCTINTERP_API void find_names (std::set<std::string>& names, bool all);
 
@@ -181,7 +181,7 @@
     find_methods (std::map<std::string, cdef_method>& meths,
                   bool only_inherited, bool include_ctor = false);
 
-    cdef_class wrap (void)
+    cdef_class wrap ()
     {
       m_count++;
       return cdef_class (this);
@@ -237,7 +237,7 @@
 
   // Create an invalid class object.
 
-  cdef_class (void) : cdef_meta_object () { }
+  cdef_class () : cdef_meta_object () { }
 
   cdef_class (const std::string& nm,
               const std::list<cdef_class>& superclasses)
@@ -264,7 +264,7 @@
     return *this;
   }
 
-  ~cdef_class (void) = default;
+  ~cdef_class () = default;
 
   OCTINTERP_API cdef_method
   find_method (const std::string& nm, bool local = false);
@@ -303,25 +303,25 @@
     return get_rep ()->get_property_map (mode);
   }
 
-  string_vector get_names (void) { return get_rep ()->get_names (); }
+  string_vector get_names () { return get_rep ()->get_names (); }
 
-  bool is_abstract (void) const { return get_rep ()->is_abstract (); }
+  bool is_abstract () const { return get_rep ()->is_abstract (); }
 
-  bool is_sealed (void) const { return get_rep ()->is_sealed (); }
+  bool is_sealed () const { return get_rep ()->is_sealed (); }
 
   void set_directory (const std::string& dir)
   {
     get_rep ()->set_directory (dir);
   }
 
-  std::string get_directory (void) const
+  std::string get_directory () const
   {
     return get_rep ()->get_directory ();
   }
 
-  std::string get_name (void) const { return get_rep ()->get_name (); }
+  std::string get_name () const { return get_rep ()->get_name (); }
 
-  bool is_builtin (void) const { return get_directory ().empty (); }
+  bool is_builtin () const { return get_directory ().empty (); }
 
   void delete_object (const cdef_object& obj)
   {
@@ -359,7 +359,7 @@
 
   OCTINTERP_API octave_value get_method_function (const std::string& nm);
 
-  octave_value get_constructor_function (void)
+  octave_value get_constructor_function ()
   {
     return get_method_function (get_name ());
   }
@@ -384,27 +384,27 @@
     get_rep ()->run_constructor (obj, args);
   }
 
-  void mark_as_handle_class (void)
+  void mark_as_handle_class ()
   {
     get_rep ()->mark_as_handle_class ();
   }
 
-  bool is_handle_class (void) const
+  bool is_handle_class () const
   {
     return get_rep ()->is_handle_class ();
   }
 
-  void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); }
+  void mark_as_meta_class () { get_rep ()->mark_as_meta_class (); }
 
-  bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
+  bool is_meta_class () const { return get_rep ()->is_meta_class (); }
 
   void doc_string (const std::string& txt) { get_rep ()->doc_string (txt); }
 
-  std::string doc_string (void) const { return get_rep ()->doc_string (); }
+  std::string doc_string () const { return get_rep ()->doc_string (); }
 
   void file_name (const std::string& nm) { get_rep ()->file_name (nm); }
 
-  std::string file_name (void) const { return get_rep ()->file_name (); }
+  std::string file_name () const { return get_rep ()->file_name (); }
 
 public:
 
@@ -417,12 +417,12 @@
 
 private:
 
-  cdef_class_rep * get_rep (void)
+  cdef_class_rep * get_rep ()
   {
     return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ());
   }
 
-  const cdef_class_rep * get_rep (void) const
+  const cdef_class_rep * get_rep () const
   {
     return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ());
   }
--- a/libinterp/octave-value/cdef-manager.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-manager.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,13 +47,9 @@
 
   OCTINTERP_API cdef_manager (interpreter& interp);
 
-  // No copying!
-
-  cdef_manager (const cdef_manager&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (cdef_manager)
 
-  cdef_manager& operator = (const cdef_manager&) = delete;
-
-  ~cdef_manager (void) = default;
+  ~cdef_manager () = default;
 
   OCTINTERP_API cdef_class
   find_class (const std::string& name, bool error_if_not_found = true,
@@ -90,12 +86,12 @@
     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_class& meta_class () const { return m_meta_class; }
+  const cdef_class& meta_property () const { return m_meta_property; }
+  const cdef_class& meta_method () const { return m_meta_method; }
+  const cdef_class& meta_package () const { return m_meta_package; }
 
-  const cdef_package& meta (void) const { return m_meta; }
+  const cdef_package& meta () const { return m_meta; }
 
   OCTINTERP_API cdef_class
   make_class (const std::string& name,
--- a/libinterp/octave-value/cdef-method.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-method.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -68,7 +68,7 @@
 }
 
 void
-cdef_method::cdef_method_rep::check_method (void)
+cdef_method::cdef_method_rep::check_method ()
 {
   if (is_external ())
     {
@@ -134,7 +134,11 @@
   check_method ();
 
   if (m_function.is_defined ())
-    retval = feval (m_function, args, nargout);
+    {
+      interpreter& interp = __get_interpreter__ ();
+
+      retval = interp.feval (m_function, args, nargout);
+    }
 
   return retval;
 }
@@ -166,14 +170,16 @@
       for (int i = 0; i < args.length (); i++)
         new_args(i+1) = args(i);
 
-      retval = feval (m_function, new_args, nargout);
+      interpreter& interp = __get_interpreter__ ();
+
+      retval = interp.feval (m_function, new_args, nargout);
     }
 
   return retval;
 }
 
 bool
-cdef_method::cdef_method_rep::is_constructor (void) const
+cdef_method::cdef_method_rep::is_constructor () const
 {
   if (m_function.is_function())
     return m_function.function_value ()->is_classdef_constructor ();
@@ -190,7 +196,7 @@
 }
 
 std::string
-cdef_method::cdef_method_rep::get_doc_string (void)
+cdef_method::cdef_method_rep::get_doc_string ()
 {
   check_method ();
 
@@ -200,7 +206,7 @@
 }
 
 bool
-cdef_method::cdef_method_rep::check_access (void) const
+cdef_method::cdef_method_rep::check_access () const
 {
   cdef_class cls (to_cdef (get ("DefiningClass")));
 
--- a/libinterp/octave-value/cdef-method.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-method.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,33 +52,33 @@
   {
   public:
 
-    cdef_method_rep (void)
+    cdef_method_rep ()
       : cdef_meta_object_rep (), m_function (), m_dispatch_type ()
     { }
 
     cdef_method_rep& operator = (const cdef_method_rep& m) = delete;
 
-    ~cdef_method_rep (void) = default;
+    ~cdef_method_rep () = default;
 
-    cdef_object_rep * copy (void) const { return new cdef_method_rep(*this); }
+    cdef_object_rep * copy () const { return new cdef_method_rep(*this); }
 
-    bool is_method (void) const { return true; }
+    bool is_method () const { return true; }
 
-    std::string get_name (void) const { return get("Name").string_value (); }
+    std::string get_name () 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 (); }
+    bool is_static () const { return get("Static").bool_value (); }
 
-    octave_value get_function (void) const { return m_function; }
+    octave_value get_function () const { return m_function; }
 
     void set_function (const octave_value& fcn) { m_function = fcn; }
 
-    OCTINTERP_API std::string get_doc_string (void);
+    OCTINTERP_API std::string get_doc_string ();
 
-    OCTINTERP_API bool check_access (void) const;
+    OCTINTERP_API bool check_access () const;
 
-    bool is_external (void) const { return ! m_dispatch_type.empty (); }
+    bool is_external () const { return ! m_dispatch_type.empty (); }
 
     void mark_as_external (const std::string& dtype)
     {
@@ -94,7 +94,7 @@
              const octave_value_list& args, int nargout,
              bool do_check_access = true, const std::string& who = "");
 
-    OCTINTERP_API bool is_constructor (void) const;
+    OCTINTERP_API bool is_constructor () const;
 
     OCTINTERP_API bool is_defined_in_class (const std::string& cname) const;
 
@@ -114,9 +114,9 @@
         m_dispatch_type (m.m_dispatch_type)
     { }
 
-    OCTINTERP_API void check_method (void);
+    OCTINTERP_API void check_method ();
 
-    cdef_method wrap (void)
+    cdef_method wrap ()
     {
       m_count++;
       return cdef_method (this);
@@ -132,7 +132,7 @@
 
 public:
 
-  cdef_method (void) : cdef_meta_object () { }
+  cdef_method () : cdef_meta_object () { }
 
   cdef_method (const std::string& nm)
     : cdef_meta_object (new cdef_method_rep ())
@@ -158,7 +158,7 @@
     return *this;
   }
 
-  ~cdef_method (void) = default;
+  ~cdef_method () = default;
 
   // normal invocation
   octave_value_list execute (const octave_value_list& args, int nargout,
@@ -177,28 +177,28 @@
     return get_rep ()->execute (obj, args, nargout, do_check_access, who);
   }
 
-  bool check_access (void) const { return get_rep ()->check_access (); }
+  bool check_access () const { return get_rep ()->check_access (); }
 
-  std::string get_name (void) const { return get_rep ()->get_name (); }
+  std::string get_name () const { return get_rep ()->get_name (); }
 
-  bool is_static (void) const { return get_rep ()->is_static (); }
+  bool is_static () const { return get_rep ()->is_static (); }
 
   void set_function (const octave_value& fcn)
   {
     get_rep ()->set_function (fcn);
   }
 
-  octave_value get_function (void) const
+  octave_value get_function () const
   {
     return get_rep ()->get_function ();
   }
 
-  std::string get_doc_string (void)
+  std::string get_doc_string ()
   {
     return get_rep ()->get_doc_string ();
   }
 
-  bool is_constructor (void) const
+  bool is_constructor () const
   {
     return get_rep ()->is_constructor ();
   }
@@ -208,7 +208,7 @@
     return get_rep ()->is_defined_in_class (cname);
   }
 
-  bool is_external (void) const { return get_rep ()->is_external (); }
+  bool is_external () const { return get_rep ()->is_external (); }
 
   void mark_as_external (const std::string& dtype)
   {
@@ -217,12 +217,12 @@
 
 private:
 
-  cdef_method_rep * get_rep (void)
+  cdef_method_rep * get_rep ()
   {
     return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ());
   }
 
-  const cdef_method_rep * get_rep (void) const
+  const cdef_method_rep * get_rep () const
   {
     return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ());
   }
--- a/libinterp/octave-value/cdef-object.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-object.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -111,19 +111,19 @@
 }
 
 cdef_class
-cdef_object_rep::get_class (void) const
+cdef_object_rep::get_class () const
 {
   err_invalid_object ("get_class");
 }
 
 std::string
-cdef_object_rep::class_name (void) const
+cdef_object_rep::class_name () const
 {
   return get_class ().get_name ();
 }
 
 string_vector
-cdef_object_rep::map_keys (void) const
+cdef_object_rep::map_keys () const
 {
   cdef_class cls = get_class ();
 
@@ -134,7 +134,7 @@
 }
 
 octave_map
-cdef_object::map_value (void) const
+cdef_object::map_value () const
 {
   octave_map retval;
 
@@ -180,13 +180,13 @@
 }
 
 cdef_class
-cdef_object::get_class (void) const
+cdef_object::get_class () const
 {
   return m_rep->get_class ();
 }
 
 cdef_class
-cdef_object_base::get_class (void) const
+cdef_object_base::get_class () const
 {
   return cdef_class (m_klass);
 }
@@ -203,7 +203,7 @@
 }
 
 cdef_object_rep *
-cdef_object_base::make_array (void) const
+cdef_object_base::make_array () const
 {
   cdef_object_rep *r = new cdef_object_array ();
 
@@ -735,7 +735,7 @@
   m_ctor_list.erase (cls);
 }
 
-handle_cdef_object::~handle_cdef_object (void)
+handle_cdef_object::~handle_cdef_object ()
 {
 #if DEBUG_TRACE
   std::cerr << "deleting " << get_class ().get_name ()
@@ -743,7 +743,7 @@
 #endif
 }
 
-value_cdef_object::~value_cdef_object (void)
+value_cdef_object::~value_cdef_object ()
 {
 #if DEBUG_TRACE
   std::cerr << "deleting " << get_class ().get_name ()
--- a/libinterp/octave-value/cdef-object.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-object.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,48 +53,48 @@
 
   friend class cdef_object;
 
-  cdef_object_rep (void) : m_count (1) { }
+  cdef_object_rep () : m_count (1) { }
 
   cdef_object_rep& operator = (const cdef_object_rep&) = delete;
 
-  virtual ~cdef_object_rep (void) = default;
+  virtual ~cdef_object_rep () = default;
 
-  virtual cdef_class get_class (void) const;
+  virtual cdef_class get_class () const;
 
   virtual void set_class (const cdef_class&)
   {
     err_invalid_object ("set_class");
   }
 
-  virtual cdef_object_rep * clone (void) const
+  virtual cdef_object_rep * clone () const
   {
     err_invalid_object ("clone");
   }
 
-  virtual cdef_object_rep * empty_clone (void) const
+  virtual cdef_object_rep * empty_clone () const
   {
     err_invalid_object ("empty_clone");
   }
 
-  virtual cdef_object_rep * copy (void) const
+  virtual cdef_object_rep * copy () const
   {
     err_invalid_object ("copy");
   }
 
-  virtual cdef_object_rep * make_array (void) const
+  virtual cdef_object_rep * make_array () const
   {
     err_invalid_object ("make_array");
   }
 
-  virtual bool is_array (void) const { return false; }
+  virtual bool is_array () const { return false; }
 
-  virtual bool is_value_object (void) const { return false; }
+  virtual bool is_value_object () const { return false; }
 
-  virtual bool is_handle_object (void) const { return false; }
+  virtual bool is_handle_object () const { return false; }
 
-  virtual bool is_meta_object (void) const { return false; }
+  virtual bool is_meta_object () const { return false; }
 
-  virtual Array<cdef_object> array_value (void) const
+  virtual Array<cdef_object> array_value () const
   {
     err_invalid_object ("array_value");
   }
@@ -137,11 +137,11 @@
     err_invalid_object ("subsasgn");
   }
 
-  virtual string_vector map_keys (void) const;
+  virtual string_vector map_keys () const;
 
-  virtual bool is_valid (void) const { return false; }
+  virtual bool is_valid () const { return false; }
 
-  OCTINTERP_API std::string class_name (void) const;
+  OCTINTERP_API std::string class_name () const;
 
   virtual void mark_for_construction (const cdef_class&)
   {
@@ -158,7 +158,7 @@
     err_invalid_object ("is_partially_constructed_for");
   }
 
-  virtual void mark_as_constructed (void)
+  virtual void mark_as_constructed ()
   {
     err_invalid_object ("mark_as_constructed");
   }
@@ -168,18 +168,18 @@
     err_invalid_object ("mark_as_constructed");
   }
 
-  virtual bool is_constructed (void) const
+  virtual bool is_constructed () const
   {
     err_invalid_object ("is_constructed");
   }
 
-  virtual octave_idx_type static_count (void) const { return 0; }
+  virtual octave_idx_type static_count () const { return 0; }
 
-  virtual void destroy (void) { delete this; }
+  virtual void destroy () { delete this; }
 
   OCTINTERP_API void release (const cdef_object& obj);
 
-  virtual dim_vector dims (void) const { return dim_vector (); }
+  virtual dim_vector dims () const { return dim_vector (); }
 
 protected:
 
@@ -205,14 +205,14 @@
 public:
 
   // FIXME: use a null object?
-  cdef_object (void) : m_rep (new cdef_object_rep ()) { }
+  cdef_object () : m_rep (new cdef_object_rep ()) { }
 
   cdef_object (const cdef_object& obj) : m_rep (obj.m_rep)
   { m_rep->m_count++; }
 
   cdef_object (cdef_object_rep *r) : m_rep (r) { }
 
-  virtual ~cdef_object (void) { m_rep->release (*this); }
+  virtual ~cdef_object () { m_rep->release (*this); }
 
   cdef_object& operator = (const cdef_object& obj)
   {
@@ -227,37 +227,37 @@
     return *this;
   }
 
-  OCTINTERP_API cdef_class get_class (void) const;
+  OCTINTERP_API cdef_class get_class () const;
 
   void set_class (const cdef_class& cls) { m_rep->set_class (cls); }
 
-  std::string class_name (void) const { return m_rep->class_name (); }
+  std::string class_name () const { return m_rep->class_name (); }
 
-  cdef_object clone (void) const { return cdef_object (m_rep->clone ()); }
+  cdef_object clone () const { return cdef_object (m_rep->clone ()); }
 
-  cdef_object empty_clone (void) const
+  cdef_object empty_clone () const
   {
     return cdef_object (m_rep->empty_clone ());
   }
 
-  dim_vector dims (void) const { return m_rep->dims (); }
+  dim_vector dims () const { return m_rep->dims (); }
 
-  cdef_object make_array (void) const
+  cdef_object make_array () const
   {
     return cdef_object (m_rep->make_array ());
   }
 
-  cdef_object copy (void) const { return cdef_object (m_rep->copy ()); }
+  cdef_object copy () const { return cdef_object (m_rep->copy ()); }
 
-  bool is_array (void) const { return m_rep->is_array (); }
+  bool is_array () const { return m_rep->is_array (); }
 
-  bool is_value_object (void) const { return m_rep->is_value_object (); }
+  bool is_value_object () const { return m_rep->is_value_object (); }
 
-  bool is_handle_object (void) const { return m_rep->is_handle_object (); }
+  bool is_handle_object () const { return m_rep->is_handle_object (); }
 
-  bool is_meta_object (void) const { return m_rep->is_meta_object (); }
+  bool is_meta_object () const { return m_rep->is_meta_object (); }
 
-  Array<cdef_object> array_value (void) const
+  Array<cdef_object> array_value () const
   { return m_rep->array_value (); }
 
   void put (const std::string& pname, const octave_value& val)
@@ -303,20 +303,20 @@
     return m_rep->subsasgn (type, idx, rhs);
   }
 
-  string_vector map_keys (void) const { return m_rep->map_keys (); }
+  string_vector map_keys () const { return m_rep->map_keys (); }
 
-  OCTINTERP_API octave_map map_value (void) const;
+  OCTINTERP_API octave_map map_value () const;
 
-  const cdef_object_rep * get_rep (void) const { return m_rep; }
+  const cdef_object_rep * get_rep () const { return m_rep; }
 
-  bool ok (void) const { return m_rep->is_valid (); }
+  bool ok () const { return m_rep->is_valid (); }
 
   void mark_for_construction (const cdef_class& cls)
   {
     m_rep->mark_for_construction (cls);
   }
 
-  bool is_constructed (void) const { return m_rep->is_constructed (); }
+  bool is_constructed () const { return m_rep->is_constructed (); }
 
   bool is_constructed_for (const cdef_class& cls) const
   {
@@ -328,7 +328,7 @@
     return m_rep->is_partially_constructed_for (cls);
   }
 
-  void mark_as_constructed (void) { m_rep->mark_as_constructed (); }
+  void mark_as_constructed () { m_rep->mark_as_constructed (); }
 
   void mark_as_constructed (const cdef_class& cls)
   { m_rep->mark_as_constructed (cls); }
@@ -337,7 +337,7 @@
 
 protected:
 
-  cdef_object_rep * get_rep (void) { return m_rep; }
+  cdef_object_rep * get_rep () { return m_rep; }
 
   void make_unique (int ignore_copies)
   {
@@ -356,24 +356,24 @@
 {
 public:
 
-  cdef_object_base (void)
+  cdef_object_base ()
     : cdef_object_rep (), m_klass ()
   { }
 
   cdef_object_base& operator = (const cdef_object_base&) = delete;
 
-  ~cdef_object_base (void) { }
+  ~cdef_object_base () { }
 
-  OCTINTERP_API cdef_class get_class (void) const;
+  OCTINTERP_API cdef_class get_class () const;
 
   OCTINTERP_API void set_class (const cdef_class& cls);
 
-  cdef_object_rep * empty_clone (void) const
+  cdef_object_rep * empty_clone () const
   {
     return new cdef_object_base (*this);
   }
 
-  OCTINTERP_API cdef_object_rep * make_array (void) const;
+  OCTINTERP_API cdef_object_rep * make_array () const;
 
 protected:
 
@@ -394,7 +394,7 @@
 {
 public:
 
-  cdef_object_array (void) : cdef_object_base () { }
+  cdef_object_array () : cdef_object_base () { }
 
   cdef_object_array (const Array<cdef_object>& a)
     : cdef_object_base (), m_array (a)
@@ -402,20 +402,20 @@
 
   cdef_object_array& operator = (const cdef_object_array&) = delete;
 
-  ~cdef_object_array (void) = default;
+  ~cdef_object_array () = default;
 
-  cdef_object_rep * clone (void) const
+  cdef_object_rep * clone () const
   {
     return new cdef_object_array (*this);
   }
 
-  dim_vector dims (void) const { return m_array.dims (); }
+  dim_vector dims () const { return m_array.dims (); }
 
-  bool is_valid (void) const { return true; }
+  bool is_valid () const { return true; }
 
-  bool is_array (void) const { return true; }
+  bool is_array () const { return true; }
 
-  Array<cdef_object> array_value (void) const { return m_array; }
+  Array<cdef_object> array_value () const { return m_array; }
 
   OCTINTERP_API octave_value_list
   subsref (const std::string& type, const std::list<octave_value_list>& idx,
@@ -446,7 +446,7 @@
 
   Array<cdef_object> m_array;
 
-  void fill_empty_values (void) { fill_empty_values (m_array); }
+  void fill_empty_values () { fill_empty_values (m_array); }
 
   OCTINTERP_API void fill_empty_values (Array<cdef_object>& arr);
 
@@ -462,13 +462,13 @@
 {
 public:
 
-  cdef_object_scalar (void) : cdef_object_base () { }
+  cdef_object_scalar () : cdef_object_base () { }
 
   cdef_object_scalar& operator = (const cdef_object_scalar&) = delete;
 
-  ~cdef_object_scalar (void) = default;
+  ~cdef_object_scalar () = default;
 
-  dim_vector dims (void) const { return dim_vector (1, 1); }
+  dim_vector dims () const { return dim_vector (1, 1); }
 
   void break_closure_cycles (const std::shared_ptr<stack_frame>& frame);
 
@@ -521,11 +521,11 @@
   OCTINTERP_API bool
   is_partially_constructed_for (const cdef_class& cls) const;
 
-  void mark_as_constructed (void) { m_ctor_list.clear (); }
+  void mark_as_constructed () { m_ctor_list.clear (); }
 
   OCTINTERP_API void mark_as_constructed (const cdef_class& cls);
 
-  bool is_constructed (void) const { return m_ctor_list.empty (); }
+  bool is_constructed () const { return m_ctor_list.empty (); }
 
 protected:
 
@@ -549,27 +549,27 @@
 {
 public:
 
-  handle_cdef_object (void) : cdef_object_scalar () { }
+  handle_cdef_object () : cdef_object_scalar () { }
 
   handle_cdef_object& operator = (const handle_cdef_object&) = delete;
 
-  OCTINTERP_API ~handle_cdef_object (void);
+  OCTINTERP_API ~handle_cdef_object ();
 
-  cdef_object_rep * clone (void) const
+  cdef_object_rep * clone () const
   {
     handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
     obj->m_count++;
     return obj;
   }
 
-  cdef_object_rep * copy (void) const
+  cdef_object_rep * copy () const
   {
     return new handle_cdef_object (*this);
   }
 
-  bool is_valid (void) const { return true; }
+  bool is_valid () const { return true; }
 
-  bool is_handle_object (void) const { return true; }
+  bool is_handle_object () const { return true; }
 
 protected:
 
@@ -585,22 +585,22 @@
 {
 public:
 
-  value_cdef_object (void) : cdef_object_scalar () { }
+  value_cdef_object () : cdef_object_scalar () { }
 
   value_cdef_object& operator = (const value_cdef_object&) = delete;
 
-  OCTINTERP_API ~value_cdef_object (void);
+  OCTINTERP_API ~value_cdef_object ();
 
-  cdef_object_rep * clone (void) const
+  cdef_object_rep * clone () const
   {
     return new value_cdef_object (*this);
   }
 
-  cdef_object_rep * copy (void) const { return clone (); }
+  cdef_object_rep * copy () const { return clone (); }
 
-  bool is_valid (void) const { return true; }
+  bool is_valid () const { return true; }
 
-  bool is_value_object (void) const { return true; }
+  bool is_value_object () const { return true; }
 
 private:
 
@@ -616,24 +616,24 @@
 {
 public:
 
-  cdef_meta_object_rep (void) : handle_cdef_object () { }
+  cdef_meta_object_rep () : handle_cdef_object () { }
 
   cdef_meta_object_rep& operator = (const cdef_meta_object_rep&) = delete;
 
-  ~cdef_meta_object_rep (void) = default;
+  ~cdef_meta_object_rep () = default;
 
-  cdef_object_rep * copy (void) const
+  cdef_object_rep * copy () const
   { return new cdef_meta_object_rep (*this); }
 
-  bool is_meta_object (void) const { return true; }
+  bool is_meta_object () const { return true; }
 
-  virtual bool is_class (void) const { return false; }
+  virtual bool is_class () const { return false; }
 
-  virtual bool is_property (void) const { return false; }
+  virtual bool is_property () const { return false; }
 
-  virtual bool is_method (void) const { return false; }
+  virtual bool is_method () const { return false; }
 
-  virtual bool is_package (void) const { return false; }
+  virtual bool is_package () const { return false; }
 
   virtual octave_value_list
   meta_subsref (const std::string& /* type */,
@@ -643,7 +643,7 @@
     error ("subsref: invalid meta object");
   }
 
-  virtual void meta_release (void) { }
+  virtual void meta_release () { }
 
   virtual bool meta_accepts_postfix_index (char /* type */) const
   {
@@ -664,7 +664,7 @@
 {
 public:
 
-  cdef_meta_object (void) : cdef_object () { }
+  cdef_meta_object () : cdef_object () { }
 
   // Object consistency is checked in sub-classes.
   cdef_meta_object (const cdef_meta_object& obj) : cdef_object (obj) { }
@@ -675,15 +675,15 @@
 
   cdef_meta_object& operator = (const cdef_object&) = delete;
 
-  ~cdef_meta_object (void) = default;
+  ~cdef_meta_object () = default;
 
-  bool is_class (void) const { return get_rep ()->is_class (); }
+  bool is_class () const { return get_rep ()->is_class (); }
 
-  bool is_property (void) const { return get_rep ()->is_property (); }
+  bool is_property () const { return get_rep ()->is_property (); }
 
-  bool is_method (void) const { return get_rep ()->is_method (); }
+  bool is_method () const { return get_rep ()->is_method (); }
 
-  bool is_package (void) const { return get_rep ()->is_package (); }
+  bool is_package () const { return get_rep ()->is_package (); }
 
   octave_value_list
   meta_subsref (const std::string& type,
@@ -692,7 +692,7 @@
     return get_rep ()->meta_subsref (type, idx, nargout);
   }
 
-  void meta_release (void) { get_rep ()->meta_release (); }
+  void meta_release () { get_rep ()->meta_release (); }
 
   bool meta_accepts_postfix_index (char type) const
   {
@@ -701,12 +701,12 @@
 
 private:
 
-  cdef_meta_object_rep * get_rep (void)
+  cdef_meta_object_rep * get_rep ()
   {
     return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ());
   }
 
-  const cdef_meta_object_rep * get_rep (void) const
+  const cdef_meta_object_rep * get_rep () const
   {
     return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ());
   }
--- a/libinterp/octave-value/cdef-package.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-package.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,6 @@
 #include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
-#include "parse.h"
 #include "pt-assign.h"
 #include "pt-classdef.h"
 #include "pt-idx.h"
@@ -85,26 +84,26 @@
   Cell retval (1, m.size ());
   int i = 0;
 
-  for (auto it = m.begin (); it != m.end (); ++it, ++i)
-    retval(i) = to_ov (it->second);
+  for (const auto& it : m)
+    retval(i++) = to_ov (it.second);
 
   return retval;
 }
 
 Cell
-cdef_package::cdef_package_rep::get_classes (void) const
+cdef_package::cdef_package_rep::get_classes () const
 {
   return map2Cell (m_class_map);
 }
 
 Cell
-cdef_package::cdef_package_rep::get_functions (void) const
+cdef_package::cdef_package_rep::get_functions () const
 {
   return map2Cell (m_function_map);
 }
 
 Cell
-cdef_package::cdef_package_rep::get_packages (void) const
+cdef_package::cdef_package_rep::get_packages () const
 {
   return map2Cell (m_package_map);
 }
@@ -133,8 +132,7 @@
         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");
+        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;
@@ -161,7 +159,9 @@
               {
                 octave_value_list tmp_args;
 
-                retval = feval (o, tmp_args, nargout);
+                interpreter& interp = __get_interpreter__ ();
+
+                retval = interp.feval (o, tmp_args, nargout);
               }
             else
               retval(0) = o;
@@ -186,7 +186,7 @@
 }
 
 void
-cdef_package::cdef_package_rep::meta_release (void)
+cdef_package::cdef_package_rep::meta_release ()
 {
   // FIXME: Do we really want to unregister the package, as it
   //        could still be referenced by classes or sub-packages?
--- a/libinterp/octave-value/cdef-package.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-package.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,18 +55,18 @@
   {
   public:
 
-    cdef_package_rep (void) : cdef_meta_object_rep (), m_member_count (0) { }
+    cdef_package_rep () : cdef_meta_object_rep (), m_member_count (0) { }
 
     cdef_package_rep& operator = (const cdef_package_rep&) = delete;
 
-    ~cdef_package_rep (void) = default;
+    ~cdef_package_rep () = default;
 
-    cdef_object_rep * copy (void) const
+    cdef_object_rep * copy () const
     { return new cdef_package_rep (*this); }
 
-    bool is_package (void) const { return true; }
+    bool is_package () const { return true; }
 
-    std::string get_name (void) const { return get("Name").string_value (); }
+    std::string get_name () const { return get("Name").string_value (); }
 
     void set_name (const std::string& nm) { put ("Name", nm); }
 
@@ -79,15 +79,15 @@
     OCTINTERP_API void
     install_package (const cdef_package& pack, const std::string& nm);
 
-    OCTINTERP_API Cell get_classes (void) const;
+    OCTINTERP_API Cell get_classes () const;
 
-    OCTINTERP_API Cell get_functions (void) const;
+    OCTINTERP_API Cell get_functions () const;
 
-    OCTINTERP_API Cell get_packages (void) const;
+    OCTINTERP_API Cell get_packages () const;
 
-    octave_idx_type static_count (void) const { return m_member_count; }
+    octave_idx_type static_count () const { return m_member_count; }
 
-    void destroy (void)
+    void destroy ()
     {
       if (m_member_count)
         {
@@ -106,7 +106,7 @@
     meta_subsref (const std::string& type,
                   const std::list<octave_value_list>& idx, int nargout);
 
-    OCTINTERP_API void meta_release (void);
+    OCTINTERP_API void meta_release ();
 
     bool meta_accepts_postfix_index (char type) const
     {
@@ -141,7 +141,7 @@
         m_package_map (p.m_package_map), m_member_count (p.m_member_count)
     { }
 
-    cdef_package wrap (void)
+    cdef_package wrap ()
     {
       m_count++;
       return cdef_package (this);
@@ -150,7 +150,7 @@
 
 public:
 
-  cdef_package (void) : cdef_meta_object () { }
+  cdef_package () : cdef_meta_object () { }
 
   cdef_package (const std::string& nm)
     : cdef_meta_object (new cdef_package_rep ())
@@ -176,7 +176,7 @@
     return *this;
   }
 
-  ~cdef_package (void) = default;
+  ~cdef_package () = default;
 
   void install_class (const cdef_class& cls, const std::string& nm)
   {
@@ -193,22 +193,22 @@
     get_rep ()->install_package (pack, nm);
   }
 
-  Cell get_classes (void) const
+  Cell get_classes () const
   {
     return get_rep ()->get_classes ();
   }
 
-  Cell get_functions (void) const
+  Cell get_functions () const
   {
     return get_rep ()->get_functions ();
   }
 
-  Cell get_packages (void) const
+  Cell get_packages () const
   {
     return get_rep ()->get_packages ();
   }
 
-  std::string get_name (void) const { return get_rep ()->get_name (); }
+  std::string get_name () const { return get_rep ()->get_name (); }
 
   octave_value find (const std::string& nm)
   {
@@ -217,12 +217,12 @@
 
 private:
 
-  cdef_package_rep * get_rep (void)
+  cdef_package_rep * get_rep ()
   {
     return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ());
   }
 
-  const cdef_package_rep * get_rep (void) const
+  const cdef_package_rep * get_rep () const
   {
     return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ());
   }
--- a/libinterp/octave-value/cdef-property.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-property.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,6 @@
 #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"
@@ -133,7 +132,9 @@
 
       args(0) = to_ov (obj);
 
-      args = feval (get_fcn, args, 1);
+      interpreter& interp = __get_interpreter__ ();
+
+      args = interp.feval (get_fcn, args, 1);
 
       retval = args(0);
     }
@@ -207,11 +208,13 @@
       args(0) = to_ov (obj);
       args(1) = val;
 
+      interpreter& interp = __get_interpreter__ ();
+
       if (obj.is_handle_object ())
-        feval (set_fcn, args, 0);
+        interp.feval (set_fcn, args, 0);
       else
         {
-          args = feval (set_fcn, args, 1);
+          args = interp.feval (set_fcn, args, 1);
 
           if (args.length () > 0 && args(0).is_defined ())
             {
@@ -230,7 +233,7 @@
 }
 
 bool
-cdef_property::cdef_property_rep::check_get_access (void) const
+cdef_property::cdef_property_rep::check_get_access () const
 {
   cdef_class cls (to_cdef (get ("DefiningClass")));
 
@@ -240,7 +243,7 @@
 }
 
 bool
-cdef_property::cdef_property_rep::check_set_access (void) const
+cdef_property::cdef_property_rep::check_set_access () const
 {
   cdef_class cls (to_cdef (get ("DefiningClass")));
 
--- a/libinterp/octave-value/cdef-property.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-property.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,24 +53,24 @@
   {
   public:
 
-    cdef_property_rep (void) : cdef_meta_object_rep () { }
+    cdef_property_rep () : cdef_meta_object_rep () { }
 
     cdef_property_rep& operator = (const cdef_property_rep& p) = delete;
 
-    ~cdef_property_rep (void) = default;
+    ~cdef_property_rep () = default;
 
-    cdef_object_rep * copy (void) const
+    cdef_object_rep * copy () const
     {
       return new cdef_property_rep (*this);
     }
 
-    bool is_property (void) const { return true; }
+    bool is_property () const { return true; }
 
-    std::string get_name (void) const { return get("Name").string_value (); }
+    std::string get_name () 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 (); }
+    bool is_constant () const { return get("Constant").bool_value (); }
 
     octave_value get_value (bool do_check_access = true,
                             const std::string& who = "") const;
@@ -83,9 +83,9 @@
                     bool do_check_access = true,
                     const std::string& who = "");
 
-    OCTINTERP_API bool check_get_access (void) const;
+    OCTINTERP_API bool check_get_access () const;
 
-    OCTINTERP_API bool check_set_access (void) const;
+    OCTINTERP_API bool check_set_access () const;
 
   private:
     cdef_property_rep (const cdef_property_rep& p)
@@ -94,7 +94,7 @@
 
     OCTINTERP_API bool is_recursive_set (const cdef_object& obj) const;
 
-    cdef_property wrap (void)
+    cdef_property wrap ()
     {
       m_count++;
       return cdef_property (this);
@@ -107,7 +107,7 @@
 
 public:
 
-  cdef_property (void) : cdef_meta_object () { }
+  cdef_property () : cdef_meta_object () { }
 
   cdef_property (const std::string& nm)
     : cdef_meta_object (new cdef_property_rep ())
@@ -133,7 +133,7 @@
     return *this;
   }
 
-  ~cdef_property (void) = default;
+  ~cdef_property () = default;
 
   octave_value get_value (const cdef_object& obj, bool do_check_access = true,
                           const std::string& who = "") const
@@ -154,28 +154,28 @@
     get_rep ()->set_value (obj, val, do_check_access, who);
   }
 
-  bool check_get_access (void) const
+  bool check_get_access () const
   {
     return get_rep ()->check_get_access ();
   }
 
-  bool check_set_access (void) const
+  bool check_set_access () const
   {
     return get_rep ()->check_set_access ();
   }
 
-  std::string get_name (void) const { return get_rep ()->get_name (); }
+  std::string get_name () const { return get_rep ()->get_name (); }
 
-  bool is_constant (void) const { return get_rep ()->is_constant (); }
+  bool is_constant () const { return get_rep ()->is_constant (); }
 
 private:
 
-  cdef_property_rep * get_rep (void)
+  cdef_property_rep * get_rep ()
   {
     return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ());
   }
 
-  const cdef_property_rep * get_rep (void) const
+  const cdef_property_rep * get_rep () const
   {
     return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ());
   }
--- a/libinterp/octave-value/cdef-utils.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-utils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -282,7 +282,7 @@
 }
 
 cdef_class
-get_class_context (void)
+get_class_context ()
 {
   std::string dummy_string;
   bool dummy_bool;
--- a/libinterp/octave-value/cdef-utils.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/cdef-utils.h	Fri Jun 23 20:51:51 2023 +0200
@@ -99,7 +99,7 @@
 get_class_context (std::string& name, bool& in_constructor);
 
 extern OCTINTERP_API cdef_class
-get_class_context (void);
+get_class_context ();
 
 extern OCTINTERP_API bool
 check_access (const cdef_class& cls, const octave_value& acc,
--- a/libinterp/octave-value/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -51,6 +51,7 @@
   %reldir%/ov-flt-cx-mat.h \
   %reldir%/ov-flt-re-diag.h \
   %reldir%/ov-flt-re-mat.h \
+  %reldir%/ov-inline.h \
   %reldir%/ov-java.h \
   %reldir%/ov-lazy-idx.h \
   %reldir%/ov-legacy-range.h \
@@ -61,6 +62,7 @@
   %reldir%/ov-perm.h \
   %reldir%/ov-range-traits.h \
   %reldir%/ov-range.h \
+  %reldir%/ov-ref.h \
   %reldir%/ov-re-diag.h \
   %reldir%/ov-re-mat.h \
   %reldir%/ov-scalar.h \
@@ -69,6 +71,7 @@
   %reldir%/ov-typeinfo.h \
   %reldir%/ov-usr-fcn.h \
   %reldir%/ov.h \
+  %reldir%/ov-vm.h \
   %reldir%/ovl.h \
   $(OV_INTTYPE_INC) \
   $(OV_SPARSE_INC)
@@ -127,6 +130,7 @@
   %reldir%/ov-oncleanup.cc \
   %reldir%/ov-perm.cc \
   %reldir%/ov-range.cc \
+  %reldir%/ov-ref.cc \
   %reldir%/ov-re-diag.cc \
   %reldir%/ov-re-mat.cc \
   %reldir%/ov-scalar.cc \
--- a/libinterp/octave-value/ov-base-diag.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-diag.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -192,7 +192,7 @@
                   {
                     m_matrix.dgelem (i0(0)) = val;
                     retval = this;
-                    this->count++;
+                    this->m_count++;
                     // invalidate cache
                     m_dense_cache = octave_value ();
                   }
@@ -220,7 +220,7 @@
                   {
                     m_matrix.dgelem (i0(0)) = val;
                     retval = this;
-                    this->count++;
+                    this->m_count++;
                     // invalidate cache
                     m_dense_cache = octave_value ();
                   }
@@ -276,10 +276,10 @@
   return retval;
 }
 
-// Return true if this matrix has all true elements (non-zero, not NA/NaN).
+// Return true if this matrix has all true elements (nonzero, not NA/NaN).
 template <typename DMT, typename MT>
 bool
-octave_base_diag<DMT, MT>::is_true (void) const
+octave_base_diag<DMT, MT>::is_true () const
 {
   if (dims ().numel () > 1)
     {
@@ -473,7 +473,7 @@
 
 template <typename DMT, typename MT>
 float_display_format
-octave_base_diag<DMT, MT>::get_edit_display_format (void) const
+octave_base_diag<DMT, MT>::get_edit_display_format () const
 {
   // FIXME
   return float_display_format ();
@@ -551,7 +551,7 @@
 
 template <typename DMT, typename MT>
 bool
-octave_base_diag<DMT, MT>::print_as_scalar (void) const
+octave_base_diag<DMT, MT>::print_as_scalar () const
 {
   dim_vector dv = dims ();
 
@@ -657,7 +657,7 @@
 
 template <typename DMT, typename MT>
 octave_value
-octave_base_diag<DMT, MT>::to_dense (void) const
+octave_base_diag<DMT, MT>::to_dense () const
 {
   if (! m_dense_cache.is_defined ())
     m_dense_cache = MT (m_matrix);
--- a/libinterp/octave-value/ov-base-diag.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-diag.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 
 public:
 
-  octave_base_diag (void)
+  octave_base_diag ()
     : octave_base_value (), m_matrix (), m_dense_cache () { }
 
   octave_base_diag (const DMT& m)
@@ -60,13 +60,13 @@
   octave_base_diag (const octave_base_diag& m)
     : octave_base_value (), m_matrix (m.m_matrix), m_dense_cache () { }
 
-  ~octave_base_diag (void) = default;
+  ~octave_base_diag () = default;
 
-  std::size_t byte_size (void) const { return m_matrix.byte_size (); }
+  std::size_t byte_size () const { return m_matrix.byte_size (); }
 
-  octave_value squeeze (void) const { return m_matrix; }
+  octave_value squeeze () const { return m_matrix; }
 
-  octave_value full_value (void) const { return to_dense (); }
+  octave_value full_value () 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
@@ -87,9 +87,9 @@
   subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
             const octave_value& rhs);
 
-  dim_vector dims (void) const { return m_matrix.dims (); }
+  dim_vector dims () const { return m_matrix.dims (); }
 
-  octave_idx_type nnz (void) const { return diag ().nnz (); }
+  octave_idx_type nnz () const { return diag ().nnz (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return to_dense ().reshape (new_dims); }
@@ -110,7 +110,7 @@
   octave_value all (int dim = 0) const { return MT (m_matrix).all (dim); }
   octave_value any (int dim = 0) const { return MT (m_matrix).any (dim); }
 
-  MatrixType matrix_type (void) const { return MatrixType::Diagonal; }
+  MatrixType matrix_type () const { return MatrixType::Diagonal; }
   MatrixType matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
@@ -136,17 +136,17 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const
   { return to_dense ().is_sorted_rows (mode); }
 
-  bool is_matrix_type (void) const { return true; }
+  bool is_matrix_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  OCTINTERP_API bool is_true (void) const;
+  OCTINTERP_API bool is_true () const;
 
-  bool is_diag_matrix (void) const { return true; }
+  bool is_diag_matrix () const { return true; }
 
   OCTINTERP_API double double_value (bool = false) const;
 
@@ -190,28 +190,28 @@
   sparse_complex_matrix_value (bool = false) const;
 
   int8NDArray
-  int8_array_value (void) const { return to_dense ().int8_array_value (); }
+  int8_array_value () const { return to_dense ().int8_array_value (); }
 
   int16NDArray
-  int16_array_value (void) const { return to_dense ().int16_array_value (); }
+  int16_array_value () const { return to_dense ().int16_array_value (); }
 
   int32NDArray
-  int32_array_value (void) const { return to_dense ().int32_array_value (); }
+  int32_array_value () const { return to_dense ().int32_array_value (); }
 
   int64NDArray
-  int64_array_value (void) const { return to_dense ().int64_array_value (); }
+  int64_array_value () const { return to_dense ().int64_array_value (); }
 
   uint8NDArray
-  uint8_array_value (void) const { return to_dense ().uint8_array_value (); }
+  uint8_array_value () const { return to_dense ().uint8_array_value (); }
 
   uint16NDArray
-  uint16_array_value (void) const { return to_dense ().uint16_array_value (); }
+  uint16_array_value () const { return to_dense ().uint16_array_value (); }
 
   uint32NDArray
-  uint32_array_value (void) const { return to_dense ().uint32_array_value (); }
+  uint32_array_value () const { return to_dense ().uint32_array_value (); }
 
   uint64NDArray
-  uint64_array_value (void) const { return to_dense ().uint64_array_value (); }
+  uint64_array_value () const { return to_dense ().uint64_array_value (); }
 
   OCTINTERP_API octave_value
   convert_to_str_internal (bool pad, bool force, char type) const;
@@ -219,7 +219,7 @@
   OCTINTERP_API void
   print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
@@ -236,7 +236,7 @@
 
   OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;
 
-  OCTINTERP_API bool print_as_scalar (void) const;
+  OCTINTERP_API bool print_as_scalar () const;
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -251,7 +251,7 @@
 
   DMT m_matrix;
 
-  OCTINTERP_API octave_value to_dense (void) const;
+  OCTINTERP_API octave_value to_dense () const;
 
   virtual bool chk_valid_scalar (const octave_value&,
                                  typename DMT::element_type&) const = 0;
--- a/libinterp/octave-value/ov-base-int.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-int.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -144,7 +144,7 @@
 
 template <typename T>
 octave_base_value *
-octave_base_int_matrix<T>::try_narrowing_conversion (void)
+octave_base_int_matrix<T>::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -205,70 +205,70 @@
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_double (void) const
+octave_base_int_matrix<MT>::as_double () const
 {
   return NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_single (void) const
+octave_base_int_matrix<MT>::as_single () const
 {
   return FloatNDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_int8 (void) const
+octave_base_int_matrix<MT>::as_int8 () const
 {
   return int8NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_int16 (void) const
+octave_base_int_matrix<MT>::as_int16 () const
 {
   return int16NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_int32 (void) const
+octave_base_int_matrix<MT>::as_int32 () const
 {
   return int32NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_int64 (void) const
+octave_base_int_matrix<MT>::as_int64 () const
 {
   return int64NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_uint8 (void) const
+octave_base_int_matrix<MT>::as_uint8 () const
 {
   return uint8NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_uint16 (void) const
+octave_base_int_matrix<MT>::as_uint16 () const
 {
   return uint16NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_uint32 (void) const
+octave_base_int_matrix<MT>::as_uint32 () const
 {
   return uint32NDArray (this->m_matrix);
 }
 
 template <typename MT>
 octave_value
-octave_base_int_matrix<MT>::as_uint64 (void) const
+octave_base_int_matrix<MT>::as_uint64 () const
 {
   return uint64NDArray (this->m_matrix);
 }
@@ -599,70 +599,70 @@
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_double (void) const
+octave_base_int_scalar<T>::as_double () const
 {
   return static_cast<double> (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_single (void) const
+octave_base_int_scalar<T>::as_single () const
 {
   return static_cast<float> (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_int8 (void) const
+octave_base_int_scalar<T>::as_int8 () const
 {
   return octave_int8 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_int16 (void) const
+octave_base_int_scalar<T>::as_int16 () const
 {
   return octave_int16 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_int32 (void) const
+octave_base_int_scalar<T>::as_int32 () const
 {
   return octave_int32 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_int64 (void) const
+octave_base_int_scalar<T>::as_int64 () const
 {
   return octave_int64 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_uint8 (void) const
+octave_base_int_scalar<T>::as_uint8 () const
 {
   return octave_uint8 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_uint16 (void) const
+octave_base_int_scalar<T>::as_uint16 () const
 {
   return octave_uint16 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_uint32 (void) const
+octave_base_int_scalar<T>::as_uint32 () const
 {
   return octave_uint32 (this->scalar);
 }
 
 template <typename T>
 octave_value
-octave_base_int_scalar<T>::as_uint64 (void) const
+octave_base_int_scalar<T>::as_uint64 () const
 {
   return octave_uint64 (this->scalar);
 }
--- a/libinterp/octave-value/ov-base-int.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-int.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,25 +51,25 @@
 {
 public:
 
-  octave_base_int_matrix (void) : octave_base_matrix<T> () { }
+  octave_base_int_matrix () : octave_base_matrix<T> () { }
 
   octave_base_int_matrix (const T& nda) : octave_base_matrix<T> (nda) { }
 
-  ~octave_base_int_matrix (void) = default;
+  ~octave_base_int_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_base_int_matrix (*this); }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_base_int_matrix (); }
 
-  OCTINTERP_API octave_base_value * try_narrowing_conversion (void);
+  OCTINTERP_API octave_base_value * try_narrowing_conversion ();
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  //  void increment (void) { matrix += 1; }
+  //  void increment () { matrix += 1; }
 
-  //  void decrement (void) { matrix -= 1; }
+  //  void decrement () { matrix -= 1; }
 
   OCTINTERP_API void
   print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
@@ -77,18 +77,18 @@
   OCTINTERP_API octave_value
   convert_to_str_internal (bool, bool, char type) const;
 
-  OCTINTERP_API octave_value as_double (void) const;
-  OCTINTERP_API octave_value as_single (void) const;
+  OCTINTERP_API octave_value as_double () const;
+  OCTINTERP_API octave_value as_single () const;
 
-  OCTINTERP_API octave_value as_int8 (void) const;
-  OCTINTERP_API octave_value as_int16 (void) const;
-  OCTINTERP_API octave_value as_int32 (void) const;
-  OCTINTERP_API octave_value as_int64 (void) const;
+  OCTINTERP_API octave_value as_int8 () const;
+  OCTINTERP_API octave_value as_int16 () const;
+  OCTINTERP_API octave_value as_int32 () const;
+  OCTINTERP_API octave_value as_int64 () const;
 
-  OCTINTERP_API octave_value as_uint8 (void) const;
-  OCTINTERP_API octave_value as_uint16 (void) const;
-  OCTINTERP_API octave_value as_uint32 (void) const;
-  OCTINTERP_API octave_value as_uint64 (void) const;
+  OCTINTERP_API octave_value as_uint8 () const;
+  OCTINTERP_API octave_value as_uint16 () const;
+  OCTINTERP_API octave_value as_uint32 () const;
+  OCTINTERP_API octave_value as_uint64 () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
@@ -123,42 +123,44 @@
 {
 public:
 
-  octave_base_int_scalar (void) : octave_base_scalar<T> () { }
+  octave_base_int_scalar () : octave_base_scalar<T> () { }
 
   octave_base_int_scalar (const T& s) : octave_base_scalar<T> (s) { }
 
-  ~octave_base_int_scalar (void) = default;
+  ~octave_base_int_scalar () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_base_int_scalar (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_base_int_scalar (); }
 
-  octave_base_value * try_narrowing_conversion (void) { return nullptr; }
+  octave_base_value * try_narrowing_conversion () { return nullptr; }
 
-  bool isreal (void) const { return true; }
+  bool is_maybe_function (void) const { return false; }
+
+  bool isreal () const { return true; }
 
-  bool is_real_scalar (void) const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  //  void increment (void) { scalar += 1; }
+  //  void increment () { scalar += 1; }
 
-  //  void decrement (void) { scalar -= 1; }
+  //  void decrement () { scalar -= 1; }
 
   OCTINTERP_API octave_value
   convert_to_str_internal (bool, bool, char type) const;
 
-  OCTINTERP_API octave_value as_double (void) const;
-  OCTINTERP_API octave_value as_single (void) const;
+  OCTINTERP_API octave_value as_double () const;
+  OCTINTERP_API octave_value as_single () const;
 
-  OCTINTERP_API octave_value as_int8 (void) const;
-  OCTINTERP_API octave_value as_int16 (void) const;
-  OCTINTERP_API octave_value as_int32 (void) const;
-  OCTINTERP_API octave_value as_int64 (void) const;
+  OCTINTERP_API octave_value as_int8 () const;
+  OCTINTERP_API octave_value as_int16 () const;
+  OCTINTERP_API octave_value as_int32 () const;
+  OCTINTERP_API octave_value as_int64 () const;
 
-  OCTINTERP_API octave_value as_uint8 (void) const;
-  OCTINTERP_API octave_value as_uint16 (void) const;
-  OCTINTERP_API octave_value as_uint32 (void) const;
-  OCTINTERP_API octave_value as_uint64 (void) const;
+  OCTINTERP_API octave_value as_uint8 () const;
+  OCTINTERP_API octave_value as_uint16 () const;
+  OCTINTERP_API octave_value as_uint32 () const;
+  OCTINTERP_API octave_value as_uint64 () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
--- a/libinterp/octave-value/ov-base-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,9 +39,33 @@
 #include "ov-base.h"
 #include "ov-base-mat.h"
 #include "ov-base-scalar.h"
+#include "ov-inline.h"
 #include "pr-output.h"
 
 template <typename MT>
+octave_value_list
+octave_base_matrix<MT>::simple_subsref (char type, octave_value_list& idx, int)
+{
+  switch (type)
+    {
+    case '(':
+      return do_index_op (idx);
+      break;
+
+    case '{':
+    case '.':
+      {
+        std::string nm = type_name ();
+        error ("%s cannot be indexed with %c", nm.c_str (), type);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+}
+
+template <typename MT>
 octave_value
 octave_base_matrix<MT>::subsref (const std::string& type,
                                  const std::list<octave_value_list>& idx)
@@ -417,10 +441,10 @@
   return retval;
 }
 
-// Return true if this matrix has all true elements (non-zero, not NA/NaN).
+// Return true if this matrix has all true elements (nonzero, not NA/NaN).
 template <typename MT>
 bool
-octave_base_matrix<MT>::is_true (void) const
+octave_base_matrix<MT>::is_true () const
 {
   bool retval = false;
   dim_vector dv = m_matrix.dims ();
@@ -446,7 +470,7 @@
 
 template <typename MT>
 bool
-octave_base_matrix<MT>::print_as_scalar (void) const
+octave_base_matrix<MT>::print_as_scalar () const
 {
   dim_vector dv = dims ();
 
@@ -523,7 +547,7 @@
 
 template <typename MT>
 float_display_format
-octave_base_matrix<MT>::get_edit_display_format (void) const
+octave_base_matrix<MT>::get_edit_display_format () const
 {
   return make_format (m_matrix);
 }
@@ -550,6 +574,54 @@
 }
 
 template <typename MT>
+octave_value
+octave_base_matrix<MT>::checked_full_matrix_elem (octave_idx_type i) const
+{
+  return m_matrix.checkelem (i);
+}
+
+template <typename MT>
+octave_value
+octave_base_matrix<MT>::checked_full_matrix_elem (octave_idx_type i, octave_idx_type j) const
+{
+  return m_matrix.checkelem (i, j);
+}
+
+template <typename MT>
+octave_value
+octave_base_matrix<MT>::vm_extract_forloop_value (octave_idx_type counter)
+{
+  // TODO: Maybe this is slow? Should preferably be done once per loop
+  octave_value_list idx;
+  octave_value arg = octave_value_factory::make_copy (this);
+
+  dim_vector dv = arg.dims ().redim (2);
+  octave_idx_type nrows = dv(0);
+
+  if (arg.ndims () > 2)
+    arg = arg.reshape (dv);
+
+  octave_idx_type iidx;
+
+  // for row vectors, use single index to speed things up.
+  if (nrows == 1)
+    {
+      idx.resize (1);
+      iidx = 0;
+    }
+  else
+    {
+      idx.resize (2);
+      idx(0) = octave_value::magic_colon_t;
+      iidx = 1;
+    }
+
+  // One based indexing
+  idx(iidx) = counter + 1;
+  return arg.index_op (idx).storable_value ();
+}
+
+template <typename MT>
 bool
 octave_base_matrix<MT>::fast_elem_insert (octave_idx_type n,
     const octave_value& x)
--- a/libinterp/octave-value/ov-base-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 
   typedef MT object_type;
 
-  octave_base_matrix (void)
+  octave_base_matrix ()
     : octave_base_value (), m_matrix (), m_typ (), m_idx_cache () { }
 
   octave_base_matrix (const MT& m, const MatrixType& t = MatrixType ())
@@ -71,15 +71,17 @@
                    : nullptr)
   { }
 
-  ~octave_base_matrix (void) { clear_cached_info (); }
+  ~octave_base_matrix () { clear_cached_info (); }
 
-  std::size_t byte_size (void) const { return m_matrix.byte_size (); }
+  std::size_t byte_size () const { return m_matrix.byte_size (); }
+
+  octave_value squeeze () const { return MT (m_matrix.squeeze ()); }
 
-  octave_value squeeze (void) const { return MT (m_matrix.squeeze ()); }
+  octave_value full_value () const { return m_matrix; }
 
-  octave_value full_value (void) const { return m_matrix; }
-
-  void maybe_economize (void) { m_matrix.maybe_economize (); }
+  void maybe_economize () { m_matrix.maybe_economize (); }
+  bool vm_need_storable_call (void) const { return true; }
+  bool is_maybe_function (void) const { return false; }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -89,6 +91,9 @@
   OCTINTERP_API octave_value
   subsref (const std::string& type, const std::list<octave_value_list>& idx);
 
+  octave_value_list
+  simple_subsref (char type, octave_value_list& idx, int nargout);
+
   octave_value_list subsref (const std::string& type,
                              const std::list<octave_value_list>& idx, int)
   { return subsref (type, idx); }
@@ -114,13 +119,13 @@
 
   OCTINTERP_API void delete_elements (const octave_value_list& idx);
 
-  dim_vector dims (void) const { return m_matrix.dims (); }
+  dim_vector dims () const { return m_matrix.dims (); }
 
-  octave_idx_type numel (void) const { return m_matrix.numel (); }
+  octave_idx_type numel () const { return m_matrix.numel (); }
 
-  int ndims (void) const { return m_matrix.ndims (); }
+  int ndims () const { return m_matrix.ndims (); }
 
-  octave_idx_type nnz (void) const { return m_matrix.nnz (); }
+  octave_idx_type nnz () const { return m_matrix.nnz (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return MT (m_matrix.reshape (new_dims)); }
@@ -133,7 +138,7 @@
   octave_value all (int dim = 0) const { return m_matrix.all (dim); }
   octave_value any (int dim = 0) const { return m_matrix.any (dim); }
 
-  MatrixType matrix_type (void) const { return m_typ ? *m_typ : MatrixType (); }
+  MatrixType matrix_type () const { return m_typ ? *m_typ : MatrixType (); }
   MatrixType matrix_type (const MatrixType& _typ) const;
 
   octave_value diag (octave_idx_type k = 0) const
@@ -157,17 +162,19 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const
   { return m_matrix.is_sorted_rows (mode); }
 
-  bool is_matrix_type (void) const { return true; }
+  bool is_matrix_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool is_full_num_matrix () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_defined () const { return true; }
+
+  bool is_constant () const { return true; }
 
-  OCTINTERP_API bool is_true (void) const;
+  OCTINTERP_API bool is_true () const;
 
-  OCTINTERP_API bool print_as_scalar (void) const;
+  OCTINTERP_API bool print_as_scalar () const;
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -176,19 +183,19 @@
 
   OCTINTERP_API void short_disp (std::ostream& os) const;
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
                 octave_idx_type i, octave_idx_type j) const;
 
-  MT& matrix_ref (void)
+  MT& matrix_ref ()
   {
     clear_cached_info ();
     return m_matrix;
   }
 
-  const MT& matrix_ref (void) const
+  const MT& matrix_ref () const
   {
     return m_matrix;
   }
@@ -201,7 +208,16 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data (void) const { return m_matrix.data (); }
+  const void * mex_get_data () const { return m_matrix.data (); }
+
+  OCTINTERP_API octave_value
+  vm_extract_forloop_value (octave_idx_type idx);
+
+  octave_value
+  checked_full_matrix_elem (octave_idx_type i) const;
+
+  octave_value
+  checked_full_matrix_elem (octave_idx_type i, octave_idx_type j) const;
 
 protected:
 
@@ -210,11 +226,11 @@
   octave::idx_vector set_idx_cache (const octave::idx_vector& idx) const
   {
     delete m_idx_cache;
-    m_idx_cache = (idx ? new octave::idx_vector (idx) : nullptr);
+    m_idx_cache = new octave::idx_vector (idx);
     return idx;
   }
 
-  void clear_cached_info (void) const
+  void clear_cached_info () const
   {
     delete m_typ; m_typ = nullptr;
     delete m_idx_cache; m_idx_cache = nullptr;
--- a/libinterp/octave-value/ov-base-scalar.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-scalar.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -69,6 +69,14 @@
 
 template <typename ST>
 octave_value
+octave_base_scalar<ST>::vm_extract_forloop_value (octave_idx_type)
+{
+  return octave_value (scalar);
+}
+
+
+template <typename ST>
+octave_value
 octave_base_scalar<ST>::subsasgn (const std::string& type,
                                   const std::list<octave_value_list>& idx,
                                   const octave_value& rhs)
@@ -107,7 +115,7 @@
 
 template <typename ST>
 dim_vector
-octave_base_scalar<ST>::dims (void) const
+octave_base_scalar<ST>::dims () const
 {
   static dim_vector dv (1, 1);
   return dv;
@@ -143,7 +151,7 @@
 
 template <typename ST>
 bool
-octave_base_scalar<ST>::is_true (void) const
+octave_base_scalar<ST>::is_true () const
 {
   if (octave::math::isnan (scalar))
     octave::err_nan_to_logical_conversion ();
@@ -194,7 +202,7 @@
 
 template <typename ST>
 float_display_format
-octave_base_scalar<ST>::get_edit_display_format (void) const
+octave_base_scalar<ST>::get_edit_display_format () const
 {
   return make_format (scalar);
 }
--- a/libinterp/octave-value/ov-base-scalar.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-scalar.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 
   typedef ST scalar_type;
 
-  octave_base_scalar (void)
+  octave_base_scalar ()
     : octave_base_value (), scalar () { }
 
   octave_base_scalar (const ST& s)
@@ -61,11 +61,11 @@
   octave_base_scalar (const octave_base_scalar& s)
     : octave_base_value (), scalar (s.scalar) { }
 
-  ~octave_base_scalar (void) = default;
+  ~octave_base_scalar () = default;
 
-  octave_value squeeze (void) const { return scalar; }
+  octave_value squeeze () const { return scalar; }
 
-  octave_value full_value (void) const { return scalar; }
+  octave_value full_value () const { return scalar; }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -83,23 +83,23 @@
   subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
             const octave_value& rhs);
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  OCTINTERP_API dim_vector dims (void) const;
+  OCTINTERP_API dim_vector dims () const;
 
-  octave_idx_type numel (void) const { return 1; }
+  octave_idx_type numel () const { return 1; }
 
-  int ndims (void) const { return 2; }
+  int ndims () const { return 2; }
 
-  octave_idx_type nnz (void) const { return (scalar != ST () ? 1 : 0); }
+  octave_idx_type nnz () const { return (scalar != ST () ? 1 : 0); }
 
   OCTINTERP_API octave_value permute (const Array<int>&, bool = false) const;
 
   OCTINTERP_API octave_value reshape (const dim_vector& new_dims) const;
 
-  std::size_t byte_size (void) const { return sizeof (ST); }
+  std::size_t byte_size () const { return sizeof (ST); }
 
   octave_value all (int = 0) const { return (scalar != ST ()); }
 
@@ -131,15 +131,17 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const
   { return mode == UNSORTED ? ASCENDING : mode; }
 
-  MatrixType matrix_type (void) const { return MatrixType::Diagonal; }
+  MatrixType matrix_type () const { return MatrixType::Diagonal; }
   MatrixType matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
-  bool is_scalar_type (void) const { return true; }
+  bool is_maybe_function (void) const { return false; }
+
+  bool is_scalar_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  OCTINTERP_API bool is_true (void) const;
+  OCTINTERP_API bool is_true () const;
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -151,7 +153,7 @@
 
   OCTINTERP_API void short_disp (std::ostream& os) const;
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
@@ -159,17 +161,24 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data (void) const { return &scalar; }
+  const void * mex_get_data () const { return &scalar; }
 
-  const ST& scalar_ref (void) const { return scalar; }
+  const ST& scalar_ref () const { return scalar; }
 
-  ST& scalar_ref (void) { return scalar; }
+  ST& scalar_ref () { return scalar; }
 
   OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;
 
+  OCTINTERP_API octave_value
+  vm_extract_forloop_value (octave_idx_type idx);
+
   OCTINTERP_API bool
   fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
+  bool vm_need_dispatch_assign_rhs (void) { return false; }
+  bool vm_need_dispatch_assign_lhs (void) { return false; }
+  bool vm_need_dispatch_push (void) { return false; }
+
 protected:
 
   // The value of this scalar.
--- a/libinterp/octave-value/ov-base-sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -242,7 +242,7 @@
 
 template <typename T>
 bool
-octave_base_sparse<T>::is_true (void) const
+octave_base_sparse<T>::is_true () const
 {
   bool retval = false;
   dim_vector dv = matrix.dims ();
@@ -272,7 +272,7 @@
 
 template <typename T>
 bool
-octave_base_sparse<T>::print_as_scalar (void) const
+octave_base_sparse<T>::print_as_scalar () const
 {
   dim_vector dv = dims ();
 
@@ -379,7 +379,7 @@
 
 template <typename MT>
 float_display_format
-octave_base_sparse<MT>::get_edit_display_format (void) const
+octave_base_sparse<MT>::get_edit_display_format () const
 {
   return float_display_format ();
   //  return make_format (this->matrix);
--- a/libinterp/octave-value/ov-base-sparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base-sparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 {
 public:
 
-  octave_base_sparse (void)
+  octave_base_sparse ()
     : octave_base_value (), matrix (), typ (MatrixType ())
   { }
 
@@ -73,19 +73,19 @@
   octave_base_sparse (const octave_base_sparse& a)
     : octave_base_value (), matrix (a.matrix), typ (a.typ) { }
 
-  ~octave_base_sparse (void) = default;
+  ~octave_base_sparse () = default;
 
-  octave_idx_type numel (void) const { return dims ().safe_numel (); }
+  octave_idx_type numel () const { return dims ().safe_numel (); }
 
-  octave_idx_type nnz (void) const { return matrix.nnz (); }
+  octave_idx_type nnz () const { return matrix.nnz (); }
 
-  octave_idx_type nzmax (void) const { return matrix.nzmax (); }
+  octave_idx_type nzmax () const { return matrix.nzmax (); }
 
-  std::size_t byte_size (void) const { return matrix.byte_size (); }
+  std::size_t byte_size () const { return matrix.byte_size (); }
 
-  octave_value squeeze (void) const { return matrix.squeeze (); }
+  octave_value squeeze () const { return matrix.squeeze (); }
 
-  octave_value full_value (void) const { return matrix.matrix_value (); }
+  octave_value full_value () 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
@@ -163,7 +163,7 @@
 
   OCTINTERP_API void delete_elements (const octave_value_list& idx);
 
-  dim_vector dims (void) const { return matrix.dims (); }
+  dim_vector dims () const { return matrix.dims (); }
 
   OCTINTERP_API octave_value
   do_index_op (const octave_value_list& idx, bool resize_ok = false);
@@ -196,23 +196,23 @@
   sortmode issorted (sortmode mode = UNSORTED) const
   { return full_value ().issorted (mode); }
 
-  MatrixType matrix_type (void) const { return typ; }
+  MatrixType matrix_type () const { return typ; }
   MatrixType matrix_type (const MatrixType& _typ) const
   { MatrixType ret = typ; typ = _typ; return ret; }
 
-  bool is_matrix_type (void) const { return true; }
+  bool is_matrix_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool issparse (void) const { return true; }
+  bool issparse () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  OCTINTERP_API bool is_true (void) const;
+  OCTINTERP_API bool is_true () const;
 
-  OCTINTERP_API bool print_as_scalar (void) const;
+  OCTINTERP_API bool print_as_scalar () const;
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -226,7 +226,7 @@
 
   OCTINTERP_API bool load_ascii (std::istream& is);
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
@@ -234,11 +234,11 @@
 
   // These functions exists to support the MEX interface.
   // You should not use them anywhere else.
-  const void * mex_get_data (void) const { return matrix.data (); }
+  const void * mex_get_data () const { return matrix.data (); }
 
-  const octave_idx_type * mex_get_ir (void) const { return matrix.ridx (); }
+  const octave_idx_type * mex_get_ir () const { return matrix.ridx (); }
 
-  const octave_idx_type * mex_get_jc (void) const { return matrix.cidx (); }
+  const octave_idx_type * mex_get_jc () const { return matrix.cidx (); }
 
   OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;
 
--- a/libinterp/octave-value/ov-base.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -61,6 +61,7 @@
 #include "pr-output.h"
 #include "utils.h"
 #include "variables.h"
+#include "ov-inline.h"
 
 builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
 {
@@ -101,87 +102,124 @@
 // DEPRECATED in Octave 8.
 bool Vsparse_auto_mutate = false;
 
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+   // Disable this warning for the use of the "count" member variable in
+   // the default constructor.  Push the current state so we can restore
+   // the warning state.
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+  octave_base_value::octave_base_value () : m_count (1), count (m_count) { }
+
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+#  pragma GCC diagnostic pop
+#endif
+
 octave_base_value *
-octave_base_value::empty_clone (void) const
+octave_base_value::empty_clone () const
 {
   return resize (dim_vector ()).clone ();
 }
 
+// FIXME: Unlike other virtual functions in the octave_base_value
+// class, the storable_value and make_storable_value functions defined
+// here are not used by the corresponding octave_value functions.  This
+// inconsistency is likely to cause some confusion.
 octave_value
-octave_base_value::squeeze (void) const
+octave_base_value::storable_value (void)
+{
+  return octave_value_factory::make_copy (this);
+}
+
+octave_base_value *
+octave_base_value::make_storable_value (void)
+{
+  return this;
+}
+
+octave_value
+octave_base_value::squeeze () const
 {
   std::string nm = type_name ();
   error ("squeeze: invalid operation for %s type", nm.c_str ());
 }
 
 octave_value
-octave_base_value::full_value (void) const
+octave_base_value::full_value () const
 {
   err_wrong_type_arg ("full: invalid operation for %s type", type_name ());
 }
 
 octave_value
-octave_base_value::as_double (void) const
+octave_base_value::as_double () const
 {
   err_invalid_conversion (type_name (), "double");
 }
 
 octave_value
-octave_base_value::as_single (void) const
+octave_base_value::as_double_or_copy (void)
+{
+  const octave_base_value * cthis = this;
+  return cthis->as_double ();
+}
+
+octave_value
+octave_base_value::as_single () const
 {
   err_invalid_conversion (type_name (), "single");
 }
 
 octave_value
-octave_base_value::as_int8 (void) const
+octave_base_value::as_int8 () const
 {
   err_invalid_conversion (type_name (), "int8");
 }
 
 octave_value
-octave_base_value::as_int16 (void) const
+octave_base_value::as_int16 () const
 {
   err_invalid_conversion (type_name (), "int16");
 }
 
 octave_value
-octave_base_value::as_int32 (void) const
+octave_base_value::as_int32 () const
 {
   err_invalid_conversion (type_name (), "int32");
 }
 
 octave_value
-octave_base_value::as_int64 (void) const
+octave_base_value::as_int64 () const
 {
   err_invalid_conversion (type_name (), "int64");
 }
 
 octave_value
-octave_base_value::as_uint8 (void) const
+octave_base_value::as_uint8 () const
 {
   err_invalid_conversion (type_name (), "uint8");
 }
 
 octave_value
-octave_base_value::as_uint16 (void) const
+octave_base_value::as_uint16 () const
 {
   err_invalid_conversion (type_name (), "uint16");
 }
 
 octave_value
-octave_base_value::as_uint32 (void) const
+octave_base_value::as_uint32 () const
 {
   err_invalid_conversion (type_name (), "uint32");
 }
 
 octave_value
-octave_base_value::as_uint64 (void) const
+octave_base_value::as_uint64 () const
 {
   err_invalid_conversion (type_name (), "uint64");
 }
 
 Matrix
-octave_base_value::size (void)
+octave_base_value::size ()
 {
   const dim_vector dv = dims ();
   Matrix mdv (1, dv.ndims ());
@@ -196,6 +234,15 @@
   return octave::dims_to_numel (dims (), idx);
 }
 
+octave_value_list
+octave_base_value::
+simple_subsref (char type, octave_value_list& idx, int nargout)
+{
+  std::list<octave_value_list> idx_list;
+  idx_list.push_back (idx);
+  return subsref (std::string {type}, idx_list, nargout);
+}
+
 octave_value
 octave_base_value::subsref (const std::string&,
                             const std::list<octave_value_list>&)
@@ -236,6 +283,34 @@
 }
 
 octave_value
+octave_base_value::vm_extract_forloop_value (octave_idx_type idx)
+{
+  return fast_elem_extract (idx).as_double_or_copy ();
+}
+
+double
+octave_base_value::vm_extract_forloop_double (octave_idx_type)
+{
+  error ("Type error extracting for loop iterator double value for VM");
+}
+
+bool
+octave_base_value::maybe_update_double (double)
+{
+  return false;
+}
+
+octave_value
+octave_base_value::simple_subsasgn (char type, octave_value_list& idx,
+                                    const octave_value& rhs)
+{
+  std::list<octave_value_list> idx_list;
+  idx_list.push_back (idx);
+
+  return subsasgn (std::string {type}, idx_list, rhs);
+}
+
+octave_value
 octave_base_value::subsasgn (const std::string& type,
                              const std::list<octave_value_list>& idx,
                              const octave_value& rhs)
@@ -313,19 +388,19 @@
 }
 
 octave_idx_type
-octave_base_value::nnz (void) const
+octave_base_value::nnz () const
 {
   err_wrong_type_arg ("octave_base_value::nnz ()", type_name ());
 }
 
 octave_idx_type
-octave_base_value::nzmax (void) const
+octave_base_value::nzmax () const
 {
   return numel ();
 }
 
 octave_idx_type
-octave_base_value::nfields (void) const
+octave_base_value::nfields () const
 {
   err_wrong_type_arg ("octave_base_value::nfields ()", type_name ());
 }
@@ -349,7 +424,7 @@
 }
 
 MatrixType
-octave_base_value::matrix_type (void) const
+octave_base_value::matrix_type () const
 {
   err_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ());
 }
@@ -392,7 +467,7 @@
 }
 
 void
-octave_base_value::convert_to_row_or_column_vector (void)
+octave_base_value::convert_to_row_or_column_vector ()
 {
   err_wrong_type_arg
   ("octave_base_value::convert_to_row_or_column_vector ()", type_name ());
@@ -445,7 +520,7 @@
 }
 
 float_display_format
-octave_base_value::get_edit_display_format (void) const
+octave_base_value::get_edit_display_format () const
 {
   return float_display_format ();
 }
@@ -681,103 +756,103 @@
 }
 
 PermMatrix
-octave_base_value::perm_matrix_value (void) const
+octave_base_value::perm_matrix_value () const
 {
   err_wrong_type_arg ("octave_base_value::perm_matrix_value()", type_name ());
 }
 
 octave_int8
-octave_base_value::int8_scalar_value (void) const
+octave_base_value::int8_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::int8_scalar_value()", type_name ());
 }
 
 octave_int16
-octave_base_value::int16_scalar_value (void) const
+octave_base_value::int16_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::int16_scalar_value()", type_name ());
 }
 
 octave_int32
-octave_base_value::int32_scalar_value (void) const
+octave_base_value::int32_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::int32_scalar_value()", type_name ());
 }
 
 octave_int64
-octave_base_value::int64_scalar_value (void) const
+octave_base_value::int64_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::int64_scalar_value()", type_name ());
 }
 
 octave_uint8
-octave_base_value::uint8_scalar_value (void) const
+octave_base_value::uint8_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint8_scalar_value()", type_name ());
 }
 
 octave_uint16
-octave_base_value::uint16_scalar_value (void) const
+octave_base_value::uint16_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint16_scalar_value()", type_name ());
 }
 
 octave_uint32
-octave_base_value::uint32_scalar_value (void) const
+octave_base_value::uint32_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint32_scalar_value()", type_name ());
 }
 
 octave_uint64
-octave_base_value::uint64_scalar_value (void) const
+octave_base_value::uint64_scalar_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint64_scalar_value()", type_name ());
 }
 
 int8NDArray
-octave_base_value::int8_array_value (void) const
+octave_base_value::int8_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::int8_array_value()", type_name ());
 }
 
 int16NDArray
-octave_base_value::int16_array_value (void) const
+octave_base_value::int16_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::int16_array_value()", type_name ());
 }
 
 int32NDArray
-octave_base_value::int32_array_value (void) const
+octave_base_value::int32_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::int32_array_value()", type_name ());
 }
 
 int64NDArray
-octave_base_value::int64_array_value (void) const
+octave_base_value::int64_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::int64_array_value()", type_name ());
 }
 
 uint8NDArray
-octave_base_value::uint8_array_value (void) const
+octave_base_value::uint8_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint8_array_value()", type_name ());
 }
 
 uint16NDArray
-octave_base_value::uint16_array_value (void) const
+octave_base_value::uint16_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint16_array_value()", type_name ());
 }
 
 uint32NDArray
-octave_base_value::uint32_array_value (void) const
+octave_base_value::uint32_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint32_array_value()", type_name ());
 }
 
 uint64NDArray
-octave_base_value::uint64_array_value (void) const
+octave_base_value::uint64_array_value () const
 {
   err_wrong_type_arg ("octave_base_value::uint64_array_value()", type_name ());
 }
@@ -799,7 +874,7 @@
 }
 
 std::string
-octave_base_value::xstring_value (void) const
+octave_base_value::xstring_value () const
 {
   wrong_type_arg_error ();
 
@@ -807,85 +882,27 @@
 }
 
 Array<std::string>
-octave_base_value::cellstr_value (void) const
+octave_base_value::cellstr_value () const
 {
   err_wrong_type_arg ("octave_base_value::cellstr_value()", type_name ());
 }
 
 octave::range<double>
-octave_base_value::range_value (void) const
+octave_base_value::range_value () const
 {
   err_wrong_type_arg ("octave_base_value::range_value()", type_name ());
 }
 
-// For now, disable all but range<double>.
-
-#if 0
-
-octave::range<float>
-octave_base_value::float_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::float_range_value()", type_name ());
-}
-
-octave::range<octave_int8>
-octave_base_value::int8_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::int8_range_value()", type_name ());
-}
-
-octave::range<octave_int16>
-octave_base_value::int16_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::int16_range_value()", type_name ());
-}
-
-octave::range<octave_int32>
-octave_base_value::int32_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::int32_range_value()", type_name ());
-}
-
-octave::range<octave_int64>
-octave_base_value::int64_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::int64_range_value()", type_name ());
-}
-
-octave::range<octave_uint8>
-octave_base_value::uint8_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::uint8_range_value()", type_name ());
-}
-
-octave::range<octave_uint16>
-octave_base_value::uint16_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::uint16_range_value()", type_name ());
-}
-
-octave::range<octave_uint32>
-octave_base_value::uint32_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::uint32_range_value()", type_name ());
-}
-
-octave::range<octave_uint64>
-octave_base_value::uint64_range_value (void) const
-{
-  err_wrong_type_arg ("octave_base_value::uint64_range_value()", type_name ());
-}
-
-#endif
+// For now, enable only range<double>.
 
 octave_map
-octave_base_value::map_value (void) const
+octave_base_value::map_value () const
 {
   err_wrong_type_arg ("octave_base_value::map_value()", type_name ());
 }
 
 octave_scalar_map
-octave_base_value::scalar_map_value (void) const
+octave_base_value::scalar_map_value () const
 {
   octave_map tmp = map_value ();
 
@@ -896,7 +913,7 @@
 }
 
 string_vector
-octave_base_value::map_keys (void) const
+octave_base_value::map_keys () const
 {
   err_wrong_type_arg ("octave_base_value::map_keys()", type_name ());
 }
@@ -908,20 +925,20 @@
 }
 
 std::size_t
-octave_base_value::nparents (void) const
+octave_base_value::nparents () const
 {
   err_wrong_type_arg ("octave_base_value::nparents()", type_name ());
 }
 
 std::list<std::string>
-octave_base_value::parent_class_name_list (void) const
+octave_base_value::parent_class_name_list () const
 {
   err_wrong_type_arg ("octave_base_value::parent_class_name_list()",
                       type_name ());
 }
 
 string_vector
-octave_base_value::parent_class_names (void) const
+octave_base_value::parent_class_names () const
 {
   err_wrong_type_arg ("octave_base_value::parent_class_names()", type_name ());
 }
@@ -945,6 +962,14 @@
   return nullptr;
 }
 
+octave_value_ref *
+octave_base_value::ref_rep ()
+{
+  err_wrong_type_arg ("octave_base_value::ref_value()", type_name ());
+
+  return nullptr;
+}
+
 octave_user_function *
 octave_base_value::user_function_value (bool silent)
 {
@@ -982,7 +1007,7 @@
 }
 
 octave_value_list
-octave_base_value::list_value (void) const
+octave_base_value::list_value () const
 {
   err_wrong_type_arg ("octave_base_value::list_value()", type_name ());
 }
@@ -1159,7 +1184,7 @@
   warning_with_id
   ("Octave:load-save-unavailable",
    "%s: loading %s files not available in this version of Octave",
-   t_name.c_str (), type);
+   s_t_name.c_str (), type);
 }
 
 void
@@ -1168,11 +1193,11 @@
   warning_with_id
   ("Octave:load-save-unavailable",
    "%s: saving %s files not available in this version of Octave",
-   t_name.c_str (), type);
+   s_t_name.c_str (), type);
 }
 
 void
-octave_base_value::wrong_type_arg_error (void) const
+octave_base_value::wrong_type_arg_error () const
 {
   err_wrong_type_arg (type_name ());
 }
@@ -1184,19 +1209,19 @@
 }
 
 void
-octave_base_value::lock (void)
+octave_base_value::lock ()
 {
   err_wrong_type_arg ("octave_base_value::lock ()", type_name ());
 }
 
 void
-octave_base_value::unlock (void)
+octave_base_value::unlock ()
 {
   err_wrong_type_arg ("octave_base_value::unlock ()", type_name ());
 }
 
 octave_value
-octave_base_value::dump (void) const
+octave_base_value::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "class", this->class_name () },
@@ -1233,6 +1258,128 @@
 }
 
 octave_value
+octave_base_value::simple_numeric_assign (char type, octave_value_list& idx,
+                                          const octave_value& rhs)
+{
+  octave_value retval;
+
+  if (idx.empty ())
+    error ("missing index in indexed assignment");
+
+  int t_lhs = type_id ();
+  int t_rhs = rhs.type_id ();
+
+  octave::type_info& ti = octave::__get_type_info__ ();
+
+  octave::type_info::assign_op_fcn f
+    = ti.lookup_assign_op (octave_value::op_asn_eq, t_lhs, t_rhs);
+
+  bool done = false;
+
+  if (f)
+    {
+      f (*this, idx, rhs.get_rep ());
+
+      done = true;
+    }
+
+  if (done)
+    {
+      m_count++;
+      retval = octave_value (this);
+    }
+  else
+    {
+      int t_result = ti.lookup_pref_assign_conv (t_lhs, t_rhs);
+
+      if (t_result >= 0)
+        {
+          octave_base_value::type_conv_fcn cf
+            = ti.lookup_widening_op (t_lhs, t_result);
+
+          if (! cf)
+            err_indexed_assignment (type_name (), rhs.type_name ());
+
+          octave_base_value *tmp = cf (*this);
+
+          if (! tmp)
+            err_assign_conversion_failed (type_name (), rhs.type_name ());
+
+          octave_value val (tmp);
+
+          retval = val.simple_subsasgn (type, idx, rhs);
+
+          done = true;
+        }
+
+      if (! done)
+        {
+          octave_value tmp_rhs;
+
+          octave_base_value::type_conv_info cf_rhs
+            = rhs.numeric_conversion_function ();
+
+          octave_base_value::type_conv_info cf_this
+            = numeric_conversion_function ();
+
+          // Try biased (one-sided) conversions first.
+          if (cf_rhs.type_id () >= 0
+              && (ti.lookup_assign_op (octave_value::op_asn_eq,
+                                       t_lhs, cf_rhs.type_id ())
+                  || ti.lookup_pref_assign_conv (t_lhs,
+                                                 cf_rhs.type_id ()) >= 0))
+            cf_this = nullptr;
+          else if (cf_this.type_id () >= 0
+                   && (ti.lookup_assign_op (octave_value::op_asn_eq,
+                                            cf_this.type_id (), t_rhs)
+                       || ti.lookup_pref_assign_conv (cf_this.type_id (),
+                                                      t_rhs) >= 0))
+            cf_rhs = nullptr;
+
+          if (cf_rhs)
+            {
+              octave_base_value *tmp = cf_rhs (rhs.get_rep ());
+
+              if (! tmp)
+                err_assign_conversion_failed (type_name (), rhs.type_name ());
+
+              tmp_rhs = octave_value (tmp);
+            }
+          else
+            tmp_rhs = rhs;
+
+          m_count++;
+          octave_value tmp_lhs = octave_value (this);
+
+          if (cf_this)
+            {
+              octave_base_value *tmp = cf_this (*this);
+
+              if (! tmp)
+                err_assign_conversion_failed (type_name (), rhs.type_name ());
+
+              tmp_lhs = octave_value (tmp);
+            }
+
+          if (! cf_this && ! cf_rhs)
+            err_no_conversion (octave_value::assign_op_as_string
+                               (octave_value::op_asn_eq),
+                               type_name (), rhs.type_name ());
+
+          retval = tmp_lhs.simple_subsasgn (type, idx, tmp_rhs);
+
+          done = true;
+        }
+    }
+
+  // The assignment may have converted to a type that is wider than necessary.
+
+  retval.maybe_mutate ();
+
+  return retval;
+}
+
+octave_value
 octave_base_value::numeric_assign (const std::string& type,
                                    const std::list<octave_value_list>& idx,
                                    const octave_value& rhs)
@@ -1261,7 +1408,7 @@
 
   if (done)
     {
-      count++;
+      m_count++;
       retval = octave_value (this);
     }
   else
@@ -1324,7 +1471,7 @@
           else
             tmp_rhs = rhs;
 
-          count++;
+          m_count++;
           octave_value tmp_lhs = octave_value (this);
 
           if (cf_this)
@@ -1395,7 +1542,7 @@
 // For resetting print state.
 
 void
-octave_base_value::reset (void) const
+octave_base_value::reset () const
 {
   s_beginning_of_line = true;
   s_curr_print_indent_level = 0;
@@ -1407,6 +1554,18 @@
   return octave_value ();
 }
 
+octave_value
+octave_base_value::checked_full_matrix_elem (octave_idx_type) const
+{
+  err_wrong_type_arg ("octave_base_value::checked_full_matrix_elem (octave_idx_type)", type_name ());
+}
+
+octave_value
+octave_base_value::checked_full_matrix_elem (octave_idx_type, octave_idx_type) const
+{
+  err_wrong_type_arg ("octave_base_value::checked_full_matrix_elem (octave_idx_type, octave_idx_type)", type_name ());
+}
+
 bool
 octave_base_value::fast_elem_insert (octave_idx_type, const octave_value&)
 {
@@ -1521,7 +1680,7 @@
 }
 
 bool
-called_from_builtin (void)
+called_from_builtin ()
 {
   octave::tree_evaluator& tw = octave::__get_evaluator__ ();
 
--- a/libinterp/octave-value/ov-base.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-base.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,7 +55,7 @@
 // object is required to load a user-defined octave_value object,
 // maybe this function should be declared in a public header file?
 
-extern OCTINTERP_API type_info& __get_type_info__ (void);
+extern OCTINTERP_API type_info& __get_type_info__ ();
 
 // For now just preserve the old interface and don't mark it as deprecated.
 // This function is currently an internal, private function.  Additional
@@ -78,6 +78,9 @@
 class octave_user_code;
 class octave_fcn_handle;
 class octave_value_list;
+class octave_value_ref;
+class octave_fcn_cache;
+class octave_value_vm;
 
 enum builtin_type_t
 {
@@ -186,32 +189,32 @@
 
 #define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(VIRTUAL)                  \
   public:                                                               \
-    VIRTUAL int type_id (void) const { return t_id; }                   \
-    VIRTUAL std::string type_name (void) const { return t_name; }       \
-    VIRTUAL std::string class_name (void) const { return c_name; }      \
-    static int static_type_id (void) { return t_id; }                   \
-    static std::string static_type_name (void) { return t_name; }       \
-    static std::string static_class_name (void) { return c_name; }      \
-    static void register_type (void);                                   \
+    VIRTUAL int type_id () const { return s_t_id; }                   \
+    VIRTUAL std::string type_name () const { return s_t_name; }       \
+    VIRTUAL std::string class_name () const { return s_c_name; }      \
+    static int static_type_id () { return s_t_id; }                   \
+    static std::string static_type_name () { return s_t_name; }       \
+    static std::string static_class_name () { return s_c_name; }      \
+    static void register_type ();                                   \
     static void register_type (octave::type_info&);                     \
                                                                         \
   private:                                                              \
-    static int t_id;                                                    \
-    static const std::string t_name;                                    \
-    static const std::string c_name;
+    static int s_t_id;                                                    \
+    static const std::string s_t_name;                                    \
+    static const std::string s_c_name;
 
 #define DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS(cls, type)           \
-  template <> void cls<type>::register_type (void);                     \
+  template <> void cls<type>::register_type ();                     \
   template <> void cls<type>::register_type (octave::type_info&);       \
-  template <> int cls<type>::t_id;                                      \
-  template <> const std::string cls<type>::t_name;                      \
-  template <> const std::string cls<type>::c_name;
+  template <> int cls<type>::s_t_id;                                      \
+  template <> const std::string cls<type>::s_t_name;                      \
+  template <> const std::string cls<type>::s_c_name;
 
 #define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA_INTERNAL(tspec, t, n, c)    \
-  tspec int t::t_id (-1);                                               \
-  tspec const std::string t::t_name (n);                                \
-  tspec const std::string t::c_name (c);                                \
-  tspec void t::register_type (void)                                    \
+  tspec int t::s_t_id (-1);                                               \
+  tspec const std::string t::s_t_name (n);                                \
+  tspec const std::string t::s_c_name (c);                                \
+  tspec void t::register_type ()                                    \
   {                                                                     \
     octave::type_info& type_info = octave::__get_type_info__ ();        \
                                                                         \
@@ -220,7 +223,7 @@
   tspec void t::register_type (octave::type_info& ti)                   \
   {                                                                     \
     octave_value v (new t ());                                          \
-    t_id = ti.register_type (t::t_name, t::c_name, v);                  \
+    s_t_id = ti.register_type (t::s_t_name, t::s_c_name, v);                  \
   }
 
 #define DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)           \
@@ -248,12 +251,12 @@
     type_conv_info (type_conv_fcn f = nullptr, int t = -1)
       : m_fcn (f), m_type_id (t) { }
 
-    operator type_conv_fcn (void) const { return m_fcn; }
+    operator type_conv_fcn () const { return m_fcn; }
 
     octave_base_value * operator () (const octave_base_value& v) const
     { return (*m_fcn) (v); }
 
-    int type_id (void) const { return m_type_id; }
+    int type_id () const { return m_type_id; }
 
   private:
     type_conv_fcn m_fcn;
@@ -261,60 +264,66 @@
   };
 
   friend class octave_value;
+  friend class octave_value_vm;
 
-  octave_base_value (void) : count (1) { }
+  octave_base_value ();
 
-  octave_base_value (const octave_base_value&) : count (1) { }
+  octave_base_value (const octave_base_value&) : octave_base_value () { }
 
-  virtual ~octave_base_value (void) = default;
+  virtual ~octave_base_value () = default;
 
   // Unconditional clone.  Always clones.
   virtual octave_base_value *
-  clone (void) const { return new octave_base_value (*this); }
+  clone () const { return new octave_base_value (*this); }
 
   // Empty clone.
   virtual octave_base_value *
-  empty_clone (void) const;
+  empty_clone () const;
 
   // Unique clone.  Usually clones, but may be overridden to fake the
   // cloning when sharing copies is to be controlled from within an
   // instance (see octave_class).
   virtual octave_base_value *
-  unique_clone (void) { return clone (); }
+  unique_clone () { return clone (); }
 
   virtual void break_closure_cycles (const std::shared_ptr<octave::stack_frame>&) { }
 
   virtual type_conv_info
-  numeric_conversion_function (void) const
+  numeric_conversion_function () const
   { return type_conv_info (); }
 
   virtual type_conv_info
-  numeric_demotion_function (void) const
+  numeric_demotion_function () const
   { return type_conv_info (); }
 
-  virtual octave_value squeeze (void) const;
+  virtual octave_value squeeze () const;
+
+  virtual octave_value full_value () const;
 
-  virtual octave_value full_value (void) const;
+  // Will return a copy of it-self when the representation
+  // allready is a scalar (.i.e. double). The const variant
+  // as_double () would allocate a new octave value.
+  virtual octave_value as_double_or_copy (void);
 
-  virtual octave_value as_double (void) const;
-  virtual octave_value as_single (void) const;
+  virtual octave_value as_double () const;
+  virtual octave_value as_single () const;
 
-  virtual octave_value as_int8 (void) const;
-  virtual octave_value as_int16 (void) const;
-  virtual octave_value as_int32 (void) const;
-  virtual octave_value as_int64 (void) const;
+  virtual octave_value as_int8 () const;
+  virtual octave_value as_int16 () const;
+  virtual octave_value as_int32 () const;
+  virtual octave_value as_int64 () const;
 
-  virtual octave_value as_uint8 (void) const;
-  virtual octave_value as_uint16 (void) const;
-  virtual octave_value as_uint32 (void) const;
-  virtual octave_value as_uint64 (void) const;
+  virtual octave_value as_uint8 () const;
+  virtual octave_value as_uint16 () const;
+  virtual octave_value as_uint32 () const;
+  virtual octave_value as_uint64 () const;
 
-  virtual octave_base_value * try_narrowing_conversion (void)
+  virtual octave_base_value * try_narrowing_conversion ()
   { return nullptr; }
 
-  virtual void maybe_economize (void) { }
+  virtual void maybe_economize () { }
 
-  virtual Matrix size (void);
+  virtual Matrix size ();
 
   virtual octave_idx_type xnumel (const octave_value_list&);
 
@@ -334,6 +343,9 @@
            const std::list<octave_value_list>& idx,
            bool auto_add);
 
+  virtual octave_value_list
+  simple_subsref (char type, octave_value_list& idx, int nargout);
+
   virtual octave_value
   do_index_op (const octave_value_list& idx, bool resize_ok = false);
 
@@ -345,40 +357,44 @@
             const octave_value& rhs);
 
   virtual octave_value
+  simple_subsasgn (char type, octave_value_list& idx,
+                   const octave_value& rhs);
+
+  virtual octave_value
   undef_subsasgn (const std::string& type,
                   const std::list<octave_value_list>& idx,
                   const octave_value& rhs);
 
   virtual octave::idx_vector index_vector (bool require_integers = false) const;
 
-  virtual dim_vector dims (void) const { return dim_vector (); }
+  virtual dim_vector dims () const { return dim_vector (); }
 
-  octave_idx_type rows (void) const
+  octave_idx_type rows () const
   {
     const dim_vector dv = dims ();
 
     return dv(0);
   }
 
-  octave_idx_type columns (void) const
+  octave_idx_type columns () const
   {
     const dim_vector dv = dims ();
 
     return dv(1);
   }
 
-  virtual int ndims (void) const
+  virtual int ndims () const
   { return dims ().ndims (); }
 
-  virtual octave_idx_type numel (void) const { return dims ().numel (); }
+  virtual octave_idx_type numel () const { return dims ().numel (); }
 
-  virtual std::size_t byte_size (void) const { return 0; }
+  virtual std::size_t byte_size () const { return 0; }
 
-  virtual octave_idx_type nnz (void) const;
+  virtual octave_idx_type nnz () const;
 
-  virtual octave_idx_type nzmax (void) const;
+  virtual octave_idx_type nzmax () const;
 
-  virtual octave_idx_type nfields (void) const;
+  virtual octave_idx_type nfields () const;
 
   virtual octave_value reshape (const dim_vector&) const;
 
@@ -386,143 +402,158 @@
 
   virtual octave_value resize (const dim_vector&, bool fill = false) const;
 
-  virtual MatrixType matrix_type (void) const;
+  virtual MatrixType matrix_type () const;
 
   virtual MatrixType matrix_type (const MatrixType& typ) const;
 
-  virtual bool is_defined (void) const { return false; }
+  virtual bool is_defined () const { return false; }
 
-  virtual bool is_storable (void) const { return true; }
+  virtual bool is_storable () const { return true; }
 
-  virtual bool is_legacy_object (void) const { return false; }
+  virtual bool is_legacy_object () const { return false; }
 
-  bool isempty (void) const { return (dims ().any_zero ()); }
+  bool isempty () const { return (dims ().any_zero ()); }
 
-  bool is_zero_by_zero (void) const { return dims().zero_by_zero (); }
+  bool is_zero_by_zero () const { return dims().zero_by_zero (); }
 
-  virtual bool iscell (void) const { return false; }
+  virtual bool iscell () const { return false; }
 
-  virtual bool iscellstr (void) const { return false; }
+  virtual bool iscellstr () const { return false; }
 
-  virtual bool is_real_scalar (void) const { return false; }
+  virtual bool is_real_scalar () const { return false; }
 
-  virtual bool is_real_matrix (void) const { return false; }
+  virtual bool is_real_matrix () const { return false; }
 
-  virtual bool is_complex_scalar (void) const { return false; }
+  virtual bool is_complex_scalar () const { return false; }
 
-  virtual bool is_complex_matrix (void) const { return false; }
+  virtual bool is_complex_matrix () const { return false; }
 
-  virtual bool is_bool_scalar (void) const { return false; }
+  virtual bool is_bool_scalar () const { return false; }
 
-  virtual bool is_bool_matrix (void) const { return false; }
+  virtual bool is_bool_matrix () const { return false; }
 
-  virtual bool is_char_matrix (void) const { return false; }
+  virtual bool is_char_matrix () const { return false; }
 
-  virtual bool is_diag_matrix (void) const { return false; }
+  virtual bool is_diag_matrix () const { return false; }
 
-  virtual bool is_perm_matrix (void) const { return false; }
+  virtual bool is_perm_matrix () const { return false; }
 
-  virtual bool is_string (void) const { return false; }
+  virtual bool is_string () const { return false; }
 
-  virtual bool is_sq_string (void) const { return false; }
+  virtual bool is_sq_string () const { return false; }
 
-  virtual bool is_range (void) const { return false; }
+  virtual bool is_range () const { return false; }
 
-  virtual bool isstruct (void) const { return false; }
+  virtual bool isstruct () const { return false; }
 
-  virtual bool isobject (void) const { return false; }
+  virtual bool isobject () const { return false; }
 
-  virtual bool is_classdef_meta (void) const { return false; }
+  virtual bool is_classdef_meta () const { return false; }
 
-  virtual bool is_classdef_superclass_ref (void) const { return false; }
+  virtual bool is_classdef_superclass_ref () const { return false; }
 
-  virtual bool is_classdef_object (void) const { return false; }
+  virtual bool is_classdef_object () const { return false; }
 
-  virtual bool is_package (void) const { return false; }
+  virtual bool is_package () const { return false; }
 
-  virtual bool isjava (void) const { return false; }
+  virtual bool isjava () const { return false; }
 
-  virtual bool is_cs_list (void) const { return false; }
+  virtual bool is_cs_list () const { return false; }
 
-  virtual bool is_magic_colon (void) const { return false; }
+  virtual bool is_magic_colon () const { return false; }
 
-  virtual bool is_all_va_args (void) const { return false; }
+  virtual bool is_all_va_args () const { return false; }
 
   virtual octave_value all (int = 0) const;
 
   virtual octave_value any (int = 0) const;
 
-  virtual builtin_type_t builtin_type (void) const { return btyp_unknown; }
+  virtual builtin_type_t builtin_type () const { return btyp_unknown; }
 
-  virtual bool is_double_type (void) const { return false; }
+  virtual bool is_double_type () const { return false; }
 
-  virtual bool is_single_type (void) const { return false; }
+  virtual bool is_single_type () const { return false; }
 
-  virtual bool isfloat (void) const { return false; }
+  virtual bool isfloat () const { return false; }
 
-  virtual bool is_int8_type (void) const { return false; }
+  virtual bool is_int8_type () const { return false; }
 
-  virtual bool is_int16_type (void) const { return false; }
+  virtual bool is_int16_type () const { return false; }
 
-  virtual bool is_int32_type (void) const { return false; }
+  virtual bool is_int32_type () const { return false; }
 
-  virtual bool is_int64_type (void) const { return false; }
+  virtual bool is_int64_type () const { return false; }
 
-  virtual bool is_uint8_type (void) const { return false; }
+  virtual bool is_uint8_type () const { return false; }
 
-  virtual bool is_uint16_type (void) const { return false; }
+  virtual bool is_uint16_type () const { return false; }
 
-  virtual bool is_uint32_type (void) const { return false; }
+  virtual bool is_uint32_type () const { return false; }
 
-  virtual bool is_uint64_type (void) const { return false; }
+  virtual bool is_uint64_type () const { return false; }
 
-  virtual bool islogical (void) const { return false; }
+  virtual bool islogical () const { return false; }
 
-  virtual bool isinteger (void) const { return false; }
+  virtual bool isinteger () const { return false; }
 
-  virtual bool isreal (void) const { return false; }
+  virtual bool isreal () const { return false; }
 
-  virtual bool iscomplex (void) const { return false; }
+  virtual bool iscomplex () const { return false; }
 
   // Would be nice to get rid of the next four functions:
 
-  virtual bool is_scalar_type (void) const { return false; }
+  virtual bool is_scalar_type () const { return false; }
 
-  virtual bool is_matrix_type (void) const { return false; }
+  virtual bool is_matrix_type () const { return false; }
+
+  virtual bool is_full_num_matrix () const { return false; }
 
-  virtual bool isnumeric (void) const { return false; }
+  virtual bool isnumeric () const { return false; }
 
-  virtual bool issparse (void) const { return false; }
+  virtual bool issparse () const { return false; }
+
+  virtual bool is_true () const { return false; }
 
-  virtual bool is_true (void) const { return false; }
+  virtual bool is_magic_int () const { return false; }
 
-  virtual bool is_magic_int (void) const { return false; }
+  virtual bool isnull () const { return false; }
+
+  virtual bool is_constant () const { return false; }
 
-  virtual bool isnull (void) const { return false; }
+  virtual bool is_function_handle () const { return false; }
+
+  virtual bool is_anonymous_function () const { return false; }
 
-  virtual bool is_constant (void) const { return false; }
+  virtual bool is_inline_function () const { return false; }
 
-  virtual bool is_function_handle (void) const { return false; }
+  virtual bool is_function () const { return false; }
 
-  virtual bool is_anonymous_function (void) const { return false; }
+  virtual bool is_user_script () const { return false; }
 
-  virtual bool is_inline_function (void) const { return false; }
+  virtual bool is_user_function () const { return false; }
+
+  virtual bool is_user_code () const { return false; }
 
-  virtual bool is_function (void) const { return false; }
+  virtual bool is_builtin_function () const { return false; }
 
-  virtual bool is_user_script (void) const { return false; }
+  virtual bool is_dld_function () const { return false; }
 
-  virtual bool is_user_function (void) const { return false; }
+  virtual bool is_mex_function () const { return false; }
 
-  virtual bool is_user_code (void) const { return false; }
+  virtual bool is_function_cache (void) const { return false; }
 
-  virtual bool is_builtin_function (void) const { return false; }
+  // Checks if the ov could be a function. If it is undefined,
+  // the name associated with the ov could be a function to call.
+  virtual bool is_maybe_function (void) const
+  { return !is_defined () || is_function (); }
 
-  virtual bool is_dld_function (void) const { return false; }
+  virtual bool has_function_cache (void) const { return false; }
+
+  virtual octave_function * get_cached_fcn (const octave_value_list&) { return nullptr; }
 
-  virtual bool is_mex_function (void) const { return false; }
+  virtual octave_fcn_cache * fcn_cache_value (void) { return nullptr; }
 
-  virtual void erase_subfunctions (void) { }
+  virtual void erase_subfunctions () { }
 
   virtual short int short_value (bool = false, bool = false) const;
 
@@ -552,7 +583,7 @@
   virtual float float_scalar_value (bool frc_str_conv = false) const
   { return float_value (frc_str_conv); }
 
-  virtual Cell cell_value (void) const;
+  virtual Cell cell_value () const;
 
   virtual Matrix matrix_value (bool = false) const;
 
@@ -599,85 +630,63 @@
   virtual FloatComplexDiagMatrix
   float_complex_diag_matrix_value (bool = false) const;
 
-  virtual PermMatrix perm_matrix_value (void) const;
+  virtual PermMatrix perm_matrix_value () const;
 
-  virtual octave_int8 int8_scalar_value (void) const;
+  virtual octave_int8 int8_scalar_value () const;
 
-  virtual octave_int16 int16_scalar_value (void) const;
+  virtual octave_int16 int16_scalar_value () const;
 
-  virtual octave_int32 int32_scalar_value (void) const;
+  virtual octave_int32 int32_scalar_value () const;
 
-  virtual octave_int64 int64_scalar_value (void) const;
+  virtual octave_int64 int64_scalar_value () const;
 
-  virtual octave_uint8 uint8_scalar_value (void) const;
+  virtual octave_uint8 uint8_scalar_value () const;
 
-  virtual octave_uint16 uint16_scalar_value (void) const;
+  virtual octave_uint16 uint16_scalar_value () const;
 
-  virtual octave_uint32 uint32_scalar_value (void) const;
+  virtual octave_uint32 uint32_scalar_value () const;
 
-  virtual octave_uint64 uint64_scalar_value (void) const;
+  virtual octave_uint64 uint64_scalar_value () const;
 
-  virtual int8NDArray int8_array_value (void) const;
+  virtual int8NDArray int8_array_value () const;
 
-  virtual int16NDArray int16_array_value (void) const;
+  virtual int16NDArray int16_array_value () const;
 
-  virtual int32NDArray int32_array_value (void) const;
+  virtual int32NDArray int32_array_value () const;
 
-  virtual int64NDArray int64_array_value (void) const;
+  virtual int64NDArray int64_array_value () const;
 
-  virtual uint8NDArray uint8_array_value (void) const;
+  virtual uint8NDArray uint8_array_value () const;
 
-  virtual uint16NDArray uint16_array_value (void) const;
+  virtual uint16NDArray uint16_array_value () const;
 
-  virtual uint32NDArray uint32_array_value (void) const;
+  virtual uint32NDArray uint32_array_value () const;
 
-  virtual uint64NDArray uint64_array_value (void) const;
+  virtual uint64NDArray uint64_array_value () const;
 
   virtual string_vector string_vector_value (bool pad = false) const;
 
   virtual std::string string_value (bool force = false) const;
 
-  virtual Array<std::string> cellstr_value (void) const;
-
-  virtual octave::range<double> range_value (void) const;
-
-  // For now, disable all but range<double>.
-
-#if 0
+  virtual Array<std::string> cellstr_value () const;
 
-  virtual octave::range<float> float_range_value (void) const;
-
-  virtual octave::range<octave_int8> int8_range_value (void) const;
+  virtual octave::range<double> range_value () const;
 
-  virtual octave::range<octave_int16> int16_range_value (void) const;
-
-  virtual octave::range<octave_int32> int32_range_value (void) const;
+  // For now, enable only range<double>.
 
-  virtual octave::range<octave_int64> int64_range_value (void) const;
-
-  virtual octave::range<octave_uint8> uint8_range_value (void) const;
-
-  virtual octave::range<octave_uint16> uint16_range_value (void) const;
-
-  virtual octave::range<octave_uint32> uint32_range_value (void) const;
+  virtual octave_map map_value () const;
 
-  virtual octave::range<octave_uint64> uint64_range_value (void) const;
-
-#endif
+  virtual octave_scalar_map scalar_map_value () const;
 
-  virtual octave_map map_value (void) const;
-
-  virtual octave_scalar_map scalar_map_value (void) const;
-
-  virtual string_vector map_keys (void) const;
+  virtual string_vector map_keys () const;
 
   virtual bool isfield (const std::string&) const;
 
-  virtual std::size_t nparents (void) const;
+  virtual std::size_t nparents () const;
 
-  virtual std::list<std::string> parent_class_name_list (void) const;
+  virtual std::list<std::string> parent_class_name_list () const;
 
-  virtual string_vector parent_class_names (void) const;
+  virtual string_vector parent_class_names () const;
 
   virtual octave_base_value * find_parent_class (const std::string&)
   { return nullptr; }
@@ -700,21 +709,21 @@
 
   virtual octave_fcn_handle * fcn_handle_value (bool silent = false);
 
-  virtual octave_value_list list_value (void) const;
+  virtual octave_value_list list_value () const;
 
   virtual octave_value convert_to_str (bool pad = false, bool force = false,
                                        char type = '\'') const;
   virtual octave_value
   convert_to_str_internal (bool pad, bool force, char type) const;
 
-  virtual void convert_to_row_or_column_vector (void);
+  virtual void convert_to_row_or_column_vector ();
 
   // The following extractor functions don't perform any implicit type
   // conversions.
 
   virtual std::string xstring_value () const;
 
-  virtual bool print_as_scalar (void) const { return false; }
+  virtual bool print_as_scalar () const { return false; }
 
   virtual void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -730,7 +739,7 @@
 
   virtual void short_disp (std::ostream& os) const { os << "..."; }
 
-  virtual float_display_format get_edit_display_format (void) const;
+  virtual float_display_format get_edit_display_format () const;
 
   virtual std::string edit_display (const float_display_format&,
                                     octave_idx_type, octave_idx_type) const
@@ -758,11 +767,11 @@
          oct_data_conv::data_type output_type, int skip,
          octave::mach_info::float_format flt_fmt) const;
 
-  virtual const void * mex_get_data (void) const { return nullptr; }
+  virtual const void * mex_get_data () const { return nullptr; }
 
-  virtual const octave_idx_type * mex_get_ir (void) const { return nullptr; }
+  virtual const octave_idx_type * mex_get_ir () const { return nullptr; }
 
-  virtual const octave_idx_type * mex_get_jc (void) const { return nullptr; }
+  virtual const octave_idx_type * mex_get_jc () const { return nullptr; }
 
   virtual mxArray * as_mxArray (bool interleaved) const;
 
@@ -783,15 +792,41 @@
 
   virtual sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
-  virtual void lock (void);
+  virtual void lock ();
+
+  virtual void unlock ();
+
+  virtual bool islocked () const { return false; }
+
+  virtual void call_object_destructor () { }
 
-  virtual void unlock (void);
+  virtual void maybe_call_dtor () { }
+
+  virtual octave_value dump () const;
+
+  virtual octave_value storable_value (void);
+
+  virtual octave_base_value * make_storable_value (void);
+
+  virtual bool vm_need_storable_call (void) const { return false; }
 
-  virtual bool islocked (void) const { return false; }
+  virtual bool vm_need_dispatch_assign_rhs (void) { return true; }
+  virtual bool vm_need_dispatch_assign_lhs (void) { return true; }
+  virtual bool vm_need_dispatch_push (void) { return true; }
+
+  virtual bool is_ref () const { return false; }
+
+  virtual octave_value_ref * ref_rep ();
 
-  virtual void call_object_destructor (void) { }
+  virtual octave_value
+  vm_extract_forloop_value (octave_idx_type idx);
 
-  virtual octave_value dump (void) const;
+  virtual double
+  vm_extract_forloop_double (octave_idx_type idx);
+
+  virtual bool maybe_update_double (double d);
+
+  virtual bool is_trivial_range () const { return false; };
 
   // Standard mappers.  Register new ones here.
   enum unary_mapper_t
@@ -882,6 +917,12 @@
   virtual bool
   fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
+  virtual octave_value
+  checked_full_matrix_elem (octave_idx_type i) const;
+
+  virtual octave_value
+  checked_full_matrix_elem (octave_idx_type i, octave_idx_type j) const;
+
 protected:
 
   // This should only be called for derived types.
@@ -891,29 +932,38 @@
                   const std::list<octave_value_list>& idx,
                   const octave_value& rhs);
 
-  void reset_indent_level (void) const
+  OCTINTERP_API octave_value
+  simple_numeric_assign (char type, octave_value_list& idx,
+                         const octave_value& rhs);
+
+  void reset_indent_level () const
   { s_curr_print_indent_level = 0; }
 
-  void increment_indent_level (void) const
+  void increment_indent_level () const
   { s_curr_print_indent_level += 2; }
 
-  void decrement_indent_level (void) const
+  void decrement_indent_level () const
   { s_curr_print_indent_level -= 2; }
 
-  int current_print_indent_level (void) const
+  int current_print_indent_level () const
   { return s_curr_print_indent_level; }
 
   OCTINTERP_API void indent (std::ostream& os) const;
 
   OCTINTERP_API void newline (std::ostream& os) const;
 
-  OCTINTERP_API void reset (void) const;
+  OCTINTERP_API void reset () const;
 
   // A reference count.
   // NOTE: the declaration is octave_idx_type because with 64-bit indexing,
   // it is well possible to have more than MAX_INT copies of a single value
   // (think of an empty cell array with >2G elements).
-  octave::refcount<octave_idx_type> count;
+  octave::refcount<octave_idx_type> m_count;
+
+  // FIXME: Create an alias "count" to the real member variable m_count.
+  // This name is deprecated in Octave 9 and will be removed in Octave 11.
+  OCTAVE_DEPRECATED (9, "use octave_base_value::m_count instead")
+  octave::refcount<octave_idx_type>& count;
 
   OCTINTERP_API static const char * get_umap_name (unary_mapper_t);
 
@@ -922,7 +972,7 @@
 
 private:
 
-  OCTINTERP_API void wrong_type_arg_error (void) const;
+  OCTINTERP_API void wrong_type_arg_error () const;
 
   //--------
 
@@ -938,9 +988,9 @@
 {
 public:
 
-  octave_base_dld_value (void) = default;
+  octave_base_dld_value () = default;
 
-  ~octave_base_dld_value (void)
+  ~octave_base_dld_value ()
   {
     m_containing_dynamic_library.delete_later ();
   }
@@ -965,6 +1015,6 @@
 
 // Tells whether some regular octave_value_base methods are being called from
 // within the "builtin" function.
-extern OCTINTERP_API bool called_from_builtin (void);
+extern OCTINTERP_API bool called_from_builtin ();
 
 #endif
--- a/libinterp/octave-value/ov-bool-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -79,14 +79,14 @@
 }
 
 octave_base_value::type_conv_info
-octave_bool_matrix::numeric_conversion_function (void) const
+octave_bool_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_matrix::static_type_id ());
 }
 
 octave_base_value *
-octave_bool_matrix::try_narrowing_conversion (void)
+octave_bool_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -167,61 +167,61 @@
 }
 
 octave_value
-octave_bool_matrix::as_double (void) const
+octave_bool_matrix::as_double () const
 {
   return NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_single (void) const
+octave_bool_matrix::as_single () const
 {
   return FloatNDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_int8 (void) const
+octave_bool_matrix::as_int8 () const
 {
   return int8NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_int16 (void) const
+octave_bool_matrix::as_int16 () const
 {
   return int16NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_int32 (void) const
+octave_bool_matrix::as_int32 () const
 {
   return int32NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_int64 (void) const
+octave_bool_matrix::as_int64 () const
 {
   return int64NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_uint8 (void) const
+octave_bool_matrix::as_uint8 () const
 {
   return uint8NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_uint16 (void) const
+octave_bool_matrix::as_uint16 () const
 {
   return uint16NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_uint32 (void) const
+octave_bool_matrix::as_uint32 () const
 {
   return uint32NDArray (m_matrix);
 }
 
 octave_value
-octave_bool_matrix::as_uint64 (void) const
+octave_bool_matrix::as_uint64 () const
 {
   return uint64NDArray (m_matrix);
 }
@@ -361,15 +361,9 @@
       os.write (reinterpret_cast<char *> (&tmp), 4);
     }
 
-  boolNDArray m = bool_array_value ();
-  bool *mtmp = m.fortran_vec ();
-  octave_idx_type nel = m.numel ();
-  OCTAVE_LOCAL_BUFFER (char, htmp, nel);
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    htmp[i] = (mtmp[i] ? 1 : 0);
-
-  os.write (htmp, nel);
+  const bool *mtmp = m_matrix.data ();
+  octave_idx_type nel = m_matrix.numel ();
+  os.write (reinterpret_cast<const char*> (mtmp), nel);
 
   return true;
 }
@@ -444,7 +438,6 @@
   int rank = dv.ndims ();
   hid_t space_hid, data_hid;
   space_hid = data_hid = -1;
-  boolNDArray m = bool_array_value ();
 
   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
 
@@ -468,15 +461,11 @@
       return false;
     }
 
-  octave_idx_type nel = m.numel ();
-  bool *mtmp = m.fortran_vec ();
-  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    htmp[i] = mtmp[i];
+  const bool *mtmp = m_matrix.data ();
 
   retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
-                     octave_H5P_DEFAULT, htmp) >= 0;
+                     octave_H5P_DEFAULT,
+                     reinterpret_cast<const char*> (mtmp)) >= 0;
 
   H5Dclose (data_hid);
   H5Sclose (space_hid);
--- a/libinterp/octave-value/ov-bool-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 public:
 
-  octave_bool_matrix (void)
+  octave_bool_matrix ()
     : octave_base_matrix<boolNDArray> () { }
 
   octave_bool_matrix (const boolNDArray& bnda)
@@ -77,17 +77,17 @@
   octave_bool_matrix (const octave_bool_matrix& bm)
     : octave_base_matrix<boolNDArray> (bm) { }
 
-  ~octave_bool_matrix (void) = default;
+  ~octave_bool_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_bool_matrix (*this); }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_bool_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   {
@@ -95,39 +95,39 @@
            : set_idx_cache (octave::idx_vector (m_matrix));
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_bool; }
+  builtin_type_t builtin_type () const { return btyp_bool; }
 
-  bool is_bool_matrix (void) const { return true; }
+  bool is_bool_matrix () const { return true; }
 
-  bool islogical (void) const { return true; }
+  bool islogical () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool isnumeric (void) const { return false; }
+  bool isnumeric () const { return false; }
 
   int8NDArray
-  int8_array_value (void) const { return int8NDArray (m_matrix); }
+  int8_array_value () const { return int8NDArray (m_matrix); }
 
   int16NDArray
-  int16_array_value (void) const { return int16NDArray (m_matrix); }
+  int16_array_value () const { return int16NDArray (m_matrix); }
 
   int32NDArray
-  int32_array_value (void) const { return int32NDArray (m_matrix); }
+  int32_array_value () const { return int32NDArray (m_matrix); }
 
   int64NDArray
-  int64_array_value (void) const { return int64NDArray (m_matrix); }
+  int64_array_value () const { return int64NDArray (m_matrix); }
 
   uint8NDArray
-  uint8_array_value (void) const { return uint8NDArray (m_matrix); }
+  uint8_array_value () const { return uint8NDArray (m_matrix); }
 
   uint16NDArray
-  uint16_array_value (void) const { return uint16NDArray (m_matrix); }
+  uint16_array_value () const { return uint16NDArray (m_matrix); }
 
   uint32NDArray
-  uint32_array_value (void) const { return uint32NDArray (m_matrix); }
+  uint32_array_value () const { return uint32NDArray (m_matrix); }
 
   uint64NDArray
-  uint64_array_value (void) const { return uint64NDArray (m_matrix); }
+  uint64_array_value () const { return uint64NDArray (m_matrix); }
 
   double double_value (bool = false) const;
 
@@ -194,21 +194,21 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   // Use matrix_ref here to clear index cache.
-  void invert (void) { matrix_ref ().invert (); }
+  void invert () { matrix_ref ().invert (); }
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-bool-sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -67,7 +67,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_sparse_bool_matrix::numeric_conversion_function (void) const
+octave_sparse_bool_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_sparse_matrix::static_type_id ());
@@ -172,7 +172,7 @@
 }
 
 octave_value
-octave_sparse_bool_matrix::as_double (void) const
+octave_sparse_bool_matrix::as_double () const
 {
   return SparseMatrix (this->matrix);
 }
--- a/libinterp/octave-value/ov-bool-sparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 public:
 
-  octave_sparse_bool_matrix (void)
+  octave_sparse_bool_matrix ()
     : octave_base_sparse<SparseBoolMatrix> () { }
 
   octave_sparse_bool_matrix (const SparseBoolMatrix& bnda)
@@ -75,14 +75,14 @@
   octave_sparse_bool_matrix (const octave_sparse_bool_matrix& bm)
     : octave_base_sparse<SparseBoolMatrix> (bm) { }
 
-  ~octave_sparse_bool_matrix (void) = default;
+  ~octave_sparse_bool_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_sparse_bool_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_sparse_bool_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
   // FIXME: Adapt idx_vector to allow sparse logical indexing without overflow!
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
@@ -90,15 +90,15 @@
     return octave::idx_vector (matrix);
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_bool; }
+  builtin_type_t builtin_type () const { return btyp_bool; }
 
-  bool is_bool_matrix (void) const { return true; }
+  bool is_bool_matrix () const { return true; }
 
-  bool islogical (void) const { return true; }
+  bool islogical () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool isnumeric (void) const { return false; }
+  bool isnumeric () const { return false; }
 
   double double_value (bool = false) const;
 
@@ -130,7 +130,7 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  octave_value as_double (void) const;
+  octave_value as_double () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-bool.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -69,7 +69,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_bool::numeric_conversion_function (void) const
+octave_bool::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_scalar::static_type_id ());
@@ -95,61 +95,61 @@
 }
 
 octave_value
-octave_bool::as_double (void) const
+octave_bool::as_double () const
 {
   return static_cast<double> (scalar);
 }
 
 octave_value
-octave_bool::as_single (void) const
+octave_bool::as_single () const
 {
   return static_cast<float> (scalar);
 }
 
 octave_value
-octave_bool::as_int8 (void) const
+octave_bool::as_int8 () const
 {
   return octave_int8 (scalar);
 }
 
 octave_value
-octave_bool::as_int16 (void) const
+octave_bool::as_int16 () const
 {
   return octave_int16 (scalar);
 }
 
 octave_value
-octave_bool::as_int32 (void) const
+octave_bool::as_int32 () const
 {
   return octave_int32 (scalar);
 }
 
 octave_value
-octave_bool::as_int64 (void) const
+octave_bool::as_int64 () const
 {
   return octave_int64 (scalar);
 }
 
 octave_value
-octave_bool::as_uint8 (void) const
+octave_bool::as_uint8 () const
 {
   return octave_uint8 (scalar);
 }
 
 octave_value
-octave_bool::as_uint16 (void) const
+octave_bool::as_uint16 () const
 {
   return octave_uint16 (scalar);
 }
 
 octave_value
-octave_bool::as_uint32 (void) const
+octave_bool::as_uint32 () const
 {
   return octave_uint32 (scalar);
 }
 
 octave_value
-octave_bool::as_uint64 (void) const
+octave_bool::as_uint64 () const
 {
   return octave_uint64 (scalar);
 }
--- a/libinterp/octave-value/ov-bool.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-bool.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_bool (void)
+  octave_bool ()
     : octave_base_scalar<bool> (false) { }
 
   octave_bool (bool b)
@@ -63,13 +63,13 @@
   octave_bool (const octave_bool& s)
     : octave_base_scalar<bool> (s) { }
 
-  ~octave_bool (void) = default;
+  ~octave_bool () = default;
 
-  octave_base_value * clone (void) const { return new octave_bool (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * clone () const { return new octave_bool (*this); }
+  octave_base_value * empty_clone () const
   { return new octave_bool_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
@@ -77,75 +77,75 @@
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   { return octave::idx_vector (scalar); }
 
-  builtin_type_t builtin_type (void) const { return btyp_bool; }
+  builtin_type_t builtin_type () const { return btyp_bool; }
 
-  bool is_real_scalar (void) const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  bool is_bool_scalar (void) const { return true; }
+  bool is_bool_scalar () const { return true; }
 
-  bool islogical (void) const { return true; }
+  bool islogical () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool isnumeric (void) const { return false; }
+  bool isnumeric () const { return false; }
 
-  bool is_true (void) const { return scalar; }
+  bool is_true () const { return scalar; }
 
   int8NDArray
-  int8_array_value (void) const
+  int8_array_value () const
   { return int8NDArray (dim_vector (1, 1), scalar); }
 
   int16NDArray
-  int16_array_value (void) const
+  int16_array_value () const
   { return int16NDArray (dim_vector (1, 1), scalar); }
 
   int32NDArray
-  int32_array_value (void) const
+  int32_array_value () const
   { return int32NDArray (dim_vector (1, 1), scalar); }
 
   int64NDArray
-  int64_array_value (void) const
+  int64_array_value () const
   { return int64NDArray (dim_vector (1, 1), scalar); }
 
   uint8NDArray
-  uint8_array_value (void) const
+  uint8_array_value () const
   { return uint8NDArray (dim_vector (1, 1), scalar); }
 
   uint16NDArray
-  uint16_array_value (void) const
+  uint16_array_value () const
   { return uint16NDArray (dim_vector (1, 1), scalar); }
 
   uint32NDArray
-  uint32_array_value (void) const
+  uint32_array_value () const
   { return uint32NDArray (dim_vector (1, 1), scalar); }
 
   uint64NDArray
-  uint64_array_value (void) const
+  uint64_array_value () const
   { return uint64NDArray (dim_vector (1, 1), scalar); }
 
   octave_int8
-  int8_scalar_value (void) const { return octave_int8 (scalar); }
+  int8_scalar_value () const { return octave_int8 (scalar); }
 
   octave_int16
-  int16_scalar_value (void) const { return octave_int16 (scalar); }
+  int16_scalar_value () const { return octave_int16 (scalar); }
 
   octave_int32
-  int32_scalar_value (void) const { return octave_int32 (scalar); }
+  int32_scalar_value () const { return octave_int32 (scalar); }
 
   octave_int64
-  int64_scalar_value (void) const { return octave_int64 (scalar); }
+  int64_scalar_value () const { return octave_int64 (scalar); }
 
   octave_uint8
-  uint8_scalar_value (void) const { return octave_uint8 (scalar); }
+  uint8_scalar_value () const { return octave_uint8 (scalar); }
 
   octave_uint16
-  uint16_scalar_value (void) const { return octave_uint16 (scalar); }
+  uint16_scalar_value () const { return octave_uint16 (scalar); }
 
   octave_uint32
-  uint32_scalar_value (void) const { return octave_uint32 (scalar); }
+  uint32_scalar_value () const { return octave_uint32 (scalar); }
 
   octave_uint64
-  uint64_scalar_value (void) const { return octave_uint64 (scalar); }
+  uint64_scalar_value () const { return octave_uint64 (scalar); }
 
   double double_value (bool = false) const { return scalar; }
 
@@ -209,18 +209,18 @@
   boolNDArray bool_array_value (bool = false) const
   { return boolNDArray (dim_vector (1, 1), scalar); }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   octave_value resize (const dim_vector& dv, bool fill = false) const;
 
--- a/libinterp/octave-value/ov-builtin.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-builtin.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,13 +50,13 @@
 }
 
 octave_builtin::fcn
-octave_builtin::function (void) const
+octave_builtin::function () const
 {
   return m_fcn;
 }
 
 octave_builtin::meth
-octave_builtin::method (void) const
+octave_builtin::method () const
 {
   return m_meth;
 }
--- a/libinterp/octave-value/ov-builtin.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-builtin.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 public:
 
-  octave_builtin (void)
+  octave_builtin ()
     : octave_function (), m_fcn (nullptr), m_meth (nullptr), m_file ()
   { }
 
@@ -82,27 +82,23 @@
     : octave_function (nm, ds), m_fcn (nullptr), m_meth (mm), m_file (fnm)
   { }
 
-  // No copying!
-
-  octave_builtin (const octave_builtin& ob) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_builtin)
 
-  octave_builtin& operator = (const octave_builtin& ob) = delete;
+  ~octave_builtin () = default;
 
-  ~octave_builtin (void) = default;
-
-  std::string src_file_name (void) const { return m_file; }
+  std::string src_file_name () const { return m_file; }
 
   octave_function * function_value (bool = false) { return this; }
 
-  bool is_builtin_function (void) const { return true; }
+  bool is_builtin_function () const { return true; }
 
   octave_value_list
   execute (octave::tree_evaluator& tw, int nargout = 0,
            const octave_value_list& args = octave_value_list ());
 
-  fcn function (void) const;
+  fcn function () const;
 
-  meth method (void) const;
+  meth method () const;
 
   void push_dispatch_class (const std::string& dispatch_type);
 
--- a/libinterp/octave-value/ov-cell.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cell.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -364,7 +364,7 @@
         else
           octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
 
-        count++;
+        m_count++;
         retval = octave_value (this);
       }
       break;
@@ -396,7 +396,7 @@
         else
           err_nonbraced_cs_list_assignment ();
 
-        count++;
+        m_count++;
         retval = octave_value (this);
       }
       break;
@@ -428,7 +428,7 @@
 }
 
 bool
-octave_cell::iscellstr (void) const
+octave_cell::iscellstr () const
 {
   bool retval;
   if (m_cellstr_cache.get ())
@@ -466,7 +466,7 @@
 }
 
 std::size_t
-octave_cell::byte_size (void) const
+octave_cell::byte_size () const
 {
   std::size_t retval = 0;
 
@@ -559,13 +559,13 @@
 }
 
 bool
-octave_cell::is_true (void) const
+octave_cell::is_true () const
 {
   error ("invalid conversion from cell array to logical value");
 }
 
 octave_value_list
-octave_cell::list_value (void) const
+octave_cell::list_value () const
 {
   return octave_value_list (m_matrix);
 }
@@ -633,7 +633,7 @@
 }
 
 Array<std::string>
-octave_cell::cellstr_value (void) const
+octave_cell::cellstr_value () const
 {
   if (! iscellstr ())
     error ("invalid conversion from cell array to array of strings");
@@ -645,7 +645,7 @@
 }
 
 bool
-octave_cell::print_as_scalar (void) const
+octave_cell::print_as_scalar () const
 {
   return true;
 }
@@ -995,7 +995,7 @@
 }
 
 const void *
-octave_cell::mex_get_data (void) const
+octave_cell::mex_get_data () const
 {
   clear_cellstr_cache ();
   return m_matrix.data ();
@@ -1286,6 +1286,8 @@
 }
 
 /*
+## Note: Matlab compatibility requires using 0 for negative dimensions.
+%!assert (size (cell (2, -3)), [2, 0])
 
 %!test <*63132>
 %! x = {1, 3};
@@ -1336,11 +1338,10 @@
     return ovl (args(0));
   else
     {
-      string_vector s = args(
-                          0).xstring_vector_value ("cellstr: argument STRING must be a 2-D character array");
+      string_vector s = args(0).xstring_vector_value ("cellstr: argument STRING must be a 2-D character array");
 
       return ovl (s.isempty () ? Cell (octave_value (""))
-                  : Cell (s, true));
+                               : Cell (s, true));
     }
 }
 
--- a/libinterp/octave-value/ov-cell.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cell.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,7 +51,7 @@
 {
 public:
 
-  octave_cell (void)
+  octave_cell ()
     : octave_base_matrix<Cell> (), m_cellstr_cache () { }
 
   octave_cell (const Cell& c)
@@ -64,17 +64,13 @@
   octave_cell (const octave_cell& c)
     : octave_base_matrix<Cell> (c), m_cellstr_cache () { }
 
-  ~octave_cell (void) = default;
+  ~octave_cell () = default;
 
-  octave_base_value * clone (void) const { return new octave_cell (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_cell (); }
+  octave_base_value * clone () const { return new octave_cell (*this); }
+  octave_base_value * empty_clone () const { return new octave_cell (); }
 
   void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);
 
-#if 0
-  octave_base_value * try_narrowing_conversion (void);
-#endif
-
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx)
   {
@@ -107,7 +103,7 @@
 
   void delete_elements (const octave_value_list& idx);
 
-  std::size_t byte_size (void) const;
+  std::size_t byte_size () const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
 
@@ -120,36 +116,38 @@
 
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
-  bool is_matrix_type (void) const { return false; }
+  bool is_matrix_type () const { return false; }
 
-  bool isnumeric (void) const { return false; }
+  bool isnumeric () const { return false; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool iscell (void) const { return true; }
+  bool iscell () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return btyp_cell; }
+  builtin_type_t builtin_type () const { return btyp_cell; }
 
-  bool iscellstr (void) const;
+  bool iscellstr () const;
+
+  bool is_true () const;
 
-  bool is_true (void) const;
+  bool is_full_num_matrix () const { return false; }
 
-  Cell cell_value (void) const { return m_matrix; }
+  Cell cell_value () const { return m_matrix; }
 
-  octave_value_list list_value (void) const;
+  octave_value_list list_value () const;
 
   octave_value convert_to_str_internal (bool pad, bool, char type) const
   { return octave_value (string_vector_value (pad), type); }
 
   string_vector string_vector_value (bool pad = false) const;
 
-  Array<std::string> cellstr_value (void) const;
+  Array<std::string> cellstr_value () const;
 
   Array<std::string> cellstr_value (const char *fmt, ...) const;
 
-  bool print_as_scalar (void) const;
+  bool print_as_scalar () const;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -178,11 +176,11 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data (void) const;
+  const void * mex_get_data () const;
 
 private:
 
-  void clear_cellstr_cache (void) const
+  void clear_cellstr_cache () const
   { m_cellstr_cache.reset (); }
 
   //--------
--- a/libinterp/octave-value/ov-ch-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-ch-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -154,61 +154,61 @@
 }
 
 octave_value
-octave_char_matrix::as_double (void) const
+octave_char_matrix::as_double () const
 {
   return NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_single (void) const
+octave_char_matrix::as_single () const
 {
   return FloatNDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_int8 (void) const
+octave_char_matrix::as_int8 () const
 {
   return int8NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_int16 (void) const
+octave_char_matrix::as_int16 () const
 {
   return int16NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_int32 (void) const
+octave_char_matrix::as_int32 () const
 {
   return int32NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_int64 (void) const
+octave_char_matrix::as_int64 () const
 {
   return int64NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_uint8 (void) const
+octave_char_matrix::as_uint8 () const
 {
   return uint8NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_uint16 (void) const
+octave_char_matrix::as_uint16 () const
 {
   return uint16NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_uint32 (void) const
+octave_char_matrix::as_uint32 () const
 {
   return uint32NDArray (m_matrix);
 }
 
 octave_value
-octave_char_matrix::as_uint64 (void) const
+octave_char_matrix::as_uint64 () const
 {
   return uint64NDArray (m_matrix);
 }
--- a/libinterp/octave-value/ov-ch-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-ch-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 protected:
 
-  octave_char_matrix (void)
+  octave_char_matrix ()
     : octave_base_matrix<charNDArray> () { }
 
   octave_char_matrix (const charMatrix& chm)
@@ -82,21 +82,21 @@
 
 public:
 
-  ~octave_char_matrix (void) = default;
+  ~octave_char_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_char_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_char_matrix (); }
 
   octave::idx_vector index_vector (bool require_integers = false) const;
 
-  builtin_type_t builtin_type (void) const { return btyp_char; }
+  builtin_type_t builtin_type () const { return btyp_char; }
 
-  bool is_char_matrix (void) const { return true; }
-  bool is_real_matrix (void) const { return true; }
+  bool is_char_matrix () const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -148,18 +148,18 @@
   octave_value convert_to_str_internal (bool, bool, char type) const
   { return octave_value (m_matrix, type); }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-class.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-class.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -56,26 +56,25 @@
 #include "ov-typeinfo.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
-#include "parse.h"
 #include "pr-output.h"
 #include "unwind-prot.h"
 #include "variables.h"
 
 
-int octave_class::t_id (-1);
-
-const std::string octave_class::t_name ("class");
+int octave_class::s_t_id (-1);
+
+const std::string octave_class::s_t_name ("class");
 
 void
 octave_class::register_type (octave::type_info& ti)
 {
-  t_id = ti.register_type (octave_class::t_name, "<unknown>",
+  s_t_id = ti.register_type (octave_class::s_t_name, "<unknown>",
                            octave_value (new octave_class ()));
 }
 
 octave_class::octave_class (const octave_map& m, const std::string& id,
                             const octave_value_list& parents)
-  : octave_base_value (), m_map (m), c_name (id), m_obsolete_copies (0)
+  : octave_base_value (), m_map (m), m_c_name (id), m_obsolete_copies (0)
 {
   octave_idx_type n = parents.length ();
 
@@ -206,18 +205,18 @@
 }
 
 octave_base_value *
-octave_class::unique_clone (void)
+octave_class::unique_clone ()
 {
-  if (count == m_obsolete_copies)
+  if (m_count == m_obsolete_copies)
     {
       // All remaining copies are obsolete.  We don't actually need to clone.
-      count++;
+      m_count++;
       return this;
     }
   else
     {
       // In theory, this shouldn't be happening, but it's here just in case.
-      if (count < m_obsolete_copies)
+      if (m_count < m_obsolete_copies)
         m_obsolete_copies = 0;
 
       return clone ();
@@ -225,7 +224,7 @@
 }
 
 std::string
-octave_class::get_current_method_class (void)
+octave_class::get_current_method_class ()
 {
   std::string retval = class_name ();
 
@@ -246,14 +245,14 @@
 
 OCTAVE_NORETURN static
 void
-err_invalid_index1 (void)
+err_invalid_index1 ()
 {
   error ("invalid index for class");
 }
 
 OCTAVE_NORETURN static
 void
-err_invalid_index_for_assignment (void)
+err_invalid_index_for_assignment ()
 {
   error ("invalid index for class assignment");
 }
@@ -305,23 +304,25 @@
 }
 
 Matrix
-octave_class::size (void)
+octave_class::size ()
 {
   if (in_class_method () || called_from_builtin ())
     return octave_base_value::size ();
 
   Matrix retval (1, 2, 1.0);
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method ("size", class_name ());
 
   if (meth.is_defined ())
     {
-      count++;
+      m_count++;
       octave_value_list args (1, octave_value (this));
 
-      octave_value_list lv = octave::feval (meth.function_value (), args, 1);
+      octave_value_list lv = interp.feval (meth.function_value (), args, 1);
       if (lv.length () <= 0
           || ! lv(0).is_matrix_type () || ! lv(0).dims ().isvector ())
         error ("@%s/size: invalid return value", class_name ().c_str ());
@@ -352,7 +353,9 @@
   octave_idx_type retval = -1;
   const std::string cn = class_name ();
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method ("numel", cn);
 
@@ -360,13 +363,13 @@
     {
       octave_value_list args (idx.length () + 1, octave_value ());
 
-      count++;
+      m_count++;
       args(0) = octave_value (this);
 
       for (octave_idx_type i = 0; i < idx.length (); i++)
         args(i+1) = idx(i);
 
-      octave_value_list lv = octave::feval (meth.function_value (), args, 1);
+      octave_value_list lv = interp.feval (meth.function_value (), args, 1);
       if (lv.length () != 1 || ! lv(0).is_scalar_type ())
         error ("@%s/numel: invalid return value", cn.c_str ());
 
@@ -415,7 +418,7 @@
               }
             else
               retval(0) = octave_value (m_map.index (idx.front ()),
-                                        c_name, m_parent_list);
+                                        m_c_name, m_parent_list);
           }
           break;
 
@@ -447,7 +450,9 @@
     }
   else
     {
-      octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
 
       octave_value meth = symtab.find_method ("subsref", class_name ());
 
@@ -457,7 +462,7 @@
 
           args(1) = make_idx_args (type, idx, "subsref");
 
-          count++;
+          m_count++;
           args(0) = octave_value (this);
 
           // FIXME: for Matlab compatibility, let us attempt to set up a proper
@@ -479,7 +484,7 @@
               true_nargout = xnumel (tmp);
             }
 
-          retval = octave::feval (meth.function_value (), args, true_nargout);
+          retval = interp.feval (meth.function_value (), args, true_nargout);
 
           // Since we're handling subsref, if the list has more than one
           // element, return it as a comma-separated list so that we can
@@ -490,7 +495,7 @@
       else
         {
           if (type.length () == 1 && type[0] == '(')
-            retval(0) = octave_value (m_map.index (idx.front ()), c_name,
+            retval(0) = octave_value (m_map.index (idx.front ()), m_c_name,
                                       m_parent_list);
           else
             err_invalid_index1 ();
@@ -521,7 +526,7 @@
                         const std::list<octave_value_list>& idx,
                         const octave_value& rhs)
 {
-  count++;
+  m_count++;
   return subsasgn_common (octave_value (this), type, idx, rhs);
 }
 
@@ -547,7 +552,9 @@
 
   if (! (in_class_method () || called_from_builtin ()))
     {
-      octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
 
       octave_value meth = symtab.find_method ("subsasgn", class_name ());
 
@@ -589,10 +596,10 @@
               octave::unwind_protect_var<int> restore_var (m_obsolete_copies);
               m_obsolete_copies = 2;
 
-              tmp = octave::feval (meth.function_value (), args);
+              tmp = interp.feval (meth.function_value (), args);
             }
           else
-            tmp = octave::feval (meth.function_value (), args);
+            tmp = interp.feval (meth.function_value (), args);
 
           // FIXME: Should the subsasgn method be able to return
           //        more than one value?
@@ -622,7 +629,7 @@
 
       obvp->subsasgn (type, idx, rhs);
 
-      count++;
+      m_count++;
       retval = octave_value (this);
 
       return retval;
@@ -748,7 +755,7 @@
 
             m_map.assign (idx.front (), key, t_rhs);
 
-            count++;
+            m_count++;
             retval = octave_value (this);
           }
         else
@@ -759,7 +766,7 @@
 
                 m_map.assign (idx.front (), rhs_map);
 
-                count++;
+                m_count++;
                 retval = octave_value (this);
               }
             else
@@ -769,7 +776,7 @@
 
                 m_map.delete_elements (idx.front ());
 
-                count++;
+                m_count++;
                 retval = octave_value (this);
               }
           }
@@ -804,7 +811,7 @@
             m_map.setfield (key, tmp_cell);
           }
 
-        count++;
+        m_count++;
         retval = octave_value (this);
       }
       break;
@@ -823,7 +830,9 @@
 octave::idx_vector
 octave_class::index_vector (bool require_integers) const
 {
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method ("subsindex", class_name ());
 
@@ -832,9 +841,9 @@
            class_name ().c_str ());
 
   octave_value_list args;
-  args(0) = octave_value (new octave_class (m_map, c_name, m_parent_list));
-
-  octave_value_list tmp = octave::feval (meth.function_value (), args, 1);
+  args(0) = octave_value (new octave_class (m_map, m_c_name, m_parent_list));
+
+  octave_value_list tmp = interp.feval (meth.function_value (), args, 1);
 
   if (tmp(0).isobject ())
     error ("subsindex function must return a valid index vector");
@@ -848,7 +857,7 @@
 }
 
 std::size_t
-octave_class::byte_size (void) const
+octave_class::byte_size () const
 {
   // Neglect the size of the fieldnames.
 
@@ -867,11 +876,13 @@
 }
 
 bool
-octave_class::is_true (void) const
+octave_class::is_true () const
 {
   bool retval = false;
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method ("logical", class_name ());
 
@@ -879,7 +890,7 @@
     {
       octave_value in = new octave_class (*this);
 
-      octave_value_list tmp = octave::feval (meth.function_value (), in, 1);
+      octave_value_list tmp = interp.feval (meth.function_value (), in, 1);
       retval = tmp(0).is_true ();
     }
 
@@ -887,7 +898,7 @@
 }
 
 string_vector
-octave_class::map_keys (void) const
+octave_class::map_keys () const
 {
   err_wrong_type_arg ("octave_class::map_keys()", type_name ());
 }
@@ -989,7 +1000,9 @@
 {
   string_vector retval;
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method ("char", class_name ());
 
@@ -997,9 +1010,9 @@
     error ("no char method defined for class %s", class_name ().c_str ());
 
   octave_value_list args;
-  args(0) = octave_value (new octave_class (m_map, c_name, m_parent_list));
-
-  octave_value_list tmp = octave::feval (meth.function_value (), args, 1);
+  args(0) = octave_value (new octave_class (m_map, m_c_name, m_parent_list));
+
+  octave_value_list tmp = interp.feval (meth.function_value (), args, 1);
 
   if (tmp.length () >= 1)
     {
@@ -1030,12 +1043,12 @@
 // If we don't have one, we attempt to create one by calling the constructor
 // with no arguments.
 bool
-octave_class::reconstruct_exemplar (void)
+octave_class::reconstruct_exemplar ()
 {
   bool retval = false;
 
   octave_class::exemplar_const_iterator it
-    = octave_class::exemplar_map.find (c_name);
+    = octave_class::exemplar_map.find (m_c_name);
 
   if (it != octave_class::exemplar_map.end ())
     retval = true;
@@ -1045,7 +1058,7 @@
 
       octave::symbol_table& symtab = interp.get_symbol_table ();
 
-      octave_value ctor = symtab.find_method (c_name, c_name);
+      octave_value ctor = symtab.find_method (m_c_name, m_c_name);
 
       bool have_ctor = false;
 
@@ -1053,7 +1066,7 @@
         {
           octave_function *fcn = ctor.function_value ();
 
-          if (fcn && fcn->is_class_constructor (c_name))
+          if (fcn && fcn->is_class_constructor (m_c_name))
             have_ctor = true;
 
           // Something has gone terribly wrong if
@@ -1076,7 +1089,7 @@
 
           try
             {
-              result = octave::feval (ctor, ovl (), 1);
+              result = interp.feval (ctor, ovl (), 1);
             }
           catch (const octave::execution_exception&)
             {
@@ -1089,14 +1102,14 @@
             retval = true;
         }
       else
-        warning ("no constructor for class %s", c_name.c_str ());
+        warning ("no constructor for class %s", m_c_name.c_str ());
     }
 
   return retval;
 }
 
 void
-octave_class::clear_exemplar_map (void)
+octave_class::clear_exemplar_map ()
 {
   exemplar_map.clear ();
 }
@@ -1109,7 +1122,7 @@
 //  class structure here so the user's loadobj method has a chance
 //  to do its magic.
 bool
-octave_class::reconstruct_parents (void)
+octave_class::reconstruct_parents ()
 {
   bool retval = true;
   bool might_have_inheritance = false;
@@ -1135,7 +1148,7 @@
   if (might_have_inheritance)
     {
       octave_class::exemplar_const_iterator it
-        = octave_class::exemplar_map.find (c_name);
+        = octave_class::exemplar_map.find (m_c_name);
 
       if (it == octave_class::exemplar_map.end ())
         retval = false;
@@ -1165,12 +1178,15 @@
   os << "# classname: " << class_name () << "\n";
   octave_map m;
 
-  octave::load_path& lp = octave::__get_load_path__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::load_path& lp = interp.get_load_path ();
 
   if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
-      octave_value_list tmp = octave::feval ("saveobj", in, 1);
+
+      octave_value_list tmp = interp.feval ("saveobj", in, 1);
 
       m = tmp(0).map_value ();
     }
@@ -1223,8 +1239,7 @@
           if (! is)
             break;
 
-          Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (
-                          t2));
+          Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2));
 
           m.assign (nm, tcell);
         }
@@ -1232,7 +1247,7 @@
       if (! is)
         error ("load: failed to load class");
 
-      c_name = classname;
+      m_c_name = classname;
       reconstruct_exemplar ();
 
       m_map = m;
@@ -1240,12 +1255,14 @@
       if (! reconstruct_parents ())
         warning ("load: unable to reconstruct object inheritance");
 
-      octave::load_path& lp = octave::__get_load_path__ ();
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
+      octave::load_path& lp = interp.get_load_path ();
 
       if (lp.find_method (classname, "loadobj") != "")
         {
           octave_value in = new octave_class (*this);
-          octave_value_list tmp = octave::feval ("loadobj", in, 1);
+          octave_value_list tmp = interp.feval ("loadobj", in, 1);
 
           m_map = tmp(0).map_value ();
         }
@@ -1253,7 +1270,7 @@
   else if (len == 0)
     {
       m_map = octave_map (dim_vector (1, 1));
-      c_name = classname;
+      m_c_name = classname;
     }
   else
     panic_impossible ();
@@ -1271,12 +1288,14 @@
 
   octave_map m;
 
-  octave::load_path& lp = octave::__get_load_path__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::load_path& lp = interp.get_load_path ();
 
   if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
-      octave_value_list tmp = octave::feval ("saveobj", in, 1);
+      octave_value_list tmp = interp.feval ("saveobj", in, 1);
 
       m = tmp(0).map_value ();
     }
@@ -1321,7 +1340,7 @@
     classname[classname_len] = '\0';
     if (! is.read (reinterpret_cast<char *> (classname), classname_len))
       return false;
-    c_name = classname;
+    m_c_name = classname;
   }
   reconstruct_exemplar ();
 
@@ -1348,8 +1367,7 @@
           if (! is)
             break;
 
-          Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (
-                          t2));
+          Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2));
 
           m.assign (nm, tcell);
         }
@@ -1361,12 +1379,14 @@
           if (! reconstruct_parents ())
             warning ("load: unable to reconstruct object inheritance");
 
-          octave::load_path& lp = octave::__get_load_path__ ();
-
-          if (lp.find_method (c_name, "loadobj") != "")
+          octave::interpreter& interp = octave::__get_interpreter__ ();
+
+          octave::load_path& lp = interp.get_load_path ();
+
+          if (lp.find_method (m_c_name, "loadobj") != "")
             {
               octave_value in = new octave_class (*this);
-              octave_value_list tmp = octave::feval ("loadobj", in, 1);
+              octave_value_list tmp = interp.feval ("loadobj", in, 1);
 
               m_map = tmp(0).map_value ();
             }
@@ -1400,7 +1420,9 @@
   octave_map m;
   octave_map::iterator i;
 
-  octave::load_path& lp = octave::__get_load_path__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::load_path& lp = interp.get_load_path ();
 
 #if defined (HAVE_HDF5_18)
   group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
@@ -1412,7 +1434,7 @@
     goto error_cleanup;
 
   // Add the class name to the group
-  type_hid = H5Tcopy (H5T_C_S1); H5Tset_size (type_hid, c_name.length () + 1);
+  type_hid = H5Tcopy (H5T_C_S1); H5Tset_size (type_hid, m_c_name.length () + 1);
   if (type_hid < 0)
     goto error_cleanup;
 
@@ -1430,7 +1452,7 @@
 #endif
   if (class_hid < 0 || H5Dwrite (class_hid, type_hid, octave_H5S_ALL,
                                  octave_H5S_ALL, octave_H5P_DEFAULT,
-                                 c_name.c_str ()) < 0)
+                                 m_c_name.c_str ()) < 0)
     goto error_cleanup;
 
 #if defined (HAVE_HDF5_18)
@@ -1445,7 +1467,7 @@
   if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
-      octave_value_list tmp = octave::feval ("saveobj", in, 1);
+      octave_value_list tmp = interp.feval ("saveobj", in, 1);
 
       m = tmp(0).map_value ();
     }
@@ -1578,7 +1600,7 @@
       H5Dclose (data_hid);
       data_hid = -1;
 
-      c_name = classname;
+      m_c_name = classname;
     }
   while (0);
   reconstruct_exemplar ();
@@ -1597,8 +1619,7 @@
     {
       octave_value t2 = dsub.tc;
 
-      Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (
-                      t2));
+      Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2));
 
       m.assign (dsub.name, tcell);
 
@@ -1611,12 +1632,14 @@
       if (! reconstruct_parents ())
         warning ("load: unable to reconstruct object inheritance");
 
-      octave::load_path& lp = octave::__get_load_path__ ();
-
-      if (lp.find_method (c_name, "loadobj") != "")
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
+      octave::load_path& lp = interp.get_load_path ();
+
+      if (lp.find_method (m_c_name, "loadobj") != "")
         {
           octave_value in = new octave_class (*this);
-          octave_value_list tmp = octave::feval ("loadobj", in, 1);
+          octave_value_list tmp = interp.feval ("loadobj", in, 1);
 
           m_map = tmp(0).map_value ();
           retval = true;
@@ -1647,7 +1670,7 @@
 }
 
 bool
-octave_class::in_class_method (void)
+octave_class::in_class_method ()
 {
   octave::tree_evaluator& tw = octave::__get_evaluator__ ();
 
@@ -1824,8 +1847,7 @@
 
   octave_value obj = args(0);  // not const because of find_parent_class ()
   std::string obj_cls = obj.class_name ();
-  Array<std::string> clsnames = args(
-                                  1).xcellstr_value ("isa: CLASSNAME must be a string or cell array of strings");
+  Array<std::string> clsnames = args(1).xcellstr_value ("isa: CLASSNAME must be a string or cell array of strings");
 
   boolNDArray matches (clsnames.dims (), false);
 
@@ -2062,13 +2084,9 @@
 
   octave_inline_fcn (octave_inline *obj) : m_inline_obj (obj) { }
 
-  // No copying!
-
-  octave_inline_fcn (const octave_inline_fcn& ob) = delete;
-
-  octave_inline_fcn& operator = (const octave_inline_fcn& ob) = delete;
-
-  ~octave_inline_fcn (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (octave_inline_fcn)
+
+  ~octave_inline_fcn () = default;
 
   // Override default call method because we ultimately use feval to
   // execute the inline function and that will push a stack frame.
@@ -2093,7 +2111,7 @@
 // to eliminate the octave_inline class below and replace the
 // octave_value::is_inline_function method with
 //
-// bool octave_value::is_inline_function (void) const
+// bool octave_value::is_inline_function () const
 // {
 //   return class_name () == "inline";
 // }
@@ -2109,16 +2127,16 @@
 
   octave_inline (const octave_inline&) = default;
 
-  ~octave_inline (void) = default;
-
-  octave_base_value * clone (void) const { return new octave_inline (*this); }
-
-  octave_base_value * empty_clone (void) const
+  ~octave_inline () = default;
+
+  octave_base_value * clone () const { return new octave_inline (*this); }
+
+  octave_base_value * empty_clone () const
   {
     return new octave_inline (octave_map (map_keys ()));
   }
 
-  bool is_inline_function (void) const { return true; }
+  bool is_inline_function () const { return true; }
 
   octave_function * function_value (bool)
   {
--- a/libinterp/octave-value/ov-class.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-class.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,19 +55,19 @@
 {
 public:
 
-  octave_class (void)
-    : octave_base_value (), m_map (), c_name (),
+  octave_class ()
+    : octave_base_value (), m_map (), m_c_name (),
       m_parent_list (), m_obsolete_copies (0)
   { }
 
   octave_class (const octave_map& m, const std::string& id)
-    : octave_base_value (), m_map (m), c_name (id),
+    : octave_base_value (), m_map (m), m_c_name (id),
       m_parent_list (), m_obsolete_copies (0)
   { }
 
   octave_class (const octave_map& m, const std::string& id,
                 const std::list<std::string>& plist)
-    : octave_base_value (), m_map (m), c_name (id),
+    : octave_base_value (), m_map (m), m_c_name (id),
       m_parent_list (plist), m_obsolete_copies (0)
   { }
 
@@ -75,25 +75,25 @@
                 const octave_value_list& parents);
 
   octave_class (const octave_class& s)
-    : octave_base_value (s), m_map (s.m_map), c_name (s.c_name),
+    : octave_base_value (s), m_map (s.m_map), m_c_name (s.m_c_name),
       m_parent_list (s.m_parent_list), m_obsolete_copies (0)  { }
 
-  ~octave_class (void) = default;
+  ~octave_class () = default;
 
-  octave_base_value * clone (void) const { return new octave_class (*this); }
+  octave_base_value * clone () const { return new octave_class (*this); }
 
-  OCTINTERP_API octave_base_value * unique_clone (void);
+  OCTINTERP_API octave_base_value * unique_clone ();
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   {
-    return new octave_class (octave_map (m_map.keys ()), c_name, m_parent_list);
+    return new octave_class (octave_map (m_map.keys ()), m_c_name, m_parent_list);
   }
 
   void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);
 
   OCTINTERP_API Cell dotref (const octave_value_list& idx);
 
-  OCTINTERP_API Matrix size (void);
+  OCTINTERP_API Matrix size ();
 
   OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);
 
@@ -131,21 +131,21 @@
   OCTINTERP_API octave::idx_vector
   index_vector (bool require_integers = false) const;
 
-  dim_vector dims (void) const { return m_map.dims (); }
+  dim_vector dims () const { return m_map.dims (); }
 
-  OCTINTERP_API std::size_t byte_size (void) const;
+  OCTINTERP_API std::size_t byte_size () const;
 
   // This is the number of elements in each field.  The total number
   // of elements is numel () * nfields ().
-  octave_idx_type numel (void) const
+  octave_idx_type numel () const
   {
     dim_vector dv = dims ();
     return dv.numel ();
   }
 
-  octave_idx_type nfields (void) const { return m_map.nfields (); }
+  octave_idx_type nfields () const { return m_map.nfields (); }
 
-  std::size_t nparents (void) const { return m_parent_list.size (); }
+  std::size_t nparents () const { return m_parent_list.size (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   {
@@ -161,22 +161,22 @@
     return octave_value (new octave_class (retval));
   }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool isstruct (void) const { return false; }
+  bool isstruct () const { return false; }
 
-  bool isobject (void) const { return true; }
+  bool isobject () const { return true; }
 
-  OCTINTERP_API bool is_true (void) const;
+  OCTINTERP_API bool is_true () const;
 
-  octave_map map_value (void) const { return m_map; }
+  octave_map map_value () const { return m_map; }
 
-  OCTINTERP_API string_vector map_keys (void) const;
+  OCTINTERP_API string_vector map_keys () const;
 
-  std::list<std::string> parent_class_name_list (void) const
+  std::list<std::string> parent_class_name_list () const
   { return m_parent_list; }
 
-  string_vector parent_class_names (void) const
+  string_vector parent_class_names () const
   { return string_vector (m_parent_list); }
 
   OCTINTERP_API octave_base_value * find_parent_class (const std::string&);
@@ -192,11 +192,11 @@
   OCTINTERP_API void print_raw (std::ostream& os,
                                 bool pr_as_read_syntax = false) const;
 
-  OCTINTERP_API bool reconstruct_exemplar (void);
+  OCTINTERP_API bool reconstruct_exemplar ();
 
-  OCTINTERP_API static void clear_exemplar_map (void);
+  OCTINTERP_API static void clear_exemplar_map ();
 
-  OCTINTERP_API bool reconstruct_parents (void);
+  OCTINTERP_API bool reconstruct_parents ();
 
   OCTINTERP_API bool save_ascii (std::ostream& os);
 
@@ -220,24 +220,24 @@
   octave_map m_map;
 
 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 c_name; }
+  int type_id () const { return s_t_id; }
+  std::string type_name () const { return s_t_name; }
+  std::string class_name () const { return m_c_name; }
 
-  static int static_type_id (void) { return t_id; }
-  static std::string static_type_name (void) { return t_name; }
-  static std::string static_class_name (void) { return "<unknown>"; }
+  static int static_type_id () { return s_t_id; }
+  static std::string static_type_name () { return s_t_name; }
+  static std::string static_class_name () { return "<unknown>"; }
   static OCTINTERP_API void register_type (octave::type_info&);
 
 private:
-  static int t_id;
+  static int s_t_id;
 
-  static const std::string t_name;
-  std::string c_name;
+  static const std::string s_t_name;
+  std::string m_c_name;
   std::list<std::string> m_parent_list;
 
-  OCTINTERP_API bool in_class_method (void);
-  OCTINTERP_API std::string get_current_method_class (void);
+  OCTINTERP_API bool in_class_method ();
+  OCTINTERP_API std::string get_current_method_class ();
 
   OCTINTERP_API octave_value
   subsasgn_common (const octave_value& obj, const std::string& type,
@@ -253,7 +253,7 @@
   {
   public:
 
-    exemplar_info (void) : m_field_names (), m_parent_class_names () { }
+    exemplar_info () : m_field_names (), m_parent_class_names () { }
 
     OCTINTERP_API exemplar_info (const octave_value& obj);
 
@@ -271,13 +271,13 @@
       return *this;
     }
 
-    octave_idx_type nfields (void) const { return m_field_names.numel (); }
+    octave_idx_type nfields () const { return m_field_names.numel (); }
 
-    std::size_t nparents (void) const { return m_parent_class_names.size (); }
+    std::size_t nparents () const { return m_parent_class_names.size (); }
 
-    string_vector fields (void) const { return m_field_names; }
+    string_vector fields () const { return m_field_names; }
 
-    std::list<std::string> parents (void) const { return m_parent_class_names; }
+    std::list<std::string> parents () const { return m_parent_class_names; }
 
     OCTINTERP_API bool compare (const octave_value& obj) const;
 
--- a/libinterp/octave-value/ov-classdef.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-classdef.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,14 +57,14 @@
   return (ctx.ok () && octave::is_superclass (ctx, cls));
 }
 
-int octave_classdef::t_id (-1);
+int octave_classdef::s_t_id (-1);
 
-const std::string octave_classdef::t_name ("object");
+const std::string octave_classdef::s_t_name ("object");
 
 void
 octave_classdef::register_type (octave::type_info& ti)
 {
-  t_id = ti.register_type (octave_classdef::t_name, "<unknown>",
+  s_t_id = ti.register_type (octave_classdef::s_t_name, "<unknown>",
                            octave_value (new octave_classdef ()));
 }
 
@@ -88,11 +88,32 @@
 
           args(1) = make_idx_args (type, idx, "subsref");
 
-          count++;
+          m_count++;
           args(0) = octave_value (this);
 
+          // Attempt to set up a proper value for nargout at least in the
+          // simple case where the cs-list-type expression - i.e., {} or
+          // ().x, is the leading one.
+          bool maybe_cs_list_query = (type[0] == '.' || type[0] == '{'
+                                      || (type.length () > 1 && type[0] == '('
+                                          && type[1] == '.'));
+
+          if (maybe_cs_list_query)
+            {
+              // Set up a proper nargout for the subsref call by calling numel.
+              octave_value_list tmp;
+              if (type[0] != '.') tmp = idx.front ();
+              nargout = xnumel (tmp);
+            }
+
           retval = meth.execute (args, nargout, true, "subsref");
 
+          // Since we're handling subsref, if the list has more than one
+          // element, return it as a comma-separated list so that we can
+          // pass it to the evaluator
+          if (retval.length () > 1)
+            retval = octave_value (retval);
+
           return retval;
         }
     }
@@ -131,7 +152,7 @@
 
           args(1) = make_idx_args (type, idx, "subsref");
 
-          count++;
+          m_count++;
           args(0) = octave_value (this);
 
           retval = meth.execute (args, 1, true, "subsref");
@@ -168,7 +189,7 @@
 
           args(1) = make_idx_args (type, idx, "subsasgn");
 
-          count++;
+          m_count++;
           args(0) = octave_value (this);
           args(2) = rhs;
 
@@ -207,7 +228,7 @@
 }
 
 Matrix
-octave_classdef::size (void)
+octave_classdef::size ()
 {
   octave::cdef_class cls = m_object.get_class ();
 
@@ -217,7 +238,7 @@
 
       if (meth.ok ())
         {
-          count++;
+          m_count++;
           octave_value_list args (1, octave_value (this));
 
           octave_value_list lv = meth.execute (args, 1, true, "size");
@@ -247,7 +268,7 @@
         {
           octave_value_list args (idx.length () + 1, octave_value ());
 
-          count++;
+          m_count++;
           args(0) = octave_value (this);
 
           for (octave_idx_type i = 0; i < idx.length (); i++)
@@ -459,7 +480,7 @@
   return "";
 }
 
-std::string octave_classdef_meta::file_name (void) const
+std::string octave_classdef_meta::file_name () const
 {
   if (m_object.is_class ())
     {
@@ -680,11 +701,8 @@
     {
       // FIXME: this loop duplicates a significant portion of the loops
       // in octave_classdef::print_raw.
-
       const cdef_property& prop = pname_prop.second;
 
-      std::string nm = prop.get_name ();
-
       octave_value acc = prop.get ("GetAccess");
 
       if (! acc.is_string () || acc.string_value () != "public")
@@ -695,7 +713,7 @@
       if (hid.bool_value ())
         continue;
 
-      property_names.push_back (nm);
+      property_names.push_back (pname_prop.first);
     }
 
   if (nargout > 0)
@@ -722,8 +740,8 @@
 
 DEFMETHOD (__methods__, interp, args, ,
            doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{mtds} =} __methods__ (@var{obj})
-@deftypefnx {} {@var{mtds} =} __methods__ ("classname")
+@deftypefn  {} {[@var{mtds}, @var{found}] =} __methods__ (@var{obj})
+@deftypefnx {} {[@var{mtds}, @var{found}] =} __methods__ ("classname")
 Implement @code{methods} for Octave class objects and classnames.
 @seealso{methods}
 @end deftypefn */)
@@ -741,6 +759,7 @@
     err_wrong_type_arg ("__methods__", arg);
 
   string_vector sv;
+  bool found = false;
 
   cdef_class cls = lookup_class (class_name, false, true);
 
@@ -754,12 +773,23 @@
 
       for (const auto& nm_mthd : method_map)
         {
-          std::string nm = nm_mthd.first;
+          const cdef_method& method = nm_mthd.second;
+
+          octave_value acc = method.get ("Access");
+
+          if (! acc.is_string () || acc.string_value () != "public")
+            continue;
 
-          method_names.push_back (nm);
+          octave_value hid = method.get ("Hidden");
+
+          if (hid.bool_value ())
+            continue;
+
+          method_names.push_back (nm_mthd.first);
         }
 
       sv = string_vector (method_names);
+      found = true;
     }
   else
     {
@@ -767,10 +797,16 @@
       load_path& lp = interp.get_load_path ();
 
       sv = string_vector (lp.methods (class_name));
+      found = ! sv.empty ();
     }
 
-  return ovl (Cell (sv));
+  return ovl (Cell (sv), found);
 }
 
+/*
+// BIST tests are in file methods.m
+%!assert (1)
+*/
+
 OCTAVE_END_NAMESPACE(octave)
 
--- a/libinterp/octave-value/ov-classdef.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-classdef.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,41 +48,39 @@
 {
 public:
 
-  octave_classdef (void)
+  octave_classdef ()
     : octave_base_value (), m_object () { }
 
   octave_classdef (const octave::cdef_object& obj)
     : octave_base_value (), m_object (obj) { }
 
-  octave_classdef (const octave_classdef&) = delete;
-
-  octave_classdef& operator = (const octave_classdef&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_classdef)
 
-  ~octave_classdef (void) = default;
+  ~octave_classdef () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new octave_classdef (m_object.clone ());
   }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   {
     return new octave_classdef (m_object.empty_clone ());
   }
 
   octave_classdef * classdef_object_value (bool = false) { return this; }
 
-  octave::cdef_object get_object (void) const { return m_object; }
+  octave::cdef_object get_object () const { return m_object; }
 
-  octave::cdef_object& get_object_ref (void) { return m_object; }
+  octave::cdef_object& get_object_ref () { return m_object; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool isstruct (void) const { return false; }
+  bool isstruct () const { return false; }
 
-  bool isobject (void) const { return true; }
+  bool isobject () const { return true; }
 
-  bool is_classdef_object (void) const { return true; }
+  bool is_classdef_object () const { return true; }
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -120,15 +118,15 @@
                   const std::list<octave_value_list>& idx,
                   const octave_value& rhs);
 
-  OCTINTERP_API Matrix size (void);
+  OCTINTERP_API Matrix size ();
 
   OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);
 
-  string_vector map_keys (void) const { return m_object.map_keys (); }
+  string_vector map_keys () const { return m_object.map_keys (); }
 
-  octave_map map_value (void) const { return m_object.map_value (); }
+  octave_map map_value () const { return m_object.map_value (); }
 
-  dim_vector dims (void) const { return m_object.dims (); }
+  dim_vector dims () const { return m_object.dims (); }
 
   void set_property (octave_idx_type idx, const std::string& name,
                      const octave_value& pval)
@@ -149,22 +147,22 @@
 
 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 m_object.class_name (); }
+  int type_id () const { return s_t_id; }
+  std::string type_name () const { return s_t_name; }
+  std::string class_name () const { return m_object.class_name (); }
 
-  static int static_type_id (void) { return t_id; }
-  static std::string static_type_name (void) { return t_name; }
-  static std::string static_class_name (void) { return "<unknown>"; }
+  static int static_type_id () { return s_t_id; }
+  static std::string static_type_name () { return s_t_name; }
+  static std::string static_class_name () { return "<unknown>"; }
   static OCTINTERP_API void register_type (octave::type_info&);
 
 private:
 
   octave::cdef_object m_object;
 
-  static int t_id;
+  static int s_t_id;
 
-  static const std::string t_name;
+  static const std::string s_t_name;
 };
 
 void install_classdef (octave::interpreter& interp);
@@ -177,15 +175,13 @@
     : m_object (obj)
   { }
 
-  octave_classdef_meta (const octave_classdef_meta&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_classdef_meta)
 
-  octave_classdef_meta& operator = (const octave_classdef_meta&) = delete;
+  ~octave_classdef_meta () { m_object.meta_release (); }
 
-  ~octave_classdef_meta (void) { m_object.meta_release (); }
+  bool is_classdef_meta () const { return true; }
 
-  bool is_classdef_meta (void) const { return true; }
-
-  bool is_package (void) const { return m_object.is_package(); }
+  bool is_package () const { return m_object.is_package(); }
 
   octave_function * function_value (bool = false) { return this; }
 
@@ -232,7 +228,7 @@
 
   OCTINTERP_API std::string doc_string (const std::string& meth_name) const;
 
-  OCTINTERP_API std::string file_name (void) const;
+  OCTINTERP_API std::string file_name () const;
 
 private:
 
@@ -242,20 +238,18 @@
 class octave_classdef_superclass_ref : public octave_function
 {
 public:
-  octave_classdef_superclass_ref (void) = delete;
+  octave_classdef_superclass_ref () = delete;
 
   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_DISABLE_COPY_MOVE (octave_classdef_superclass_ref)
 
-  ~octave_classdef_superclass_ref (void) = default;
+  ~octave_classdef_superclass_ref () = default;
 
-  bool is_classdef_superclass_ref (void) const { return true; }
+  bool is_classdef_superclass_ref () const { return true; }
 
   octave_function * function_value (bool = false) { return this; }
 
--- a/libinterp/octave-value/ov-colon.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-colon.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,27 +49,27 @@
 {
 public:
 
-  octave_magic_colon (void)
+  octave_magic_colon ()
     : octave_base_value () { }
 
   octave_magic_colon (const octave_magic_colon&)
     : octave_base_value () { }
 
-  ~octave_magic_colon (void) = default;
+  ~octave_magic_colon () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_magic_colon (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_magic_colon (); }
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   { return octave::idx_vector (':'); }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_magic_colon (void) const { return true; }
+  bool is_magic_colon () const { return true; }
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
--- a/libinterp/octave-value/ov-complex.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-complex.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -80,19 +80,28 @@
     update_message ();
   }
 
-  ~complex_index_exception (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE (complex_index_exception)
 
-  void update_message (void)
+  ~complex_index_exception () = default;
+
+  void update_message ()
   {
     set_message (expression ()
                  + ": subscripts must be real (forgot to initialize i or j?)");
   }
 
   // ID of error to throw.
-  const char * err_id (void) const
+  const char * err_id () const
   {
     return "Octave:invalid-index";
   }
+
+  index_exception * dup ()
+  {
+    complex_index_exception *retval = new complex_index_exception {*this};
+    retval->set_identifier (retval->err_id ());
+    return retval;
+  }
 };
 
 OCTAVE_END_NAMESPACE(octave)
@@ -106,7 +115,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_complex::numeric_demotion_function (void) const
+octave_complex::numeric_demotion_function () const
 {
   return
     octave_base_value::type_conv_info (default_numeric_demotion_function,
@@ -114,7 +123,7 @@
 }
 
 octave_base_value *
-octave_complex::try_narrowing_conversion (void)
+octave_complex::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -292,13 +301,13 @@
 }
 
 octave_value
-octave_complex::as_double (void) const
+octave_complex::as_double () const
 {
   return scalar;
 }
 
 octave_value
-octave_complex::as_single (void) const
+octave_complex::as_single () const
 {
   return FloatComplex (scalar);
 }
--- a/libinterp/octave-value/ov-complex.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-complex.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_complex (void)
+  octave_complex ()
     : octave_base_scalar<Complex> () { }
 
   octave_complex (const Complex& c)
@@ -63,20 +63,20 @@
   octave_complex (const octave_complex& c)
     : octave_base_scalar<Complex> (c) { }
 
-  ~octave_complex (void) = default;
+  ~octave_complex () = default;
 
-  octave_base_value * clone (void) const { return new octave_complex (*this); }
+  octave_base_value * clone () const { return new octave_complex (*this); }
 
   // We return an octave_complex_matrix object here instead of an
   // octave_complex object so that in expressions like A(2,2,2) = 2
   // (for A previously undefined), A will be empty instead of a 1x1
   // object.
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_complex_matrix (); }
 
-  type_conv_info numeric_demotion_function (void) const;
+  type_conv_info numeric_demotion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
@@ -91,15 +91,15 @@
                   || lo_ieee_isnan (scalar.imag ())));
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_complex; }
+  builtin_type_t builtin_type () const { return btyp_complex; }
 
-  bool is_complex_scalar (void) const { return true; }
+  bool is_complex_scalar () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   OCTINTERP_API double double_value (bool = false) const;
 
@@ -162,8 +162,8 @@
     return boolNDArray (dim_vector (1, 1), scalar != 0.0);
   }
 
-  OCTINTERP_API octave_value as_double (void) const;
-  OCTINTERP_API octave_value as_single (void) const;
+  OCTINTERP_API octave_value as_double () const;
+  OCTINTERP_API octave_value as_single () const;
 
   // We don't need to override both forms of the diag method.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -172,9 +172,9 @@
 
   OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  void increment (void) { scalar += 1.0; }
+  void increment () { scalar += 1.0; }
 
-  void decrement (void) { scalar -= 1.0; }
+  void decrement () { scalar -= 1.0; }
 
   OCTINTERP_API bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-cs-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cs-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 {
 public:
 
-  octave_cs_list (void)
+  octave_cs_list ()
     : octave_base_value (), m_list () { }
 
   octave_cs_list (const octave_value_list& l)
@@ -59,20 +59,20 @@
   octave_cs_list (const octave_cs_list& l)
     : octave_base_value (), m_list (l.m_list) { }
 
-  ~octave_cs_list (void) = default;
+  ~octave_cs_list () = default;
 
-  octave_base_value * clone (void) const { return new octave_cs_list (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_cs_list (); }
+  octave_base_value * clone () const { return new octave_cs_list (*this); }
+  octave_base_value * empty_clone () const { return new octave_cs_list (); }
 
-  dim_vector dims (void) const { return dim_vector (1, m_list.length ()); }
+  dim_vector dims () const { return dim_vector (1, m_list.length ()); }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_cs_list (void) const { return true; }
+  bool is_cs_list () const { return true; }
 
-  octave_value_list list_value (void) const { return m_list; }
+  octave_value_list list_value () const { return m_list; }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
--- a/libinterp/octave-value/ov-cx-diag.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-diag.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_complex_diag_matrix::numeric_conversion_function (void) const
+octave_complex_diag_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info
          (default_numeric_conversion_function,
@@ -71,7 +71,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_complex_diag_matrix::numeric_demotion_function (void) const
+octave_complex_diag_matrix::numeric_demotion_function () const
 {
   return
     octave_base_value::type_conv_info (default_numeric_demotion_function,
@@ -79,7 +79,7 @@
 }
 
 octave_base_value *
-octave_complex_diag_matrix::try_narrowing_conversion (void)
+octave_complex_diag_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -142,13 +142,13 @@
 }
 
 octave_value
-octave_complex_diag_matrix::as_double (void) const
+octave_complex_diag_matrix::as_double () const
 {
   return m_matrix;
 }
 
 octave_value
-octave_complex_diag_matrix::as_single (void) const
+octave_complex_diag_matrix::as_single () const
 {
   return FloatComplexDiagMatrix (m_matrix);
 }
--- a/libinterp/octave-value/ov-cx-diag.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-diag.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 {
 public:
 
-  octave_complex_diag_matrix (void)
+  octave_complex_diag_matrix ()
     : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> () { }
 
   octave_complex_diag_matrix (const ComplexDiagMatrix& m)
@@ -50,28 +50,28 @@
   octave_complex_diag_matrix (const octave_complex_diag_matrix& m)
     : octave_base_diag<ComplexDiagMatrix, ComplexMatrix> (m) { }
 
-  ~octave_complex_diag_matrix (void) = default;
+  ~octave_complex_diag_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_complex_diag_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_complex_diag_matrix (); }
 
-  OCTINTERP_API type_conv_info numeric_conversion_function (void) const;
+  OCTINTERP_API type_conv_info numeric_conversion_function () const;
 
-  OCTINTERP_API type_conv_info numeric_demotion_function (void) const;
+  OCTINTERP_API type_conv_info numeric_demotion_function () const;
 
-  OCTINTERP_API octave_base_value * try_narrowing_conversion (void);
+  OCTINTERP_API octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_complex; }
+  builtin_type_t builtin_type () const { return btyp_complex; }
 
-  bool is_complex_matrix (void) const { return true; }
+  bool is_complex_matrix () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   OCTINTERP_API DiagMatrix diag_matrix_value (bool = false) const;
 
@@ -83,8 +83,8 @@
   OCTINTERP_API FloatComplexDiagMatrix
   float_complex_diag_matrix_value (bool = false) const;
 
-  OCTINTERP_API octave_value as_double (void) const;
-  OCTINTERP_API octave_value as_single (void) const;
+  OCTINTERP_API octave_value as_double () const;
+  OCTINTERP_API octave_value as_single () const;
 
   OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-cx-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -79,7 +79,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_complex_matrix::numeric_demotion_function (void) const
+octave_complex_matrix::numeric_demotion_function () const
 {
   return octave_base_value::type_conv_info
          (default_numeric_demotion_function,
@@ -87,7 +87,7 @@
 }
 
 octave_base_value *
-octave_complex_matrix::try_narrowing_conversion (void)
+octave_complex_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -281,13 +281,13 @@
 }
 
 octave_value
-octave_complex_matrix::as_double (void) const
+octave_complex_matrix::as_double () const
 {
   return m_matrix;
 }
 
 octave_value
-octave_complex_matrix::as_single (void) const
+octave_complex_matrix::as_single () const
 {
   return FloatComplexNDArray (m_matrix);
 }
@@ -613,7 +613,7 @@
 
   if (retval)
     {
-      Complex *mtmp = m.fortran_vec ();
+      const Complex *mtmp = m.data ();
       if (H5Dwrite (data_hid, complex_type_hid, octave_H5S_ALL, octave_H5S_ALL,
                     octave_H5P_DEFAULT, mtmp)
           < 0)
--- a/libinterp/octave-value/ov-cx-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_complex_matrix (void)
+  octave_complex_matrix ()
     : octave_base_matrix<ComplexNDArray> () { }
 
   octave_complex_matrix (const ComplexNDArray& m)
@@ -81,26 +81,26 @@
   octave_complex_matrix (const octave_complex_matrix& cm)
     : octave_base_matrix<ComplexNDArray> (cm) { }
 
-  ~octave_complex_matrix (void) = default;
+  ~octave_complex_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_complex_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_complex_matrix (); }
 
-  type_conv_info numeric_demotion_function (void) const;
+  type_conv_info numeric_demotion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_complex; }
+  builtin_type_t builtin_type () const { return btyp_complex; }
 
-  bool is_complex_matrix (void) const { return true; }
+  bool is_complex_matrix () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -138,18 +138,18 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
   octave_value diag (octave_idx_type k = 0) const;
 
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  void increment (void) { m_matrix += Complex (1.0); }
+  void increment () { m_matrix += Complex (1.0); }
 
-  void decrement (void) { m_matrix -= Complex (1.0); }
+  void decrement () { m_matrix -= Complex (1.0); }
 
-  void changesign (void) { m_matrix.changesign (); }
+  void changesign () { m_matrix.changesign (); }
 
   bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-cx-sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -58,7 +58,7 @@
                                      "sparse complex matrix", "double");
 
 octave_base_value *
-octave_sparse_complex_matrix::try_narrowing_conversion (void)
+octave_sparse_complex_matrix::try_narrowing_conversion ()
 {
   return (matrix.all_elements_are_real ()
           ? new octave_sparse_matrix (::real (matrix)) : nullptr);
@@ -173,7 +173,7 @@
 }
 
 octave_value
-octave_sparse_complex_matrix::as_double (void) const
+octave_sparse_complex_matrix::as_double () const
 {
   return this->matrix;
 }
--- a/libinterp/octave-value/ov-cx-sparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 public:
 
-  octave_sparse_complex_matrix (void)
+  octave_sparse_complex_matrix ()
     : octave_base_sparse<SparseComplexMatrix> () { }
 
   octave_sparse_complex_matrix (const ComplexNDArray& m)
@@ -86,24 +86,24 @@
   octave_sparse_complex_matrix (const octave_sparse_complex_matrix& cm)
     : octave_base_sparse<SparseComplexMatrix> (cm) { }
 
-  ~octave_sparse_complex_matrix (void) = default;
+  ~octave_sparse_complex_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_sparse_complex_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_sparse_complex_matrix (); }
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_complex; }
+  builtin_type_t builtin_type () const { return btyp_complex; }
 
-  bool is_complex_matrix (void) const { return true; }
+  bool is_complex_matrix () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -127,18 +127,7 @@
 
   SparseBoolMatrix sparse_bool_matrix_value (bool warn = false) const;
 
-  octave_value as_double (void) const;
-
-#if 0
-  int write (octave::stream& os, int block_size,
-             oct_data_conv::data_type output_type, int skip,
-             octave::mach_info::float_format flt_fmt) const
-  {
-    // Yes, for compatibility, we drop the imaginary part here.
-    return os.write (matrix_value (true), block_size, output_type,
-                     skip, flt_fmt);
-  }
-#endif
+  octave_value as_double () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-dld-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-dld-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -83,7 +83,7 @@
        && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
 }
 
-octave_dld_function::~octave_dld_function (void)
+octave_dld_function::~octave_dld_function ()
 {
   octave::dynamic_loader& dyn_loader = octave::__get_dynamic_loader__ ();
 
@@ -91,13 +91,13 @@
 }
 
 std::string
-octave_dld_function::fcn_file_name (void) const
+octave_dld_function::fcn_file_name () const
 {
   return m_sh_lib.file_name ();
 }
 
 octave::sys::time
-octave_dld_function::time_parsed (void) const
+octave_dld_function::time_parsed () const
 {
   return m_sh_lib.time_loaded ();
 }
--- a/libinterp/octave-value/ov-dld-fcn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-dld-fcn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 {
 public:
 
-  octave_dld_function (void)
+  octave_dld_function ()
     : m_sh_lib (), m_time_checked (), m_system_fcn_file ()
   { }
 
@@ -61,28 +61,24 @@
                        const std::string& nm = "",
                        const std::string& ds = "");
 
-  // No copying!
-
-  octave_dld_function (const octave_dld_function& fcn) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_dld_function)
 
-  octave_dld_function& operator = (const octave_dld_function& fcn) = delete;
-
-  ~octave_dld_function (void);
+  ~octave_dld_function ();
 
   void mark_fcn_file_up_to_date (const octave::sys::time& t)
   { m_time_checked = t; }
 
-  std::string fcn_file_name (void) const;
+  std::string fcn_file_name () const;
 
-  octave::sys::time time_parsed (void) const;
+  octave::sys::time time_parsed () const;
 
-  octave::sys::time time_checked (void) const { return m_time_checked; }
+  octave::sys::time time_checked () const { return m_time_checked; }
 
-  bool is_system_fcn_file (void) const { return m_system_fcn_file; }
+  bool is_system_fcn_file () const { return m_system_fcn_file; }
 
-  bool is_builtin_function (void) const { return false; }
+  bool is_builtin_function () const { return false; }
 
-  bool is_dld_function (void) const { return true; }
+  bool is_dld_function () const { return true; }
 
   static octave_dld_function * create (octave_builtin::fcn ff,
                                       const octave::dynamic_library& shl,
@@ -94,7 +90,7 @@
                                       const std::string& nm = "",
                                       const std::string& ds = "");
 
-  octave::dynamic_library get_shlib (void) const
+  octave::dynamic_library get_shlib () const
   { return m_sh_lib; }
 
 private:
--- a/libinterp/octave-value/ov-fcn-handle.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -90,18 +90,18 @@
 {
 public:
 
-  invalid_fcn_handle (void) : base_fcn_handle ("<invalid>") { }
+  invalid_fcn_handle () : base_fcn_handle ("<invalid>") { }
 
   invalid_fcn_handle (const invalid_fcn_handle&) = default;
 
-  ~invalid_fcn_handle (void) = default;
-
-  invalid_fcn_handle * clone (void) const
+  ~invalid_fcn_handle () = default;
+
+  invalid_fcn_handle * clone () const
   {
     return new invalid_fcn_handle (*this);
   }
 
-  std::string type (void) const { return "<invalid>"; }
+  std::string type () const { return "<invalid>"; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 };
@@ -120,16 +120,16 @@
 
   internal_fcn_handle (const internal_fcn_handle&) = default;
 
-  ~internal_fcn_handle (void) = default;
-
-  internal_fcn_handle * clone (void) const
+  ~internal_fcn_handle () = default;
+
+  internal_fcn_handle * clone () const
   {
     return new internal_fcn_handle (*this);
   }
 
-  std::string type (void) const { return "<internal>"; }
-
-  bool is_internal (void) const { return true; }
+  std::string type () const { return "<internal>"; }
+
+  bool is_internal () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
@@ -145,10 +145,10 @@
     return m_fcn.user_function_value ();
   }
 
-  octave_value fcn_val (void) { return m_fcn; }
+  octave_value fcn_val () { return m_fcn; }
 
   // Should be const.
-  octave_scalar_map info (void);
+  octave_scalar_map info ();
 
   friend bool is_equal_to (const internal_fcn_handle& fh1,
                            const internal_fcn_handle& fh2);
@@ -185,16 +185,16 @@
 
   simple_fcn_handle (const simple_fcn_handle&) = default;
 
-  ~simple_fcn_handle (void) = default;
-
-  simple_fcn_handle * clone (void) const
+  ~simple_fcn_handle () = default;
+
+  simple_fcn_handle * clone () const
   {
     return new simple_fcn_handle (*this);
   }
 
-  std::string type (void) const { return "simple"; }
-
-  bool is_simple (void) const { return true; }
+  std::string type () const { return "simple"; }
+
+  bool is_simple () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
@@ -204,10 +204,10 @@
 
   octave_user_function * user_function_value (bool);
 
-  octave_value fcn_val (void);
+  octave_value fcn_val ();
 
   // Should be const.
-  octave_scalar_map info (void);
+  octave_scalar_map info ();
 
   bool save_ascii (std::ostream& os);
 
@@ -229,9 +229,17 @@
   friend bool is_equal_to (const simple_fcn_handle& fh1,
                            const simple_fcn_handle& fh2);
 
+  octave_function *
+  get_cached_fcn (const octave_value_list &args);
+
+  bool has_function_cache (void) const;
+
 private:
 
   octave_value m_fcn;
+
+  // Only used by the VM via get_cached_fcn() and has_function_cache()
+  octave_fcn_cache m_cache;
 };
 
 class scoped_fcn_handle : public base_fcn_handle
@@ -252,16 +260,16 @@
 
   scoped_fcn_handle (const scoped_fcn_handle&) = default;
 
-  ~scoped_fcn_handle (void) = default;
-
-  scoped_fcn_handle * clone (void) const
+  ~scoped_fcn_handle () = default;
+
+  scoped_fcn_handle * clone () const
   {
     return new scoped_fcn_handle (*this);
   }
 
-  std::string type (void) const { return "scopedfunction"; }
-
-  bool is_scoped (void) const { return true; }
+  std::string type () const { return "scopedfunction"; }
+
+  bool is_scoped () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
@@ -277,10 +285,10 @@
     return m_fcn.user_function_value ();
   }
 
-  octave_value fcn_val (void) { return m_fcn; }
+  octave_value fcn_val () { return m_fcn; }
 
   // Should be const.
-  octave_scalar_map info (void);
+  octave_scalar_map info ();
 
   bool save_ascii (std::ostream& os);
 
@@ -304,7 +312,7 @@
 
 protected:
 
-  void find_function (void);
+  void find_function ();
 
   // The function we are handling.
   octave_value m_fcn;
@@ -331,11 +339,11 @@
     : base_fcn_handle (name), m_fcn (fcn)
   { }
 
-  std::string type (void) const { return "nested"; }
+  std::string type () const { return "nested"; }
 
   using base_fcn_handle::is_nested;
 
-  bool is_nested (void) const { return true; }
+  bool is_nested () const { return true; }
 
   // FIXME: These must go away.  They don't do the right thing for
   // scoping or overloads.
@@ -349,12 +357,12 @@
     return m_fcn.user_function_value ();
   }
 
-  octave_value fcn_val (void) { return m_fcn; }
-
-  virtual octave_value workspace (void) const = 0;
+  octave_value fcn_val () { return m_fcn; }
+
+  virtual octave_value workspace () const = 0;
 
   // Should be const.
-  octave_scalar_map info (void);
+  octave_scalar_map info ();
 
   bool save_ascii (std::ostream& os);
 
@@ -402,7 +410,7 @@
 
   nested_fcn_handle (const nested_fcn_handle&) = default;
 
-  ~nested_fcn_handle (void) = default;
+  ~nested_fcn_handle () = default;
 
   using base_nested_fcn_handle::is_nested;
 
@@ -411,21 +419,21 @@
     return frame == m_stack_context;
   }
 
-  nested_fcn_handle * clone (void) const
+  nested_fcn_handle * clone () const
   {
     return new nested_fcn_handle (*this);
   }
 
-  octave_value make_weak_nested_handle (void) const;
+  octave_value make_weak_nested_handle () const;
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
-  octave_value workspace (void) const;
+  octave_value workspace () const;
 
   friend bool is_equal_to (const nested_fcn_handle& fh1,
                            const nested_fcn_handle& fh2);
 
-  std::shared_ptr<stack_frame> stack_context (void) const
+  std::shared_ptr<stack_frame> stack_context () const
   {
     return m_stack_context;
   }
@@ -446,18 +454,18 @@
 
   weak_nested_fcn_handle (const weak_nested_fcn_handle&) = default;
 
-  ~weak_nested_fcn_handle (void) = default;
-
-  weak_nested_fcn_handle * clone (void) const
+  ~weak_nested_fcn_handle () = default;
+
+  weak_nested_fcn_handle * clone () const
   {
     return new weak_nested_fcn_handle (*this);
   }
 
-  bool is_weak_nested (void) const { return true; }
+  bool is_weak_nested () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
-  octave_value workspace (void) const;
+  octave_value workspace () const;
 
   friend bool is_equal_to (const weak_nested_fcn_handle& fh1,
                            const weak_nested_fcn_handle& fh2);
@@ -497,16 +505,16 @@
 
   class_simple_fcn_handle (const class_simple_fcn_handle&) = default;
 
-  ~class_simple_fcn_handle (void) = default;
-
-  class_simple_fcn_handle * clone (void) const
+  ~class_simple_fcn_handle () = default;
+
+  class_simple_fcn_handle * clone () const
   {
     return new class_simple_fcn_handle (*this);
   }
 
-  std::string type (void) const { return "classsimple"; }
-
-  bool is_class_simple (void) const { return true; }
+  std::string type () const { return "classsimple"; }
+
+  bool is_class_simple () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
@@ -540,12 +548,12 @@
     return m_fcn.user_function_value ();
   }
 
-  octave_value fcn_val (void) { return m_fcn; }
+  octave_value fcn_val () { return m_fcn; }
 
   // Should be const.
-  octave_scalar_map info (void);
-
-  std::string dispatch_class (void) const { return m_dispatch_class; }
+  octave_scalar_map info ();
+
+  std::string dispatch_class () const { return m_dispatch_class; }
 
   bool save_ascii (std::ostream& os);
 
@@ -627,11 +635,11 @@
 
   base_anonymous_fcn_handle (const base_anonymous_fcn_handle&) = default;
 
-  ~base_anonymous_fcn_handle (void) = default;
-
-  std::string type (void) const { return "anonymous"; }
-
-  bool is_anonymous (void) const { return true; }
+  ~base_anonymous_fcn_handle () = default;
+
+  std::string type () const { return "anonymous"; }
+
+  bool is_anonymous () const { return true; }
 
   // FIXME: These must go away.  They don't do the right thing for
   // scoping or overloads.
@@ -645,12 +653,12 @@
     return m_fcn.user_function_value ();
   }
 
-  octave_value fcn_val (void) { return m_fcn; }
-
-  virtual octave_value workspace (void) const = 0;
+  octave_value fcn_val () { return m_fcn; }
+
+  virtual octave_value workspace () const = 0;
 
   // Should be const.
-  octave_scalar_map info (void);
+  octave_scalar_map info ();
 
   bool save_ascii (std::ostream& os);
 
@@ -670,10 +678,19 @@
                   int current_print_indent_level) const;
 
   // Anonymous function handles are printed without a newline.
-  bool print_as_scalar (void) const { return false; }
+  bool print_as_scalar () const { return false; }
 
   bool parse (const std::string& fcn_text);
 
+  octave_function *
+  get_cached_fcn (const octave_value_list&) { return m_fcn.function_value (); }
+  // TODO: This is a hack to get uncompiled anonymous functions to be subsrefed in the VM
+  bool has_function_cache (void) const
+  {
+    octave_function *fn = m_fcn.function_value ();
+    return fn ? fn->is_compiled () : false;
+  }
+
 protected:
 
   // The function we are handling.
@@ -704,23 +721,23 @@
 
   anonymous_fcn_handle (const anonymous_fcn_handle&) = default;
 
-  ~anonymous_fcn_handle (void) = default;
-
-  anonymous_fcn_handle * clone (void) const
+  ~anonymous_fcn_handle () = default;
+
+  anonymous_fcn_handle * clone () const
   {
     return new anonymous_fcn_handle (*this);
   }
 
-  octave_value make_weak_anonymous_handle (void) const;
+  octave_value make_weak_anonymous_handle () const;
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
-  octave_value workspace (void) const;
+  octave_value workspace () const;
 
   friend bool is_equal_to (const anonymous_fcn_handle& fh1,
                            const anonymous_fcn_handle& fh2);
 
-  std::shared_ptr<stack_frame> stack_context (void) const
+  std::shared_ptr<stack_frame> stack_context () const
   {
     return m_stack_context;
   }
@@ -743,18 +760,18 @@
 
   weak_anonymous_fcn_handle (const weak_anonymous_fcn_handle&) = default;
 
-  ~weak_anonymous_fcn_handle (void) = default;
-
-  weak_anonymous_fcn_handle * clone (void) const
+  ~weak_anonymous_fcn_handle () = default;
+
+  weak_anonymous_fcn_handle * clone () const
   {
     return new weak_anonymous_fcn_handle (*this);
   }
 
-  bool is_weak_anonymous (void) const { return true; }
+  bool is_weak_anonymous () const { return true; }
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
-  octave_value workspace (void) const;
+  octave_value workspace () const;
 
   friend bool is_equal_to (const weak_anonymous_fcn_handle& fh1,
                            const weak_anonymous_fcn_handle& fh2);
@@ -774,14 +791,14 @@
          name.c_str ());
 }
 
-octave_value base_fcn_handle::make_weak_nested_handle (void) const
+octave_value base_fcn_handle::make_weak_nested_handle () const
 {
   std::string type_str = type ();
   error ("invalid conversion from %s handle to weak nestead handle",
          type_str.c_str ());
 }
 
-octave_value base_fcn_handle::make_weak_anonymous_handle (void) const
+octave_value base_fcn_handle::make_weak_anonymous_handle () const
 {
   std::string type_str = type ();
   error ("invalid conversion from %s handle to weak anonymous handle",
@@ -921,7 +938,7 @@
   return interp.feval (m_fcn, args, nargout);
 }
 
-octave_scalar_map internal_fcn_handle::info (void)
+octave_scalar_map internal_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -942,6 +959,205 @@
     return false;
 }
 
+// FIXME: Find a way to avoid duplication of code in
+// simple_fcn_handle::call
+octave_function *
+simple_fcn_handle::
+get_cached_fcn (const octave_value_list &args)
+{
+  if (m_cache.has_cached_function (args))
+    return m_cache.get_cached_fcn ();
+
+  {
+    // The lookup is done like in call()
+    interpreter& interp = __get_interpreter__ ();
+    symbol_table& symtab = interp.get_symbol_table ();
+
+    octave_value fcn_to_call;
+    octave_value ov_fcn = symtab.find_function (m_name, args);
+
+    if (m_fcn.is_defined ())
+      {
+        // A simple function was found when the handle was created.
+        // Use that unless we find a class method to override it.
+
+        fcn_to_call = m_fcn;
+
+        if (ov_fcn.is_defined ())
+          {
+            octave_function *fcn = ov_fcn.function_value ();
+
+            std::string dispatch_class = fcn->dispatch_class ();
+
+            if (fcn->is_class_method ())
+              {
+                // Function found through lookup is a class method
+                // so use it instead of the simple one found when
+                // the handle was created.
+
+                fcn_to_call = ov_fcn;
+              }
+          }
+      }
+    else
+      {
+        // There was no simple function found when the handle was
+        // created so use the one found here (if any).
+
+        fcn_to_call = ov_fcn;
+      }
+
+
+    if (! fcn_to_call.is_defined ())
+      err_invalid_fcn_handle (m_name);
+
+    m_cache.set_cached_function (fcn_to_call, args, 0);
+
+    return fcn_to_call.function_value ();
+  }
+}
+
+// FIXME: Find a way to avoid duplication of code in
+// simple_fcn_handle::call
+// Like call(), but instead returns true if the call() would end
+// up with another call(), or false if there would be a subsref()
+// or an error on the path to subsref() call.
+bool
+simple_fcn_handle::has_function_cache () const
+{
+  // 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.
+
+  interpreter& interp = __get_interpreter__ ();
+
+  octave_value fcn_to_call;
+
+  // The following code is similar to part of
+  // tree_evaluator::visit_index_expression but simpler because it
+  // handles a more restricted case.
+
+  symbol_table& symtab = interp.get_symbol_table ();
+
+  std::size_t pos = m_name.find ('.');
+
+  if (pos != std::string::npos)
+    {
+      // FIXME: check to see which of these cases actually work in
+      // Octave and Matlab.  For the last two, assume handle is
+      // created before object is defined as an object.
+      //
+      // We can have one of
+      //
+      //   pkg-list . fcn  (args)
+      //   pkg-list . cls . meth (args)
+      //   class-name . method  (args)
+      //   class-name . static-method  (args)
+      //   object . method  (args)
+      //   object . static-method  (args)
+
+      // 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.
+
+      std::size_t beg = 0;
+      std::size_t end = pos;
+
+      std::vector<std::string> idx_elts;
+
+      while (true)
+        {
+          end = m_name.find ('.', beg);
+
+          idx_elts.push_back (m_name.substr (beg, end-beg));
+
+          if (end == std::string::npos)
+            break;
+
+          beg = end+1;
+        }
+
+      std::size_t n_elts = idx_elts.size ();
+
+      bool have_object = false;
+      octave_value partial_expr_val;
+
+      // 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)
+            return false;
+
+          have_object = true;
+        }
+      else
+        partial_expr_val = symtab.find_function (idx_elts[0], ovl ());
+
+      std::string type;
+      std::list<octave_value_list> arg_list;
+
+      for (std::size_t i = 1; i < n_elts; i++)
+        {
+          if (partial_expr_val.is_package ())
+            {
+              if (have_object)
+                return false;
+
+              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);
+
+                  partial_expr_val
+                    = tmp_list.length () ? tmp_list(0) : octave_value ();
+
+                  if (partial_expr_val.is_cs_list ())
+                    return false;
+
+                  arg_list.clear ();
+                }
+              catch (const index_exception&)
+                {
+                  return false;
+                }
+            }
+          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.
+              return false;
+            }
+          else
+            return false;
+        }
+
+      // If we get here, we must have a function to call.
+
+      if (! partial_expr_val.is_function ())
+        return false;
+
+      return true;
+    }
+  else
+    {
+      return true;
+    }
+}
+
 octave_value_list
 simple_fcn_handle::call (int nargout, const octave_value_list& args)
 {
@@ -1166,7 +1382,7 @@
   return m_fcn.is_defined () ? m_fcn.user_function_value () : nullptr;
 }
 
-octave_value simple_fcn_handle::fcn_val (void)
+octave_value simple_fcn_handle::fcn_val ()
 {
   if (m_fcn.is_defined ())
     return m_fcn;
@@ -1182,7 +1398,7 @@
   return m_fcn;
 }
 
-octave_scalar_map simple_fcn_handle::info (void)
+octave_scalar_map simple_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -1476,7 +1692,7 @@
   return interp.feval (m_fcn, args, nargout);
 }
 
-octave_scalar_map scoped_fcn_handle::info (void)
+octave_scalar_map scoped_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -1631,7 +1847,7 @@
     return false;
 }
 
-void scoped_fcn_handle::find_function (void)
+void scoped_fcn_handle::find_function ()
 {
   // Since a scoped function is not visible by itself, try to load the
   // file named in m_file then find and define the scoped function.
@@ -1688,7 +1904,7 @@
     }
 }
 
-octave_scalar_map base_nested_fcn_handle::info (void)
+octave_scalar_map base_nested_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -1807,7 +2023,7 @@
                          current_print_indent_level);
 }
 
-octave_value nested_fcn_handle::make_weak_nested_handle (void) const
+octave_value nested_fcn_handle::make_weak_nested_handle () const
 {
   return octave_value (new octave_fcn_handle
                        (new weak_nested_fcn_handle (*this)));
@@ -1827,7 +2043,7 @@
   return oct_usr_fcn->execute (tw, nargout, args);
 }
 
-octave_value nested_fcn_handle::workspace (void) const
+octave_value nested_fcn_handle::workspace () const
 {
   return m_stack_context->workspace ();
 }
@@ -1857,7 +2073,7 @@
   return oct_usr_fcn->execute (tw, nargout, args);
 }
 
-octave_value weak_nested_fcn_handle::workspace (void) const
+octave_value weak_nested_fcn_handle::workspace () const
 {
   std::shared_ptr<stack_frame> frames = m_stack_context.lock ();
 
@@ -1925,7 +2141,7 @@
   return interp.feval (fcn_name (), args, nargout);
 }
 
-octave_scalar_map class_simple_fcn_handle::info (void)
+octave_scalar_map class_simple_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -2054,7 +2270,7 @@
 
 const std::string base_anonymous_fcn_handle::anonymous ("@<anonymous>");
 
-octave_scalar_map base_anonymous_fcn_handle::info (void)
+octave_scalar_map base_anonymous_fcn_handle::info ()
 {
   octave_scalar_map m;
 
@@ -2694,7 +2910,7 @@
     m_stack_context->mark_closure_context ();
 }
 
-octave_value anonymous_fcn_handle::make_weak_anonymous_handle (void) const
+octave_value anonymous_fcn_handle::make_weak_anonymous_handle () const
 {
   return octave_value (new octave_fcn_handle
                        (new weak_anonymous_fcn_handle (*this)));
@@ -2714,7 +2930,7 @@
   return oct_usr_fcn->execute (tw, nargout, args);
 }
 
-octave_value anonymous_fcn_handle::workspace (void) const
+octave_value anonymous_fcn_handle::workspace () const
 {
   octave_scalar_map local_vars_map;
 
@@ -2768,7 +2984,7 @@
   return oct_usr_fcn->execute (tw, nargout, args);
 }
 
-octave_value weak_anonymous_fcn_handle::workspace (void) const
+octave_value weak_anonymous_fcn_handle::workspace () const
 {
   octave_scalar_map local_vars_map;
 
@@ -2813,7 +3029,7 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-octave_fcn_handle::octave_fcn_handle (void)
+octave_fcn_handle::octave_fcn_handle ()
   : octave_base_value (), m_rep (new octave::invalid_fcn_handle ())
 { }
 
@@ -2883,7 +3099,7 @@
 }
 
 dim_vector
-octave_fcn_handle::dims (void) const
+octave_fcn_handle::dims () const
 {
   static dim_vector dv (1, 1);
   return dv;
@@ -3459,8 +3675,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  octave_fcn_handle *fh = args(
-                            0).xfcn_handle_value ("functions: FCN_HANDLE argument must be a function handle object");
+  octave_fcn_handle *fh = args(0).xfcn_handle_value ("functions: FCN_HANDLE argument must be a function handle object");
 
   return ovl (fh->info ());
 }
@@ -3476,8 +3691,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  octave_fcn_handle *fh = args(
-                            0).xfcn_handle_value ("func2str: FCN_HANDLE argument must be a function handle object");
+  octave_fcn_handle *fh = args(0).xfcn_handle_value ("func2str: FCN_HANDLE argument must be a function handle object");
 
   if (! fh)
     error ("func2str: FCN_HANDLE must be a valid function handle");
@@ -3527,8 +3741,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  std::string nm
-    = args(0).xstring_value ("str2func: FCN_NAME must be a string");
+  std::string nm = args(0).xstring_value ("str2func: FCN_NAME must be a string");
 
   if (nm.empty ())
     error ("str2func: invalid function name");
--- a/libinterp/octave-value/ov-fcn-handle.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.h	Fri Jun 23 20:51:51 2023 +0200
@@ -58,40 +58,40 @@
 
   base_fcn_handle (const base_fcn_handle&) = default;
 
-  virtual ~base_fcn_handle (void) = default;
+  virtual ~base_fcn_handle () = default;
 
-  virtual base_fcn_handle * clone (void) const = 0;
+  virtual base_fcn_handle * clone () const = 0;
 
-  virtual std::string type (void) const = 0;
+  virtual std::string type () const = 0;
 
-  virtual bool is_internal (void) const { return false; }
+  virtual bool is_internal () const { return false; }
 
-  virtual bool is_simple (void) const { return false; }
+  virtual bool is_simple () const { return false; }
 
-  virtual bool is_scoped (void) const { return false; }
+  virtual bool is_scoped () const { return false; }
 
-  virtual bool is_nested (void) const { return false; }
+  virtual bool is_nested () const { return false; }
 
   virtual bool is_nested (const std::shared_ptr<stack_frame>&) const
   {
     return false;
   }
 
-  virtual bool is_weak_nested (void) const { return false; }
+  virtual bool is_weak_nested () const { return false; }
 
-  virtual bool is_class_simple (void) const { return false; }
+  virtual bool is_class_simple () const { return false; }
 
-  virtual bool is_anonymous (void) const { return false; }
+  virtual bool is_anonymous () const { return false; }
 
-  virtual bool is_weak_anonymous (void) const { return false; }
+  virtual bool is_weak_anonymous () const { return false; }
 
-  virtual octave_value make_weak_nested_handle (void) const;
+  virtual octave_value make_weak_nested_handle () const;
 
-  virtual octave_value make_weak_anonymous_handle (void) const;
+  virtual octave_value make_weak_anonymous_handle () const;
 
-  std::string fcn_name (void) const { return m_name; }
+  std::string fcn_name () const { return m_name; }
 
-  std::string file (void) const { return m_file; }
+  std::string file () const { return m_file; }
 
   octave_value_list
   subsref (const std::string& type, const std::list<octave_value_list>& idx,
@@ -112,16 +112,16 @@
     return nullptr;
   }
 
-  virtual octave_value fcn_val (void) { return octave_value (); }
+  virtual octave_value fcn_val () { return octave_value (); }
 
-  virtual octave_value workspace (void) const { return octave_value (); }
+  virtual octave_value workspace () const { return octave_value (); }
 
   // Should be const.
-  virtual octave_scalar_map info (void) { return octave_scalar_map (); }
+  virtual octave_scalar_map info () { return octave_scalar_map (); }
 
   virtual void set_dispatch_class (const std::string& /*class_name*/) { }
 
-  virtual std::string get_dispatch_class (void) const { return ""; }
+  virtual std::string get_dispatch_class () const { return ""; }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
@@ -146,7 +146,7 @@
   { }
 
   // Function handles are printed without a newline by default.
-  virtual bool print_as_scalar (void) const { return true; }
+  virtual bool print_as_scalar () const { return true; }
 
   virtual bool
   set_fcn (const std::string& /*octaveroot*/, const std::string& /*fpath*/)
@@ -154,6 +154,11 @@
     return false;
   }
 
+  virtual octave_function *
+  get_cached_fcn (const octave_value_list&) { return nullptr; }
+  virtual bool
+  has_function_cache (void) const { return false; }
+
 protected:
 
   void warn_load (const char *file_type) const;
@@ -182,7 +187,7 @@
   // Creates an invalid function handle.  Used to create generic
   // function handle objects when loading function handles.  Further
   // dispatch happens in the octave_fcn_handle load/save functions.
-  octave_fcn_handle (void);
+  octave_fcn_handle ();
 
   // Create a handle to a built-in or internal function.
   octave_fcn_handle (const octave_value& fcn);
@@ -221,18 +226,23 @@
                      const std::shared_ptr<octave::stack_frame>& closure_frames
                      = std::shared_ptr<octave::stack_frame> ());
 
+  // Create a simple function handle that is not bound to a function.
+  // Lookup happens when a function call is attempted and the function
+  // lookup is cached in a octave_fcn_cache.
+  octave_fcn_handle (const std::string& name, octave_value cache);
+
   octave_fcn_handle (octave::base_fcn_handle *rep);
 
   octave_fcn_handle (const octave_fcn_handle& fh);
 
-  ~octave_fcn_handle (void) = default;
+  ~octave_fcn_handle () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new octave_fcn_handle (*this);
   }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   {
     return new octave_fcn_handle ();
   }
@@ -258,44 +268,44 @@
 
   octave_value_list call (int nargout, const octave_value_list& args);
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return btyp_func_handle; }
+  builtin_type_t builtin_type () const { return btyp_func_handle; }
 
-  bool is_function_handle (void) const { return true; }
+  bool is_function_handle () const { return true; }
 
-  bool is_internal (void) const { return m_rep->is_internal (); }
+  bool is_internal () const { return m_rep->is_internal (); }
 
-  bool is_simple (void) const { return m_rep->is_simple (); }
+  bool is_simple () const { return m_rep->is_simple (); }
 
-  bool is_scoped (void) const { return m_rep->is_scoped (); }
+  bool is_scoped () const { return m_rep->is_scoped (); }
 
-  bool is_nested (void) const { return m_rep->is_nested (); }
+  bool is_nested () const { return m_rep->is_nested (); }
 
   bool is_nested (const std::shared_ptr<octave::stack_frame>& frame) const
   {
     return m_rep->is_nested (frame);
   }
 
-  bool is_weak_nested (void) const { return m_rep->is_weak_nested (); }
+  bool is_weak_nested () const { return m_rep->is_weak_nested (); }
 
-  bool is_class_simple (void) const { return m_rep->is_class_simple (); }
+  bool is_class_simple () const { return m_rep->is_class_simple (); }
 
-  bool is_anonymous (void) const { return m_rep->is_anonymous (); }
+  bool is_anonymous () const { return m_rep->is_anonymous (); }
 
-  bool is_weak_anonymous (void) const { return m_rep->is_weak_anonymous (); }
+  bool is_weak_anonymous () const { return m_rep->is_weak_anonymous (); }
 
-  octave_value make_weak_nested_handle (void) const
+  octave_value make_weak_nested_handle () const
   {
     return m_rep->make_weak_nested_handle ();
   }
 
-  octave_value make_weak_anonymous_handle (void) const
+  octave_value make_weak_anonymous_handle () const
   {
     return m_rep->make_weak_anonymous_handle ();
   }
 
-  dim_vector dims (void) const;
+  dim_vector dims () const;
 
   // FIXME: These must go away.  They don't do the right thing for
   // scoping or overloads.
@@ -311,24 +321,24 @@
 
   octave_fcn_handle * fcn_handle_value (bool = false) { return this; }
 
-  octave_value fcn_val (void) { return m_rep->fcn_val (); }
+  octave_value fcn_val () { return m_rep->fcn_val (); }
 
   // FCN_NAME should be eliminated.
-  std::string fcn_name (void) const { return m_rep->fcn_name (); }
+  std::string fcn_name () const { return m_rep->fcn_name (); }
 
-  octave_value workspace (void) const
+  octave_value workspace () const
   {
     return m_rep->workspace ();
   }
 
-  octave_scalar_map info (void) { return m_rep->info (); }
+  octave_scalar_map info () { return m_rep->info (); }
 
   void set_dispatch_class (const std::string& class_name)
   {
     m_rep->set_dispatch_class (class_name);
   }
 
-  std::string get_dispatch_class (void) const
+  std::string get_dispatch_class () const
   {
     return m_rep->get_dispatch_class ();
   }
@@ -356,16 +366,20 @@
   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 m_rep->print_as_scalar (); }
+  bool print_as_scalar () const { return m_rep->print_as_scalar (); }
 
   friend bool
   is_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2);
 
+  octave_function *
+  get_cached_fcn (const octave_value_list& args) { return m_rep->get_cached_fcn (args); }
+  bool has_function_cache (void) const { return m_rep->has_function_cache (); }
+
 private:
 
   std::shared_ptr<octave::base_fcn_handle> m_rep;
 
-  octave::base_fcn_handle * get_rep (void) const { return m_rep.get (); }
+  octave::base_fcn_handle * get_rep () const { return m_rep.get (); }
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
--- a/libinterp/octave-value/ov-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,14 +34,22 @@
 #include "ov-fcn.h"
 #include "pt-eval.h"
 
+#include "error.h"
+#include "interpreter-private.h"
+#include "symtab.h"
+#include "interpreter.h"
+#include "lo-array-errwarn.h"
+
+#include "pt-bytecode-walk.h"
+
 octave_base_value *
-octave_function::clone (void) const
+octave_function::clone () const
 {
   panic_impossible ();
 }
 
 octave_base_value *
-octave_function::empty_clone (void) const
+octave_function::empty_clone () const
 {
   panic_impossible ();
 }
@@ -50,9 +58,169 @@
 octave_function::call (octave::tree_evaluator& tw, int nargout,
                        const octave_value_list& args)
 {
-  tw.push_stack_frame (this);
+  octave_user_function *usr = this->user_function_value(true);
+
+  bool is_compiled = false;
+  if (usr)
+    {
+      is_compiled = usr->is_compiled ();
+      if (octave::V__enable_vm_eval__ && !is_compiled && !usr->m_compilation_failed)
+      {
+        try
+          {
+            octave::compile_user_function (*usr, false);
+            is_compiled = true;
+          }
+        catch (std::exception &e)
+          {
+            warning ("Compilation failed with message %s", e.what ());
+            usr->m_compilation_failed = true;
+          }
+      }
+    }
+
+  // Bytecode functions push their own stack frames in the vm
+
+  if (! usr || ! is_compiled)
+    tw.push_stack_frame (this);
 
   octave::unwind_action act ([&tw] () { tw.pop_stack_frame (); });
 
   return execute (tw, nargout, args);
 }
+
+
+void
+octave_fcn_cache::set_cached_function (octave_value ov,
+                                       const octave_value_list &args,
+                                       octave_idx_type current_n_updated)
+{
+  clear_cached_function ();
+
+  if (!ov.is_defined ())
+    return;
+
+  // We need to keep a reference to the metaobject for as long as the function is alive
+  if (ov.is_classdef_meta ())
+    m_cached_object = ov;
+
+  std::vector<int> v_types;
+
+  for (int i = 0; i < args.length (); i++)
+    {
+      // FIXME: We don't cache methods or functions with class object
+      // arguments. Classes need some kind of unique simple key for this
+      // simple approach.
+      if (args(i).isobject())
+        return;
+
+      v_types.push_back (args (i).type_id ());
+    }
+
+  m_cached_args = v_types;
+  m_cached_function = ov;
+
+  m_n_updated = current_n_updated;
+}
+
+octave_value
+octave_fcn_cache::
+get_cached_obj (const octave_value_list& args)
+{
+  octave_function *fcn = nullptr;
+
+  octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated ();
+  if (has_cached_function (args))
+    {
+      if (m_n_updated == current_n_updated)
+        return m_cached_function;
+      else
+        clear_cached_function ();
+    }
+
+  if (! fcn)
+    {
+      octave::interpreter& interp =
+        octave::__get_interpreter__ ();
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
+      octave_value val = symtab.find_function (m_fcn_name, args);
+
+      if (val.is_function ())
+        {
+          fcn = val.function_value (true);
+          set_cached_function (val, args, current_n_updated);
+          return val;
+        }
+
+      val = symtab.find_function (m_fcn_name);
+      if (val.is_function ())
+        {
+          return val;
+        }
+    }
+
+  return {};
+}
+
+octave_function *
+octave_fcn_cache::
+get_cached_fcn_internal (const octave_value_list& args)
+{
+  clear_cached_function ();
+
+  octave_function *fcn = nullptr;
+  octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated ();
+
+  octave::interpreter& interp =
+    octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
+  octave_value val = symtab.find_function (m_fcn_name, args);
+
+  if (val.is_function ())
+    {
+      fcn = val.function_value (true);
+      set_cached_function (val, args, current_n_updated);
+      return fcn;
+    }
+
+  val = symtab.find_function (m_fcn_name);
+  if (val.is_function ())
+    {
+      return val.function_value (true);
+    }
+
+  return fcn;
+}
+
+octave_function *
+octave_fcn_cache::
+get_cached_fcn (const octave_value_list& args)
+{
+  octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated ();
+  if (OCTAVE_LIKELY (has_cached_function (args)))
+    if (OCTAVE_LIKELY (m_n_updated == current_n_updated))
+      return m_cached_function.function_value (true);
+
+  return get_cached_fcn_internal (args);
+}
+
+octave_value_list
+octave_fcn_cache::
+call (octave::tree_evaluator& tw,
+      octave_function *fcn,
+      const octave_value_list& args,
+      int nargout)
+{
+  try
+    {
+      return fcn->call (tw, nargout, args);
+    }
+  catch (octave::index_exception& ie)
+    {
+      error ("Proper error message here for function calls");
+      // Maybe return the octave_function pointer?
+      //tw.final_index_error (ie, m_expr);
+    }
+}
--- a/libinterp/octave-value/ov-fcn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-fcn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,66 +48,140 @@
 
 // Functions.
 
+// Class that holds a cached reference to a octave function
+// for use in the bytecode VM.
+class
+OCTINTERP_API
+octave_fcn_cache : public octave_base_value
+{
+public:
+  octave_fcn_cache (const std::string &name) :m_fcn_name (name) { }
+  octave_fcn_cache () {}
+
+  bool is_function_cache (void) const { return true; }
+
+  bool has_function_cache (void) const { return true; }
+
+  octave_function *
+  get_cached_fcn (const octave_value_list& args);
+
+  octave_function *
+  get_cached_fcn () { return m_cached_function.function_value (); }
+
+  octave_value
+  get_cached_obj (const octave_value_list& args);
+
+  octave_fcn_cache * fcn_cache_value (void)
+  {
+    return this;
+  }
+
+  octave_value_list
+  call (octave::tree_evaluator& tw,
+        octave_function *fcn,
+        const octave_value_list& args,
+        int nargout);
+
+  void set_cached_function (octave_value ov, const octave_value_list &args, octave_idx_type current_n_updated);
+
+  bool has_cached_function (const octave_value_list &args) const
+  {
+    if (m_n_updated == 0)
+      return false;
+
+    unsigned vec_n = m_cached_args.size ();
+
+    unsigned n_args = args.length ();
+    if (n_args != vec_n)
+      return false;
+
+    for (unsigned i = 0; i < n_args; i++)
+      {
+        if (args (i).type_id () != m_cached_args [i])
+          return false;
+      }
+
+    return true;
+  }
+
+private:
+
+  octave_function * get_cached_fcn_internal (const octave_value_list& args);
+
+  void clear_cached_function ()
+  {
+    m_cached_object = octave_value {};
+    m_cached_function = octave_value {};
+    m_n_updated = 0;
+    m_cached_args.clear ();
+  }
+
+  octave_value m_cached_object;
+  octave_value m_cached_function;
+  std::vector<int> m_cached_args;
+  octave_idx_type m_n_updated = 0;
+  std::string m_fcn_name;
+};
+
+
 class
 OCTINTERP_API
 octave_function : public octave_base_value
 {
 public:
 
-  octave_function (void)
+  octave_function ()
     : m_relative (false), m_locked (false), m_private (false),
       m_dispatch_class (), m_package_name (), m_name (), m_dir_name (),
       m_doc () { }
 
-  // No copying!
-
-  octave_function (const octave_function& f) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_function)
 
-  octave_function& operator = (const octave_function& f) = delete;
+  ~octave_function () = default;
 
-  ~octave_function (void) = default;
+  octave_base_value * clone () const;
+  octave_base_value * empty_clone () const;
 
-  octave_base_value * clone (void) const;
-  octave_base_value * empty_clone (void) const;
+  bool is_defined () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_function () const { return true; }
 
-  bool is_function (void) const { return true; }
-
-  virtual bool is_system_fcn_file (void) const { return false; }
+  virtual bool is_system_fcn_file () const { return false; }
 
-  virtual std::string fcn_file_name (void) const { return ""; }
+  virtual std::string fcn_file_name () const { return ""; }
 
-  virtual std::string src_file_name (void) const { return ""; }
+  virtual std::string src_file_name () const { return ""; }
 
   // The name to show in the profiler (also used as map-key).
-  virtual std::string profiler_name (void) const { return name (); }
+  virtual std::string profiler_name () const { return name (); }
 
-  virtual std::string parent_fcn_name (void) const { return ""; }
+  virtual std::string parent_fcn_name () const { return ""; }
 
-  virtual octave::symbol_scope parent_fcn_scope (void) const
+  virtual octave::symbol_scope parent_fcn_scope () const
   { return octave::symbol_scope (); }
 
-  virtual std::list<std::string> parent_fcn_names (void) const
+  virtual std::list<std::string> parent_fcn_names () const
   { return std::list<std::string> (); }
 
   virtual void mark_fcn_file_up_to_date (const octave::sys::time&) { }
 
-  virtual octave::symbol_scope scope (void) { return octave::symbol_scope (); }
+  virtual octave::symbol_scope scope () { return octave::symbol_scope (); }
 
-  virtual octave::sys::time time_parsed (void) const
+  virtual octave::sys::time time_parsed () const
   { return octave::sys::time (static_cast<OCTAVE_TIME_T> (0)); }
 
-  virtual octave::sys::time time_checked (void) const
+  virtual octave::sys::time time_checked () const
   { return octave::sys::time (static_cast<OCTAVE_TIME_T> (0)); }
 
-  virtual int call_depth (void) const { return 0; }
+  virtual int call_depth () const { return 0; }
 
-  virtual bool is_nested_function (void) const { return false; }
+  virtual bool is_nested_function () const { return false; }
 
-  virtual bool is_parent_function (void) const { return false; }
+  virtual bool is_parent_function () const { return false; }
 
-  virtual bool is_subfunction (void) const { return false; }
+  virtual bool is_subfunction () const { return false; }
+
+  virtual bool is_compiled () const { return false; }
 
   bool is_class_constructor (const std::string& cname = "") const
   {
@@ -133,9 +207,9 @@
   virtual bool is_classdef_method (const std::string& = "") const
   { return false; }
 
-  virtual bool takes_varargs (void) const { return false; }
+  virtual bool takes_varargs () const { return false; }
 
-  virtual bool takes_var_return (void) const { return false; }
+  virtual bool takes_var_return () const { return false; }
 
   // The next two functions are for dispatching to built-in
   // functions given built-in classes.
@@ -147,11 +221,11 @@
 
   void stash_dispatch_class (const std::string& nm) { m_dispatch_class = nm; }
 
-  std::string dispatch_class (void) const { return m_dispatch_class; }
+  std::string dispatch_class () const { return m_dispatch_class; }
 
   void stash_package_name (const std::string& pack) { m_package_name = pack; }
 
-  std::string package_name (void) const { return m_package_name; }
+  std::string package_name () const { return m_package_name; }
 
   virtual void
   mark_as_private_function (const std::string& cname = "")
@@ -160,7 +234,7 @@
     m_dispatch_class = cname;
   }
 
-  bool is_private_function (void) const { return m_private; }
+  bool is_private_function () const { return m_private; }
 
   bool is_private_function_of_class (const std::string& nm) const
   { return m_private && m_dispatch_class == nm; }
@@ -169,45 +243,45 @@
   is_anonymous_function_of_class (const std::string& = "") const
   { return false; }
 
-  std::string dir_name (void) const { return m_dir_name; }
+  std::string dir_name () const { return m_dir_name; }
 
   void stash_dir_name (const std::string& dir) { m_dir_name = dir; }
 
-  void lock (void)
+  void lock ()
   {
     this->lock_subfunctions ();
     m_locked = true;
   }
 
-  void unlock (void)
+  void unlock ()
   {
     this->unlock_subfunctions ();
     m_locked = false;
   }
 
-  bool islocked (void) const { return m_locked; }
+  bool islocked () const { return m_locked; }
 
-  virtual void lock_subfunctions (void) { }
+  virtual void lock_subfunctions () { }
 
-  virtual void unlock_subfunctions (void) { }
+  virtual void unlock_subfunctions () { }
 
-  virtual void maybe_relocate_end (void) { }
+  virtual void maybe_relocate_end () { }
 
   // Not valid until after the function is completely parsed.
-  virtual bool has_subfunctions (void) const { return false; }
+  virtual bool has_subfunctions () const { return false; }
 
   virtual void stash_subfunction_names (const std::list<std::string>&) { }
 
-  virtual std::list<std::string> subfunction_names (void) const
+  virtual std::list<std::string> subfunction_names () const
   { return std::list<std::string> (); }
 
-  void mark_relative (void) { m_relative = true; }
+  void mark_relative () { m_relative = true; }
 
-  bool is_relative (void) const { return m_relative; }
+  bool is_relative () const { return m_relative; }
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
-  std::string canonical_name (void) const
+  std::string canonical_name () const
   {
     if (m_package_name.empty ())
       return m_name;
@@ -220,7 +294,7 @@
   virtual std::string
   doc_string (const std::string& /*meth_name*/ = "") const { return m_doc; }
 
-  virtual void unload (void) { }
+  virtual void unload () { }
 
   virtual void accept (octave::tree_walker&) { }
 
--- a/libinterp/octave-value/ov-float.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-float.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -106,61 +106,61 @@
 }
 
 octave_value
-octave_float_scalar::as_double (void) const
+octave_float_scalar::as_double () const
 {
   return static_cast<double> (scalar);
 }
 
 octave_value
-octave_float_scalar::as_single (void) const
+octave_float_scalar::as_single () const
 {
   return scalar;
 }
 
 octave_value
-octave_float_scalar::as_int8 (void) const
+octave_float_scalar::as_int8 () const
 {
   return octave_int8 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_int16 (void) const
+octave_float_scalar::as_int16 () const
 {
   return octave_int16 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_int32 (void) const
+octave_float_scalar::as_int32 () const
 {
   return octave_int32 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_int64 (void) const
+octave_float_scalar::as_int64 () const
 {
   return octave_int64 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_uint8 (void) const
+octave_float_scalar::as_uint8 () const
 {
   return octave_uint8 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_uint16 (void) const
+octave_float_scalar::as_uint16 () const
 {
   return octave_uint16 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_uint32 (void) const
+octave_float_scalar::as_uint32 () const
 {
   return octave_uint32 (scalar);
 }
 
 octave_value
-octave_float_scalar::as_uint64 (void) const
+octave_float_scalar::as_uint64 () const
 {
   return octave_uint64 (scalar);
 }
--- a/libinterp/octave-value/ov-float.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-float.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,7 +56,7 @@
 {
 public:
 
-  octave_float_scalar (void)
+  octave_float_scalar ()
     : octave_base_scalar<float> (0.0) { }
 
   octave_float_scalar (float d)
@@ -65,15 +65,15 @@
   octave_float_scalar (const octave_float_scalar& s)
     : octave_base_scalar<float> (s) { }
 
-  ~octave_float_scalar (void) = default;
+  ~octave_float_scalar () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_scalar (*this); }
 
   // We return an octave_matrix here instead of an octave_float_scalar so
   // that in expressions like A(2,2,2) = 2 (for A previously
   // undefined), A will be empty instead of a 1x1 object.
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_matrix (); }
 
   octave_value do_index_op (const octave_value_list& idx,
@@ -85,51 +85,51 @@
   octave_value any (int = 0) const
   { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
 
-  builtin_type_t builtin_type (void) const { return btyp_float; }
+  builtin_type_t builtin_type () const { return btyp_float; }
 
-  bool is_real_scalar (void) const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   int8NDArray
-  int8_array_value (void) const
+  int8_array_value () const
   { return int8NDArray (dim_vector (1, 1), scalar); }
 
   int16NDArray
-  int16_array_value (void) const
+  int16_array_value () const
   { return int16NDArray (dim_vector (1, 1), scalar); }
 
   int32NDArray
-  int32_array_value (void) const
+  int32_array_value () const
   { return int32NDArray (dim_vector (1, 1), scalar); }
 
   int64NDArray
-  int64_array_value (void) const
+  int64_array_value () const
   { return int64NDArray (dim_vector (1, 1), scalar); }
 
   uint8NDArray
-  uint8_array_value (void) const
+  uint8_array_value () const
   { return uint8NDArray (dim_vector (1, 1), scalar); }
 
   uint16NDArray
-  uint16_array_value (void) const
+  uint16_array_value () const
   { return uint16NDArray (dim_vector (1, 1), scalar); }
 
   uint32NDArray
-  uint32_array_value (void) const
+  uint32_array_value () const
   { return uint32NDArray (dim_vector (1, 1), scalar); }
 
   uint64NDArray
-  uint64_array_value (void) const
+  uint64_array_value () const
   { return uint64NDArray (dim_vector (1, 1), scalar); }
 
 #define DEFINE_INT_SCALAR_VALUE(TYPE)         \
   octave_ ## TYPE                             \
-  TYPE ## _scalar_value (void) const          \
+  TYPE ## _scalar_value () const          \
   {                                           \
     return octave_ ## TYPE (scalar);          \
   }
@@ -220,18 +220,18 @@
     return boolNDArray (dim_vector (1, 1), scalar);
   }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   // We don't need to override both forms of the diag method.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -242,9 +242,9 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  void increment (void) { ++scalar; }
+  void increment () { ++scalar; }
 
-  void decrement (void) { --scalar; }
+  void decrement () { --scalar; }
 
   bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-flt-complex.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-complex.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -64,7 +64,7 @@
                                      "float complex scalar", "single");
 
 octave_base_value *
-octave_float_complex::try_narrowing_conversion (void)
+octave_float_complex::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -230,13 +230,13 @@
 }
 
 octave_value
-octave_float_complex::as_double (void) const
+octave_float_complex::as_double () const
 {
   return Complex (scalar);
 }
 
 octave_value
-octave_float_complex::as_single (void) const
+octave_float_complex::as_single () const
 {
   return scalar;
 }
--- a/libinterp/octave-value/ov-flt-complex.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-complex.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_float_complex (void)
+  octave_float_complex ()
     : octave_base_scalar<FloatComplex> () { }
 
   octave_float_complex (const FloatComplex& c)
@@ -63,19 +63,19 @@
   octave_float_complex (const octave_float_complex& c)
     : octave_base_scalar<FloatComplex> (c) { }
 
-  ~octave_float_complex (void) = default;
+  ~octave_float_complex () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_complex (*this); }
 
   // We return an octave_float_complex_matrix object here instead of an
   // octave_float_complex object so that in expressions like A(2,2,2) = 2
   // (for A previously undefined), A will be empty instead of a 1x1
   // object.
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_complex_matrix (); }
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
@@ -87,15 +87,15 @@
                   || lo_ieee_isnan (scalar.imag ())));
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_float_complex; }
+  builtin_type_t builtin_type () const { return btyp_float_complex; }
 
-  bool is_complex_scalar (void) const { return true; }
+  bool is_complex_scalar () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -155,8 +155,8 @@
     return boolNDArray (dim_vector (1, 1), scalar != 1.0f);
   }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
   // We don't need to override both forms of the diag method.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -165,9 +165,9 @@
 
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  void increment (void) { scalar += 1.0; }
+  void increment () { scalar += 1.0; }
 
-  void decrement (void) { scalar -= 1.0; }
+  void decrement () { scalar -= 1.0; }
 
   bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-flt-cx-diag.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,14 +52,14 @@
 }
 
 octave_base_value::type_conv_info
-octave_float_complex_diag_matrix::numeric_conversion_function (void) const
+octave_float_complex_diag_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_float_complex_matrix::static_type_id ());
 }
 
 octave_base_value *
-octave_float_complex_diag_matrix::try_narrowing_conversion (void)
+octave_float_complex_diag_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -122,13 +122,13 @@
 }
 
 octave_value
-octave_float_complex_diag_matrix::as_double (void) const
+octave_float_complex_diag_matrix::as_double () const
 {
   return ComplexDiagMatrix (m_matrix);
 }
 
 octave_value
-octave_float_complex_diag_matrix::as_single (void) const
+octave_float_complex_diag_matrix::as_single () const
 {
   return m_matrix;
 }
--- a/libinterp/octave-value/ov-flt-cx-diag.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-cx-diag.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  octave_float_complex_diag_matrix (void)
+  octave_float_complex_diag_matrix ()
     : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> () { }
 
   octave_float_complex_diag_matrix (const FloatComplexDiagMatrix& m)
@@ -51,26 +51,26 @@
   octave_float_complex_diag_matrix (const octave_float_complex_diag_matrix& m)
     : octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix> (m) { }
 
-  ~octave_float_complex_diag_matrix (void) = default;
+  ~octave_float_complex_diag_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_complex_diag_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_complex_diag_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_float_complex; }
+  builtin_type_t builtin_type () const { return btyp_float_complex; }
 
-  bool is_complex_matrix (void) const { return true; }
+  bool is_complex_matrix () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   DiagMatrix diag_matrix_value (bool = false) const;
 
@@ -80,8 +80,8 @@
 
   FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -75,7 +75,7 @@
                                      "float complex matrix", "single");
 
 octave_base_value *
-octave_float_complex_matrix::try_narrowing_conversion (void)
+octave_float_complex_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -255,13 +255,13 @@
 }
 
 octave_value
-octave_float_complex_matrix::as_double (void) const
+octave_float_complex_matrix::as_double () const
 {
   return ComplexNDArray (m_matrix);
 }
 
 octave_value
-octave_float_complex_matrix::as_single (void) const
+octave_float_complex_matrix::as_single () const
 {
   return m_matrix;
 }
@@ -569,7 +569,7 @@
 
   if (retval)
     {
-      FloatComplex *mtmp = m.fortran_vec ();
+      const FloatComplex *mtmp = m.data ();
       if (H5Dwrite (data_hid, complex_type_hid, octave_H5S_ALL, octave_H5S_ALL,
                     octave_H5P_DEFAULT, mtmp)
           < 0)
--- a/libinterp/octave-value/ov-flt-cx-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_float_complex_matrix (void)
+  octave_float_complex_matrix ()
     : octave_base_matrix<FloatComplexNDArray> () { }
 
   octave_float_complex_matrix (const FloatComplexNDArray& m)
@@ -81,24 +81,24 @@
   octave_float_complex_matrix (const octave_float_complex_matrix& cm)
     : octave_base_matrix<FloatComplexNDArray> (cm) { }
 
-  ~octave_float_complex_matrix (void) = default;
+  ~octave_float_complex_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_complex_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_complex_matrix (); }
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_float_complex; }
+  builtin_type_t builtin_type () const { return btyp_float_complex; }
 
-  bool is_complex_matrix (void) const { return true; }
+  bool is_complex_matrix () const { return true; }
 
-  bool iscomplex (void) const { return true; }
+  bool iscomplex () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -134,18 +134,18 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
   octave_value diag (octave_idx_type k = 0) const;
 
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  void increment (void) { m_matrix += FloatComplex (1.0); }
+  void increment () { m_matrix += FloatComplex (1.0); }
 
-  void decrement (void) { m_matrix -= FloatComplex (1.0); }
+  void decrement () { m_matrix -= FloatComplex (1.0); }
 
-  void changesign (void) { m_matrix.changesign (); }
+  void changesign () { m_matrix.changesign (); }
 
   bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-flt-re-diag.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,14 +51,14 @@
 }
 
 octave_base_value::type_conv_info
-octave_float_diag_matrix::numeric_conversion_function (void) const
+octave_float_diag_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_float_matrix::static_type_id ());
 }
 
 octave_base_value *
-octave_float_diag_matrix::try_narrowing_conversion (void)
+octave_float_diag_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -93,61 +93,61 @@
 }
 
 octave_value
-octave_float_diag_matrix::as_double (void) const
+octave_float_diag_matrix::as_double () const
 {
   return DiagMatrix (m_matrix);
 }
 
 octave_value
-octave_float_diag_matrix::as_single (void) const
+octave_float_diag_matrix::as_single () const
 {
   return m_matrix;
 }
 
 octave_value
-octave_float_diag_matrix::as_int8 (void) const
+octave_float_diag_matrix::as_int8 () const
 {
   return int8_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_int16 (void) const
+octave_float_diag_matrix::as_int16 () const
 {
   return int16_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_int32 (void) const
+octave_float_diag_matrix::as_int32 () const
 {
   return int32_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_int64 (void) const
+octave_float_diag_matrix::as_int64 () const
 {
   return int64_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_uint8 (void) const
+octave_float_diag_matrix::as_uint8 () const
 {
   return uint8_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_uint16 (void) const
+octave_float_diag_matrix::as_uint16 () const
 {
   return uint16_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_uint32 (void) const
+octave_float_diag_matrix::as_uint32 () const
 {
   return uint32_array_value ();
 }
 
 octave_value
-octave_float_diag_matrix::as_uint64 (void) const
+octave_float_diag_matrix::as_uint64 () const
 {
   return uint64_array_value ();
 }
--- a/libinterp/octave-value/ov-flt-re-diag.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-re-diag.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  octave_float_diag_matrix (void)
+  octave_float_diag_matrix ()
     : octave_base_diag<FloatDiagMatrix, FloatMatrix> () { }
 
   octave_float_diag_matrix (const FloatDiagMatrix& m)
@@ -51,26 +51,26 @@
   octave_float_diag_matrix (const octave_float_diag_matrix& m)
     : octave_base_diag<FloatDiagMatrix, FloatMatrix> (m) { }
 
-  ~octave_float_diag_matrix (void) = default;
+  ~octave_float_diag_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_diag_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_diag_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return btyp_float; }
+  builtin_type_t builtin_type () const { return btyp_float; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   DiagMatrix diag_matrix_value (bool = false) const;
 
@@ -80,18 +80,18 @@
 
   FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-flt-re-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -90,7 +90,7 @@
                                      "single");
 
 octave_base_value *
-octave_float_matrix::try_narrowing_conversion (void)
+octave_float_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -240,61 +240,61 @@
 }
 
 octave_value
-octave_float_matrix::as_double (void) const
+octave_float_matrix::as_double () const
 {
   return NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_single (void) const
+octave_float_matrix::as_single () const
 {
   return FloatNDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_int8 (void) const
+octave_float_matrix::as_int8 () const
 {
   return int8NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_int16 (void) const
+octave_float_matrix::as_int16 () const
 {
   return int16NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_int32 (void) const
+octave_float_matrix::as_int32 () const
 {
   return int32NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_int64 (void) const
+octave_float_matrix::as_int64 () const
 {
   return int64NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_uint8 (void) const
+octave_float_matrix::as_uint8 () const
 {
   return uint8NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_uint16 (void) const
+octave_float_matrix::as_uint16 () const
 {
   return uint16NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_uint32 (void) const
+octave_float_matrix::as_uint32 () const
 {
   return uint32NDArray (m_matrix);
 }
 
 octave_value
-octave_float_matrix::as_uint64 (void) const
+octave_float_matrix::as_uint64 () const
 {
   return uint64NDArray (m_matrix);
 }
@@ -631,7 +631,7 @@
       return false;
     }
 
-  float *mtmp = m.fortran_vec ();
+  const float *mtmp = m.data ();
   retval = H5Dwrite (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,
                      octave_H5P_DEFAULT, mtmp) >= 0;
 
--- a/libinterp/octave-value/ov-flt-re-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_float_matrix (void)
+  octave_float_matrix ()
     : octave_base_matrix<FloatNDArray> () { }
 
   octave_float_matrix (const FloatMatrix& m)
@@ -81,14 +81,14 @@
   octave_float_matrix (const octave_float_matrix& m)
     : octave_base_matrix<FloatNDArray> (m) { }
 
-  ~octave_float_matrix (void) = default;
+  ~octave_float_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_float_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_float_matrix (); }
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   {
@@ -96,39 +96,39 @@
            : set_idx_cache (octave::idx_vector (m_matrix));
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_float; }
+  builtin_type_t builtin_type () const { return btyp_float; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_single_type (void) const { return true; }
+  bool is_single_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   int8NDArray
-  int8_array_value (void) const { return int8NDArray (m_matrix); }
+  int8_array_value () const { return int8NDArray (m_matrix); }
 
   int16NDArray
-  int16_array_value (void) const { return int16NDArray (m_matrix); }
+  int16_array_value () const { return int16NDArray (m_matrix); }
 
   int32NDArray
-  int32_array_value (void) const { return int32NDArray (m_matrix); }
+  int32_array_value () const { return int32NDArray (m_matrix); }
 
   int64NDArray
-  int64_array_value (void) const { return int64NDArray (m_matrix); }
+  int64_array_value () const { return int64NDArray (m_matrix); }
 
   uint8NDArray
-  uint8_array_value (void) const { return uint8NDArray (m_matrix); }
+  uint8_array_value () const { return uint8NDArray (m_matrix); }
 
   uint16NDArray
-  uint16_array_value (void) const { return uint16NDArray (m_matrix); }
+  uint16_array_value () const { return uint16NDArray (m_matrix); }
 
   uint32NDArray
-  uint32_array_value (void) const { return uint32NDArray (m_matrix); }
+  uint32_array_value () const { return uint32NDArray (m_matrix); }
 
   uint64NDArray
-  uint64_array_value (void) const { return uint64NDArray (m_matrix); }
+  uint64_array_value () const { return uint64NDArray (m_matrix); }
 
   double double_value (bool = false) const;
 
@@ -168,29 +168,29 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   octave_value diag (octave_idx_type k = 0) const;
 
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   // Use matrix_ref here to clear index cache.
-  void increment (void) { matrix_ref () += 1.0; }
+  void increment () { matrix_ref () += 1.0; }
 
-  void decrement (void) { matrix_ref () -= 1.0; }
+  void decrement () { matrix_ref () -= 1.0; }
 
-  void changesign (void) { matrix_ref ().changesign (); }
+  void changesign () { matrix_ref ().changesign (); }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-inline.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,140 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_ov_inline_h)
+#define octave_ov_inline_h 1
+
+#include "octave-config.h"
+
+#include "ov.h"
+
+#include "ov-scalar.h"
+#include "ov-float.h"
+#include "ov-complex.h"
+#include "ov-flt-complex.h"
+#include "ov-bool.h"
+#include "ov-base.h"
+
+
+// class to construct octave_value:s inline
+
+class octave_value_factory
+{
+  public:
+
+  static octave_value make (double d)
+  {
+    return octave_value (new octave_scalar (d));
+  }
+
+  static octave_value make (float d)
+  {
+    return octave_value (new octave_float_scalar (d));
+  }
+
+  static octave_value make (short int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+  static octave_value make (unsigned short int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+  static octave_value make (int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+  static octave_value make (unsigned int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+  static octave_value make (long int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+  static octave_value make (unsigned long int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+
+#if defined (OCTAVE_HAVE_LONG_LONG_INT)
+  static octave_value make (long long int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+#endif
+
+#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
+  static octave_value make (unsigned long long int i)
+  {
+    return octave_value (new octave_scalar (i));
+  }
+#endif
+
+  static octave_value make (octave::sys::time t)
+  {
+    return octave_value (new octave_scalar (t.double_value ()));
+  }
+
+  static octave_value make (const Complex& C)
+  {
+    octave_value ov (new octave_complex (C));
+    ov.maybe_mutate (); // Fold e.g. 1+0i to 1
+    return ov;
+  }
+
+  static octave_value make (const FloatComplex& C)
+  {
+    octave_value ov (new octave_float_complex (C));
+    ov.maybe_mutate ();
+    return ov;
+  }
+
+  static octave_value make (bool b)
+  {
+    return octave_value (new octave_bool (b));
+  }
+
+  // FIXME: The octave_value (octave_base_value *rep, bool) constructor
+  // is already defined in the ov.h header file so is the
+  // octave_value_factory::make_copy function really necessary?
+
+  static octave_value make_copy (octave_base_value *rep)
+  {
+    return octave_value (rep, true);
+  }
+
+private:
+
+  ~octave_value_factory () = delete;
+  octave_value_factory () = delete;
+};
+
+#endif
--- a/libinterp/octave-value/ov-intx.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-intx.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,7 +56,7 @@
 {
 public:
 
-  OCTAVE_VALUE_INT_MATRIX_T (void)
+  OCTAVE_VALUE_INT_MATRIX_T ()
     : octave_base_int_matrix<intNDArray<OCTAVE_INT_T>> () { }
 
   OCTAVE_VALUE_INT_MATRIX_T (const intNDArray<OCTAVE_INT_T>& nda)
@@ -66,45 +66,45 @@
     : octave_base_int_matrix<intNDArray<OCTAVE_INT_T>>
       (intNDArray<OCTAVE_INT_T> (nda)) { }
 
-  ~OCTAVE_VALUE_INT_MATRIX_T (void) = default;
+  ~OCTAVE_VALUE_INT_MATRIX_T () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new OCTAVE_VALUE_INT_MATRIX_T (*this); }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new OCTAVE_VALUE_INT_MATRIX_T (); }
 
-  bool OCTAVE_TYPE_PREDICATE_FUNCTION (void) const { return true; }
+  bool OCTAVE_TYPE_PREDICATE_FUNCTION () const { return true; }
 
-  bool isinteger (void) const { return true; }
+  bool isinteger () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return OCTAVE_INT_BTYP; }
+  builtin_type_t builtin_type () const { return OCTAVE_INT_BTYP; }
 
 public:
 
   int8NDArray
-  int8_array_value (void) const { return int8NDArray (m_matrix); }
+  int8_array_value () const { return int8NDArray (m_matrix); }
 
   int16NDArray
-  int16_array_value (void) const { return int16NDArray (m_matrix); }
+  int16_array_value () const { return int16NDArray (m_matrix); }
 
   int32NDArray
-  int32_array_value (void) const { return int32NDArray (m_matrix); }
+  int32_array_value () const { return int32NDArray (m_matrix); }
 
   int64NDArray
-  int64_array_value (void) const { return int64NDArray (m_matrix); }
+  int64_array_value () const { return int64NDArray (m_matrix); }
 
   uint8NDArray
-  uint8_array_value (void) const { return uint8NDArray (m_matrix); }
+  uint8_array_value () const { return uint8NDArray (m_matrix); }
 
   uint16NDArray
-  uint16_array_value (void) const { return uint16NDArray (m_matrix); }
+  uint16_array_value () const { return uint16NDArray (m_matrix); }
 
   uint32NDArray
-  uint32_array_value (void) const { return uint32NDArray (m_matrix); }
+  uint32_array_value () const { return uint32NDArray (m_matrix); }
 
   uint64NDArray
-  uint64_array_value (void) const { return uint64NDArray (m_matrix); }
+  uint64_array_value () const { return uint64NDArray (m_matrix); }
 
   double
   double_value (bool = false) const
@@ -286,17 +286,17 @@
   }
 
   // Use matrix_ref here to clear index cache.
-  void increment (void)
+  void increment ()
   {
     matrix_ref () += OCTAVE_INT_T (1);
   }
 
-  void decrement (void)
+  void decrement ()
   {
     matrix_ref () -= OCTAVE_INT_T (1);
   }
 
-  void changesign (void)
+  void changesign ()
   {
     matrix_ref ().changesign ();
   }
@@ -393,18 +393,18 @@
 {
 public:
 
-  OCTAVE_VALUE_INT_SCALAR_T (void)
+  OCTAVE_VALUE_INT_SCALAR_T ()
     : octave_base_int_scalar<OCTAVE_INT_T> () { }
 
   OCTAVE_VALUE_INT_SCALAR_T (const OCTAVE_INT_T& nda)
     : octave_base_int_scalar<OCTAVE_INT_T> (nda) { }
 
-  ~OCTAVE_VALUE_INT_SCALAR_T (void) = default;
+  ~OCTAVE_VALUE_INT_SCALAR_T () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new OCTAVE_VALUE_INT_SCALAR_T (*this); }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new OCTAVE_VALUE_INT_MATRIX_T (); }
 
   octave_value do_index_op (const octave_value_list& idx,
@@ -427,68 +427,68 @@
     return tmp.index_op (idx, resize_ok);
   }
 
-  bool OCTAVE_TYPE_PREDICATE_FUNCTION (void) const { return true; }
+  bool OCTAVE_TYPE_PREDICATE_FUNCTION () const { return true; }
 
-  bool isinteger (void) const { return true; }
+  bool isinteger () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return OCTAVE_INT_BTYP; }
+  builtin_type_t builtin_type () const { return OCTAVE_INT_BTYP; }
 
 public:
 
   octave_int8
-  int8_scalar_value (void) const { return octave_int8 (scalar); }
+  int8_scalar_value () const { return octave_int8 (scalar); }
 
   octave_int16
-  int16_scalar_value (void) const { return octave_int16 (scalar); }
+  int16_scalar_value () const { return octave_int16 (scalar); }
 
   octave_int32
-  int32_scalar_value (void) const { return octave_int32 (scalar); }
+  int32_scalar_value () const { return octave_int32 (scalar); }
 
   octave_int64
-  int64_scalar_value (void) const { return octave_int64 (scalar); }
+  int64_scalar_value () const { return octave_int64 (scalar); }
 
   octave_uint8
-  uint8_scalar_value (void) const { return octave_uint8 (scalar); }
+  uint8_scalar_value () const { return octave_uint8 (scalar); }
 
   octave_uint16
-  uint16_scalar_value (void) const { return octave_uint16 (scalar); }
+  uint16_scalar_value () const { return octave_uint16 (scalar); }
 
   octave_uint32
-  uint32_scalar_value (void) const { return octave_uint32 (scalar); }
+  uint32_scalar_value () const { return octave_uint32 (scalar); }
 
   octave_uint64
-  uint64_scalar_value (void) const { return octave_uint64 (scalar); }
+  uint64_scalar_value () const { return octave_uint64 (scalar); }
 
   int8NDArray
-  int8_array_value (void) const
+  int8_array_value () const
   { return int8NDArray (dim_vector (1, 1), int8_scalar_value ()); }
 
   int16NDArray
-  int16_array_value (void) const
+  int16_array_value () const
   { return int16NDArray (dim_vector (1, 1), int16_scalar_value ()); }
 
   int32NDArray
-  int32_array_value (void) const
+  int32_array_value () const
   { return int32NDArray (dim_vector (1, 1), int32_scalar_value ()); }
 
   int64NDArray
-  int64_array_value (void) const
+  int64_array_value () const
   { return int64NDArray (dim_vector (1, 1), int64_scalar_value ()); }
 
   uint8NDArray
-  uint8_array_value (void) const
+  uint8_array_value () const
   { return uint8NDArray (dim_vector (1, 1), uint8_scalar_value ()); }
 
   uint16NDArray
-  uint16_array_value (void) const
+  uint16_array_value () const
   { return uint16NDArray (dim_vector (1, 1), uint16_scalar_value ()); }
 
   uint32NDArray
-  uint32_array_value (void) const
+  uint32_array_value () const
   { return uint32NDArray (dim_vector (1, 1), uint32_scalar_value ()); }
 
   uint64NDArray
-  uint64_array_value (void) const
+  uint64_array_value () const
   { return uint64NDArray (dim_vector (1, 1), uint64_scalar_value ()); }
 
   octave_value resize (const dim_vector& dv, bool fill = false) const
@@ -611,12 +611,12 @@
     return retval;
   }
 
-  void increment (void)
+  void increment ()
   {
     scalar += OCTAVE_INT_T (1);
   }
 
-  void decrement (void)
+  void decrement ()
   {
     scalar -= OCTAVE_INT_T (1);
   }
--- a/libinterp/octave-value/ov-java.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-java.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -63,7 +63,6 @@
 #include "oct-process.h"
 #include "oct-shlib.h"
 #include "ov-java.h"
-#include "parse.h"
 #include "variables.h"
 
 #if defined (HAVE_JAVA)
@@ -230,7 +229,7 @@
 {
 public:
 
-  JVMArgs (void)
+  JVMArgs ()
   {
     m_vm_args.version = JNI_VERSION_1_6;
     m_vm_args.nOptions = 0;
@@ -238,7 +237,7 @@
     m_vm_args.ignoreUnrecognized = false;
   }
 
-  ~JVMArgs (void)
+  ~JVMArgs ()
   {
     clean ();
   }
@@ -276,7 +275,7 @@
 
 private:
 
-  void clean (void)
+  void clean ()
   {
     if (m_vm_args.options != nullptr)
       {
@@ -290,7 +289,7 @@
       }
   }
 
-  void update (void)
+  void update ()
   {
     clean ();
 
@@ -341,7 +340,7 @@
 //! the options given by @c java.opts.
 
 static std::string
-initial_java_dir (void)
+initial_java_dir ()
 {
   static std::string java_dir;
 
@@ -420,7 +419,7 @@
 //! @returns The initial classpath.
 
 static std::string
-initial_class_path (void)
+initial_class_path ()
 {
   std::string java_dir = initial_java_dir ();
 
@@ -668,7 +667,7 @@
 //! @see #terminate_jvm()
 
 static void
-initialize_jvm (void)
+initialize_jvm ()
 {
   // Most of the time JVM already exists and has been initialized.
   // Also it seems, as if jvm is set, the jvm is already attached.
@@ -830,7 +829,7 @@
 //! @see #initialize_jvm()
 
 static void
-terminate_jvm (void)
+terminate_jvm ()
 {
   // There is nothing to do if jvm is not set (= nullptr).
   if (jvm)
@@ -894,7 +893,7 @@
 //! @returns A reference to jni, if #jvm is present, otherwise @c nullptr.
 
 static inline JNIEnv *
-thread_jni_env (void)
+thread_jni_env ()
 {
   JNIEnv *env = nullptr;
 
@@ -907,7 +906,7 @@
 #endif
 
 bool
-octave_java::is_java_string (void) const
+octave_java::is_java_string () const
 {
 #if defined (HAVE_JAVA)
 
@@ -1979,7 +1978,7 @@
 //! @returns 0 in any case for good reason.
 
 static int
-java_event_hook (void)
+java_event_hook ()
 {
   JNIEnv *current_env = thread_jni_env ();
 
@@ -2006,7 +2005,7 @@
 //! @c __java_get__, @c __java_set__, and @c __java2mat__.
 
 static void
-initialize_java (void)
+initialize_java ()
 {
   if (! jvm)
     {
@@ -2038,12 +2037,14 @@
   int nargout = env->GetArrayLength (argout);
   int nargin = env->GetArrayLength (argin);
 
-  octave_value_list varargin, varargout;
+  octave_value_list varargin;
 
   for (int i = 0; i < nargin; i++)
     varargin(i) = box (env, env->GetObjectArrayElement (argin, i), nullptr);
 
-  varargout = octave::feval (fname, varargin, nargout);
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave_value_list varargout = interp.feval (fname, varargin, nargout);
 
   jobjectArray_ref out_objs (env, argout), out_clss (env);
   out_objs.detach ();
@@ -2074,10 +2075,12 @@
           oct_args(i) = box (env, jobj, nullptr);
         }
 
+      octave::interpreter& interp = octave::__get_interpreter__ ();
+
       if (val.is_function_handle ())
         {
           octave_function *fcn = val.function_value ();
-          octave::feval (fcn, oct_args);
+          interp.feval (fcn, oct_args);
         }
       else if (val.iscell () && val.length () > 0
                && (val.rows () == 1 || val.columns () == 1)
@@ -2089,7 +2092,7 @@
           for (int i=1; i<c.numel (); i++)
             oct_args(len+i-1) = c(i);
 
-          octave::feval (fcn, oct_args);
+          interp.feval (fcn, oct_args);
         }
       else
         error ("trying to invoke non-invocable object");
@@ -2116,7 +2119,7 @@
 
 //! Ctor.
 
-octave_java::octave_java (void)
+octave_java::octave_java ()
   : octave_base_value (), m_java_object (nullptr), m_java_class (nullptr)
 {
 #if ! defined (HAVE_JAVA)
@@ -2143,16 +2146,16 @@
 #endif
 }
 
-int octave_java::t_id (-1);
-
-const std::string octave_java::t_name ("octave_java");
+int octave_java::s_t_id (-1);
+
+const std::string octave_java::s_t_name ("octave_java");
 
 void
 octave_java::register_type (octave::type_info& ti)
 {
 #if defined (HAVE_JAVA)
 
-  t_id = ti.register_type (octave_java::t_name, "<unknown>",
+  s_t_id = ti.register_type (octave_java::s_t_name, "<unknown>",
                            octave_value (new octave_java ()));
 
 #else
@@ -2163,7 +2166,7 @@
 }
 
 dim_vector
-octave_java::dims (void) const
+octave_java::dims () const
 {
 #if defined (HAVE_JAVA)
 
@@ -2200,10 +2203,10 @@
     case '.':
       if (type.length () > 1 && type[1] == '(')
         {
-          octave_value_list ovl;
-          count++;
+          octave_value_list ovl (2);
+          m_count++;
+          ovl(0) = (idx.front ())(0);
           ovl(1) = octave_value (this);
-          ovl(0) = (idx.front ())(0);
           auto it = idx.begin ();
           ovl.append (*++it);
           retval = octave::FjavaMethod (ovl, 1);
@@ -2211,8 +2214,8 @@
         }
       else
         {
-          octave_value_list ovl;
-          count++;
+          octave_value_list ovl (2);
+          m_count++;
           ovl(0) = octave_value (this);
           ovl(1) = (idx.front ())(0);
           retval = octave::F__java_get__ (ovl, 1);
@@ -2266,14 +2269,14 @@
       if (type.length () == 1)
         {
           // field assignment
-          octave_value_list ovl;
-          count++;
+          octave_value_list ovl (3);
+          m_count++;
           ovl(0) = octave_value (this);
           ovl(1) = (idx.front ())(0);
           ovl(2) = rhs;
           octave::F__java_set__ (ovl);
 
-          count++;
+          m_count++;
           retval = octave_value (this);
         }
       else if (type.length () > 2 && type[1] == '(')
@@ -2289,7 +2292,7 @@
           next_idx.erase (next_idx.begin ());
           u(0).subsasgn (type.substr (2), next_idx, rhs);
 
-          count++;
+          m_count++;
           retval = octave_value (this);
         }
       else if (type[1] == '.')
@@ -2300,7 +2303,7 @@
           next_idx.erase (next_idx.begin ());
           u(0).subsasgn (type.substr (1), next_idx, rhs);
 
-          count++;
+          m_count++;
           retval = octave_value (this);
         }
       else
@@ -2313,7 +2316,7 @@
           set_array_elements (current_env, TO_JOBJECT (to_java ()),
                               idx.front (), rhs);
 
-          count++;
+          m_count++;
           retval = octave_value (this);
         }
       break;
@@ -2340,7 +2343,7 @@
 }
 
 string_vector
-octave_java::map_keys (void) const
+octave_java::map_keys () const
 {
 #if defined (HAVE_JAVA)
 
@@ -3004,7 +3007,7 @@
 }
 
 void
-octave_java::release (void)
+octave_java::release ()
 {
 #if defined (HAVE_JAVA)
 
--- a/libinterp/octave-value/ov-java.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-java.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 {
 public:
 
-  octave_java (void);
+  octave_java ();
 
   octave_java (const voidptr& obj, void *cls = nullptr);
 
@@ -53,29 +53,29 @@
     init (jobj.m_java_object, jobj.m_java_class);
   }
 
-  ~octave_java (void) { release (); }
+  ~octave_java () { release (); }
 
-  void * to_java (void) const { return m_java_object; }
-  void * to_class (void) const { return m_java_class; }
+  void * to_java () const { return m_java_object; }
+  void * to_class () const { return m_java_class; }
 
-  std::string java_class_name (void) const { return m_java_classname; }
+  std::string java_class_name () const { return m_java_classname; }
 
-  octave_base_value * clone (void) const { return new octave_java (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_java (); }
+  octave_base_value * clone () const { return new octave_java (*this); }
+  octave_base_value * empty_clone () const { return new octave_java (); }
 
   bool is_instance_of (const std::string&) const;
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool isstruct (void) const { return false; }
+  bool isstruct () const { return false; }
 
-  bool isjava (void) const { return true; }
+  bool isjava () const { return true; }
 
-  string_vector map_keys (void) const;
+  string_vector map_keys () const;
 
-  dim_vector dims (void) const;
+  dim_vector dims () const;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -117,7 +117,7 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  bool is_java_string (void) const;
+  bool is_java_string () const;
 
   octave_value do_javaMethod (void *jni_env, const std::string& name,
                               const octave_value_list& args);
@@ -168,7 +168,7 @@
 
   void init (void *jobj, void *jcls);
 
-  void release (void);
+  void release ();
 
 private:
 
@@ -180,19 +180,19 @@
 
 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 m_java_classname; }
+  int type_id () const { return s_t_id; }
+  std::string type_name () const { return s_t_name; }
+  std::string class_name () const { return m_java_classname; }
 
-  static int static_type_id (void) { return t_id; }
-  static std::string static_type_name (void) { return t_name; }
-  static std::string static_class_name (void) { return "<unknown>"; }
+  static int static_type_id () { return s_t_id; }
+  static std::string static_type_name () { return s_t_name; }
+  static std::string static_class_name () { return "<unknown>"; }
   static void register_type (octave::type_info&);
 
 private:
 
-  static int t_id;
-  static const std::string t_name;
+  static int s_t_id;
+  static const std::string s_t_name;
 };
 
 extern OCTINTERP_API bool Vjava_matrix_autoconversion;
--- a/libinterp/octave-value/ov-lazy-idx.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-lazy-idx.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,14 +44,14 @@
 }
 
 octave_base_value::type_conv_info
-octave_lazy_index::numeric_conversion_function (void) const
+octave_lazy_index::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_matrix::static_type_id ());
 }
 
 octave_base_value *
-octave_lazy_index::try_narrowing_conversion (void)
+octave_lazy_index::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -97,7 +97,7 @@
 }
 
 octave_value
-octave_lazy_index::squeeze (void) const
+octave_lazy_index::squeeze () const
 {
   return octave::idx_vector (m_index.as_array ().squeeze (),
                              m_index.extent (0));
@@ -161,61 +161,61 @@
 }
 
 octave_value
-octave_lazy_index::as_double (void) const
+octave_lazy_index::as_double () const
 {
   return array_value ();
 }
 
 octave_value
-octave_lazy_index::as_single (void) const
+octave_lazy_index::as_single () const
 {
   return float_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_int8 (void) const
+octave_lazy_index::as_int8 () const
 {
   return int8_array_value  ();
 }
 
 octave_value
-octave_lazy_index::as_int16 (void) const
+octave_lazy_index::as_int16 () const
 {
   return int16_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_int32 (void) const
+octave_lazy_index::as_int32 () const
 {
   return int32_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_int64 (void) const
+octave_lazy_index::as_int64 () const
 {
   return int64_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_uint8 (void) const
+octave_lazy_index::as_uint8 () const
 {
   return uint8_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_uint16 (void) const
+octave_lazy_index::as_uint16 () const
 {
   return uint16_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_uint32 (void) const
+octave_lazy_index::as_uint32 () const
 {
   return uint32_array_value ();
 }
 
 octave_value
-octave_lazy_index::as_uint64 (void) const
+octave_lazy_index::as_uint64 () const
 {
   return uint64_array_value ();
 }
--- a/libinterp/octave-value/ov-lazy-idx.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-lazy-idx.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  octave_lazy_index (void)
+  octave_lazy_index ()
     : octave_base_value (), m_index (), m_value () { }
 
   octave_lazy_index (const octave::idx_vector& idx)
@@ -48,37 +48,37 @@
   octave_lazy_index (const octave_lazy_index& i)
     : octave_base_value (), m_index (i.m_index), m_value (i.m_value) { }
 
-  ~octave_lazy_index (void) = default;
+  ~octave_lazy_index () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_lazy_index (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_matrix (); }
+  octave_base_value * empty_clone () const { return new octave_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave_value fast_elem_extract (octave_idx_type n) const;
 
-  std::size_t byte_size (void) const
+  std::size_t byte_size () const
   { return numel () * sizeof (octave_idx_type); }
 
-  octave_value squeeze (void) const;
+  octave_value squeeze () const;
 
-  octave_value full_value (void) const { return make_value (); }
+  octave_value full_value () const { return make_value (); }
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   { return m_index; }
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -97,11 +97,11 @@
                             bool resize_ok = false)
   { return make_value ().index_op (idx, resize_ok); }
 
-  dim_vector dims (void) const { return m_index.orig_dimensions (); }
+  dim_vector dims () const { return m_index.orig_dimensions (); }
 
-  octave_idx_type numel (void) const { return m_index.length (0); }
+  octave_idx_type numel () const { return m_index.length (0); }
 
-  octave_idx_type nnz (void) const { return numel (); }
+  octave_idx_type nnz () const { return numel (); }
 
   octave_value reshape (const dim_vector& new_dims) const;
 
@@ -113,7 +113,7 @@
   octave_value all (int dim = 0) const { return make_value ().all (dim); }
   octave_value any (int dim = 0) const { return make_value ().any (dim); }
 
-  MatrixType matrix_type (void) const { return make_value ().matrix_type (); }
+  MatrixType matrix_type () const { return make_value ().matrix_type (); }
   MatrixType matrix_type (const MatrixType& _typ) const
   { return make_value ().matrix_type (_typ); }
 
@@ -128,18 +128,18 @@
 
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
-  bool is_matrix_type (void) const { return true; }
+  bool is_matrix_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_true (void) const
+  bool is_true () const
   { return make_value ().is_true (); }
 
-  bool print_as_scalar (void) const
+  bool print_as_scalar () const
   { return make_value ().print_as_scalar (); }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false)
@@ -149,7 +149,7 @@
   { make_value ().print_info (os, prefix); }
 
 #define FORWARD_VALUE_QUERY(TYPE, NAME)         \
-  TYPE NAME (void) const                        \
+  TYPE NAME () const                        \
   {                                             \
     return make_value ().NAME ();               \
   }
@@ -202,18 +202,18 @@
     return make_value ().convert_to_str_internal (pad, force, type);
   }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const
   {
@@ -238,7 +238,7 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data (void) const
+  const void * mex_get_data () const
   {
     return make_value ().mex_get_data ();
   }
@@ -255,7 +255,7 @@
 
 private:
 
-  const octave_value& make_value (void) const
+  const octave_value& make_value () const
   {
     if (m_value.is_undefined ())
       m_value = octave_value (m_index, false);
@@ -263,7 +263,7 @@
     return m_value;
   }
 
-  octave_value& make_value (void)
+  octave_value& make_value ()
   {
     if (m_value.is_undefined ())
       m_value = octave_value (m_index, false);
--- a/libinterp/octave-value/ov-legacy-range.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-legacy-range.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -31,6 +31,7 @@
 #include <ostream>
 #include <sstream>
 
+#include "Range.h"
 #include "lo-ieee.h"
 #include "lo-utils.h"
 
@@ -49,23 +50,326 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+class
+Range
+{
+public:
+
+  Range ()
+    : m_base (0), m_limit (0), m_inc (0), m_numel (0)
+  { }
+
+  // Assume range is already properly constructed, so just copy internal
+  // values.  However, we set LIMIT to the computed final value because
+  // that mimics the behavior of the other Range class constructors that
+  // reset limit to the computed final value.
+
+  Range (const octave::range<double>& r)
+    : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()),
+      m_numel (r.numel ())
+  { }
+
+  Range (const Range& r) = default;
+
+  Range& operator = (const Range& r) = default;
+
+  ~Range () = default;
+
+  Range (double b, double l)
+    : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ())
+  {
+    if (! octave::math::isinf (m_limit))
+      m_limit = limit_internal ();
+  }
+
+  Range (double b, double l, double i)
+    : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ())
+  {
+    if (! octave::math::isinf (m_limit))
+      m_limit = limit_internal ();
+  }
+
+  // The range has a finite number of elements.
+  bool ok () const
+  {
+    return (octave::math::isfinite (m_limit)
+            && (m_numel >= 0 || m_numel == -2));
+  }
+
+  double base () const { return m_base; }
+  double limit () const { return m_limit; }
+  double increment () const { return m_inc; }
+
+  octave_idx_type numel () const { return m_numel; }
+
+  bool all_elements_are_ints () const;
+
+  Matrix matrix_value () const;
+
+  double min () const;
+  double max () const;
+
+private:
+
+  double m_base;
+  double m_limit;
+  double m_inc;
+
+  octave_idx_type m_numel;
+
+  octave_idx_type numel_internal () const;
+
+  double limit_internal () const;
+
+  void init ();
+};
+
+bool
+Range::all_elements_are_ints () const
+{
+  // If the base and increment are ints, the final value in the range will also
+  // be an integer, even if the limit is not.  If there is one or fewer
+  // elements only the base needs to be an integer.
+
+  return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc))
+          && (octave::math::nint_big (m_base) == m_base || m_numel < 1)
+          && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1));
+}
+
+Matrix
+Range::matrix_value () const
+{
+  Matrix retval (1, m_numel);
+
+  if (m_numel > 0)
+    {
+      // The first element must always be *exactly* the base.
+      // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).
+      retval(0) = m_base;
+
+      double b = m_base;
+      double increment = m_inc;
+      for (octave_idx_type i = 1; i < m_numel - 1; i++)
+        retval.xelem (i) = b + i * increment;
+
+      retval.xelem (m_numel - 1) = m_limit;
+    }
+
+  return retval;
+}
+
+// NOTE: max and min only return useful values if numel > 0.
+//       do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0.
+
+double
+Range::min () const
+{
+  double retval = 0.0;
+  if (m_numel > 0)
+    {
+      if (m_inc > 0)
+        retval = m_base;
+      else
+        {
+          retval = m_base + (m_numel - 1) * m_inc;
+
+          // Require '<=' test.  See note in max ().
+          if (retval <= m_limit)
+            retval = m_limit;
+        }
+
+    }
+  return retval;
+}
+
+double
+Range::max () const
+{
+  double retval = 0.0;
+  if (m_numel > 0)
+    {
+      if (m_inc > 0)
+        {
+          retval = m_base + (m_numel - 1) * m_inc;
+
+          // On some machines (x86 with extended precision floating point
+          // arithmetic, for example) it is possible that we can overshoot the
+          // limit by approximately the machine precision even though we were
+          // very careful in our calculation of the number of elements.
+          // Therefore, we clip the result to the limit if it overshoots.
+          // The test also includes equality (>= m_limit) to have expressions
+          // such as -5:1:-0 result in a -0 endpoint.
+          if (retval >= m_limit)
+            retval = m_limit;
+        }
+      else
+        retval = m_base;
+    }
+  return retval;
+}
+
+// C  See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5.
+// C
+// C===Tolerant FLOOR function.
+// C
+// C    X  -  is given as a Double Precision argument to be operated on.
+// C          It is assumed that X is represented with M mantissa bits.
+// C    CT -  is   given   as   a   Comparison   Tolerance   such   that
+// C          0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between
+// C          X and A whole number is  less  than  CT,  then  TFLOOR  is
+// C          returned   as   this   whole   number.   By  treating  the
+// C          floating-point numbers as a finite ordered set  note  that
+// C          the  heuristic  EPS=2.**(-(M-1))   and   CT=3*EPS   causes
+// C          arguments  of  TFLOOR/TCEIL to be treated as whole numbers
+// C          if they are  exactly  whole  numbers  or  are  immediately
+// C          adjacent to whole number representations.  Since EPS,  the
+// C          "distance"  between  floating-point  numbers  on  the unit
+// C          interval, and M, the number of bits in X'S mantissa, exist
+// C          on  every  floating-point   computer,   TFLOOR/TCEIL   are
+// C          consistently definable on every floating-point computer.
+// C
+// C          For more information see the following references:
+// C    (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL  QUOTE
+// C        QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5.
+// C    (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling",  APL
+// C        QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through
+// C        FL5, the history of five years of evolutionary development of
+// C        FL5 - the seven lines of code below - by open collaboration
+// C        and corroboration of the mathematical-computing community.
+// C
+// C  Penn State University Center for Academic Computing
+// C  H. D. Knoble - August, 1978.
+
+static inline double
+tfloor (double x, double ct)
+{
+// C---------FLOOR(X) is the largest integer algebraically less than
+// C         or equal to X; that is, the unfuzzy FLOOR function.
+
+//  DINT (X) = X - DMOD (X, 1.0);
+//  FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0);
+
+// C---------Hagerty's FL5 function follows...
+
+  double q = 1.0;
+
+  if (x < 0.0)
+    q = 1.0 - ct;
+
+  double rmax = q / (2.0 - ct);
+
+  double t1 = 1.0 + std::floor (x);
+  t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1);
+  t1 = (rmax < t1 ? rmax : t1);
+  t1 = (ct > t1 ? ct : t1);
+  t1 = std::floor (x + t1);
+
+  if (x <= 0.0 || (t1 - x) < rmax)
+    return t1;
+  else
+    return t1 - 1.0;
+}
+
+static inline bool
+teq (double u, double v,
+     double ct = 3.0 * std::numeric_limits<double>::epsilon ())
+{
+  double tu = std::abs (u);
+  double tv = std::abs (v);
+
+  return std::abs (u - v) < ((tu > tv ? tu : tv) * ct);
+}
+
+octave_idx_type
+Range::numel_internal () const
+{
+  octave_idx_type retval = -1;
+
+  if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc)
+      || octave::math::isnan (m_limit))
+    retval = -2;
+  else if (octave::math::isinf (m_limit)
+           && ((m_inc > 0 && m_limit > 0)
+               || (m_inc < 0 && m_limit < 0)))
+    retval = std::numeric_limits<octave_idx_type>::max () - 1;
+  else if (m_inc == 0
+           || (m_limit > m_base && m_inc < 0)
+           || (m_limit < m_base && m_inc > 0))
+    {
+      retval = 0;
+    }
+  else
+    {
+      double ct = 3.0 * std::numeric_limits<double>::epsilon ();
+
+      double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct);
+
+      octave_idx_type n_elt = (tmp > 0.0
+                               ? static_cast<octave_idx_type> (tmp) : 0);
+
+      // If the final element that we would compute for the range is equal to
+      // the limit of the range, or is an adjacent floating point number,
+      // accept it.  Otherwise, try a range with one fewer element.  If that
+      // fails, try again with one more element.
+      //
+      // I'm not sure this is very good, but it seems to work better than just
+      // using tfloor as above.  For example, without it, the expression
+      // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9].
+
+      if (! teq (m_base + (n_elt - 1) * m_inc, m_limit))
+        {
+          if (teq (m_base + (n_elt - 2) * m_inc, m_limit))
+            n_elt--;
+          else if (teq (m_base + n_elt * m_inc, m_limit))
+            n_elt++;
+        }
+
+      retval = ((n_elt < std::numeric_limits<octave_idx_type>::max ())
+                ? n_elt : -1);
+    }
+
+  return retval;
+}
+
+double
+Range::limit_internal () const
+{
+  double new_limit = m_inc > 0 ? max () : min ();
+
+  // If result must be an integer then force the new_limit to be one.
+  if (all_elements_are_ints ())
+    new_limit = std::round (new_limit);
+
+  return new_limit;
+}
+
+void
+Range::init ()
+{
+  m_numel = numel_internal ();
+
+  if (! octave::math::isinf (m_limit))
+    m_limit = limit_internal ();
+}
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_legacy_range, "range", "double");
 
-octave_legacy_range::octave_legacy_range (void)
-  : octave_base_value (), range () { }
+octave_legacy_range::octave_legacy_range ()
+  : octave_base_value (), m_range (new Range ()) { }
 
 octave_legacy_range::octave_legacy_range (const Range& r)
-  : octave_base_value (), range (r)
+  : octave_base_value (), m_range (new Range (r))
 {
-  if (range.numel () < 0 && range.numel () != -2)
+  if (m_range->numel () < 0 && m_range->numel () != -2)
     error ("invalid range");
 }
 
+octave_legacy_range::octave_legacy_range (const octave_legacy_range& r)
+  : octave_base_value (r), m_range ()
+{
+  m_range.reset (new Range (*(r.m_range)));
+}
+
 static octave_base_value *
 default_numeric_conversion_function (const octave_base_value& a)
 {
@@ -75,21 +379,21 @@
 }
 
 octave_base_value::type_conv_info
-octave_legacy_range::numeric_conversion_function (void) const
+octave_legacy_range::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
-         octave_matrix::static_type_id ());
+                                            octave_matrix::static_type_id ());
 }
 
 octave_base_value *
-octave_legacy_range::try_narrowing_conversion (void)
+octave_legacy_range::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
-  switch (range.numel ())
+  switch (m_range->numel ())
     {
     case 1:
-      retval = new octave_scalar (range.base ());
+      retval = new octave_scalar (m_range->base ());
       break;
 
     case 0:
@@ -97,17 +401,17 @@
       break;
 
     case -2:
-      retval = new octave_matrix (range.matrix_value ());
+      retval = new octave_matrix (m_range->matrix_value ());
       break;
 
     default:
       {
-        if (range.increment () == 0)
-          retval = new octave_matrix (range.matrix_value ());
+        if (m_range->increment () == 0)
+          retval = new octave_matrix (m_range->matrix_value ());
         else
           retval = new octave_range
-          (octave::range<double> (range.base (), range.increment (),
-                                  range.limit (), range.numel ()));
+            (octave::range<double> (m_range->base (), m_range->increment (),
+                                    m_range->limit (), m_range->numel ()));
       }
       break;
     }
@@ -145,9 +449,9 @@
     error ("load: failed to load range constant");
 
   if (inc != 0)
-    range = Range (base, limit, inc);
+    m_range.reset (new Range (base, limit, inc));
   else
-    range = Range (base, inc, static_cast<octave_idx_type> (limit));
+    m_range.reset (new Range (base, inc, static_cast<octave_idx_type> (limit)));
 
   return true;
 }
@@ -173,9 +477,9 @@
   if (swap)
     swap_bytes<8> (&inc);
   if (inc != 0)
-    range = Range (bas, lim, inc);
+    m_range.reset (new Range (bas, lim, inc));
   else
-    range = Range (bas, inc, static_cast<octave_idx_type> (lim));
+    m_range.reset (new Range (bas, inc, static_cast<octave_idx_type> (lim)));
 
   return true;
 }
@@ -245,14 +549,14 @@
       octave_idx_type nel;
       if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX,
                                 "OCTAVE_RANGE_NELEM", &nel))
-        range = Range (rangevals[0], rangevals[2], nel);
+        m_range.reset (new Range (rangevals[0], rangevals[2], nel));
       else
         {
           if (rangevals[2] != 0)
-            range = Range (rangevals[0], rangevals[1], rangevals[2]);
+            m_range.reset (new Range (rangevals[0], rangevals[1], rangevals[2]));
           else
-            range = Range (rangevals[0], rangevals[2],
-                           static_cast<octave_idx_type> (rangevals[1]));
+            m_range.reset (new Range (rangevals[0], rangevals[2],
+                                      static_cast<octave_idx_type> (rangevals[1])));
         }
     }
 
@@ -269,7 +573,3 @@
 
   return retval;
 }
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
--- a/libinterp/octave-value/ov-legacy-range.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-legacy-range.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,10 +31,9 @@
 #include <cstdlib>
 
 #include <iosfwd>
+#include <memory>
 #include <string>
 
-#include "Range.h"
-
 #include "lo-mappers.h"
 #include "lo-utils.h"
 #include "mx-base.h"
@@ -45,6 +44,8 @@
 #include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 
+class Range;
+
 class octave_value_list;
 
 // Legacy Range values.
@@ -61,19 +62,19 @@
 {
 public:
 
-  octave_legacy_range (void);
+  octave_legacy_range ();
 
   octave_legacy_range (const Range& r);
 
-  octave_legacy_range (const octave_legacy_range& r) = default;
+  octave_legacy_range (const octave_legacy_range& r);
 
   // No assignment.
 
   octave_legacy_range& operator = (const octave_legacy_range&) = delete;
 
-  ~octave_legacy_range (void) { }
+  ~octave_legacy_range () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new octave_legacy_range (*this);
   }
@@ -81,17 +82,17 @@
   // A range is really just a special kind of real matrix object.  In
   // the places where we need to call empty_clone, it makes more sense
   // to create an empty matrix (0x0) instead of an empty range (1x0).
-  octave_base_value * empty_clone (void) const { return new octave_matrix (); }
+  octave_base_value * empty_clone () const { return new octave_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_legacy_object (void) const { return true; }
+  bool is_legacy_object () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
   bool load_ascii (std::istream& is);
 
@@ -102,7 +103,7 @@
 
 private:
 
-  Range range;
+  std::unique_ptr<Range> m_range;
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
--- a/libinterp/octave-value/ov-magic-int.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-magic-int.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -104,70 +104,70 @@
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_double (void) const
+octave_base_magic_int<T>::as_double () const
 {
   return static_cast<double> (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_single (void) const
+octave_base_magic_int<T>::as_single () const
 {
   return static_cast<float> (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_int8 (void) const
+octave_base_magic_int<T>::as_int8 () const
 {
   return octave_int8 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_int16 (void) const
+octave_base_magic_int<T>::as_int16 () const
 {
   return octave_int16 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_int32 (void) const
+octave_base_magic_int<T>::as_int32 () const
 {
   return octave_int32 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_int64 (void) const
+octave_base_magic_int<T>::as_int64 () const
 {
   return octave_int64 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_uint8 (void) const
+octave_base_magic_int<T>::as_uint8 () const
 {
   return octave_uint8 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_uint16 (void) const
+octave_base_magic_int<T>::as_uint16 () const
 {
   return octave_uint16 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_uint32 (void) const
+octave_base_magic_int<T>::as_uint32 () const
 {
   return octave_uint32 (scalar_ref ());
 }
 
 template <typename T>
 octave_value
-octave_base_magic_int<T>::as_uint64 (void) const
+octave_base_magic_int<T>::as_uint64 () const
 {
   return octave_uint64 (scalar_ref ());
 }
@@ -306,7 +306,7 @@
                                      "double");
 
 octave_base_value::type_conv_info
-octave_magic_uint::numeric_conversion_function (void) const
+octave_magic_uint::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conv_fcn,
          octave_scalar::static_type_id ());
@@ -316,7 +316,7 @@
                                      "double");
 
 octave_base_value::type_conv_info
-octave_magic_int::numeric_conversion_function (void) const
+octave_magic_int::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conv_fcn,
          octave_scalar::static_type_id ());
--- a/libinterp/octave-value/ov-magic-int.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-magic-int.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,26 +52,26 @@
 {
 public:
 
-  octave_base_magic_int (void)
+  octave_base_magic_int ()
     : octave_base_scalar<T> (0) { }
 
   octave_base_magic_int (const T& val)
     : octave_base_scalar<T> (val) { }
 
-  ~octave_base_magic_int (void) = default;
+  ~octave_base_magic_int () = default;
 
   // We return an octave_matrix here instead of an octave_scalar so
   // that in expressions like A(2,2,2) = 2 (for A previously
   // undefined), A will be empty instead of a 1x1 object.
-  octave_base_value * empty_clone (void) const { return new octave_matrix (); }
+  octave_base_value * empty_clone () const { return new octave_matrix (); }
 
   // Although SCALAR is a protected member of the base class, it is not
   // directly visible here without the explicit octave_base_slalar<T>::
   // qualification.  Why not?
 
-  const T& scalar_ref (void) const { return octave_base_scalar<T>::scalar; }
+  const T& scalar_ref () const { return octave_base_scalar<T>::scalar; }
 
-  T& scalar_ref (void) { return octave_base_scalar<T>::scalar; }
+  T& scalar_ref () { return octave_base_scalar<T>::scalar; }
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
@@ -80,66 +80,67 @@
 
   octave_value any (int = 0) const { return scalar_ref () != T (0); }
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
-
-  bool is_storable (void) const { return false; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_magic_int (void) const { return true; }
+  bool is_storable () const { return false; }
 
-  bool is_real_scalar (void) const { return true; }
+  bool is_magic_int () const { return true; }
+  bool vm_need_storable_call (void) const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  int8NDArray int8_array_value (void) const
+  bool isfloat () const { return true; }
+
+  int8NDArray int8_array_value () const
   { return int8NDArray (dim_vector (1, 1), double_value ()); }
 
-  int16NDArray int16_array_value (void) const
+  int16NDArray int16_array_value () const
   { return int16NDArray (dim_vector (1, 1), double_value ()); }
 
-  int32NDArray int32_array_value (void) const
+  int32NDArray int32_array_value () const
   { return int32NDArray (dim_vector (1, 1), double_value ()); }
 
-  int64NDArray int64_array_value (void) const
+  int64NDArray int64_array_value () const
   { return int64NDArray (dim_vector (1, 1), double_value ()); }
 
-  uint8NDArray uint8_array_value (void) const
+  uint8NDArray uint8_array_value () const
   { return uint8NDArray (dim_vector (1, 1), double_value ()); }
 
-  uint16NDArray uint16_array_value (void) const
+  uint16NDArray uint16_array_value () const
   { return uint16NDArray (dim_vector (1, 1), double_value ()); }
 
-  uint32NDArray uint32_array_value (void) const
+  uint32NDArray uint32_array_value () const
   { return uint32NDArray (dim_vector (1, 1), double_value ()); }
 
-  uint64NDArray uint64_array_value (void) const
+  uint64NDArray uint64_array_value () const
   { return uint64NDArray (dim_vector (1, 1), double_value ()); }
 
-  octave_int8 int8_scalar_value (void) const
+  octave_int8 int8_scalar_value () const
   { return octave_int8 (double_value ()); }
 
-  octave_int16 int16_scalar_value (void) const
+  octave_int16 int16_scalar_value () const
   { return octave_int16 (double_value ()); }
 
-  octave_int32 int32_scalar_value (void) const
+  octave_int32 int32_scalar_value () const
   { return octave_int32 (double_value ()); }
 
-  octave_int64 int64_scalar_value (void) const
+  octave_int64 int64_scalar_value () const
   { return octave_int64 (double_value ()); }
 
-  octave_uint8 uint8_scalar_value (void) const
+  octave_uint8 uint8_scalar_value () const
   { return octave_uint8 (double_value ()); }
 
-  octave_uint16 uint16_scalar_value (void) const
+  octave_uint16 uint16_scalar_value () const
   { return octave_uint16 (double_value ()); }
 
-  octave_uint32 uint32_scalar_value (void) const
+  octave_uint32 uint32_scalar_value () const
   { return octave_uint32 (double_value ()); }
 
-  octave_uint64 uint64_scalar_value (void) const
+  octave_uint64 uint64_scalar_value () const
   { return octave_uint64 (double_value ()); }
 
   double double_value (bool = false) const
@@ -221,18 +222,18 @@
     return boolNDArray (dim_vector (1, 1), double_value ());
   }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   // We don't need to override both forms of the diag method.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -243,9 +244,9 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  void increment (void) { scalar_ref () += T (1); }
+  void increment () { scalar_ref () += T (1); }
 
-  void decrement (void) { scalar_ref () -= T (1); }
+  void decrement () { scalar_ref () -= T (1); }
 
   bool save_ascii (std::ostream& os);
 
@@ -279,20 +280,20 @@
 {
 public:
 
-  octave_magic_uint (void)
+  octave_magic_uint ()
     : octave_base_magic_int<octave_uint64> (0) { }
 
   octave_magic_uint (const octave_uint64& val)
     : octave_base_magic_int<octave_uint64> (val) { }
 
-  ~octave_magic_uint (void) = default;
+  ~octave_magic_uint () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new octave_magic_uint (*this);
   }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
 private:
 
@@ -305,20 +306,20 @@
 {
 public:
 
-  octave_magic_int (void)
+  octave_magic_int ()
     : octave_base_magic_int<octave_int64> (0) { }
 
   octave_magic_int (const octave_int64& val)
     : octave_base_magic_int<octave_int64> (val) { }
 
-  ~octave_magic_int (void) = default;
+  ~octave_magic_int () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new octave_magic_int (*this);
   }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
 private:
 
--- a/libinterp/octave-value/ov-mex-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -68,7 +68,7 @@
        && oct_file_dir == file_name.substr (0, oct_file_dir.length ()));
 }
 
-octave_mex_function::~octave_mex_function (void)
+octave_mex_function::~octave_mex_function ()
 {
   if (m_exit_fcn_ptr)
     (*m_exit_fcn_ptr) ();
@@ -79,13 +79,13 @@
 }
 
 std::string
-octave_mex_function::fcn_file_name (void) const
+octave_mex_function::fcn_file_name () const
 {
   return m_sh_lib.file_name ();
 }
 
 octave::sys::time
-octave_mex_function::time_parsed (void) const
+octave_mex_function::time_parsed () const
 {
   return m_sh_lib.time_loaded ();
 }
--- a/libinterp/octave-value/ov-mex-fcn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-mex-fcn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 {
 public:
 
-  octave_mex_function (void)
+  octave_mex_function ()
     : m_mex_fcn_ptr (nullptr), m_exit_fcn_ptr (nullptr), m_sh_lib (),
       m_time_checked (), m_interleaved (false), m_is_fmex (false),
       m_is_system_fcn_file (false)
@@ -62,13 +62,9 @@
                        const octave::dynamic_library& shl,
                        const std::string& nm = "");
 
-  // No copying!
-
-  octave_mex_function (const octave_mex_function& fcn) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_mex_function)
 
-  octave_mex_function& operator = (const octave_mex_function& fcn) = delete;
-
-  ~octave_mex_function (void);
+  ~octave_mex_function ();
 
   octave_function * function_value (bool = false) { return this; }
 
@@ -79,37 +75,37 @@
     m_time_checked = t;
   }
 
-  std::string fcn_file_name (void) const;
+  std::string fcn_file_name () const;
 
-  octave::sys::time time_parsed (void) const;
+  octave::sys::time time_parsed () const;
 
-  octave::sys::time time_checked (void) const { return m_time_checked; }
+  octave::sys::time time_checked () const { return m_time_checked; }
 
-  bool is_system_fcn_file (void) const { return m_is_system_fcn_file; }
+  bool is_system_fcn_file () const { return m_is_system_fcn_file; }
 
-  bool is_builtin_function (void) const { return false; }
+  bool is_builtin_function () const { return false; }
 
-  bool is_mex_function (void) const { return true; }
+  bool is_mex_function () const { return true; }
 
-  bool use_interleaved_complex (void) const { return m_interleaved; }
+  bool use_interleaved_complex () const { return m_interleaved; }
 
   octave_value_list
   execute (octave::tree_evaluator& tw, int nargout = 0,
            const octave_value_list& args = octave_value_list ());
 
-  void atexit (void (*fcn) (void)) { m_exit_fcn_ptr = fcn; }
+  void atexit (void (*fcn) ()) { m_exit_fcn_ptr = fcn; }
 
-  octave::dynamic_library get_shlib (void) const { return m_sh_lib; }
+  octave::dynamic_library get_shlib () const { return m_sh_lib; }
 
-  void * mex_fcn_ptr (void) const { return m_mex_fcn_ptr; }
+  void * mex_fcn_ptr () const { return m_mex_fcn_ptr; }
 
-  bool is_fmex (void) const { return m_is_fmex; }
+  bool is_fmex () const { return m_is_fmex; }
 
 private:
 
   void *m_mex_fcn_ptr;
 
-  void (*m_exit_fcn_ptr) (void);
+  void (*m_exit_fcn_ptr) ();
 
   octave::dynamic_library m_sh_lib;
 
--- a/libinterp/octave-value/ov-null-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-null-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_null_matrix::numeric_conversion_function (void) const
+octave_null_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info
          (default_null_matrix_numeric_conversion_function,
@@ -67,7 +67,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_null_str::numeric_conversion_function (void) const
+octave_null_str::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info
          (default_null_str_numeric_conversion_function,
@@ -89,7 +89,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_null_sq_str::numeric_conversion_function (void) const
+octave_null_sq_str::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info
          (default_null_sq_str_numeric_conversion_function,
--- a/libinterp/octave-value/ov-null-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-null-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,15 +45,16 @@
 OCTINTERP_API
 octave_null_matrix : public octave_matrix
 {
-  octave_null_matrix (void) : octave_matrix () { }
+  octave_null_matrix () : octave_matrix () { }
 
 public:
 
   static const octave_value instance;
 
-  bool isnull (void) const { return true; }
+  bool isnull () const { return true; }
+  bool vm_need_storable_call (void) const { return true; }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
 private:
 
@@ -66,17 +67,18 @@
 OCTINTERP_API
 octave_null_str : public octave_char_matrix_str
 {
-  octave_null_str (void) : octave_char_matrix_str () { }
+  octave_null_str () : octave_char_matrix_str () { }
 
 public:
 
   static const octave_value instance;
 
-  bool is_storable (void) const { return false; }
+  bool is_storable () const { return false; }
 
-  bool isnull (void) const { return true; }
+  bool isnull () const { return true; }
+  bool vm_need_storable_call (void) const { return true; }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
 private:
 
@@ -89,17 +91,18 @@
 OCTINTERP_API
 octave_null_sq_str : public octave_char_matrix_sq_str
 {
-  octave_null_sq_str (void) : octave_char_matrix_sq_str () { }
+  octave_null_sq_str () : octave_char_matrix_sq_str () { }
 
 public:
 
   static const octave_value instance;
 
-  bool is_storable (void) const { return false; }
+  bool is_storable () const { return false; }
 
-  bool isnull (void) const { return true; }
+  bool isnull () const { return true; }
+  bool vm_need_storable_call (void) const { return true; }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
 private:
 
--- a/libinterp/octave-value/ov-oncleanup.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-oncleanup.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,6 @@
 #include "ov-oncleanup.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
-#include "parse.h"
 #include "pt-misc.h"
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, "onCleanup",
@@ -66,13 +65,13 @@
     }
 }
 
-octave_oncleanup::~octave_oncleanup (void)
+octave_oncleanup::~octave_oncleanup ()
 {
   call_object_destructor ();
 }
 
 octave_scalar_map
-octave_oncleanup::scalar_map_value (void) const
+octave_oncleanup::scalar_map_value () const
 {
   octave_scalar_map retval;
   retval.setfield ("task", m_fcn);
@@ -146,7 +145,7 @@
 }
 
 void
-octave_oncleanup::call_object_destructor (void)
+octave_oncleanup::call_object_destructor ()
 {
   if (m_fcn.is_undefined ())
     return;
@@ -171,7 +170,7 @@
   try
     {
       // Run the actual code.
-      octave::feval (the_fcn);
+      interp.feval (the_fcn);
     }
   catch (const octave::interrupt_exception&)
     {
--- a/libinterp/octave-value/ov-oncleanup.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-oncleanup.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,11 +39,11 @@
 {
 public:
 
-  octave_oncleanup (void) = default;
+  octave_oncleanup () = default;
 
   octave_oncleanup (const octave_value& m_fcn);
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     if (m_fcn.is_defined ())
       error ("onCleanup: internal error: cloning nonempty object");
@@ -51,22 +51,22 @@
     return empty_clone ();
   }
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   {
     return new octave_oncleanup ();
   }
 
-  ~octave_oncleanup (void);
+  ~octave_oncleanup ();
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool isobject (void) const { return true; } // do we want this?
+  bool isobject () const { return true; } // do we want this?
 
-  octave_map map_value (void) const { return scalar_map_value (); }
+  octave_map map_value () const { return scalar_map_value (); }
 
-  octave_scalar_map scalar_map_value (void) const;
+  octave_scalar_map scalar_map_value () const;
 
-  dim_vector dims (void) const
+  dim_vector dims () const
   {
     static dim_vector dv (1, 1);
     return dv;
@@ -89,7 +89,13 @@
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  void call_object_destructor (void);
+  void call_object_destructor ();
+
+  void maybe_call_dtor ()
+  {
+    if (m_count == 1)
+      call_object_destructor ();
+  }
 
 private:
 
--- a/libinterp/octave-value/ov-perm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-perm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -118,7 +118,7 @@
           else
             {
               retval = this;
-              this->count++;
+              this->m_count++;
             }
         }
     }
@@ -134,10 +134,10 @@
   return retval;
 }
 
-// Return true if this matrix has all true elements (non-zero, not NaN/NA).
+// Return true if this matrix has all true elements (nonzero, not NaN/NA).
 // A permutation cannot have NaN/NA.
 bool
-octave_perm_matrix::is_true (void) const
+octave_perm_matrix::is_true () const
 {
   if (dims ().numel () > 1)
     {
@@ -254,67 +254,67 @@
 }
 
 octave_value
-octave_perm_matrix::as_double (void) const
+octave_perm_matrix::as_double () const
 {
   return m_matrix;
 }
 
 octave_value
-octave_perm_matrix::as_single (void) const
+octave_perm_matrix::as_single () const
 {
   return float_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_int8 (void) const
+octave_perm_matrix::as_int8 () const
 {
   return int8_array_value  ();
 }
 
 octave_value
-octave_perm_matrix::as_int16 (void) const
+octave_perm_matrix::as_int16 () const
 {
   return int16_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_int32 (void) const
+octave_perm_matrix::as_int32 () const
 {
   return int32_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_int64 (void) const
+octave_perm_matrix::as_int64 () const
 {
   return int64_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_uint8 (void) const
+octave_perm_matrix::as_uint8 () const
 {
   return uint8_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_uint16 (void) const
+octave_perm_matrix::as_uint16 () const
 {
   return uint16_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_uint32 (void) const
+octave_perm_matrix::as_uint32 () const
 {
   return uint32_array_value ();
 }
 
 octave_value
-octave_perm_matrix::as_uint64 (void) const
+octave_perm_matrix::as_uint64 () const
 {
   return uint64_array_value ();
 }
 
 float_display_format
-octave_perm_matrix::get_edit_display_format (void) const
+octave_perm_matrix::get_edit_display_format () const
 {
   return float_display_format (float_format (1, 0, 0));
 }
@@ -440,7 +440,7 @@
 }
 
 bool
-octave_perm_matrix::print_as_scalar (void) const
+octave_perm_matrix::print_as_scalar () const
 {
   dim_vector dv = dims ();
 
@@ -470,7 +470,7 @@
 }
 
 octave_value
-octave_perm_matrix::to_dense (void) const
+octave_perm_matrix::to_dense () const
 {
   if (! m_dense_cache.is_defined ())
     m_dense_cache = Matrix (m_matrix);
@@ -490,7 +490,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_perm_matrix::numeric_conversion_function (void) const
+octave_perm_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_matrix::static_type_id ());
@@ -552,7 +552,7 @@
 }
 
 octave_base_value *
-octave_perm_matrix::try_narrowing_conversion (void)
+octave_perm_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
--- a/libinterp/octave-value/ov-perm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-perm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,24 +40,24 @@
 octave_perm_matrix : public octave_base_value
 {
 public:
-  octave_perm_matrix (void) : m_matrix (), m_dense_cache () { }
+  octave_perm_matrix () : m_matrix (), m_dense_cache () { }
 
   octave_perm_matrix (const PermMatrix& p) : m_matrix (p), m_dense_cache () { }
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_perm_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_perm_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
-  std::size_t byte_size (void) const { return m_matrix.byte_size (); }
+  std::size_t byte_size () const { return m_matrix.byte_size (); }
 
-  octave_value squeeze (void) const { return m_matrix; }
+  octave_value squeeze () const { return m_matrix; }
 
-  octave_value full_value (void) const { return to_dense (); }
+  octave_value full_value () 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
@@ -74,9 +74,9 @@
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
-  dim_vector dims (void) const { return m_matrix.dims (); }
+  dim_vector dims () const { return m_matrix.dims (); }
 
-  octave_idx_type nnz (void) const { return m_matrix.rows (); }
+  octave_idx_type nnz () const { return m_matrix.rows (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return to_dense ().reshape (new_dims); }
@@ -90,7 +90,7 @@
   octave_value all (int dim = 0) const { return to_dense ().all (dim); }
   octave_value any (int dim = 0) const { return to_dense ().any (dim); }
 
-  MatrixType matrix_type (void) const { return MatrixType::Permuted_Diagonal; }
+  MatrixType matrix_type () const { return MatrixType::Permuted_Diagonal; }
   MatrixType matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
@@ -117,27 +117,27 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const
   { return to_dense ().is_sorted_rows (mode); }
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_perm_matrix (void) const { return true; }
+  bool is_perm_matrix () const { return true; }
 
-  bool is_matrix_type (void) const { return true; }
+  bool is_matrix_type () const { return true; }
 
-  bool isnumeric (void) const { return true; }
+  bool isnumeric () const { return true; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
-  bool is_true (void) const;
+  bool is_true () const;
 
   double double_value (bool = false) const;
 
@@ -148,7 +148,7 @@
 
   octave::idx_vector index_vector (bool require_integers = false) const;
 
-  PermMatrix perm_matrix_value (void) const
+  PermMatrix perm_matrix_value () const
   { return m_matrix; }
 
   Matrix matrix_value (bool = false) const;
@@ -182,47 +182,47 @@
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
   int8NDArray
-  int8_array_value (void) const { return to_dense ().int8_array_value (); }
+  int8_array_value () const { return to_dense ().int8_array_value (); }
 
   int16NDArray
-  int16_array_value (void) const { return to_dense ().int16_array_value (); }
+  int16_array_value () const { return to_dense ().int16_array_value (); }
 
   int32NDArray
-  int32_array_value (void) const { return to_dense ().int32_array_value (); }
+  int32_array_value () const { return to_dense ().int32_array_value (); }
 
   int64NDArray
-  int64_array_value (void) const { return to_dense ().int64_array_value (); }
+  int64_array_value () const { return to_dense ().int64_array_value (); }
 
   uint8NDArray
-  uint8_array_value (void) const { return to_dense ().uint8_array_value (); }
+  uint8_array_value () const { return to_dense ().uint8_array_value (); }
 
   uint16NDArray
-  uint16_array_value (void) const { return to_dense ().uint16_array_value (); }
+  uint16_array_value () const { return to_dense ().uint16_array_value (); }
 
   uint32NDArray
-  uint32_array_value (void) const { return to_dense ().uint32_array_value (); }
+  uint32_array_value () const { return to_dense ().uint32_array_value (); }
 
   uint64NDArray
-  uint64_array_value (void) const { return to_dense ().uint64_array_value (); }
+  uint64_array_value () const { return to_dense ().uint64_array_value (); }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  float_display_format get_edit_display_format (void) const;
+  float_display_format get_edit_display_format () const;
 
   std::string edit_display (const float_display_format& fmt,
                             octave_idx_type i, octave_idx_type j) const;
@@ -242,7 +242,7 @@
 
   mxArray * as_mxArray (bool interleaved) const;
 
-  bool print_as_scalar (void) const;
+  bool print_as_scalar () const;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -259,7 +259,7 @@
 
   PermMatrix m_matrix;
 
-  virtual octave_value to_dense (void) const;
+  virtual octave_value to_dense () const;
 
   mutable octave_value m_dense_cache;
 
--- a/libinterp/octave-value/ov-range.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-range.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,6 +53,7 @@
 #include "ops.h"
 #include "ovl.h"
 #include "oct-hdf5.h"
+#include "ov-inline.h"
 #include "ov-range-traits.h"
 #include "ov-range.h"
 #include "ov-re-mat.h"
@@ -69,114 +70,21 @@
 template <>
 octave_hdf5_id ov_range<double>::hdf5_save_type = H5T_NATIVE_DOUBLE;
 
-// For now, disable all but ov_range<double>.
-
-#  if 0
-
-template <>
-octave_hdf5_id ov_range<float>::hdf5_save_type = H5T_NATIVE_FLOAT;
-
-template <>
-octave_hdf5_id ov_range<octave_int8>::hdf5_save_type = H5T_NATIVE_INT8;
-
-template <>
-octave_hdf5_id ov_range<octave_int16>::hdf5_save_type = H5T_NATIVE_INT16;
-
-template <>
-octave_hdf5_id ov_range<octave_int32>::hdf5_save_type = H5T_NATIVE_INT32;
-
-template <>
-octave_hdf5_id ov_range<octave_int64>::hdf5_save_type = H5T_NATIVE_INT64;
-
-template <>
-octave_hdf5_id ov_range<octave_uint8>::hdf5_save_type = H5T_NATIVE_UINT8;
-
-template <>
-octave_hdf5_id ov_range<octave_uint16>::hdf5_save_type = H5T_NATIVE_UINT16;
-
-template <>
-octave_hdf5_id ov_range<octave_uint32>::hdf5_save_type = H5T_NATIVE_UINT32;
-
-template <>
-octave_hdf5_id ov_range<octave_uint64>::hdf5_save_type = H5T_NATIVE_UINT64;
-
-#  endif
+// For now, enable only ov_range<double>.
 
 #else
 
 template <>
 octave_hdf5_id ov_range<double>::hdf5_save_type = 0;
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-octave_hdf5_id ov_range<float>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_int8>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_int16>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_int32>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_int64>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_uint8>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_uint16>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_uint32>::hdf5_save_type = 0;
-
-template <>
-octave_hdf5_id ov_range<octave_uint64>::hdf5_save_type = 0;
-
-#  endif
+// For now, enable only ov_range<double>.
 
 #endif
 
 DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<double>,
     "double_range", "double");
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<float>,
-    "float_range", "single");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_int8>,
-    "int8_range", "int8");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_int16>,
-    "int16_range", "int16");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_int32>,
-    "int32_range", "int32");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_int64>,
-    "int64_range", "int64");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_uint8>,
-    "uint8_range", "uint8");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_uint16>,
-    "uint16_range", "uint16");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_uint32>,
-    "uint32_range", "uint32");
-
-DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range<octave_uint64>,
-    "uint64_range", "uint64");
-
-#endif
+// For now, enable only ov_range<double>.
 
 template <typename T>
 static octave_base_value *
@@ -191,7 +99,7 @@
 
 template <typename T>
 octave_base_value::type_conv_info
-ov_range<T>::numeric_conversion_function (void) const
+ov_range<T>::numeric_conversion_function () const
 {
   typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
 
@@ -201,7 +109,7 @@
 
 template <typename T>
 octave_base_value *
-ov_range<T>::try_narrowing_conversion (void)
+ov_range<T>::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -414,79 +322,12 @@
 
 template <typename T>
 octave::range<double>
-ov_range<T>::range_value (void) const
+ov_range<T>::range_value () const
 {
   err_wrong_type_arg ("ov_range<T>::range_value()", type_name ());
 }
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <typename T>
-octave::range<float>
-ov_range<T>::float_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::float_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_int8>
-ov_range<T>::int8_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::int8_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_int16>
-ov_range<T>::int16_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::int16_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_int32>
-ov_range<T>::int32_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::int32_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_int64>
-ov_range<T>::int64_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::int64_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_uint8>
-ov_range<T>::uint8_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::uint8_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_uint16>
-ov_range<T>::uint16_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::uint16_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_uint32>
-ov_range<T>::uint32_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::uint32_range_value ()", type_name ());
-}
-
-template <typename T>
-octave::range<octave_uint64>
-ov_range<T>::uint64_range_value (void) const
-{
-  err_wrong_type_arg ("ov_range<T>::uint64_range_value ()", type_name ());
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 template <typename T>
 octave_value
@@ -500,70 +341,70 @@
 
 template <typename T>
 octave_value
-ov_range<T>::as_double (void) const
+ov_range<T>::as_double () const
 {
   return NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_single (void) const
+ov_range<T>::as_single () const
 {
   return FloatMatrix (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_int8 (void) const
+ov_range<T>::as_int8 () const
 {
   return int8NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_int16 (void) const
+ov_range<T>::as_int16 () const
 {
   return int16NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_int32 (void) const
+ov_range<T>::as_int32 () const
 {
   return int32NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_int64 (void) const
+ov_range<T>::as_int64 () const
 {
   return int64NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_uint8 (void) const
+ov_range<T>::as_uint8 () const
 {
   return uint8NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_uint16 (void) const
+ov_range<T>::as_uint16 () const
 {
   return uint16NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_uint32 (void) const
+ov_range<T>::as_uint32 () const
 {
   return uint32NDArray (raw_array_value ());
 }
 
 template <typename T>
 octave_value
-ov_range<T>::as_uint64 (void) const
+ov_range<T>::as_uint64 () const
 {
   return uint64NDArray (raw_array_value ());
 }
@@ -655,7 +496,7 @@
 
 template <typename T>
 float_display_format
-ov_range<T>::get_edit_display_format (void) const
+ov_range<T>::get_edit_display_format () const
 {
   return make_format (m_range);
 }
@@ -715,39 +556,7 @@
 
 // specialize for saving with "reverse" flag
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::save_ascii (std::ostream& os)
-{
-  return xsave_ascii (os, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint16>::save_ascii (std::ostream& os)
-{
-  return xsave_ascii (os, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint32>::save_ascii (std::ostream& os)
-{
-  return xsave_ascii (os, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint64>::save_ascii (std::ostream& os)
-{
-  return xsave_ascii (os, m_range, true);
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 template <typename T>
 bool
@@ -780,39 +589,7 @@
 
 // specialize for loading with "reverse" flag
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::load_ascii (std::istream& is)
-{
-  return xload_ascii (is, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint16>::load_ascii (std::istream& is)
-{
-  return xload_ascii (is, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint32>::load_ascii (std::istream& is)
-{
-  return xload_ascii (is, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint64>::load_ascii (std::istream& is)
-{
-  return xload_ascii (is, m_range, true);
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 /*
 %!test
@@ -874,39 +651,7 @@
   return xsave_binary (os, save_as_floats, m_range, false);
 }
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::save_binary (std::ostream& os, bool save_as_floats)
-{
-  return xsave_binary (os, save_as_floats, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint16>::save_binary (std::ostream& os, bool save_as_floats)
-{
-  return xsave_binary (os, save_as_floats, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint32>::save_binary (std::ostream& os, bool save_as_floats)
-{
-  return xsave_binary (os, save_as_floats, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint64>::save_binary (std::ostream& os, bool save_as_floats)
-{
-  return xsave_binary (os, save_as_floats, m_range, true);
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 template <typename T>
 bool
@@ -954,43 +699,7 @@
   return xload_binary (is, swap, fmt, m_range, false);
 }
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::load_binary (std::istream& is, bool swap,
-                                     octave::mach_info::float_format fmt)
-{
-  return xload_binary (is, swap, fmt, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint16>::load_binary (std::istream& is, bool swap,
-                                      octave::mach_info::float_format fmt)
-{
-  return xload_binary (is, swap, fmt, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint32>::load_binary (std::istream& is, bool swap,
-                                      octave::mach_info::float_format fmt)
-{
-  return xload_binary (is, swap, fmt, m_range, true);
-}
-
-template <>
-bool
-ov_range<octave_uint64>::load_binary (std::istream& is, bool swap,
-                                      octave::mach_info::float_format fmt)
-{
-  return xload_binary (is, swap, fmt, m_range, true);
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 /*
 %!test
@@ -1139,87 +848,7 @@
 #endif
 }
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
-                                   bool save_as_floats)
-{
-#if defined (HAVE_HDF5)
-  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
-                     true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-  octave_unused_parameter (save_as_floats);
-
-  warn_save ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint16>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
-                                    bool save_as_floats)
-{
-#if defined (HAVE_HDF5)
-  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
-                     true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-  octave_unused_parameter (save_as_floats);
-
-  warn_save ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint32>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
-                                    bool save_as_floats)
-{
-#if defined (HAVE_HDF5)
-  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
-                     true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-  octave_unused_parameter (save_as_floats);
-
-  warn_save ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint64>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
-                                    bool save_as_floats)
-{
-#if defined (HAVE_HDF5)
-  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
-                     true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-  octave_unused_parameter (save_as_floats);
-
-  warn_save ("hdf5");
-
-  return false;
-#endif
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 #if defined (HAVE_HDF5)
 
@@ -1298,75 +927,7 @@
 #endif
 }
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-bool
-ov_range<octave_uint8>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
-{
-#if defined (HAVE_HDF5)
-  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-
-  warn_load ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint16>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
-{
-#if defined (HAVE_HDF5)
-  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-
-  warn_load ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint32>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
-{
-#if defined (HAVE_HDF5)
-  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-
-  warn_load ("hdf5");
-
-  return false;
-#endif
-}
-
-template <>
-bool
-ov_range<octave_uint64>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
-{
-#if defined (HAVE_HDF5)
-  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
-#else
-  octave_unused_parameter (loc_id);
-  octave_unused_parameter (name);
-
-  warn_load ("hdf5");
-
-  return false;
-#endif
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 /*
 %!testif HAVE_HDF5
@@ -1417,6 +978,47 @@
   return retval;
 }
 
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA  (octave_trivial_range,
+                                     "trivial range", "double");
+
+template <typename T>
+bool
+ov_range<T>::could_be_trivial_range () { return false; }
+
+template <>
+bool
+ov_range<double>::could_be_trivial_range ()
+{
+  octave_idx_type n = m_range.numel ();
+  if (n > std::numeric_limits<int>::max())
+    return false;
+  if (n <= 1)
+    return false;
+
+  double f = m_range.final_value ();
+  if (f > std::numeric_limits<int>::max()
+      || f < std::numeric_limits<int>::min())
+    return false;
+  if (std::isnan (f))
+    return false;
+
+  return true;
+}
+
+template <typename T>
+octave_value
+ov_range<T>::as_trivial_range ()
+{
+  error ("Type error returning trivial range");
+}
+
+template <>
+octave_value
+ov_range<double>::as_trivial_range ()
+{
+  return octave_value (new octave_trivial_range (m_range.numel (), m_range.base (), m_range.increment ()));
+}
+
 template <typename T>
 octave_value
 ov_range<T>::fast_elem_extract (octave_idx_type n) const
@@ -1428,79 +1030,30 @@
 
 template <>
 octave::range<double>
-ov_range<double>::range_value (void) const
-{
-  return m_range;
-}
-
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-octave::range<float>
-ov_range<float>::float_range_value (void) const
-{
-  return m_range;
-}
-
-template <>
-octave::range<octave_int8>
-ov_range<octave_int8>::int8_range_value (void) const
-{
-  return m_range;
-}
-
-template <>
-octave::range<octave_int16>
-ov_range<octave_int16>::int16_range_value (void) const
-{
-  return m_range;
-}
-
-template <>
-octave::range<octave_int32>
-ov_range<octave_int32>::int32_range_value (void) const
+ov_range<double>::range_value () const
 {
   return m_range;
 }
 
-template <>
-octave::range<octave_int64>
-ov_range<octave_int64>::int64_range_value (void) const
+template <typename T>
+octave_value
+ov_range<T>::vm_extract_forloop_value (octave_idx_type n)
 {
-  return m_range;
-}
+  octave_value ov = octave_value_factory::make (m_range.elem (n));
 
-template <>
-octave::range<octave_uint8>
-ov_range<octave_uint8>::uint8_range_value (void) const
-{
-  return m_range;
+  return ov.as_double_or_copy ();
 }
 
 template <>
-octave::range<octave_uint16>
-ov_range<octave_uint16>::uint16_range_value (void) const
+octave_value
+ov_range<double>::vm_extract_forloop_value (octave_idx_type n)
 {
-  return m_range;
+  octave_value ov = octave_value_factory::make (m_range.elem (n));
+
+  return ov;
 }
 
-template <>
-octave::range<octave_uint32>
-ov_range<octave_uint32>::uint32_range_value (void) const
-{
-  return m_range;
-}
-
-template <>
-octave::range<octave_uint64>
-ov_range<octave_uint64>::uint64_range_value (void) const
-{
-  return m_range;
-}
-
-#endif
+// For now, enable only ov_range<double>.
 
 template <>
 octave::idx_vector
@@ -1520,7 +1073,7 @@
 
 template <>
 octave_idx_type
-ov_range<double>::nnz (void) const
+ov_range<double>::nnz () const
 {
   return m_range.nnz ();
 }
--- a/libinterp/octave-value/ov-range.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-range.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,6 +51,44 @@
 
 class octave_value_list;
 
+
+class octave_trivial_range : public octave_base_value
+{
+public:
+
+  octave_trivial_range (octave_idx_type numel, double base, double incr)
+      : m_numel (numel), m_base (base), m_increment(incr) { }
+
+  octave_trivial_range () {};
+
+  octave_trivial_range (const octave_trivial_range&) = default;
+
+  OCTINTERP_API octave_value
+  vm_extract_forloop_value (octave_idx_type i)
+  {
+    if (i < m_numel - 1)
+      return m_base + static_cast<int> (i) * m_increment;
+    return m_base + (m_numel - 1) * m_increment;
+  }
+
+  double
+  vm_extract_forloop_double (octave_idx_type i)
+  {
+    if (i < m_numel - 1)
+      return m_base + static_cast<int> (i) * m_increment;
+    return m_base + (m_numel - 1) * m_increment;
+  }
+
+  bool is_trivial_range () const { return true; };
+
+private:
+  int m_numel = 0;
+  int m_base = 0;
+  int m_increment = 0;
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
 // For now, we only need ov_range<double> but we don't attempt to
 // enforce that restriction.
 
@@ -60,7 +98,7 @@
 {
 public:
 
-  ov_range (void)
+  ov_range ()
     : octave_base_value (), m_range (), m_idx_cache () { }
 
   ov_range (const octave::range<T>& r)
@@ -85,9 +123,9 @@
   // No assignment.
   ov_range& operator = (const ov_range&) = delete;
 
-  ~ov_range (void) { clear_cached_info (); }
+  ~ov_range () { clear_cached_info (); }
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   {
     return new ov_range (*this);
   }
@@ -96,16 +134,16 @@
   // the places where we need to call empty_clone, it makes more sense
   // to create an empty matrix (0x0) instead of an empty range (1x0).
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   {
     return new typename octave_value_range_traits<T>::matrix_type ();
   }
 
-  OCTINTERP_API type_conv_info numeric_conversion_function (void) const;
+  OCTINTERP_API type_conv_info numeric_conversion_function () const;
 
-  OCTINTERP_API octave_base_value * try_narrowing_conversion (void);
+  OCTINTERP_API octave_base_value * try_narrowing_conversion ();
 
-  builtin_type_t builtin_type (void) const { return class_to_btyp<T>::btyp; }
+  builtin_type_t builtin_type () const { return class_to_btyp<T>::btyp; }
 
   // We don't need to override all three forms of subsref.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -124,15 +162,21 @@
 
   OCTINTERP_API octave::idx_vector index_vector (bool require_integers = false) const;
 
-  dim_vector dims (void) const
+  dim_vector dims () const
   {
     octave_idx_type n = numel ();
     return dim_vector (n > 0, n);
   }
 
-  octave_idx_type numel (void) const { return m_range.numel (); }
+  OCTINTERP_API octave_value as_trivial_range ();
+  OCTINTERP_API bool could_be_trivial_range ();
 
-  octave_idx_type nnz (void) const
+  OCTINTERP_API octave_value
+  vm_extract_forloop_value (octave_idx_type idx);
+
+  octave_idx_type numel () const { return m_range.numel (); }
+
+  octave_idx_type nnz () const
   {
     // FIXME: this is a potential waste of memory.
 
@@ -143,7 +187,7 @@
   OCTINTERP_API octave_value
   resize (const dim_vector& dv, bool fill = false) const;
 
-  std::size_t byte_size (void) const { return 3 * sizeof (T); }
+  std::size_t byte_size () const { return 3 * sizeof (T); }
 
   octave_value reshape (const dim_vector& new_dims) const
   {
@@ -155,53 +199,54 @@
     return raw_array_value ().permute (vec, inv);
   }
 
-  octave_value squeeze (void) const { return m_range; }
+  octave_value squeeze () const { return m_range; }
 
-  octave_value full_value (void) const { return raw_array_value (); }
+  octave_value full_value () const { return raw_array_value (); }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_storable (void) const { return m_range.is_storable (); }
+  bool is_storable () const { return m_range.is_storable (); }
 
-  bool is_constant (void) const { return true; }
-
-  bool is_range (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool is_double_type (void) const { return builtin_type () == btyp_double; }
+  bool is_range () const { return true; }
+  bool vm_need_storable_call (void) const { return true; }
 
-  bool is_single_type (void) const { return builtin_type () == btyp_float; }
+  bool is_double_type () const { return builtin_type () == btyp_double; }
 
-  bool isfloat (void) const { return btyp_isfloat (builtin_type ()); }
+  bool is_single_type () const { return builtin_type () == btyp_float; }
 
-  bool is_int8_type (void) const { return builtin_type () == btyp_int8; }
+  bool isfloat () const { return btyp_isfloat (builtin_type ()); }
 
-  bool is_int16_type (void) const { return builtin_type () == btyp_int16; }
+  bool is_int8_type () const { return builtin_type () == btyp_int8; }
 
-  bool is_int32_type (void) const { return builtin_type () == btyp_int32; }
+  bool is_int16_type () const { return builtin_type () == btyp_int16; }
 
-  bool is_int64_type (void) const { return builtin_type () == btyp_int64; }
+  bool is_int32_type () const { return builtin_type () == btyp_int32; }
+
+  bool is_int64_type () const { return builtin_type () == btyp_int64; }
 
-  bool is_uint8_type (void) const { return builtin_type () == btyp_uint8; }
+  bool is_uint8_type () const { return builtin_type () == btyp_uint8; }
 
-  bool is_uint16_type (void) const { return builtin_type () == btyp_uint16; }
+  bool is_uint16_type () const { return builtin_type () == btyp_uint16; }
 
-  bool is_uint32_type (void) const { return builtin_type () == btyp_uint32; }
+  bool is_uint32_type () const { return builtin_type () == btyp_uint32; }
 
-  bool is_uint64_type (void) const { return builtin_type () == btyp_uint64; }
+  bool is_uint64_type () const { return builtin_type () == btyp_uint64; }
 
-  bool isinteger (void) const
+  bool isinteger () const
   {
     return btyp_isinteger (builtin_type ());
   }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool isnumeric (void) const
+  bool isnumeric () const
   {
     return btyp_isnumeric (builtin_type ());
   }
 
-  bool is_true (void) const { return nnz () == numel (); }
+  bool is_true () const { return nnz () == numel (); }
 
   octave_value all (int dim = 0) const
   {
@@ -268,7 +313,7 @@
     return (mode == UNSORTED) ? ASCENDING : mode;
   }
 
-  Array<T> raw_array_value (void) const { return m_range.array_value (); }
+  Array<T> raw_array_value () const { return m_range.array_value (); }
 
   OCTINTERP_API double double_value (bool = false) const;
 
@@ -310,42 +355,42 @@
   // functions to avoid the intermediate conversion to a matrix
   // object.
 
-  int8NDArray int8_array_value (void) const
+  int8NDArray int8_array_value () const
   {
     return raw_array_value ();
   }
 
-  int16NDArray int16_array_value (void) const
+  int16NDArray int16_array_value () const
   {
     return raw_array_value ();
   }
 
-  int32NDArray int32_array_value (void) const
+  int32NDArray int32_array_value () const
   {
     return raw_array_value ();
   }
 
-  int64NDArray int64_array_value (void) const
+  int64NDArray int64_array_value () const
   {
     return raw_array_value ();
   }
 
-  uint8NDArray uint8_array_value (void) const
+  uint8NDArray uint8_array_value () const
   {
     return raw_array_value ();
   }
 
-  uint16NDArray uint16_array_value (void) const
+  uint16NDArray uint16_array_value () const
   {
     return raw_array_value ();
   }
 
-  uint32NDArray uint32_array_value (void) const
+  uint32NDArray uint32_array_value () const
   {
     return raw_array_value ();
   }
 
-  uint64NDArray uint64_array_value (void) const
+  uint64NDArray uint64_array_value () const
   {
     return raw_array_value ();
   }
@@ -386,47 +431,25 @@
     return raw_array_value ();
   }
 
-  OCTINTERP_API octave::range<double> range_value (void) const;
-
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-  OCTINTERP_API octave::range<float> float_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_int8> int8_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_int16> int16_range_value (void) const;
+  OCTINTERP_API octave::range<double> range_value () const;
 
-  OCTINTERP_API octave::range<octave_int32> int32_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_int64> int64_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_uint8> uint8_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_uint16> uint16_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_uint32> uint32_range_value (void) const;
-
-  OCTINTERP_API octave::range<octave_uint64> uint64_range_value (void) const;
-
-#endif
+// For now, enable only ov_range<double>.
 
   OCTINTERP_API octave_value
   convert_to_str_internal (bool pad, bool force, char type) const;
 
-  OCTINTERP_API octave_value as_double (void) const;
-  OCTINTERP_API octave_value as_single (void) const;
+  OCTINTERP_API octave_value as_double () const;
+  OCTINTERP_API octave_value as_single () const;
 
-  OCTINTERP_API octave_value as_int8 (void) const;
-  OCTINTERP_API octave_value as_int16 (void) const;
-  OCTINTERP_API octave_value as_int32 (void) const;
-  OCTINTERP_API octave_value as_int64 (void) const;
+  OCTINTERP_API octave_value as_int8 () const;
+  OCTINTERP_API octave_value as_int16 () const;
+  OCTINTERP_API octave_value as_int32 () const;
+  OCTINTERP_API octave_value as_int64 () const;
 
-  OCTINTERP_API octave_value as_uint8 (void) const;
-  OCTINTERP_API octave_value as_uint16 (void) const;
-  OCTINTERP_API octave_value as_uint32 (void) const;
-  OCTINTERP_API octave_value as_uint64 (void) const;
+  OCTINTERP_API octave_value as_uint8 () const;
+  OCTINTERP_API octave_value as_uint16 () const;
+  OCTINTERP_API octave_value as_uint32 () const;
+  OCTINTERP_API octave_value as_uint64 () const;
 
   OCTINTERP_API void print (std::ostream& os, bool pr_as_read_syntax = false);
 
@@ -438,7 +461,7 @@
 
   OCTINTERP_API void short_disp (std::ostream& os) const;
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   OCTINTERP_API std::string
   edit_display (const float_display_format& fmt,
@@ -486,11 +509,11 @@
   octave::idx_vector set_idx_cache (const octave::idx_vector& idx) const
   {
     delete m_idx_cache;
-    m_idx_cache = (idx ? new octave::idx_vector (idx) : nullptr);
+    m_idx_cache = new octave::idx_vector (idx);
     return idx;
   }
 
-  void clear_cached_info (void) const
+  void clear_cached_info () const
   {
     delete m_idx_cache; m_idx_cache = nullptr;
   }
@@ -504,69 +527,15 @@
 
 DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, double)
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, float)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int8)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int16)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int32)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int64)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint8)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint16)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint32)
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint64)
-
-#endif
+// For now, enable only ov_range<double>.
 
 // Specializations.
 
 template <>
 OCTINTERP_API octave::range<double>
-ov_range<double>::range_value (void) const;
-
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-template <>
-OCTINTERP_API octave::range<float>
-ov_range<float>::float_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_int8>
-ov_range<octave_int8>::int8_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_int16>
-ov_range<octave_int16>::int16_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_int32>
-ov_range<octave_int32>::int32_range_value (void) const;
+ov_range<double>::range_value () const;
 
-template <>
-OCTINTERP_API octave::range<octave_int64>
-ov_range<octave_int64>::int64_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_uint8>
-ov_range<octave_uint8>::uint8_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_uint16>
-ov_range<octave_uint16>::uint16_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_uint32>
-ov_range<octave_uint32>::uint32_range_value (void) const;
-
-template <>
-OCTINTERP_API octave::range<octave_uint64>
-ov_range<octave_uint64>::uint64_range_value (void) const;
-
-#endif
+// For now, enable only ov_range<double>.
 
 // The following specializations are here to preserve previous Range
 // performance until solutions can be generalized for other types.
@@ -577,7 +546,7 @@
 
 template <>
 OCTINTERP_API octave_idx_type
-ov_range<double>::nnz (void) const;
+ov_range<double>::nnz () const;
 
 // The following specialization is also historical baggage.  For double
 // ranges, we can produce special double-valued diagnoal matrix objects
@@ -596,26 +565,9 @@
 OCTINTERP_API void
 ov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const;
 
-
 typedef ov_range<double> octave_double_range;
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-typedef ov_range<float> octave_float_range;
-
-typedef ov_range<octave_int8> octave_int8_range;
-typedef ov_range<octave_int16> octave_int16_range;
-typedef ov_range<octave_int32> octave_int32_range;
-typedef ov_range<octave_int64> octave_int64_range;
-
-typedef ov_range<octave_uint8> octave_uint8_range;
-typedef ov_range<octave_uint16> octave_uint16_range;
-typedef ov_range<octave_uint32> octave_uint32_range;
-typedef ov_range<octave_uint64> octave_uint64_range;
-
-#endif
+// For now, enable only ov_range<double>.
 
 typedef octave_double_range octave_range;
 
--- a/libinterp/octave-value/ov-re-diag.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-diag.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,7 +51,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_diag_matrix::numeric_conversion_function (void) const
+octave_diag_matrix::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_matrix::static_type_id ());
@@ -66,7 +66,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_diag_matrix::numeric_demotion_function (void) const
+octave_diag_matrix::numeric_demotion_function () const
 {
   return octave_base_value::type_conv_info
          (default_numeric_demotion_function,
@@ -74,7 +74,7 @@
 }
 
 octave_base_value *
-octave_diag_matrix::try_narrowing_conversion (void)
+octave_diag_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -118,7 +118,7 @@
               else
                 {
                   retval = this;
-                  this->count++;
+                  this->m_count++;
                 }
             }
         }
@@ -161,61 +161,61 @@
 }
 
 octave_value
-octave_diag_matrix::as_double (void) const
+octave_diag_matrix::as_double () const
 {
   return m_matrix;
 }
 
 octave_value
-octave_diag_matrix::as_single (void) const
+octave_diag_matrix::as_single () const
 {
   return FloatDiagMatrix (m_matrix);
 }
 
 octave_value
-octave_diag_matrix::as_int8 (void) const
+octave_diag_matrix::as_int8 () const
 {
   return int8_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_int16 (void) const
+octave_diag_matrix::as_int16 () const
 {
   return int16_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_int32 (void) const
+octave_diag_matrix::as_int32 () const
 {
   return int32_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_int64 (void) const
+octave_diag_matrix::as_int64 () const
 {
   return int64_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_uint8 (void) const
+octave_diag_matrix::as_uint8 () const
 {
   return uint8_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_uint16 (void) const
+octave_diag_matrix::as_uint16 () const
 {
   return uint16_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_uint32 (void) const
+octave_diag_matrix::as_uint32 () const
 {
   return uint32_array_value ();
 }
 
 octave_value
-octave_diag_matrix::as_uint64 (void) const
+octave_diag_matrix::as_uint64 () const
 {
   return uint64_array_value ();
 }
--- a/libinterp/octave-value/ov-re-diag.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-diag.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  octave_diag_matrix (void)
+  octave_diag_matrix ()
     : octave_base_diag<DiagMatrix, Matrix> () { }
 
   octave_diag_matrix (const DiagMatrix& m)
@@ -51,31 +51,31 @@
   octave_diag_matrix (const octave_diag_matrix& m)
     : octave_base_diag<DiagMatrix, Matrix> (m) { }
 
-  ~octave_diag_matrix (void) = default;
+  ~octave_diag_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_diag_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_diag_matrix (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
-  type_conv_info numeric_demotion_function (void) const;
+  type_conv_info numeric_demotion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   DiagMatrix diag_matrix_value (bool = false) const;
 
@@ -85,18 +85,18 @@
 
   FloatComplexDiagMatrix float_complex_diag_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- a/libinterp/octave-value/ov-re-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -98,7 +98,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_matrix::numeric_demotion_function (void) const
+octave_matrix::numeric_demotion_function () const
 {
   return octave_base_value::type_conv_info
          (default_numeric_demotion_function,
@@ -106,7 +106,7 @@
 }
 
 octave_base_value *
-octave_matrix::try_narrowing_conversion (void)
+octave_matrix::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -250,61 +250,61 @@
 }
 
 octave_value
-octave_matrix::as_double (void) const
+octave_matrix::as_double () const
 {
   return NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_single (void) const
+octave_matrix::as_single () const
 {
   return FloatNDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_int8 (void) const
+octave_matrix::as_int8 () const
 {
   return int8NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_int16 (void) const
+octave_matrix::as_int16 () const
 {
   return int16NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_int32 (void) const
+octave_matrix::as_int32 () const
 {
   return int32NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_int64 (void) const
+octave_matrix::as_int64 () const
 {
   return int64NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_uint8 (void) const
+octave_matrix::as_uint8 () const
 {
   return uint8NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_uint16 (void) const
+octave_matrix::as_uint16 () const
 {
   return uint16NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_uint32 (void) const
+octave_matrix::as_uint32 () const
 {
   return uint32NDArray (m_matrix);
 }
 
 octave_value
-octave_matrix::as_uint64 (void) const
+octave_matrix::as_uint64 () const
 {
   return uint64NDArray (m_matrix);
 }
@@ -350,7 +350,7 @@
 }
 
 octave_value
-octave_matrix::squeeze (void) const
+octave_matrix::squeeze () const
 {
   if (m_idx_cache)
     {
@@ -757,7 +757,7 @@
       return false;
     }
 
-  double *mtmp = m.fortran_vec ();
+  const double *mtmp = m.data ();
   retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL,
                      octave_H5S_ALL, octave_H5P_DEFAULT, mtmp) >= 0;
 
--- a/libinterp/octave-value/ov-re-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_matrix (void)
+  octave_matrix ()
     : octave_base_matrix<NDArray> () { }
 
   octave_matrix (const Matrix& m)
@@ -96,14 +96,14 @@
     set_idx_cache (cache);
   }
 
-  ~octave_matrix (void) = default;
+  ~octave_matrix () = default;
 
-  octave_base_value * clone (void) const { return new octave_matrix (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_matrix (); }
+  octave_base_value * clone () const { return new octave_matrix (*this); }
+  octave_base_value * empty_clone () const { return new octave_matrix (); }
 
-  type_conv_info numeric_demotion_function (void) const;
+  type_conv_info numeric_demotion_function () const;
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   {
@@ -111,39 +111,39 @@
            : set_idx_cache (octave::idx_vector (m_matrix));
   }
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   int8NDArray
-  int8_array_value (void) const { return int8NDArray (m_matrix); }
+  int8_array_value () const { return int8NDArray (m_matrix); }
 
   int16NDArray
-  int16_array_value (void) const { return int16NDArray (m_matrix); }
+  int16_array_value () const { return int16NDArray (m_matrix); }
 
   int32NDArray
-  int32_array_value (void) const { return int32NDArray (m_matrix); }
+  int32_array_value () const { return int32NDArray (m_matrix); }
 
   int64NDArray
-  int64_array_value (void) const { return int64NDArray (m_matrix); }
+  int64_array_value () const { return int64NDArray (m_matrix); }
 
   uint8NDArray
-  uint8_array_value (void) const { return uint8NDArray (m_matrix); }
+  uint8_array_value () const { return uint8NDArray (m_matrix); }
 
   uint16NDArray
-  uint16_array_value (void) const { return uint16NDArray (m_matrix); }
+  uint16_array_value () const { return uint16NDArray (m_matrix); }
 
   uint32NDArray
-  uint32_array_value (void) const { return uint32NDArray (m_matrix); }
+  uint32_array_value () const { return uint32NDArray (m_matrix); }
 
   uint64NDArray
-  uint64_array_value (void) const { return uint64NDArray (m_matrix); }
+  uint64_array_value () const { return uint64NDArray (m_matrix); }
 
   double double_value (bool = false) const;
 
@@ -180,18 +180,18 @@
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   octave_value diag (octave_idx_type k = 0) const;
 
@@ -199,7 +199,7 @@
 
   octave_value reshape (const dim_vector& new_dims) const;
 
-  octave_value squeeze (void) const;
+  octave_value squeeze () const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
   octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
@@ -212,11 +212,11 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
   // Use matrix_ref here to clear index cache.
-  void increment (void) { matrix_ref () += 1.0; }
+  void increment () { matrix_ref () += 1.0; }
 
-  void decrement (void) { matrix_ref () -= 1.0; }
+  void decrement () { matrix_ref () -= 1.0; }
 
-  void changesign (void) { matrix_ref ().changesign (); }
+  void changesign () { matrix_ref ().changesign (); }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
--- a/libinterp/octave-value/ov-re-sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -214,7 +214,7 @@
 }
 
 octave_value
-octave_sparse_matrix::as_double (void) const
+octave_sparse_matrix::as_double () const
 {
   return this->matrix;
 }
--- a/libinterp/octave-value/ov-re-sparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-re-sparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_sparse_matrix (void)
+  octave_sparse_matrix ()
     : octave_base_sparse<SparseMatrix> () { }
 
   octave_sparse_matrix (const Matrix& m)
@@ -84,24 +84,24 @@
   octave_sparse_matrix (const octave_sparse_matrix& m)
     : octave_base_sparse<SparseMatrix> (m) { }
 
-  ~octave_sparse_matrix (void) = default;
+  ~octave_sparse_matrix () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_sparse_matrix (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_sparse_matrix (); }
 
   octave::idx_vector index_vector (bool require_integers = false) const;
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_real_matrix (void) const { return true; }
+  bool is_real_matrix () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   double double_value (bool = false) const;
 
@@ -132,14 +132,7 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  octave_value as_double (void) const;
-
-#if 0
-  int write (octave::stream& os, int block_size,
-             oct_data_conv::data_type output_type, int skip,
-             octave::mach_info::float_format flt_fmt) const
-  { return os.write (matrix, block_size, output_type, skip, flt_fmt); }
-#endif
+  octave_value as_double () const;
 
   bool save_binary (std::ostream& os, bool save_as_floats);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-ref.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,123 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2007-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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.h"
+#include "ov-ref.h"
+
+
+#include "interpreter.h"
+#include "interpreter-private.h"
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_value_ref_global,
+                                     "global value reference",
+                                     "global value reference");
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_value_ref_persistent,
+                                     "global value persistent",
+                                     "global value persistent");
+void
+octave_value_ref::maybe_call_dtor ()
+{
+  ref ().m_rep->maybe_call_dtor ();
+}
+
+bool
+octave_value_ref::is_defined () const
+{
+  return const_cast<octave_value_ref*> (this)->ref ().m_rep->is_defined ();
+}
+
+bool
+octave_value_ref::is_maybe_function () const
+{
+  return const_cast<octave_value_ref*> (this)->ref ().m_rep->is_maybe_function ();
+}
+
+octave_base_value *
+octave_value_ref::unique_clone ()
+{
+  return ref ().m_rep->unique_clone ();
+}
+
+octave_value
+octave_value_ref::simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs)
+{
+  octave_value ans = ref ().m_rep->simple_subsasgn (type, idx, rhs);
+  ref () = ans;
+  return octave_value {this, true};
+}
+
+octave_value
+octave_value_ref::subsasgn (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            const octave_value& rhs)
+{
+  octave_value ans = ref ().m_rep->subsasgn (type, idx, rhs);
+  ref () = ans;
+  return octave_value {this, true};
+}
+
+octave_value
+octave_value_ref_global::deref ()
+{
+  auto &interp = octave::__get_interpreter__();
+  return interp.global_varval (m_name);
+}
+
+void
+octave_value_ref_global::set_value (octave_value val)
+{
+  auto &interp = octave::__get_interpreter__();
+  interp.global_assign (m_name, val);
+}
+
+octave_value&
+octave_value_ref_global::ref ()
+{
+  auto& tw = octave::__get_evaluator__();
+  return tw.global_varref (m_name);
+}
+
+octave_value
+octave_value_ref_persistent::deref ()
+{
+  return m_scope.persistent_varval (m_offset);
+}
+
+void
+octave_value_ref_persistent::set_value (octave_value val)
+{
+  octave_value &ov_pers = m_scope.persistent_varref (m_offset);
+  ov_pers = val;
+}
+
+octave_value &
+octave_value_ref_persistent::ref ()
+{
+  return m_scope.persistent_varref (m_offset);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-ref.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 1996-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_ov_ref_h)
+#define octave_ov_ref_h 1
+
+#include "octave-config.h"
+
+#include "ov-base.h"
+#include "ovl.h"
+#include "symscope.h"
+
+#include <string>
+#include <memory>
+
+// octave_value_ref is to be used by the VM to implement
+// global and persistent values.
+//
+// octave_value_ref need to overload any virtual call
+// used by the assign and push slot op-codes.
+//
+// Any octave_value_ref should never leave the VM slots
+// on the VM stack.
+
+// Abstract type
+class OCTINTERP_API
+octave_value_ref : public octave_base_value
+{
+public:
+    octave_value_ref () = default;
+    ~octave_value_ref () = default;
+
+    octave_value_ref * ref_rep () { return this; }
+    bool is_ref () const { return true; }
+
+    virtual octave_value deref () = 0;
+    virtual void set_value (octave_value val) = 0;
+    virtual octave_value & ref () = 0;
+    virtual void maybe_save_state  () {};
+
+    virtual bool is_global_ref () { return false; }
+    virtual bool is_persistent_ref () { return false; }
+
+    void maybe_call_dtor ();
+    octave_value simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs);
+    octave_value subsasgn (const std::string& type, const std::list<octave_value_list>& idx, const octave_value& rhs);
+    octave_base_value * unique_clone ();
+    bool is_defined () const;
+    bool is_maybe_function (void) const;
+};
+
+class OCTINTERP_API
+octave_value_ref_global : public octave_value_ref
+{
+public:
+    octave_value_ref_global () = default;
+    ~octave_value_ref_global () = default;
+    octave_value_ref_global (std::string name)
+        : m_name (name) {};
+
+    octave_value deref ();
+    octave_value & ref ();
+    void set_value (octave_value val);
+
+    bool is_global_ref () { return true; }
+
+private:
+    std::string m_name;
+
+    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+class OCTINTERP_API
+octave_value_ref_persistent : public octave_value_ref
+{
+public:
+    octave_value_ref_persistent () = default;
+    ~octave_value_ref_persistent () = default;
+    octave_value_ref_persistent (octave::symbol_scope scope, int offset)
+        : m_offset (offset), m_scope (scope) {};
+
+    octave_value deref ();
+    octave_value & ref ();
+    void set_value (octave_value val);
+
+    bool is_persistent_ref () { return true; }
+
+private:
+    int m_offset;
+    octave::symbol_scope m_scope;
+
+    DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
--- a/libinterp/octave-value/ov-scalar.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-scalar.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,6 +54,7 @@
 #include "xdiv.h"
 #include "xpow.h"
 #include "ops.h"
+#include "ov-inline.h"
 
 #include "ls-oct-text.h"
 #include "ls-hdf5.h"
@@ -76,7 +77,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_scalar::numeric_demotion_function (void) const
+octave_scalar::numeric_demotion_function () const
 {
   return octave_base_value::type_conv_info
          (default_numeric_demotion_function,
@@ -125,61 +126,67 @@
 }
 
 octave_value
+octave_scalar::as_double_or_copy (void)
+{
+  return octave_value_factory::make_copy (this);
+}
+
+octave_value
 octave_scalar::as_double (void) const
 {
   return scalar;
 }
 
 octave_value
-octave_scalar::as_single (void) const
+octave_scalar::as_single () const
 {
   return static_cast<float> (scalar);
 }
 
 octave_value
-octave_scalar::as_int8 (void) const
+octave_scalar::as_int8 () const
 {
   return octave_int8 (scalar);
 }
 
 octave_value
-octave_scalar::as_int16 (void) const
+octave_scalar::as_int16 () const
 {
   return octave_int16 (scalar);
 }
 
 octave_value
-octave_scalar::as_int32 (void) const
+octave_scalar::as_int32 () const
 {
   return octave_int32 (scalar);
 }
 
 octave_value
-octave_scalar::as_int64 (void) const
+octave_scalar::as_int64 () const
 {
   return octave_int64 (scalar);
 }
 
 octave_value
-octave_scalar::as_uint8 (void) const
+octave_scalar::as_uint8 () const
 {
   return octave_uint8 (scalar);
 }
 
 octave_value
-octave_scalar::as_uint16 (void) const
+octave_scalar::as_uint16 () const
 {
   return octave_uint16 (scalar);
 }
 
 octave_value
-octave_scalar::as_uint32 (void) const
+octave_scalar::as_uint32 () const
 {
   return octave_uint32 (scalar);
 }
 
 octave_value
-octave_scalar::as_uint64 (void) const
+octave_scalar::as_uint64 () const
 {
   return octave_uint64 (scalar);
 }
--- a/libinterp/octave-value/ov-scalar.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-scalar.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,7 +55,7 @@
 {
 public:
 
-  octave_scalar (void)
+  octave_scalar ()
     : octave_base_scalar<double> (0.0) { }
 
   octave_scalar (double d)
@@ -64,19 +64,19 @@
   octave_scalar (const octave_scalar& s)
     : octave_base_scalar<double> (s) { }
 
-  ~octave_scalar (void) = default;
+  ~octave_scalar () = default;
 
-  octave_base_value * clone (void) const { return new octave_scalar (*this); }
+  octave_base_value * clone () const { return new octave_scalar (*this); }
 
   // We return an octave_matrix here instead of an octave_scalar so
   // that in expressions like A(2,2,2) = 2 (for A previously
   // undefined), A will be empty instead of a 1x1 object.
-  octave_base_value * empty_clone (void) const { return new octave_matrix (); }
+  octave_base_value * empty_clone () const { return new octave_matrix (); }
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
-  type_conv_info numeric_demotion_function (void) const;
+  type_conv_info numeric_demotion_function () const;
 
   octave::idx_vector index_vector (bool /* require_integers */ = false) const
   { return octave::idx_vector (scalar); }
@@ -84,51 +84,51 @@
   octave_value any (int = 0) const
   { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
 
-  builtin_type_t builtin_type (void) const { return btyp_double; }
+  builtin_type_t builtin_type () const { return btyp_double; }
 
-  bool is_real_scalar (void) const { return true; }
+  bool is_real_scalar () const { return true; }
 
-  bool isreal (void) const { return true; }
+  bool isreal () const { return true; }
 
-  bool is_double_type (void) const { return true; }
+  bool is_double_type () const { return true; }
 
-  bool isfloat (void) const { return true; }
+  bool isfloat () const { return true; }
 
   int8NDArray
-  int8_array_value (void) const
+  int8_array_value () const
   { return int8NDArray (dim_vector (1, 1), scalar); }
 
   int16NDArray
-  int16_array_value (void) const
+  int16_array_value () const
   { return int16NDArray (dim_vector (1, 1), scalar); }
 
   int32NDArray
-  int32_array_value (void) const
+  int32_array_value () const
   { return int32NDArray (dim_vector (1, 1), scalar); }
 
   int64NDArray
-  int64_array_value (void) const
+  int64_array_value () const
   { return int64NDArray (dim_vector (1, 1), scalar); }
 
   uint8NDArray
-  uint8_array_value (void) const
+  uint8_array_value () const
   { return uint8NDArray (dim_vector (1, 1), scalar); }
 
   uint16NDArray
-  uint16_array_value (void) const
+  uint16_array_value () const
   { return uint16NDArray (dim_vector (1, 1), scalar); }
 
   uint32NDArray
-  uint32_array_value (void) const
+  uint32_array_value () const
   { return uint32NDArray (dim_vector (1, 1), scalar); }
 
   uint64NDArray
-  uint64_array_value (void) const
+  uint64_array_value () const
   { return uint64NDArray (dim_vector (1, 1), scalar); }
 
 #define DEFINE_INT_SCALAR_VALUE(TYPE)           \
   octave_ ## TYPE                               \
-  TYPE ## _scalar_value (void) const            \
+  TYPE ## _scalar_value () const            \
   {                                             \
     return octave_ ## TYPE (scalar);            \
   }
@@ -223,18 +223,28 @@
     return boolNDArray (dim_vector (1, 1), scalar);
   }
 
-  octave_value as_double (void) const;
-  octave_value as_single (void) const;
+  octave_value as_double_or_copy (void);
+
+  bool maybe_update_double (double d)
+  {
+    if (m_count != 1)
+      return false;
+    scalar = d;
+    return true;
+  }
 
-  octave_value as_int8 (void) const;
-  octave_value as_int16 (void) const;
-  octave_value as_int32 (void) const;
-  octave_value as_int64 (void) const;
+  octave_value as_double () const;
+  octave_value as_single () const;
 
-  octave_value as_uint8 (void) const;
-  octave_value as_uint16 (void) const;
-  octave_value as_uint32 (void) const;
-  octave_value as_uint64 (void) const;
+  octave_value as_int8 () const;
+  octave_value as_int16 () const;
+  octave_value as_int32 () const;
+  octave_value as_int64 () const;
+
+  octave_value as_uint8 () const;
+  octave_value as_uint16 () const;
+  octave_value as_uint32 () const;
+  octave_value as_uint64 () const;
 
   // We don't need to override both forms of the diag method.  The using
   // declaration will avoid warnings about partially-overloaded virtual
@@ -245,9 +255,9 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  void increment (void) { ++scalar; }
+  void increment () { ++scalar; }
 
-  void decrement (void) { --scalar; }
+  void decrement () { --scalar; }
 
   bool save_ascii (std::ostream& os);
 
--- a/libinterp/octave-value/ov-str-mat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-str-mat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -80,7 +80,7 @@
 }
 
 octave_base_value::type_conv_info
-octave_char_matrix_str::numeric_conversion_function (void) const
+octave_char_matrix_str::numeric_conversion_function () const
 {
   return octave_base_value::type_conv_info (default_numeric_conversion_function,
          octave_matrix::static_type_id ());
@@ -252,7 +252,7 @@
 */
 
 Array<std::string>
-octave_char_matrix_str::cellstr_value (void) const
+octave_char_matrix_str::cellstr_value () const
 {
   Array<std::string> retval;
 
@@ -328,7 +328,7 @@
       for (int i=0; i < dv.ndims (); i++)
         os << ' ' << dv(i);
       os << "\n";
-      os.write (tmp.fortran_vec (), dv.numel ());
+      os.write (tmp.data (), dv.numel ());
       os << "\n";
     }
   else
@@ -486,7 +486,7 @@
     }
 
   charNDArray m = char_array_value ();
-  os.write (m.fortran_vec (), dv.numel ());
+  os.write (m.data (), dv.numel ());
   return true;
 }
 
--- a/libinterp/octave-value/ov-str-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-str-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 {
 public:
 
-  octave_char_matrix_str (void)
+  octave_char_matrix_str ()
     : octave_char_matrix () { }
 
   octave_char_matrix_str (const charMatrix& chm)
@@ -84,20 +84,20 @@
   octave_char_matrix_str (const octave_char_matrix_str& chms)
     : octave_char_matrix (chms) { }
 
-  ~octave_char_matrix_str (void) = default;
+  ~octave_char_matrix_str () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_char_matrix_str (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_char_matrix_str (); }
 
-  type_conv_info numeric_conversion_function (void) const;
+  type_conv_info numeric_conversion_function () const;
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false)
   { return do_index_op_internal (idx, resize_ok); }
 
-  octave_value squeeze (void) const
+  octave_value squeeze () const
   { return octave_value (charNDArray (m_matrix.squeeze ())); }
 
   octave_value reshape (const dim_vector& new_dims) const
@@ -116,9 +116,9 @@
   octave_value diag (octave_idx_type k = 0) const
   { return octave_value (m_matrix.diag (k)); }
 
-  bool is_string (void) const { return true; }
+  bool is_string () const { return true; }
 
-  bool isnumeric (void) const { return false; }
+  bool isnumeric () const { return false; }
 
   double double_value (bool = false) const;
 
@@ -136,9 +136,9 @@
 
   std::string string_value (bool force = false) const;
 
-  std::string xstring_value (void) const { return string_value (); }
+  std::string xstring_value () const { return string_value (); }
 
-  Array<std::string> cellstr_value (void) const;
+  Array<std::string> cellstr_value () const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
   { return octave_value (m_matrix.sort (dim, mode)); }
@@ -147,7 +147,7 @@
                      sortmode mode = ASCENDING) const
   { return octave_value (m_matrix.sort (sidx, dim, mode)); }
 
-  bool print_as_scalar (void) const { return (rows () <= 1); }
+  bool print_as_scalar () const { return (rows () <= 1); }
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -191,7 +191,7 @@
 {
 public:
 
-  octave_char_matrix_sq_str (void)
+  octave_char_matrix_sq_str ()
     : octave_char_matrix_str () { }
 
   octave_char_matrix_sq_str (const charMatrix& chm)
@@ -221,14 +221,14 @@
   octave_char_matrix_sq_str (const octave_char_matrix_sq_str& chms)
     : octave_char_matrix_str (chms) { }
 
-  ~octave_char_matrix_sq_str (void) = default;
+  ~octave_char_matrix_sq_str () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_char_matrix_sq_str (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_char_matrix_sq_str (); }
 
-  octave_value squeeze (void) const
+  octave_value squeeze () const
   { return octave_value (charNDArray (m_matrix.squeeze ()), '\''); }
 
   octave_value reshape (const dim_vector& new_dims) const
@@ -252,7 +252,7 @@
   octave_value diag (octave_idx_type k = 0) const
   { return octave_value (m_matrix.diag (k), '\''); }
 
-  bool is_sq_string (void) const { return true; }
+  bool is_sq_string () const { return true; }
 
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false)
--- a/libinterp/octave-value/ov-struct.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-struct.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,6 +52,7 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 #include "pr-output.h"
+#include "ov-inline.h"
 
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct", "struct");
@@ -76,7 +77,7 @@
 }
 
 octave_base_value *
-octave_struct::try_narrowing_conversion (void)
+octave_struct::try_narrowing_conversion ()
 {
   octave_base_value *retval = nullptr;
 
@@ -109,7 +110,7 @@
 }
 
 static void
-err_invalid_index_for_assignment (void)
+err_invalid_index_for_assignment ()
 {
   error ("invalid index for structure array assignment");
 }
@@ -465,7 +466,7 @@
 
                 m_map.assign (idxf, key, tmp_cell);
 
-                count++;
+                m_count++;
                 retval = octave_value (this);
               }
             else
@@ -478,7 +479,7 @@
                     m_map.assign (idxf,
                                   key, Cell (t_rhs.storable_value ()));
 
-                    count++;
+                    m_count++;
                     retval = octave_value (this);
                   }
                 else
@@ -493,7 +494,7 @@
 
                 m_map.assign (idx.front (), rhs_map);
 
-                count++;
+                m_count++;
                 retval = octave_value (this);
               }
             else
@@ -503,7 +504,7 @@
 
                 m_map.delete_elements (idx.front ());
 
-                count++;
+                m_count++;
                 retval = octave_value (this);
               }
           }
@@ -540,7 +541,7 @@
             m_map.setfield (key, tmp_cell);
           }
 
-        count++;
+        m_count++;
         retval = octave_value (this);
       }
       break;
@@ -571,7 +572,7 @@
 }
 
 std::size_t
-octave_struct::byte_size (void) const
+octave_struct::byte_size () const
 {
   // Neglect the size of the fieldnames.
 
@@ -1095,6 +1096,39 @@
   return retval;
 }
 
+octave_value
+octave_struct::vm_extract_forloop_value (octave_idx_type counter)
+{
+  // TODO: Maybe this is slow? Should preferably be done once per loop
+  octave_value_list idx;
+  octave_value arg = octave_value_factory::make_copy (this);
+
+  dim_vector dv = arg.dims ().redim (2);
+  octave_idx_type nrows = dv(0);
+
+  if (arg.ndims () > 2)
+    arg = arg.reshape (dv);
+
+  octave_idx_type iidx;
+
+  // for row vectors, use single index to speed things up.
+  if (nrows == 1)
+    {
+      idx.resize (1);
+      iidx = 0;
+    }
+  else
+    {
+      idx.resize (2);
+      idx(0) = octave_value::magic_colon_t;
+      iidx = 1;
+    }
+
+  // One based indexing
+  idx(iidx) = counter + 1;
+  return arg.index_op (idx).storable_value ();
+}
+
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_scalar_struct, "scalar struct",
                                     "struct");
 
@@ -1271,7 +1305,7 @@
 
       m_map.setfield (key, t_rhs.storable_value ());
 
-      count++;
+      m_count++;
       retval = this;
     }
   else
@@ -1292,7 +1326,7 @@
 }
 
 std::size_t
-octave_scalar_struct::byte_size (void) const
+octave_scalar_struct::byte_size () const
 {
   // Neglect the size of the fieldnames.
 
@@ -1694,7 +1728,7 @@
 }
 
 octave_value
-octave_scalar_struct::to_array (void)
+octave_scalar_struct::to_array ()
 {
   return new octave_struct (octave_map (m_map));
 }
@@ -1794,8 +1828,7 @@
     {
       if (nargin == 2)
         {
-          Array<std::string> cstr = args(
-                                      1).xcellstr_value ("struct: second argument should be a cell array of field names");
+          Array<std::string> cstr = args(1).xcellstr_value ("struct: second argument should be a cell array of field names");
 
           return ovl (octave_map (args(0).dims (), cstr));
         }
@@ -2020,7 +2053,7 @@
 
 OCTAVE_NORETURN
 static void
-invalid_cell2struct_fields_error (void)
+invalid_cell2struct_fields_error ()
 {
   error ("cell2struct: FIELDS must be a cell array of strings or a scalar string");
 }
@@ -2091,8 +2124,7 @@
   if (nargin < 2 || nargin > 3)
     print_usage ();
 
-  const Cell vals
-    = args(0).xcell_value ("cell2struct: argument CELL must be of type cell");
+  const Cell vals = args(0).xcell_value ("cell2struct: argument CELL must be of type cell");
 
   const Array<std::string> fields = get_cell2struct_fields (args(1));
 
@@ -2183,7 +2215,7 @@
 
   octave_map m = args(0).xmap_value ("rmfield: first argument must be a struct");
 
-  octave_value_list fval = Fcellstr (args(1), 1);
+  octave_value_list fval = Fcellstr (ovl (args(1)), 1);
 
   Cell fcell = fval(0).cell_value ();
 
--- a/libinterp/octave-value/ov-struct.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-struct.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 {
 public:
 
-  octave_struct (void)
+  octave_struct ()
     : octave_base_value (), m_map () { }
 
   octave_struct (const octave_map& m)
@@ -59,14 +59,14 @@
   octave_struct (const octave_struct& s)
     : octave_base_value (), m_map (s.m_map) { }
 
-  ~octave_struct (void) = default;
+  ~octave_struct () = default;
 
-  octave_base_value * clone (void) const { return new octave_struct (*this); }
-  octave_base_value * empty_clone (void) const { return new octave_struct (); }
+  octave_base_value * clone () const { return new octave_struct (*this); }
+  octave_base_value * empty_clone () const { return new octave_struct (); }
 
   void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);
 
-  octave_base_value * try_narrowing_conversion (void);
+  octave_base_value * try_narrowing_conversion ();
 
   Cell dotref (const octave_value_list& idx, bool auto_add = false);
 
@@ -91,7 +91,7 @@
                          const std::list<octave_value_list>& idx,
                          const octave_value& rhs);
 
-  octave_value squeeze (void) const { return m_map.squeeze (); }
+  octave_value squeeze () const { return m_map.squeeze (); }
 
   octave_value permute (const Array<int>& vec, bool inv = false) const
   { return m_map.permute (vec, inv); }
@@ -99,18 +99,20 @@
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
-  dim_vector dims (void) const { return m_map.dims (); }
+  dim_vector dims () const { return m_map.dims (); }
 
-  std::size_t byte_size (void) const;
+  octave_value vm_extract_forloop_value (octave_idx_type idx);
+
+  std::size_t byte_size () const;
 
   // This is the number of elements in each field.  The total number
   // of elements is numel () * nfields ().
-  octave_idx_type numel (void) const
+  octave_idx_type numel () const
   {
     return m_map.numel ();
   }
 
-  octave_idx_type nfields (void) const { return m_map.nfields (); }
+  octave_idx_type nfields () const { return m_map.nfields (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return m_map.reshape (new_dims); }
@@ -118,17 +120,17 @@
   octave_value resize (const dim_vector& dv, bool fill = false) const
   { octave_map tmap = m_map; tmap.resize (dv, fill); return tmap; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool isstruct (void) const { return true; }
+  bool isstruct () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return btyp_struct; }
+  builtin_type_t builtin_type () const { return btyp_struct; }
 
-  octave_map map_value (void) const { return m_map; }
+  octave_map map_value () const { return m_map; }
 
-  string_vector map_keys (void) const { return m_map.fieldnames (); }
+  string_vector map_keys () const { return m_map.fieldnames (); }
 
   bool isfield (const std::string& field_name) const
   { return m_map.isfield (field_name); }
@@ -178,7 +180,7 @@
 {
 public:
 
-  octave_scalar_struct (void)
+  octave_scalar_struct ()
     : octave_base_value (), m_map () { }
 
   octave_scalar_struct (const octave_scalar_map& m)
@@ -190,11 +192,11 @@
   octave_scalar_struct (const octave_scalar_struct& s)
     : octave_base_value (), m_map (s.m_map) { }
 
-  ~octave_scalar_struct (void) = default;
+  ~octave_scalar_struct () = default;
 
-  octave_base_value * clone (void) const
+  octave_base_value * clone () const
   { return new octave_scalar_struct (*this); }
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return new octave_scalar_struct (); }
 
   void break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame);
@@ -218,7 +220,7 @@
                          const std::list<octave_value_list>& idx,
                          const octave_value& rhs);
 
-  octave_value squeeze (void) const { return m_map; }
+  octave_value squeeze () const { return m_map; }
 
   octave_value permute (const Array<int>& vec, bool inv = false) const
   { return octave_map (m_map).permute (vec, inv); }
@@ -226,18 +228,18 @@
   octave_value do_index_op (const octave_value_list& idx,
                             bool resize_ok = false);
 
-  dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; }
+  dim_vector dims () const { static dim_vector dv (1, 1); return dv; }
 
-  std::size_t byte_size (void) const;
+  std::size_t byte_size () const;
 
   // This is the number of elements in each field.  The total number
   // of elements is numel () * nfields ().
-  octave_idx_type numel (void) const
+  octave_idx_type numel () const
   {
     return 1;
   }
 
-  octave_idx_type nfields (void) const { return m_map.nfields (); }
+  octave_idx_type nfields () const { return m_map.nfields (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return octave_map (m_map).reshape (new_dims); }
@@ -245,19 +247,19 @@
   octave_value resize (const dim_vector& dv, bool fill = false) const
   { octave_map tmap = m_map; tmap.resize (dv, fill); return tmap; }
 
-  bool is_defined (void) const { return true; }
+  bool is_defined () const { return true; }
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  bool isstruct (void) const { return true; }
+  bool isstruct () const { return true; }
 
-  builtin_type_t builtin_type (void) const { return btyp_struct; }
+  builtin_type_t builtin_type () const { return btyp_struct; }
 
-  octave_map map_value (void) const { return m_map; }
+  octave_map map_value () const { return m_map; }
 
-  octave_scalar_map scalar_map_value (void) const { return m_map; }
+  octave_scalar_map scalar_map_value () const { return m_map; }
 
-  string_vector map_keys (void) const { return m_map.fieldnames (); }
+  string_vector map_keys () const { return m_map.fieldnames (); }
 
   bool isfield (const std::string& field_name) const
   { return m_map.isfield (field_name); }
@@ -295,7 +297,7 @@
 
 private:
 
-  octave_value to_array (void);
+  octave_value to_array ();
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
--- a/libinterp/octave-value/ov-typeinfo.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-typeinfo.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -581,7 +581,7 @@
 }
 
 string_vector
-type_info::installed_type_names (void) const
+type_info::installed_type_names () const
 {
   string_vector retval (m_num_types);
 
@@ -592,7 +592,7 @@
 }
 
 octave_scalar_map
-type_info::unary_ops_map (void) const
+type_info::unary_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -617,7 +617,7 @@
 }
 
 octave_scalar_map
-type_info::non_const_unary_ops_map (void) const
+type_info::non_const_unary_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -642,7 +642,7 @@
 }
 
 octave_scalar_map
-type_info::binary_ops_map (void) const
+type_info::binary_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -668,7 +668,7 @@
 }
 
 octave_scalar_map
-type_info::compound_binary_ops_map (void) const
+type_info::compound_binary_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -695,7 +695,7 @@
 }
 
 octave_scalar_map
-type_info::assign_ops_map (void) const
+type_info::assign_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -721,7 +721,7 @@
 }
 
 octave_scalar_map
-type_info::assignany_ops_map (void) const
+type_info::assignany_ops_map () const
 {
   octave_scalar_map retval;
 
@@ -746,7 +746,7 @@
 }
 
 octave_scalar_map
-type_info::installed_type_info (void) const
+type_info::installed_type_info () const
 {
   octave_scalar_map retval;
 
@@ -875,14 +875,14 @@
   return type_info.lookup_widening_op (t, t_result);
 }
 
-string_vector installed_type_names (void)
+string_vector installed_type_names ()
 {
   octave::type_info& type_info = octave::__get_type_info__ ();
 
   return type_info.installed_type_names ();
 }
 
-octave_scalar_map installed_type_info (void)
+octave_scalar_map installed_type_info ()
 {
   octave::type_info& type_info = octave::__get_type_info__ ();
 
--- a/libinterp/octave-value/ov-typeinfo.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-typeinfo.h	Fri Jun 23 20:51:51 2023 +0200
@@ -69,13 +69,9 @@
 
   explicit type_info (int init_tab_sz = 16);
 
-  // No copying!
-
-  type_info (const type_info&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (type_info)
 
-  type_info& operator = (const type_info&) = delete;
-
-  ~type_info (void) = default;
+  ~type_info () = default;
 
   // It is intentional that there is no install_type function.
 
@@ -219,21 +215,21 @@
 
   octave_base_value::type_conv_fcn lookup_widening_op (int, int);
 
-  string_vector installed_type_names (void) const;
+  string_vector installed_type_names () const;
 
-  octave_scalar_map installed_type_info (void) const;
+  octave_scalar_map installed_type_info () const;
 
-  octave_scalar_map unary_ops_map (void) const;
+  octave_scalar_map unary_ops_map () const;
 
-  octave_scalar_map non_const_unary_ops_map (void) const;
+  octave_scalar_map non_const_unary_ops_map () const;
 
-  octave_scalar_map binary_ops_map (void) const;
+  octave_scalar_map binary_ops_map () const;
 
-  octave_scalar_map compound_binary_ops_map (void) const;
+  octave_scalar_map compound_binary_ops_map () const;
 
-  octave_scalar_map assign_ops_map (void) const;
+  octave_scalar_map assign_ops_map () const;
 
-  octave_scalar_map assignany_ops_map (void) const;
+  octave_scalar_map assignany_ops_map () const;
 
 private:
 
@@ -328,9 +324,9 @@
 extern OCTINTERP_API octave_base_value::type_conv_fcn
 lookup_widening_op (int t, int t_result);
 
-extern OCTINTERP_API string_vector installed_type_names (void);
+extern OCTINTERP_API string_vector installed_type_names ();
 
-extern OCTINTERP_API octave_scalar_map installed_type_info (void);
+extern OCTINTERP_API octave_scalar_map installed_type_info ();
 
 OCTAVE_END_NAMESPACE(octave_value_typeinfo)
 
--- a/libinterp/octave-value/ov-usr-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -60,11 +60,12 @@
 #include "profiler.h"
 #include "variables.h"
 #include "ov-fcn-handle.h"
+#include "pt-bytecode-walk.h"
 
 // Whether to optimize subsasgn method calls.
 static bool Voptimize_subsasgn_calls = true;
 
-octave_user_code::~octave_user_code (void)
+octave_user_code::~octave_user_code ()
 {
   // This function is no longer valid, so remove the pointer to it from
   // the corresponding scope.
@@ -85,7 +86,7 @@
 }
 
 void
-octave_user_code::get_file_info (void)
+octave_user_code::get_file_info ()
 {
   m_file_info = new octave::file_info (m_file_name);
 
@@ -128,13 +129,13 @@
 }
 
 std::map<std::string, octave_value>
-octave_user_code::subfunctions (void) const
+octave_user_code::subfunctions () const
 {
   return std::map<std::string, octave_value> ();
 }
 
 octave_value
-octave_user_code::dump (void) const
+octave_user_code::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "scope_info", m_scope ? m_scope.dump () : "0x0" },
@@ -153,7 +154,7 @@
                                      "user-defined script",
                                      "user-defined script");
 
-octave_user_script::octave_user_script (void)
+octave_user_script::octave_user_script ()
   : octave_user_code ()
 { }
 
@@ -228,7 +229,7 @@
     m_cmd_list->mark_as_function_body ();
 }
 
-octave_user_function::~octave_user_function (void)
+octave_user_function::~octave_user_function ()
 {
   delete m_param_list;
   delete m_ret_list;
@@ -253,7 +254,7 @@
 // information (yet).
 
 void
-octave_user_function::maybe_relocate_end_internal (void)
+octave_user_function::maybe_relocate_end_internal ()
 {
   if (m_cmd_list && ! m_cmd_list->empty ())
     {
@@ -289,7 +290,7 @@
 }
 
 void
-octave_user_function::maybe_relocate_end (void)
+octave_user_function::maybe_relocate_end ()
 {
   std::map<std::string, octave_value> fcns = subfunctions ();
 
@@ -314,7 +315,7 @@
 }
 
 std::string
-octave_user_function::profiler_name (void) const
+octave_user_function::profiler_name () const
 {
   std::ostringstream result;
 
@@ -337,7 +338,7 @@
 }
 
 void
-octave_user_function::mark_as_system_fcn_file (void)
+octave_user_function::mark_as_system_fcn_file ()
 {
   if (! m_file_name.empty ())
     {
@@ -367,19 +368,19 @@
 }
 
 void
-octave_user_function::erase_subfunctions (void)
+octave_user_function::erase_subfunctions ()
 {
   m_scope.erase_subfunctions ();
 }
 
 bool
-octave_user_function::takes_varargs (void) const
+octave_user_function::takes_varargs () const
 {
   return (m_param_list && m_param_list->takes_varargs ());
 }
 
 bool
-octave_user_function::takes_var_return (void) const
+octave_user_function::takes_var_return () const
 {
   return (m_ret_list && m_ret_list->takes_varargs ());
 }
@@ -393,19 +394,19 @@
 }
 
 void
-octave_user_function::lock_subfunctions (void)
+octave_user_function::lock_subfunctions ()
 {
   m_scope.lock_subfunctions ();
 }
 
 void
-octave_user_function::unlock_subfunctions (void)
+octave_user_function::unlock_subfunctions ()
 {
   m_scope.unlock_subfunctions ();
 }
 
 std::map<std::string, octave_value>
-octave_user_function::subfunctions (void) const
+octave_user_function::subfunctions () const
 {
   return m_scope.subfunctions ();
 }
@@ -442,7 +443,7 @@
 }
 
 bool
-octave_user_function::has_subfunctions (void) const
+octave_user_function::has_subfunctions () const
 {
   return m_scope.has_subfunctions ();
 }
@@ -454,7 +455,7 @@
 }
 
 std::list<std::string>
-octave_user_function::subfunction_names (void) const
+octave_user_function::subfunction_names () const
 {
   return m_scope.subfunction_names ();
 }
@@ -481,7 +482,26 @@
 octave_user_function::call (octave::tree_evaluator& tw, int nargout,
                             const octave_value_list& args)
 {
-  tw.push_stack_frame (this);
+  bool is_compiled = false;
+
+  is_compiled = this->is_compiled ();
+  if (octave::V__enable_vm_eval__ && !is_compiled && !m_compilation_failed)
+  {
+    try
+      {
+        octave::compile_user_function (*this, false);
+        is_compiled = true;
+      }
+    catch (std::exception &e)
+      {
+        warning ("Auto-compilation of %s failed with message %s", name().c_str (), e.what ());
+        this->m_compilation_failed = true;
+      }
+  }
+
+  // Bytecode functions push their own stack frames in the vm
+  if (!is_compiled)
+    tw.push_stack_frame (this);
 
   octave::unwind_action act ([&tw] () { tw.pop_stack_frame (); });
 
@@ -502,7 +522,7 @@
 }
 
 octave::tree_expression *
-octave_user_function::special_expr (void)
+octave_user_function::special_expr ()
 {
   panic_unless (is_special_expr ());
   panic_if (m_cmd_list->length () != 1);
@@ -512,7 +532,7 @@
 }
 
 bool
-octave_user_function::subsasgn_optimization_ok (void)
+octave_user_function::subsasgn_optimization_ok ()
 {
   bool retval = false;
   if (Voptimize_subsasgn_calls
@@ -529,7 +549,7 @@
 }
 
 std::string
-octave_user_function::ctor_type_str (void) const
+octave_user_function::ctor_type_str () const
 {
   std::string retval;
 
@@ -556,7 +576,7 @@
 }
 
 std::string
-octave_user_function::method_type_str (void) const
+octave_user_function::method_type_str () const
 {
   std::string retval;
 
@@ -583,7 +603,7 @@
 }
 
 octave_value
-octave_user_function::dump (void) const
+octave_user_function::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "user_code", octave_user_code::dump () },
@@ -621,7 +641,7 @@
 }
 
 void
-octave_user_function::restore_warning_states (void)
+octave_user_function::restore_warning_states ()
 {
   octave::interpreter& interp = octave::__get_interpreter__ ();
 
--- a/libinterp/octave-value/ov-usr-fcn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,6 +36,7 @@
 #include "ov-typeinfo.h"
 #include "symscope.h"
 #include "unwind-prot.h"
+#include "pt-bytecode.h"
 
 class string_vector;
 
@@ -73,15 +74,11 @@
 
 public:
 
-  // No copying!
-
-  octave_user_code (const octave_user_code& f) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_user_code)
 
-  octave_user_code& operator = (const octave_user_code& f) = delete;
+  ~octave_user_code ();
 
-  ~octave_user_code (void);
-
-  bool is_user_code (void) const { return true; }
+  bool is_user_code () const { return true; }
 
   std::string get_code_line (std::size_t line);
 
@@ -91,7 +88,9 @@
   void cache_function_text (const std::string& text,
                             const octave::sys::time& timestamp);
 
-  octave::symbol_scope scope (void) { return m_scope; }
+  octave::symbol_scope scope () { return m_scope; }
+
+  std::size_t scope_num_symbols () { return m_scope.num_symbols (); }
 
   void stash_fcn_file_name (const std::string& nm) { m_file_name = nm; }
 
@@ -104,26 +103,26 @@
     mark_fcn_file_up_to_date (t);
   }
 
-  std::string fcn_file_name (void) const { return m_file_name; }
+  std::string fcn_file_name () const { return m_file_name; }
 
-  octave::sys::time time_parsed (void) const { return m_t_parsed; }
+  octave::sys::time time_parsed () const { return m_t_parsed; }
 
-  octave::sys::time time_checked (void) const { return m_t_checked; }
+  octave::sys::time time_checked () const { return m_t_checked; }
 
   virtual octave_value find_subfunction (const std::string&) const
   {
     return octave_value ();
   }
 
-  virtual std::map<std::string, octave_value> subfunctions (void) const;
+  virtual std::map<std::string, octave_value> subfunctions () const;
 
-  octave::tree_statement_list * body (void) { return m_cmd_list; }
+  octave::tree_statement_list * body () { return m_cmd_list; }
 
-  octave_value dump (void) const;
+  octave_value dump () const;
 
 protected:
 
-  void get_file_info (void);
+  void get_file_info ();
 
   // Our symbol table scope.
   octave::symbol_scope m_scope;
@@ -153,7 +152,7 @@
 {
 public:
 
-  octave_user_script (void);
+  octave_user_script ();
 
   octave_user_script (const std::string& fnm, const std::string& nm,
                       const octave::symbol_scope& scope = octave::symbol_scope (),
@@ -164,13 +163,9 @@
                       const octave::symbol_scope& scope = octave::symbol_scope (),
                       const std::string& ds = "");
 
-  // No copying!
-
-  octave_user_script (const octave_user_script& f) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_user_script)
 
-  octave_user_script& operator = (const octave_user_script& f) = delete;
-
-  ~octave_user_script (void) = default;
+  ~octave_user_script () = default;
 
   octave_function * function_value (bool = false) { return this; }
 
@@ -181,7 +176,7 @@
   // Scripts and user functions are both considered "scripts" because
   // they are written in Octave's scripting language.
 
-  bool is_user_script (void) const { return true; }
+  bool is_user_script () const { return true; }
 
   // We must overload the call method so that we call the proper
   // push_stack_frame method, which is overloaded for pointers to
@@ -215,13 +210,9 @@
                         octave::tree_parameter_list *rl = nullptr,
                         octave::tree_statement_list *cl = nullptr);
 
-  // No copying!
-
-  octave_user_function (const octave_user_function& fcn) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_user_function)
 
-  octave_user_function& operator = (const octave_user_function& fcn) = delete;
-
-  ~octave_user_function (void);
+  ~octave_user_function ();
 
   octave_function * function_value (bool = false) { return this; }
 
@@ -239,8 +230,8 @@
     m_location_column = col;
   }
 
-  int beginning_line (void) const { return m_location_line; }
-  int beginning_column (void) const { return m_location_column; }
+  int beginning_line () const { return m_location_line; }
+  int beginning_column () const { return m_location_column; }
 
   void stash_fcn_end_location (int line, int col)
   {
@@ -248,10 +239,10 @@
     m_end_location_column = col;
   }
 
-  int ending_line (void) const { return m_end_location_line; }
-  int ending_column (void) const { return m_end_location_column; }
+  int ending_line () const { return m_end_location_line; }
+  int ending_column () const { return m_end_location_column; }
 
-  void maybe_relocate_end (void);
+  void maybe_relocate_end ();
 
   void stash_parent_fcn_scope (const octave::symbol_scope& ps);
 
@@ -259,68 +250,68 @@
 
   void stash_trailing_comment (octave::comment_list *tc) { m_trail_comm = tc; }
 
-  std::string profiler_name (void) const;
+  std::string profiler_name () const;
 
-  std::string parent_fcn_name (void) const
+  std::string parent_fcn_name () const
   {
     octave::symbol_scope pscope = parent_fcn_scope ();
 
     return pscope.fcn_name ();
   }
 
-  octave::symbol_scope parent_fcn_scope (void) const
+  octave::symbol_scope parent_fcn_scope () const
   {
     return m_scope.parent_scope ();
   }
 
-  std::list<std::string> parent_fcn_names (void) const
+  std::list<std::string> parent_fcn_names () const
   {
     return m_scope.parent_fcn_names ();
   }
 
-  void mark_as_system_fcn_file (void);
+  void mark_as_system_fcn_file ();
 
-  bool is_system_fcn_file (void) const { return m_system_fcn_file; }
+  bool is_system_fcn_file () const { return m_system_fcn_file; }
 
-  bool is_user_function (void) const { return true; }
+  bool is_user_function () const { return true; }
 
-  void erase_subfunctions (void);
+  void erase_subfunctions ();
 
-  bool takes_varargs (void) const;
+  bool takes_varargs () const;
 
-  bool takes_var_return (void) const;
+  bool takes_var_return () const;
 
   void mark_as_private_function (const std::string& cname = "");
 
-  void lock_subfunctions (void);
+  void lock_subfunctions ();
 
-  void unlock_subfunctions (void);
+  void unlock_subfunctions ();
 
-  std::map<std::string, octave_value> subfunctions (void) const;
+  std::map<std::string, octave_value> subfunctions () const;
 
   octave_value find_subfunction (const std::string& subfuns) const;
 
-  bool has_subfunctions (void) const;
+  bool has_subfunctions () const;
 
   void stash_subfunction_names (const std::list<std::string>& names);
 
-  std::list<std::string> subfunction_names (void) const;
+  std::list<std::string> subfunction_names () const;
 
   octave_value_list all_va_args (const octave_value_list& args);
 
   void stash_function_name (const std::string& s) { m_name = s; }
 
-  void mark_as_subfunction (void) { m_subfunction = true; }
+  void mark_as_subfunction () { m_subfunction = true; }
 
-  bool is_subfunction (void) const { return m_subfunction; }
+  bool is_subfunction () const { return m_subfunction; }
 
-  void mark_as_inline_function (void) { m_inline_function = true; }
+  void mark_as_inline_function () { m_inline_function = true; }
 
-  bool is_inline_function (void) const { return m_inline_function; }
+  bool is_inline_function () const { return m_inline_function; }
 
-  void mark_as_anonymous_function (void) { m_anonymous_function = true; }
+  void mark_as_anonymous_function () { m_anonymous_function = true; }
 
-  bool is_anonymous_function (void) const { return m_anonymous_function; }
+  bool is_anonymous_function () const { return m_anonymous_function; }
 
   bool is_anonymous_function_of_class
   (const std::string& cname = "") const
@@ -335,18 +326,18 @@
   // If we are a special expression, then the function body consists of exactly
   // one expression.  The expression's result is the return value of the
   // function.
-  bool is_special_expr (void) const
+  bool is_special_expr () const
   {
     return is_inline_function () || is_anonymous_function ();
   }
 
-  void mark_as_nested_function (void) { m_nested_function = true; }
+  void mark_as_nested_function () { m_nested_function = true; }
 
-  bool is_nested_function (void) const { return m_nested_function; }
+  bool is_nested_function () const { return m_nested_function; }
 
-  bool is_parent_function (void) const { return m_scope.is_parent (); }
+  bool is_parent_function () const { return m_scope.is_parent (); }
 
-  void mark_as_legacy_constructor (void) { m_class_constructor = legacy; }
+  void mark_as_legacy_constructor () { m_class_constructor = legacy; }
 
   bool is_legacy_constructor (const std::string& cname = "") const
   {
@@ -354,7 +345,7 @@
             ? (cname.empty () ? true : cname == dispatch_class ()) : false);
   }
 
-  void mark_as_classdef_constructor (void) { m_class_constructor = classdef; }
+  void mark_as_classdef_constructor () { m_class_constructor = classdef; }
 
   bool is_classdef_constructor (const std::string& cname = "") const
   {
@@ -362,7 +353,7 @@
             ? (cname.empty () ? true : cname == dispatch_class ()) : false);
   }
 
-  void mark_as_legacy_method (void) { m_class_method = legacy; }
+  void mark_as_legacy_method () { m_class_method = legacy; }
 
   bool is_legacy_method (const std::string& cname = "") const
   {
@@ -370,7 +361,7 @@
             ? (cname.empty () ? true : cname == dispatch_class ()) : false);
   }
 
-  void mark_as_classdef_method (void) { m_class_method = classdef; }
+  void mark_as_classdef_method () { m_class_method = classdef; }
 
   bool is_classdef_method (const std::string& cname = "") const
   {
@@ -391,26 +382,52 @@
   execute (octave::tree_evaluator& tw, int nargout = 0,
            const octave_value_list& args = octave_value_list ());
 
-  octave::tree_parameter_list * parameter_list (void) { return m_param_list; }
+  octave::tree_parameter_list * parameter_list () { return m_param_list; }
 
-  octave::tree_parameter_list * return_list (void) { return m_ret_list; }
+  octave::tree_parameter_list * return_list () { return m_ret_list; }
 
-  octave::comment_list * leading_comment (void) { return m_lead_comm; }
+  octave::comment_list * leading_comment () { return m_lead_comm; }
 
-  octave::comment_list * trailing_comment (void) { return m_trail_comm; }
+  octave::comment_list * trailing_comment () { return m_trail_comm; }
 
   // 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);
+  octave::tree_expression * special_expr ();
 
-  bool subsasgn_optimization_ok (void);
+  bool subsasgn_optimization_ok ();
 
   void accept (octave::tree_walker& tw);
 
-  octave_value dump (void) const;
+  octave_value dump () const;
+
+  void set_bytecode (octave::bytecode &bytecode)
+  {
+    m_bytecode = bytecode;
+  }
+
+  void clear_bytecode ()
+  {
+    m_bytecode = octave::bytecode {};
+
+    auto subs = subfunctions ();
+    for (auto kv : subs)
+      {
+        octave_user_function *sub = kv.second.user_function_value ();
+        if (sub)
+          sub->clear_bytecode ();
+      }
+  }
+
+  bool is_compiled () const { return m_bytecode.m_code.size (); }
+
+  octave::bytecode &get_bytecode () { return m_bytecode; }
+
+  bool m_compilation_failed = false;
 
 private:
 
+  octave::bytecode m_bytecode;
+
   enum class_method_type
   {
     none,
@@ -418,8 +435,8 @@
     classdef
   };
 
-  std::string ctor_type_str (void) const;
-  std::string method_type_str (void) const;
+  std::string ctor_type_str () const;
+  std::string method_type_str () const;
 
   // List of arguments for this function.  These are local variables.
   octave::tree_parameter_list *m_param_list;
@@ -466,7 +483,7 @@
   // Enum describing whether this function is a method for a class.
   class_method_type m_class_method;
 
-  void maybe_relocate_end_internal (void);
+  void maybe_relocate_end_internal ();
 
   void print_code_function_header (const std::string& prefix);
 
@@ -475,7 +492,7 @@
   // XXX FIXME (public)
 public:
 
-  void restore_warning_states (void);
+  void restore_warning_states ();
 
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-vm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,203 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 1996-2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_ov_vm_h)
+#define octave_ov_vm_h 1
+
+#include "octave-config.h"
+
+#include "ov.h"
+#include "load-path.h"
+
+
+// octave_value_vm is to be used only by the VM
+// and need to have the same bit representation as
+// an octave_value.
+//
+// A octave_value_vm object might not be assigned
+// to itself or have a nullptr m_rep when being
+// assigned to.
+
+class octave_value_vm
+{
+public:
+  octave_value_vm ()
+      : m_rep (octave_value::nil_rep ())
+  {
+      m_rep->m_count++;
+  }
+
+  octave_value_vm (octave_base_value *rep, bool count_add1 = true)
+    : m_rep (rep)
+  {
+    if (count_add1)
+      m_rep->m_count++;
+  }
+
+  octave_value_vm (const octave_value_vm& a)
+      : m_rep (a.m_rep)
+  {
+      m_rep->m_count++;
+  }
+  octave_value_vm (const octave_value& a)
+      : m_rep (a.m_rep)
+  {
+      m_rep->m_count++;
+  }
+
+  octave_value_vm (octave_value_vm&& a)
+  : m_rep (a.m_rep)
+  {
+      a.m_rep = nullptr;
+  }
+  octave_value_vm (octave_value&& a)
+  : m_rep (a.m_rep)
+  {
+      a.m_rep = nullptr;
+  }
+
+  ~octave_value_vm () __attribute__ ((always_inline))
+  {
+      // Because we define a move constructor and a move assignment
+      // operator, rep may be a nullptr here.  We should only need to
+      // protect the move assignment operator in a similar way.
+
+    if (m_rep && --m_rep->m_count == 0)
+      delete m_rep;
+  }
+
+  octave_value_vm& operator = (const octave_value_vm& a)
+  {
+    if (--m_rep->m_count == 0)
+      delete m_rep;
+
+    m_rep = a.m_rep;
+    m_rep->m_count++;
+
+    return *this;
+  }
+
+  octave_value_vm& operator = (octave_value_vm&& a)
+  {
+    if (--m_rep->m_count == 0)
+      delete m_rep;
+
+    m_rep = a.m_rep;
+    a.m_rep = nullptr;
+
+    return *this;
+  }
+
+  octave_value_vm& operator = (octave_value&& a)
+  {
+    if (--m_rep->m_count == 0)
+      delete m_rep;
+
+    m_rep = a.m_rep;
+    a.m_rep = nullptr;
+
+    return *this;
+  }
+
+  static void release_rep (octave_base_value *rep)
+  {
+    if (--rep->m_count == 0)
+      delete rep;
+  }
+
+  void steal_ov_rep (octave_value &&ov)
+  {
+    if (m_rep && --m_rep->m_count == 0)
+      delete m_rep;
+
+    m_rep = ov.m_rep;
+    ov.m_rep = nullptr;
+  }
+
+  octave_base_value & get_rep () { return *m_rep; }
+
+  octave_value_vm& operator = (octave_base_value *rep)
+  {
+    if (--m_rep->m_count == 0)
+      delete m_rep;
+
+    m_rep = rep;
+
+    return *this;
+  }
+
+  bool vm_need_dispatch_push () __attribute__ ((pure, always_inline, nothrow))
+  { return m_rep->vm_need_dispatch_push (); }
+
+  bool vm_need_dispatch_assign_rhs () __attribute__ ((pure, always_inline, nothrow))
+  { return m_rep->vm_need_dispatch_assign_rhs (); }
+
+  bool vm_need_dispatch_assign_lhs () __attribute__ ((pure, always_inline, nothrow))
+  { return m_rep->vm_need_dispatch_assign_lhs (); }
+
+  int type_id() const __attribute__ ((pure, always_inline, nothrow))
+  { return m_rep->type_id (); }
+
+  bool is_matrix_type () const __attribute__ ((pure, always_inline, nothrow))
+  { return m_rep->is_matrix_type (); }
+
+  octave_base_value *m_rep;
+};
+
+class
+octave_cached_value : public octave_base_value
+{
+public:
+
+  octave_cached_value ()
+  {
+    m_n_updated = octave::load_path::get_weak_n_updated ();
+  }
+
+  void set_cached_obj (octave_value cache_obj)
+  {
+    m_cached_object = cache_obj;
+  }
+
+  octave_value get_cached_value ()
+  {
+    return m_cached_object;
+  }
+
+  bool cache_is_valid ()
+  {
+    return m_n_updated == octave::load_path::get_weak_n_updated () && m_cached_object.is_defined ();
+  }
+
+  bool is_defined () const { return true; }
+
+
+private:
+
+  octave_value m_cached_object;
+  octave_idx_type m_n_updated = 0;
+};
+
+#endif
--- a/libinterp/octave-value/ov.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -118,7 +118,7 @@
 // Octave's value type.
 
 octave_base_value *
-octave_value::nil_rep (void)
+octave_value::nil_rep ()
 {
   static octave_base_value nr;
   return &nr;
@@ -1073,36 +1073,6 @@
   maybe_mutate ();
 }
 
-// Remove when public constructor that uses this function is removed.
-octave_base_value *
-octave_value::make_range_rep_deprecated (double base, double inc, double limit)
-{
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  return dynamic_cast<octave_base_value *>
-         (new octave_legacy_range (Range (base, inc, limit)));
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-// Remove when public constructor that uses this function is removed.
-octave_base_value *
-octave_value::make_range_rep_deprecated (const Range& r, bool force_range)
-{
-  if (! force_range && ! r.ok ())
-    error ("invalid range");
-
-  if ((force_range || Voptimize_range))
-    return dynamic_cast<octave_base_value *> (new octave_legacy_range (r));
-  else
-    return dynamic_cast<octave_base_value *> (new octave_matrix (r.matrix_value ()));
-}
-
 octave_value::octave_value (const octave::range<double>& r, bool force_range)
   : m_rep (force_range || Voptimize_range
            ? dynamic_cast<octave_base_value *> (new ov_range<double> (r))
@@ -1111,108 +1081,7 @@
   maybe_mutate ();
 }
 
-// For now, disable all but range<double>.
-
-#if 0
-
-octave_value::octave_value (const octave::range<float>& r, bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<float> (r))
-           : dynamic_cast<octave_base_value *> (new octave_float_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_int8>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_int8> (r))
-           : dynamic_cast<octave_base_value *> (new octave_int8_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_int16>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_int16> (r))
-           : dynamic_cast<octave_base_value *> (new octave_int16_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_int32>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_int32> (r))
-           : dynamic_cast<octave_base_value *> (new octave_int32_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_int64>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_int64> (r))
-           : dynamic_cast<octave_base_value *> (new octave_int64_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_uint8>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint8> (r))
-           : dynamic_cast<octave_base_value *> (new octave_uint8_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_uint16>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint16> (r))
-           : dynamic_cast<octave_base_value *> (new octave_uint16_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_uint32>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint32> (r))
-           : dynamic_cast<octave_base_value *> (new octave_uint32_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<octave_uint64>& r,
-                            bool force_range)
-  : m_rep (force_range || Voptimize_range
-           ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint64> (r))
-           : dynamic_cast<octave_base_value *> (new octave_uint64_matrix (r.array_value ())))
-{
-  maybe_mutate ();
-}
-
-octave_value::octave_value (const octave::range<char>& r, char type,
-                            bool /*force_range*/)
-#if 0
-  : m_rep (force_range || optimize_range
-           ? dynamic_cast<octave_base_value *> (new octave_char_range (r, type))
-           : dynamic_cast<octave_base_value *> (type == '"'
-               ? new octave_char_matrix_dq_str (r.array_value ())
-               : new octave_char_matrix_sq_str (r.array_value ())))
-#else
-  : m_rep (type == '"'
-           ? new octave_char_matrix_dq_str (r.array_value ())
-           : new octave_char_matrix_sq_str (r.array_value ()))
-#endif
-{
-  maybe_mutate ();
-}
-
-#endif
+// For now, enable only range<double>.
 
 octave_value::octave_value (const octave_map& m)
   : m_rep (new octave_struct (m))
@@ -1248,15 +1117,8 @@
   : m_rep (new octave_magic_colon ())
 { }
 
-octave_value::octave_value (octave_base_value *new_rep, bool borrow)
-  : m_rep (new_rep)
-{
-  if (borrow)
-    m_rep->count++;
-}
-
 octave_base_value *
-octave_value::clone (void) const
+octave_value::clone () const
 {
   return m_rep->clone ();
 }
@@ -1289,13 +1151,13 @@
 }
 
 void
-octave_value::maybe_mutate (void)
+octave_value::maybe_mutate ()
 {
   octave_base_value *tmp = m_rep->try_narrowing_conversion ();
 
   if (tmp && tmp != m_rep)
     {
-      if (--m_rep->count == 0)
+      if (--m_rep->m_count == 0)
         delete m_rep;
 
       m_rep = tmp;
@@ -1579,6 +1441,13 @@
 }
 
 octave_value_list
+octave_value::
+simple_subsref (char type, octave_value_list& idx, int nargout)
+{
+  return m_rep->simple_subsref (type, idx, nargout);
+}
+
+octave_value_list
 octave_value::subsref (const std::string& type,
                        const std::list<octave_value_list>& idx, int nargout)
 {
@@ -1618,6 +1487,21 @@
 }
 
 octave_value
+octave_value::maybe_as_trivial_range ()
+{
+  if (m_rep->is_trivial_range ())
+    return *this;
+  if (!is_range ())
+    return *this;
+
+  ov_range<double> range = range_value ();
+  if (!range.could_be_trivial_range ())
+    return *this;
+
+  return range.as_trivial_range ();
+}
+
+octave_value
 octave_value::next_subsref (bool auto_add, const std::string& type,
                             const std::list<octave_value_list>& idx,
                             std::size_t skip)
@@ -1633,6 +1517,34 @@
     return *this;
 }
 
+octave_idx_type
+octave_value::end_index (octave_idx_type index_position,
+                         octave_idx_type num_indices) const
+{
+  dim_vector dv = dims ();
+  int ndims = dv.ndims ();
+
+  if (num_indices < ndims)
+    {
+      for (int i = num_indices; i < ndims; i++)
+        dv(num_indices-1) *= dv(i);
+
+      if (num_indices == 1)
+        {
+          ndims = 2;
+          dv.resize (ndims);
+          dv(1) = 1;
+        }
+      else
+        {
+          ndims = num_indices;
+          dv.resize (ndims);
+        }
+    }
+
+  return (index_position < ndims ? dv(index_position) : 1);
+}
+
 octave_value
 octave_value::subsasgn (const std::string& type,
                         const std::list<octave_value_list>& idx,
@@ -1686,7 +1598,7 @@
       octave::type_info::assign_op_fcn f = nullptr;
 
       // Only attempt to operate in-place if this variable is unshared.
-      if (m_rep->count == 1)
+      if (m_rep->m_count == 1)
         {
           int tthis = this->type_id ();
           int trhs = rhs.type_id ();
@@ -1724,7 +1636,7 @@
 // unresolved const issues that prevent that solution from working.
 
 std::string
-octave_value::get_dims_str (void) const
+octave_value::get_dims_str () const
 {
   octave_value tmp = *this;
 
@@ -1739,7 +1651,7 @@
 }
 
 octave_idx_type
-octave_value::length (void) const
+octave_value::length () const
 {
   octave_idx_type retval = 0;
 
@@ -1803,19 +1715,19 @@
 }
 
 Cell
-octave_value::cell_value (void) const
+octave_value::cell_value () const
 {
   return m_rep->cell_value ();
 }
 
 octave_map
-octave_value::map_value (void) const
+octave_value::map_value () const
 {
   return m_rep->map_value ();
 }
 
 octave_scalar_map
-octave_value::scalar_map_value (void) const
+octave_value::scalar_map_value () const
 {
   return m_rep->scalar_map_value ();
 }
@@ -1857,7 +1769,7 @@
 }
 
 octave_value_list
-octave_value::list_value (void) const
+octave_value::list_value () const
 {
   return m_rep->list_value ();
 }
@@ -1891,10 +1803,10 @@
 
 ComplexColumnVector
 octave_value::complex_column_vector_value (bool force_string_conv,
-    bool frc_vec_conv) const
+                                           bool frc_vec_conv) const
 {
   return ComplexColumnVector (complex_vector_value (force_string_conv,
-                              frc_vec_conv));
+                                                    frc_vec_conv));
 }
 
 RowVector
@@ -1910,7 +1822,7 @@
                                         bool frc_vec_conv) const
 {
   return ComplexRowVector (complex_vector_value (force_string_conv,
-                           frc_vec_conv));
+                                                 frc_vec_conv));
 }
 
 Array<double>
@@ -1920,8 +1832,8 @@
   Array<double> retval = array_value (force_string_conv);
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "real vector"));
+                                           force_vector_conversion,
+                                           type_name (), "real vector"));
 }
 
 template <typename T>
@@ -1989,8 +1901,8 @@
     }
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "integer vector"));
+                                           force_vector_conversion,
+                                           type_name (), "integer vector"));
 }
 
 template <typename T>
@@ -2008,8 +1920,8 @@
 
 Array<octave_idx_type>
 octave_value::octave_idx_type_vector_value (bool require_int,
-    bool force_string_conv,
-    bool force_vector_conversion) const
+                                            bool force_string_conv,
+                                            bool force_vector_conversion) const
 {
   Array<octave_idx_type> retval;
 
@@ -2059,8 +1971,8 @@
     }
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "integer vector"));
+                                           force_vector_conversion,
+                                           type_name (), "integer vector"));
 }
 
 Array<Complex>
@@ -2070,25 +1982,25 @@
   Array<Complex> retval = complex_array_value (force_string_conv);
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "complex vector"));
+                                           force_vector_conversion,
+                                           type_name (), "complex vector"));
 }
 
 FloatColumnVector
 octave_value::float_column_vector_value (bool force_string_conv,
-    bool frc_vec_conv) const
+                                         bool frc_vec_conv) const
 {
   return FloatColumnVector (float_vector_value (force_string_conv,
-                            frc_vec_conv));
+                                                frc_vec_conv));
 }
 
 FloatComplexColumnVector
 octave_value::float_complex_column_vector_value (bool force_string_conv,
-    bool frc_vec_conv) const
+                                                 bool frc_vec_conv) const
 {
   return
     FloatComplexColumnVector (float_complex_vector_value (force_string_conv,
-                              frc_vec_conv));
+                                                          frc_vec_conv));
 }
 
 FloatRowVector
@@ -2096,15 +2008,15 @@
                                       bool frc_vec_conv) const
 {
   return FloatRowVector (float_vector_value (force_string_conv,
-                         frc_vec_conv));
+                                             frc_vec_conv));
 }
 
 FloatComplexRowVector
 octave_value::float_complex_row_vector_value (bool force_string_conv,
-    bool frc_vec_conv) const
+                                              bool frc_vec_conv) const
 {
   return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
-                                frc_vec_conv));
+                                                           frc_vec_conv));
 }
 
 Array<float>
@@ -2114,19 +2026,19 @@
   Array<float> retval = float_array_value (force_string_conv);
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "real vector"));
+                                           force_vector_conversion,
+                                           type_name (), "real vector"));
 }
 
 Array<FloatComplex>
 octave_value::float_complex_vector_value (bool force_string_conv,
-    bool force_vector_conversion) const
+                                          bool force_vector_conversion) const
 {
   Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
 
   return retval.reshape (make_vector_dims (retval.dims (),
-                         force_vector_conversion,
-                         type_name (), "complex vector"));
+                                           force_vector_conversion,
+                                           type_name (), "complex vector"));
 }
 
 // NAME can't always be "x ## FCN" because some of the original
@@ -2214,8 +2126,7 @@
 XVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value)
 XVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value)
 XVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value)
-XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value,
-                  float_complex_diag_matrix_value)
+XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value)
 
 XVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value)
 
@@ -2247,21 +2158,7 @@
 
 XVALUE_EXTRACTOR (octave::range<double>, xrange_value, range_value)
 
-// For now, disable all but ov_range<double>.
-
-#if 0
-
-XVALUE_EXTRACTOR (octave::range<float>, xfloat_range_value, float_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_int8>, xint8_range_value, int8_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_int16>, xint16_range_value, int16_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_int32>, xint32_range_value, int32_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_int64>, xint64_range_value, int64_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_uint8>, xuint8_range_value, uint8_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_uint16>, xuint16_range_value, uint16_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_uint32>, xuint32_range_value, uint32_range_value)
-XVALUE_EXTRACTOR (octave::range<octave_uint64>, xuint64_range_value, uint64_range_value)
-
-#endif
+// For now, enable only ov_range<double>.
 
 XVALUE_EXTRACTOR (octave_map, xmap_value, map_value)
 XVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value)
@@ -2273,16 +2170,13 @@
 XVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value)
 
 XVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value)
-XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value,
-                  float_complex_column_vector_value)
+XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value)
 
 XVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value)
-XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value,
-                  float_complex_row_vector_value)
+XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value)
 
 XVALUE_EXTRACTOR (Array<int>, xint_vector_value, int_vector_value)
-XVALUE_EXTRACTOR (Array<octave_idx_type>, xoctave_idx_type_vector_value,
-                  octave_idx_type_vector_value)
+XVALUE_EXTRACTOR (Array<octave_idx_type>, xoctave_idx_type_vector_value, octave_idx_type_vector_value)
 
 XVALUE_EXTRACTOR (Array<double>, xvector_value, vector_value)
 XVALUE_EXTRACTOR (Array<Complex>, xcomplex_vector_value, complex_vector_value)
@@ -2301,7 +2195,7 @@
 #undef XVALUE_EXTRACTOR
 
 octave_value
-octave_value::storable_value (void) const
+octave_value::storable_value () const
 {
   octave_value retval = *this;
   if (isnull ())
@@ -2317,19 +2211,19 @@
 }
 
 void
-octave_value::make_storable_value (void)
+octave_value::make_storable_value ()
 {
   if (isnull ())
     {
       octave_base_value *rc = m_rep->empty_clone ();
-      if (--m_rep->count == 0)
+      if (--m_rep->m_count == 0)
         delete m_rep;
       m_rep = rc;
     }
   else if (is_magic_int ())
     {
       octave_base_value *rc = new octave_scalar (m_rep->double_value ());
-      if (--m_rep->count == 0)
+      if (--m_rep->m_count == 0)
         delete m_rep;
       m_rep = rc;
     }
@@ -2340,7 +2234,7 @@
 }
 
 float_display_format
-octave_value::get_edit_display_format (void) const
+octave_value::get_edit_display_format () const
 {
   return m_rep->get_edit_display_format ();
 }
@@ -2357,7 +2251,7 @@
 octave_value::print_info (std::ostream& os, const std::string& prefix) const
 {
   os << prefix << "type_name: " << type_name () << "\n"
-     << prefix << "count:     " << get_count () << "\n"
+     << prefix << "m_count:     " << get_count () << "\n"
      << prefix << "m_rep info:  ";
 
   m_rep->print_info (os, prefix + ' ');
@@ -2520,7 +2414,7 @@
 
           if (! tmp)
             err_unary_op_conversion_failed
-            (octave_value::unary_op_as_string (op), type_name ());
+              (octave_value::unary_op_as_string (op), type_name ());
 
           octave_base_value *old_rep = m_rep;
           m_rep = tmp;
@@ -2533,14 +2427,14 @@
             {
               f (*m_rep);
 
-              if (old_rep && --old_rep->count == 0)
+              if (old_rep && --old_rep->m_count == 0)
                 delete old_rep;
             }
           else
             {
               if (old_rep)
                 {
-                  if (--m_rep->count == 0)
+                  if (--m_rep->m_count == 0)
                     delete m_rep;
 
                   m_rep = old_rep;
@@ -2559,7 +2453,7 @@
       octave::type_info::non_const_unary_op_fcn f = nullptr;
 
       // Only attempt to operate in-place if this variable is unshared.
-      if (m_rep->count == 1)
+      if (m_rep->m_count == 1)
         {
           octave::type_info& ti = octave::__get_type_info__ ();
 
@@ -2952,7 +2846,7 @@
 }
 
 OCTAVE_NORETURN static void
-err_cat_op_conv (void)
+err_cat_op_conv ()
 {
   error ("type conversion failed for concatenation operator");
 }
@@ -3657,21 +3551,7 @@
 
   ov_range<double>::register_type (ti);
 
-  // For now, disable all but ov_range<double>.
-
-#if 0
-
-  ov_range<float>::register_type (ti);
-  ov_range<octave_int8>::register_type (ti);
-  ov_range<octave_int16>::register_type (ti);
-  ov_range<octave_int32>::register_type (ti);
-  ov_range<octave_int64>::register_type (ti);
-  ov_range<octave_uint8>::register_type (ti);
-  ov_range<octave_uint16>::register_type (ti);
-  ov_range<octave_uint32>::register_type (ti);
-  ov_range<octave_uint64>::register_type (ti);
-
-#endif
+  // For now, enable only ov_range<double>.
 
   octave_bool::register_type (ti);
   octave_bool_matrix::register_type (ti);
@@ -3720,6 +3600,7 @@
   octave_lazy_index::register_type (ti);
   octave_oncleanup::register_type (ti);
   octave_java::register_type (ti);
+  octave_trivial_range::register_type (ti);
 }
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -3748,8 +3629,7 @@
                    std::string& type_string,
                    std::list<octave_value_list>& idx)
 {
-  const octave_map m =
-    arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name);
+  const octave_map m = arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name);
 
   if (m.nfields () != 2 || ! m.contains ("type") || ! m.contains ("subs"))
     error ("%s: second argument must be a structure with fields 'type' and 'subs'",
--- a/libinterp/octave-value/ov.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ov.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,6 @@
 #include <memory>
 #include <map>
 
-#include "Range.h"
 #include "data-conv.h"
 #include "idx-vector.h"
 #include "mach-info.h"
@@ -49,6 +48,8 @@
 
 class stack_frame;
 class type_info;
+class vm;
+class bytecode_fcn_stack_frame;
 
 OCTAVE_END_NAMESPACE(octave)
 
@@ -61,6 +62,7 @@
 class octave_user_function;
 class octave_fcn_handle;
 class octave_value_list;
+class octave_fcn_cache;
 
 #include "mxtypes.h"
 
@@ -167,10 +169,10 @@
 
   enum magic_colon { magic_colon_t };
 
-  octave_value (void)
+  octave_value ()
     : m_rep (nil_rep ())
   {
-    m_rep->count++;
+    m_rep->m_count++;
   }
 
   OCTINTERP_API octave_value (short int i);
@@ -288,71 +290,10 @@
   OCTINTERP_API octave_value (const Array<std::string>& cellstr);
   OCTINTERP_API octave_value (const octave::idx_vector& idx, bool lazy = true);
 
-private:
-
-  // Remove when public constructors that use this function are removed.
-  static OCTINTERP_API octave_base_value *
-  make_range_rep_deprecated (double base, double inc, double limit);
-
-  // Remove when public constructors that use this function are removed.
-  static OCTINTERP_API octave_base_value *
-  make_range_rep_deprecated (const Range& r, bool force_range);
-
-public:
-
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'octave_value (range<double>&)' instead")
-  octave_value (double base, double limit, double inc)
-    : m_rep (make_range_rep_deprecated (base, inc, limit))
-  {
-    maybe_mutate ();
-  }
-
-  OCTAVE_DEPRECATED (7, "use 'octave_value (range<double>&)' instead")
-  octave_value (const Range& r, bool force_range = false)
-    : m_rep (make_range_rep_deprecated (r, force_range))
-  {
-    maybe_mutate ();
-  }
-#endif
-
   OCTINTERP_API octave_value (const octave::range<double>& r,
                               bool force_range = false);
 
-  // For now, disable all but range<double>.
-
-#if 0
-
-  OCTINTERP_API octave_value (const octave::range<float>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_int8>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_int16>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_int32>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_int64>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_uint8>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_uint16>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_uint32>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<octave_uint64>& r,
-                              bool force_range = false);
-
-  OCTINTERP_API octave_value (const octave::range<char>& r, char type,
-                              bool force_range = false);
-#endif
+  // For now, enable only range<double>.
 
   OCTINTERP_API octave_value (const octave_map& m);
   OCTINTERP_API octave_value (const octave_scalar_map& m);
@@ -368,14 +309,19 @@
 
   OCTINTERP_API octave_value (octave_value::magic_colon);
 
-  OCTINTERP_API octave_value (octave_base_value *new_rep, bool borrow = false);
+  octave_value (octave_base_value *new_rep, bool borrow = false)
+    : m_rep (new_rep)
+  {
+    if (borrow)
+      m_rep->m_count++;
+  }
 
   // Copy constructor.
 
   octave_value (const octave_value& a)
     : m_rep (a.m_rep)
   {
-    m_rep->count++;
+    m_rep->m_count++;
   }
 
   octave_value (octave_value&& a)
@@ -386,30 +332,30 @@
 
   // This should only be called for derived types.
 
-  OCTINTERP_API octave_base_value * clone (void) const;
+  OCTINTERP_API octave_base_value * clone () const;
 
-  octave_base_value * empty_clone (void) const
+  octave_base_value * empty_clone () const
   { return m_rep->empty_clone (); }
 
   // Delete the representation of this constant if the count drops to zero.
 
-  ~octave_value (void)
+  ~octave_value ()
   {
     // Because we define a move constructor and a move assignment
     // operator, rep may be a nullptr here.  We should only need to
     // protect the move assignment operator in a similar way.
 
-    if (m_rep && --m_rep->count == 0 && m_rep != nil_rep ())
+    if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())
       delete m_rep;
   }
 
-  void make_unique (void)
+  void make_unique ()
   {
-    if (m_rep->count > 1)
+    if (m_rep->m_count > 1)
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
           delete m_rep;
 
         m_rep = r;
@@ -421,11 +367,11 @@
   // know a certain copy, typically within a cell array, to be obsolete.
   void make_unique (int obsolete_copies)
   {
-    if (m_rep->count > obsolete_copies + 1)
+    if (m_rep->m_count > obsolete_copies + 1)
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
           delete m_rep;
 
         m_rep = r;
@@ -444,11 +390,11 @@
   {
     if (m_rep != a.m_rep)
       {
-        if (--m_rep->count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
           delete m_rep;
 
         m_rep = a.m_rep;
-        m_rep->count++;
+        m_rep->m_count++;
       }
 
     return *this;
@@ -462,7 +408,7 @@
 
     if (this != &a)
       {
-        if (m_rep && --m_rep->count == 0 && m_rep != nil_rep ())
+        if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -472,43 +418,48 @@
     return *this;
   }
 
-  octave_idx_type get_count (void) const { return m_rep->count; }
+  octave_idx_type get_count () const { return m_rep->m_count; }
 
-  octave_base_value::type_conv_info numeric_conversion_function (void) const
+  octave_base_value::type_conv_info numeric_conversion_function () const
   { return m_rep->numeric_conversion_function (); }
 
-  octave_base_value::type_conv_info numeric_demotion_function (void) const
+  octave_base_value::type_conv_info numeric_demotion_function () const
   { return m_rep->numeric_demotion_function (); }
 
-  OCTINTERP_API void maybe_mutate (void);
+  OCTINTERP_API void maybe_mutate ();
 
-  octave_value squeeze (void) const
+  octave_value squeeze () const
   { return m_rep->squeeze (); }
 
   // The result of full().
-  octave_value full_value (void) const
+  octave_value full_value () const
   { return m_rep->full_value (); }
 
   // Type conversions.
 
-  octave_value as_double (void) const { return m_rep->as_double (); }
-  octave_value as_single (void) const { return m_rep->as_single (); }
+  // Returns a copy of a scalar (double), or makes a scalar
+  // for other types.
+  octave_value as_double_or_copy (void) const
+  { return m_rep->as_double_or_copy (); }
+
+  octave_value as_double () const { return m_rep->as_double (); }
+  octave_value as_single () const { return m_rep->as_single (); }
 
-  octave_value as_int8 (void) const { return m_rep->as_int8 (); }
-  octave_value as_int16 (void) const { return m_rep->as_int16 (); }
-  octave_value as_int32 (void) const { return m_rep->as_int32 (); }
-  octave_value as_int64 (void) const { return m_rep->as_int64 (); }
+  octave_value as_int8 () const { return m_rep->as_int8 (); }
+  octave_value as_int16 () const { return m_rep->as_int16 (); }
+  octave_value as_int32 () const { return m_rep->as_int32 (); }
+  octave_value as_int64 () const { return m_rep->as_int64 (); }
 
-  octave_value as_uint8 (void) const { return m_rep->as_uint8 (); }
-  octave_value as_uint16 (void) const { return m_rep->as_uint16 (); }
-  octave_value as_uint32 (void) const { return m_rep->as_uint32 (); }
-  octave_value as_uint64 (void) const { return m_rep->as_uint64 (); }
+  octave_value as_uint8 () const { return m_rep->as_uint8 (); }
+  octave_value as_uint16 () const { return m_rep->as_uint16 (); }
+  octave_value as_uint32 () const { return m_rep->as_uint32 (); }
+  octave_value as_uint64 () const { return m_rep->as_uint64 (); }
 
-  octave_base_value * try_narrowing_conversion (void)
+  octave_base_value * try_narrowing_conversion ()
   { return m_rep->try_narrowing_conversion (); }
 
   // Close to dims (), but can be overloaded for classes.
-  Matrix size (void)
+  Matrix size ()
   { return m_rep->size (); }
 
   // FIXME: should this function be deprecated and removed?  It supports
@@ -535,6 +486,9 @@
   subsref (const std::string& type, const std::list<octave_value_list>& idx,
            int nargout);
 
+  octave_value_list
+  simple_subsref (char type, octave_value_list& idx, int nargout);
+
   OCTINTERP_API octave_value
   next_subsref (const std::string& type,
                 const std::list<octave_value_list>& idx, std::size_t skip = 1);
@@ -552,19 +506,20 @@
     return m_rep->do_index_op (idx, resize_ok);
   }
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'octave_value::index_op' instead")
-  octave_value do_index_op (const octave_value_list& idx,
-                            bool resize_ok = false)
-  {
-    return index_op (idx, resize_ok);
-  }
-#endif
+  OCTINTERP_API octave_idx_type
+  end_index (octave_idx_type index_position,
+             octave_idx_type num_indices) const;
 
   OCTINTERP_API octave_value
   subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
             const octave_value& rhs);
 
+  octave_value
+  simple_subsasgn (char type, octave_value_list& idx, const octave_value& rhs)
+  {
+    return m_rep->simple_subsasgn (type, idx, rhs);
+  }
+
   OCTINTERP_API octave_value
   undef_subsasgn (const std::string& type,
                   const std::list<octave_value_list>& idx,
@@ -583,35 +538,35 @@
 
   // Size.
 
-  dim_vector dims (void) const { return m_rep->dims (); }
+  dim_vector dims () const { return m_rep->dims (); }
 
-  OCTINTERP_API std::string get_dims_str (void) const;
+  OCTINTERP_API std::string get_dims_str () const;
 
-  octave_idx_type rows (void) const { return m_rep->rows (); }
+  octave_idx_type rows () const { return m_rep->rows (); }
 
-  octave_idx_type columns (void) const { return m_rep->columns (); }
+  octave_idx_type columns () const { return m_rep->columns (); }
 
-  OCTINTERP_API octave_idx_type length (void) const;
+  OCTINTERP_API octave_idx_type length () const;
 
-  int ndims (void) const { return m_rep->ndims (); }
+  int ndims () const { return m_rep->ndims (); }
 
-  bool all_zero_dims (void) const { return dims ().all_zero (); }
+  bool all_zero_dims () const { return dims ().all_zero (); }
 
   // Are the dimensions of this constant zero by zero?
-  bool is_zero_by_zero (void) const
+  bool is_zero_by_zero () const
   { return (ndims () == 2 && rows () == 0 && columns () == 0); }
 
-  octave_idx_type numel (void) const
+  octave_idx_type numel () const
   { return m_rep->numel (); }
 
-  std::size_t byte_size (void) const
+  std::size_t byte_size () const
   { return m_rep->byte_size (); }
 
-  octave_idx_type nnz (void) const { return m_rep->nnz (); }
+  octave_idx_type nnz () const { return m_rep->nnz (); }
 
-  octave_idx_type nzmax (void) const { return m_rep->nzmax (); }
+  octave_idx_type nzmax () const { return m_rep->nzmax (); }
 
-  octave_idx_type nfields (void) const { return m_rep->nfields (); }
+  octave_idx_type nfields () const { return m_rep->nfields (); }
 
   octave_value reshape (const dim_vector& dv) const
   { return m_rep->reshape (dv); }
@@ -625,7 +580,7 @@
   octave_value resize (const dim_vector& dv, bool fill = false) const
   { return m_rep->resize (dv, fill);}
 
-  MatrixType matrix_type (void) const
+  MatrixType matrix_type () const
   { return m_rep->matrix_type (); }
 
   MatrixType matrix_type (const MatrixType& typ) const
@@ -634,94 +589,94 @@
   // Does this constant have a type?  Both of these are provided since it is
   // sometimes more natural to write is_undefined() instead of ! is_defined().
 
-  bool is_defined (void) const
+  bool is_defined () const
   { return m_rep->is_defined (); }
 
-  bool is_undefined (void) const
+  bool is_undefined () const
   { return ! is_defined (); }
 
-  bool is_legacy_object (void) const
+  bool is_legacy_object () const
   { return m_rep->is_legacy_object (); }
 
-  bool isempty (void) const
+  bool isempty () const
   { return m_rep->isempty (); }
 
-  bool iscell (void) const
+  bool iscell () const
   { return m_rep->iscell (); }
 
-  bool iscellstr (void) const
+  bool iscellstr () const
   { return m_rep->iscellstr (); }
 
-  bool is_real_scalar (void) const
+  bool is_real_scalar () const
   { return m_rep->is_real_scalar (); }
 
-  bool is_real_matrix (void) const
+  bool is_real_matrix () const
   { return m_rep->is_real_matrix (); }
 
-  bool is_complex_scalar (void) const
+  bool is_complex_scalar () const
   { return m_rep->is_complex_scalar (); }
 
-  bool is_complex_matrix (void) const
+  bool is_complex_matrix () const
   { return m_rep->is_complex_matrix (); }
 
-  bool is_bool_scalar (void) const
+  bool is_bool_scalar () const
   { return m_rep->is_bool_scalar (); }
 
-  bool is_bool_matrix (void) const
+  bool is_bool_matrix () const
   { return m_rep->is_bool_matrix (); }
 
-  bool is_char_matrix (void) const
+  bool is_char_matrix () const
   { return m_rep->is_char_matrix (); }
 
-  bool is_diag_matrix (void) const
+  bool is_diag_matrix () const
   { return m_rep->is_diag_matrix (); }
 
-  bool is_perm_matrix (void) const
+  bool is_perm_matrix () const
   { return m_rep->is_perm_matrix (); }
 
-  bool is_string (void) const
+  bool is_string () const
   { return m_rep->is_string (); }
 
-  bool is_sq_string (void) const
+  bool is_sq_string () const
   { return m_rep->is_sq_string (); }
 
-  bool is_dq_string (void) const
+  bool is_dq_string () const
   { return m_rep->is_string () && ! m_rep->is_sq_string (); }
 
-  bool is_range (void) const
+  bool is_range () const
   { return m_rep->is_range (); }
 
-  bool isstruct (void) const
+  bool isstruct () const
   { return m_rep->isstruct (); }
 
-  bool is_classdef_meta (void) const
+  bool is_classdef_meta () const
   { return m_rep->is_classdef_meta (); }
 
-  bool is_classdef_object (void) const
+  bool is_classdef_object () const
   { return m_rep->is_classdef_object (); }
 
-  bool is_classdef_superclass_ref (void) const
+  bool is_classdef_superclass_ref () const
   { return m_rep->is_classdef_superclass_ref (); }
 
-  bool is_package (void) const
+  bool is_package () const
   { return m_rep->is_package (); }
 
-  bool isobject (void) const
+  bool isobject () const
   { return m_rep->isobject (); }
 
-  bool isjava (void) const
+  bool isjava () const
   { return m_rep->isjava (); }
 
-  bool is_cs_list (void) const
+  bool is_cs_list () const
   { return m_rep->is_cs_list (); }
 
-  bool is_magic_colon (void) const
+  bool is_magic_colon () const
   { return m_rep->is_magic_colon (); }
 
-  bool is_magic_int (void) const
+  bool is_magic_int () const
   { return m_rep->is_magic_int (); }
 
-  bool isnull (void) const
+  bool isnull () const
   { return m_rep->isnull (); }
 
   // Are any or all of the elements in this constant nonzero?
@@ -732,119 +687,119 @@
   octave_value any (int dim = 0) const
   { return m_rep->any (dim); }
 
-  builtin_type_t builtin_type (void) const
+  builtin_type_t builtin_type () const
   { return m_rep->builtin_type (); }
 
   // Floating point types.
 
-  bool is_double_type (void) const
+  bool is_double_type () const
   { return m_rep->is_double_type (); }
 
-  bool is_single_type (void) const
+  bool is_single_type () const
   { return m_rep->is_single_type (); }
 
-  bool isfloat (void) const
+  bool isfloat () const
   { return m_rep->isfloat (); }
 
   // Integer types.
 
-  bool is_int8_type (void) const
+  bool is_int8_type () const
   { return m_rep->is_int8_type (); }
 
-  bool is_int16_type (void) const
+  bool is_int16_type () const
   { return m_rep->is_int16_type (); }
 
-  bool is_int32_type (void) const
+  bool is_int32_type () const
   { return m_rep->is_int32_type (); }
 
-  bool is_int64_type (void) const
+  bool is_int64_type () const
   { return m_rep->is_int64_type (); }
 
-  bool is_uint8_type (void) const
+  bool is_uint8_type () const
   { return m_rep->is_uint8_type (); }
 
-  bool is_uint16_type (void) const
+  bool is_uint16_type () const
   { return m_rep->is_uint16_type (); }
 
-  bool is_uint32_type (void) const
+  bool is_uint32_type () const
   { return m_rep->is_uint32_type (); }
 
-  bool is_uint64_type (void) const
+  bool is_uint64_type () const
   { return m_rep->is_uint64_type (); }
 
-  bool isinteger (void) const
+  bool isinteger () const
   { return m_rep->isinteger (); }
 
   // Other type stuff.
 
-  bool islogical (void) const
+  bool islogical () const
   { return m_rep->islogical (); }
 
-  bool isreal (void) const
+  bool isreal () const
   { return m_rep->isreal (); }
 
-  bool iscomplex (void) const
+  bool iscomplex () const
   { return m_rep->iscomplex (); }
 
-  bool is_scalar_type (void) const
+  bool is_scalar_type () const
   { return m_rep->is_scalar_type (); }
 
-  bool is_matrix_type (void) const
+  bool is_matrix_type () const
   { return m_rep->is_matrix_type (); }
 
-  bool isnumeric (void) const
+  bool isnumeric () const
   { return m_rep->isnumeric (); }
 
-  bool issparse (void) const
+  bool issparse () const
   { return m_rep->issparse (); }
 
   // Does this constant correspond to a truth value?
 
-  bool is_true (void) const
+  bool is_true () const
   { return m_rep->is_true (); }
 
   // Do two constants match (in a switch statement)?
 
   bool is_equal (const octave_value&) const;
 
-  bool is_constant (void) const
+  bool is_constant () const
   { return m_rep->is_constant (); }
 
-  bool is_function_handle (void) const
+  bool is_function_handle () const
   { return m_rep->is_function_handle (); }
 
-  bool is_anonymous_function (void) const
+  bool is_anonymous_function () const
   { return m_rep->is_anonymous_function (); }
 
-  bool is_inline_function (void) const
+  bool is_inline_function () const
   { return m_rep->is_inline_function (); }
 
-  bool is_function (void) const
+  bool is_function () const
   { return m_rep->is_function (); }
 
-  bool is_user_script (void) const
+  bool is_user_script () const
   { return m_rep->is_user_script (); }
 
-  bool is_user_function (void) const
+  bool is_user_function () const
   { return m_rep->is_user_function (); }
 
-  bool is_user_code (void) const
+  bool is_user_code () const
   { return m_rep->is_user_code (); }
 
-  bool is_builtin_function (void) const
+  bool is_builtin_function () const
   { return m_rep->is_builtin_function (); }
 
-  bool is_dld_function (void) const
+  bool is_dld_function () const
   { return m_rep->is_dld_function (); }
 
-  bool is_mex_function (void) const
+  bool is_mex_function () const
   { return m_rep->is_mex_function (); }
 
-  void erase_subfunctions (void) { m_rep->erase_subfunctions (); }
+  void erase_subfunctions () { m_rep->erase_subfunctions (); }
 
   // Values.
 
-  octave_value eval (void) { return *this; }
+  octave_value eval () { return *this; }
 
   short int
   short_value (bool req_int = false, bool frc_str_conv = false) const
@@ -965,55 +920,55 @@
   float_complex_diag_matrix_value (bool force = false) const
   { return m_rep->float_complex_diag_matrix_value (force); }
 
-  PermMatrix perm_matrix_value (void) const
+  PermMatrix perm_matrix_value () const
   { return m_rep->perm_matrix_value (); }
 
-  octave_int8 int8_scalar_value (void) const
+  octave_int8 int8_scalar_value () const
   { return m_rep->int8_scalar_value (); }
 
-  octave_int16 int16_scalar_value (void) const
+  octave_int16 int16_scalar_value () const
   { return m_rep->int16_scalar_value (); }
 
-  octave_int32 int32_scalar_value (void) const
+  octave_int32 int32_scalar_value () const
   { return m_rep->int32_scalar_value (); }
 
-  octave_int64 int64_scalar_value (void) const
+  octave_int64 int64_scalar_value () const
   { return m_rep->int64_scalar_value (); }
 
-  octave_uint8 uint8_scalar_value (void) const
+  octave_uint8 uint8_scalar_value () const
   { return m_rep->uint8_scalar_value (); }
 
-  octave_uint16 uint16_scalar_value (void) const
+  octave_uint16 uint16_scalar_value () const
   { return m_rep->uint16_scalar_value (); }
 
-  octave_uint32 uint32_scalar_value (void) const
+  octave_uint32 uint32_scalar_value () const
   { return m_rep->uint32_scalar_value (); }
 
-  octave_uint64 uint64_scalar_value (void) const
+  octave_uint64 uint64_scalar_value () const
   { return m_rep->uint64_scalar_value (); }
 
-  int8NDArray int8_array_value (void) const
+  int8NDArray int8_array_value () const
   { return m_rep->int8_array_value (); }
 
-  int16NDArray int16_array_value (void) const
+  int16NDArray int16_array_value () const
   { return m_rep->int16_array_value (); }
 
-  int32NDArray int32_array_value (void) const
+  int32NDArray int32_array_value () const
   { return m_rep->int32_array_value (); }
 
-  int64NDArray int64_array_value (void) const
+  int64NDArray int64_array_value () const
   { return m_rep->int64_array_value (); }
 
-  uint8NDArray uint8_array_value (void) const
+  uint8NDArray uint8_array_value () const
   { return m_rep->uint8_array_value (); }
 
-  uint16NDArray uint16_array_value (void) const
+  uint16NDArray uint16_array_value () const
   { return m_rep->uint16_array_value (); }
 
-  uint32NDArray uint32_array_value (void) const
+  uint32NDArray uint32_array_value () const
   { return m_rep->uint32_array_value (); }
 
-  uint64NDArray uint64_array_value (void) const
+  uint64NDArray uint64_array_value () const
   { return m_rep->uint64_array_value (); }
 
   std::string string_value (bool force = false) const
@@ -1022,64 +977,33 @@
   string_vector string_vector_value (bool pad = false) const
   { return m_rep->string_vector_value (pad); }
 
-  Cell cell_value (void) const;
+  Cell cell_value () const;
 
-  Array<std::string> cellstr_value (void) const
+  Array<std::string> cellstr_value () const
   { return m_rep->cellstr_value (); }
 
-  octave::range<double> range_value (void) const
+  octave::range<double> range_value () const
   { return m_rep->range_value (); }
 
-  // For now, disable all but range<double>.
-
-#if 0
-
-  octave::range<float> float_range_value (void) const
-  { return m_rep->float_range_value (); }
+  // For now, enable only range<double>.
 
-  octave::range<octave_int8> int8_range_value (void) const
-  { return m_rep->int8_range_value (); }
-
-  octave::range<octave_int16> int16_range_value (void) const
-  { return m_rep->int16_range_value (); }
-
-  octave::range<octave_int32> int32_range_value (void) const
-  { return m_rep->int32_range_value (); }
-
-  octave::range<octave_int64> int64_range_value (void) const
-  { return m_rep->int64_range_value (); }
+  OCTINTERP_API octave_map map_value () const;
 
-  octave::range<octave_uint8> uint8_range_value (void) const
-  { return m_rep->uint8_range_value (); }
-
-  octave::range<octave_uint16> uint16_range_value (void) const
-  { return m_rep->uint16_range_value (); }
-
-  octave::range<octave_uint32> uint32_range_value (void) const
-  { return m_rep->uint32_range_value (); }
+  OCTINTERP_API octave_scalar_map scalar_map_value () const;
 
-  octave::range<octave_uint64> uint64_range_value (void) const
-  { return m_rep->uint64_range_value (); }
-
-#endif
-
-  OCTINTERP_API octave_map map_value (void) const;
-
-  OCTINTERP_API octave_scalar_map scalar_map_value (void) const;
-
-  string_vector map_keys (void) const
+  string_vector map_keys () const
   { return m_rep->map_keys (); }
 
   bool isfield (const std::string& field_name) const
   { return m_rep->isfield (field_name); }
 
-  std::size_t nparents (void) const
+  std::size_t nparents () const
   { return m_rep->nparents (); }
 
-  std::list<std::string> parent_class_name_list (void) const
+  std::list<std::string> parent_class_name_list () const
   { return m_rep->parent_class_name_list (); }
 
-  string_vector parent_class_names (void) const
+  string_vector parent_class_names () const
   { return m_rep->parent_class_names (); }
 
   octave_base_value *
@@ -1106,7 +1030,7 @@
   OCTINTERP_API octave_fcn_handle *
   fcn_handle_value (bool silent = false) const;
 
-  OCTINTERP_API octave_value_list list_value (void) const;
+  OCTINTERP_API octave_value_list list_value () const;
 
   OCTINTERP_API ColumnVector
   column_vector_value (bool frc_str_conv = false,
@@ -1300,38 +1224,7 @@
   OCTINTERP_API octave::range<double>
   xrange_value (const char *fmt, ...) const;
 
-  // For now, disable all but range<double>.
-
-#if 0
-
-  OCTINTERP_API octave::range<float>
-  xfloat_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_int8>
-  xint8_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_int16>
-  xint16_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_int32>
-  xint32_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_int64>
-  xint64_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_uint8>
-  xuint8_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_uint16>
-  xuint16_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_uint32>
-  xuint32_range_value (const char *fmt, ...) const;
-
-  OCTINTERP_API octave::range<octave_uint64>
-  xuint64_range_value (const char *fmt, ...) const;
-
-#endif
+  // For now, enable only range<double>.
 
   OCTINTERP_API octave_map xmap_value (const char *fmt, ...) const;
 
@@ -1393,19 +1286,19 @@
 
   // Possibly economize a lazy-indexed value.
 
-  void maybe_economize (void)
+  void maybe_economize ()
   { m_rep->maybe_economize (); }
 
   // The following two hook conversions are called on any octave_value prior to
   // storing it to a "permanent" location, like a named variable, a cell or a
   // struct component, or a return value of a function.
 
-  OCTINTERP_API octave_value storable_value (void) const;
+  OCTINTERP_API octave_value storable_value () const;
 
   // Ditto, but in place, i.e., equivalent to *this = this->storable_value (),
   // but possibly more efficient.
 
-  OCTINTERP_API void make_storable_value (void);
+  OCTINTERP_API void make_storable_value ();
 
   // FIXME: These should probably be private.
   // Conversions.  If a user of this class wants a certain kind of constant,
@@ -1419,10 +1312,10 @@
   convert_to_str_internal (bool pad, bool force, char type) const
   { return m_rep->convert_to_str_internal (pad, force, type); }
 
-  void convert_to_row_or_column_vector (void)
+  void convert_to_row_or_column_vector ()
   { m_rep->convert_to_row_or_column_vector (); }
 
-  bool print_as_scalar (void) const
+  bool print_as_scalar () const
   { return m_rep->print_as_scalar (); }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false)
@@ -1439,7 +1332,7 @@
 
   void short_disp (std::ostream& os) const { m_rep->short_disp (os); }
 
-  OCTINTERP_API float_display_format get_edit_display_format (void) const;
+  OCTINTERP_API float_display_format get_edit_display_format () const;
 
   std::string edit_display (const float_display_format& fmt,
                             octave_idx_type i, octave_idx_type j) const
@@ -1447,11 +1340,11 @@
     return m_rep->edit_display (fmt, i, j);
   }
 
-  int type_id (void) const { return m_rep->type_id (); }
+  int type_id () const { return m_rep->type_id (); }
 
-  std::string type_name (void) const { return m_rep->type_name (); }
+  std::string type_name () const { return m_rep->type_name (); }
 
-  std::string class_name (void) const { return m_rep->class_name (); }
+  std::string class_name () const { return m_rep->class_name (); }
 
   // Unary operations that are member functions.  There are also some
   // non-member functions for unary and binary operations declared
@@ -1459,28 +1352,11 @@
 
   OCTINTERP_API octave_value& non_const_unary_op (unary_op op);
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead")
-  octave_value& do_non_const_unary_op (unary_op op)
-  {
-    return non_const_unary_op (op);
-  }
-#endif
-
   OCTINTERP_API octave_value&
   non_const_unary_op (unary_op op, const std::string& type,
                       const std::list<octave_value_list>& idx);
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead")
-  octave_value& do_non_const_unary_op (unary_op op, const std::string& type,
-                                       const std::list<octave_value_list>& idx)
-  {
-    return non_const_unary_op (op, type, idx);
-  }
-#endif
-
-  const octave_base_value& get_rep (void) const { return *m_rep; }
+  const octave_base_value& get_rep () const { return *m_rep; }
 
   bool is_copy_of (const octave_value& val) const { return m_rep == val.m_rep; }
 
@@ -1508,7 +1384,7 @@
          oct_data_conv::data_type output_type, int skip,
          octave::mach_info::float_format flt_fmt) const;
 
-  octave_base_value * internal_rep (void) const { return m_rep; }
+  octave_base_value * internal_rep () const { return m_rep; }
 
   // These functions exist to support the MEX interface.
   // You should not use them anywhere else.
@@ -1517,13 +1393,13 @@
   mex_get_data (mxClassID class_id = mxUNKNOWN_CLASS,
                 mxComplexity complexity = mxREAL) const;
 
-  const octave_idx_type * mex_get_ir (void) const
+  const octave_idx_type * mex_get_ir () const
   {
     return m_rep->mex_get_ir ();
   }
 
   const octave_idx_type *
-  mex_get_jc (void) const
+  mex_get_jc () const
   {
     return m_rep->mex_get_jc ();
   }
@@ -1552,18 +1428,18 @@
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const
   { return m_rep->is_sorted_rows (mode); }
 
-  void lock (void) { m_rep->lock (); }
+  void lock () { m_rep->lock (); }
 
-  void unlock (void) { m_rep->unlock (); }
+  void unlock () { m_rep->unlock (); }
 
-  bool islocked (void) const { return m_rep->islocked (); }
+  bool islocked () const { return m_rep->islocked (); }
 
-  void call_object_destructor (void) { return m_rep->call_object_destructor (); }
+  void call_object_destructor () { return m_rep->call_object_destructor (); }
 
-  octave_value dump (void) const { return m_rep->dump (); }
+  octave_value dump () const { return m_rep->dump (); }
 
 #define MAPPER_FORWARD(F) \
-  octave_value F (void) const                           \
+  octave_value F () const                           \
   {                                                     \
     return m_rep->map (octave_base_value::umap_ ## F);    \
   }
@@ -1665,12 +1541,105 @@
 
 protected:
 
-  //! The real representation.
+  // Functions for use by the VM.
+  friend class octave_value_ref;
+  friend class octave_value_vm;
+  friend class octave::vm;
+  friend class octave::bytecode_fcn_stack_frame;
+
+  bool is_ref () const { return m_rep->is_ref (); }
+
+  octave_value_ref * ref_rep () { return m_rep->ref_rep (); }
+
+  bool is_nil (void) const { return m_rep == nil_rep (); }
+
+  // True for the types based on ov-base-mat
+  bool is_full_num_matrix () const
+  { return m_rep->is_full_num_matrix (); }
+
+  bool is_function_cache (void) const
+  { return m_rep->is_function_cache (); }
+
+  // function handles might have a function cache embedded
+  bool has_function_cache (void) const
+  { return m_rep->has_function_cache (); }
+
+  octave_function * get_cached_fcn (const octave_value_list& args)
+  { return m_rep->get_cached_fcn (args); }
+
+  // Returns true if the octave_value is either undefined or
+  // or a function.
+  bool is_maybe_function (void) const
+  { return m_rep->is_maybe_function (); }
+
+  octave_fcn_cache *
+  fcn_cache_value () const
+  {
+    return m_rep->fcn_cache_value ();
+  }
+
+  bool vm_need_storable_call () const
+  {
+    return m_rep->vm_need_storable_call ();
+  };
+
+  bool vm_need_dispatch_assign_rhs ()
+  {
+    return m_rep->vm_need_dispatch_assign_rhs ();
+  }
+
+  bool vm_need_dispatch_assign_lhs ()
+  {
+    return m_rep->vm_need_dispatch_assign_lhs ();
+  }
+
+  bool vm_need_dispatch_push ()
+  {
+    return m_rep->vm_need_dispatch_push ();
+  }
+
+  bool same_rep (octave_value &ov) const { return m_rep == ov.m_rep; }
+
+  void maybe_call_dtor () { m_rep->maybe_call_dtor (); }
+
+  octave_value
+  checked_full_matrix_elem (octave_idx_type n) const
+  { return m_rep->checked_full_matrix_elem (n); }
+
+  octave_value
+  checked_full_matrix_elem (octave_idx_type i, octave_idx_type j) const
+  { return m_rep->checked_full_matrix_elem (i, j); }
+
+  octave_value
+  vm_extract_forloop_value (octave_idx_type idx)
+  {
+    return m_rep->vm_extract_forloop_value (idx);
+  }
+
+  double
+  vm_extract_forloop_double (octave_idx_type idx)
+  {
+    return m_rep->vm_extract_forloop_double (idx);
+  }
+
+  bool
+  maybe_update_double (double d)
+  {
+    return m_rep->maybe_update_double (d);
+  }
+
+  octave_value
+  maybe_as_trivial_range ();
+
+  bool
+  is_trivial_range () { return m_rep->is_trivial_range (); }
+
+//! The real representation.
   octave_base_value *m_rep;
 
-private:
+  static OCTINTERP_API octave_base_value * nil_rep ();
 
-  static OCTINTERP_API octave_base_value * nil_rep (void);
+private:
 
   OCTINTERP_API assign_op unary_op_to_assign_op (unary_op op);
 
@@ -1736,87 +1705,6 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead")
-inline octave_value
-do_unary_op (octave::type_info& ti, octave_value::unary_op op,
-             const octave_value& a)
-{
-  return octave::unary_op (ti, op, a);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead")
-inline octave_value
-do_unary_op (octave_value::unary_op op, const octave_value& a)
-{
-  return octave::unary_op (op, a);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead")
-inline octave_value
-do_binary_op (octave::type_info& ti, octave_value::binary_op op,
-              const octave_value& a, const octave_value& b)
-{
-  return octave::binary_op (ti, op, a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead")
-inline octave_value
-do_binary_op (octave::type_info& ti, octave_value::compound_binary_op op,
-              const octave_value& a, const octave_value& b)
-{
-  return octave::binary_op (ti, op, a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead")
-inline octave_value
-do_binary_op (octave_value::binary_op op, const octave_value& a,
-              const octave_value& b)
-{
-  return octave::binary_op (op, a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead")
-inline octave_value
-do_binary_op (octave_value::compound_binary_op op, const octave_value& a,
-              const octave_value& b)
-{
-  return octave::binary_op (op, a, b);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead")
-inline octave_value
-do_cat_op (octave::type_info& ti, const octave_value& a,
-           const octave_value& b, const Array<octave_idx_type>& ra_idx)
-{
-  return octave::cat_op (ti, a, b, ra_idx);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead")
-inline octave_value
-do_cat_op (const octave_value& a, const octave_value& b,
-           const Array<octave_idx_type>& ra_idx)
-{
-  return octave::cat_op (a, b, ra_idx);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead")
-inline octave_value
-do_colon_op (const octave_value& base, const octave_value& increment,
-             const octave_value& limit, bool is_for_cmd_expr = false)
-{
-  return octave::colon_op (base, increment, limit, is_for_cmd_expr);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead")
-inline octave_value
-do_colon_op (const octave_value& base, const octave_value& limit,
-             bool is_for_cmd_expr = false)
-{
-  return octave::colon_op (base, limit, is_for_cmd_expr);
-}
-#endif
-
 #define OV_UNOP_FN(name)                                \
   inline octave_value                                   \
   name (const octave_value& a)                          \
--- a/libinterp/octave-value/ovl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ovl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -121,7 +121,7 @@
 }
 
 octave_value_list&
-octave_value_list::reverse (void)
+octave_value_list::reverse ()
 {
   octave_idx_type n = length ();
 
@@ -173,7 +173,7 @@
 }
 
 bool
-octave_value_list::all_strings_p (void) const
+octave_value_list::all_strings_p () const
 {
   octave_idx_type n = length ();
 
@@ -185,7 +185,7 @@
 }
 
 bool
-octave_value_list::all_scalars (void) const
+octave_value_list::all_scalars () const
 {
   octave_idx_type n = length ();
 
@@ -200,7 +200,7 @@
 }
 
 bool
-octave_value_list::any_cell (void) const
+octave_value_list::any_cell () const
 {
   octave_idx_type n = length ();
 
@@ -212,7 +212,7 @@
 }
 
 bool
-octave_value_list::has_magic_colon (void) const
+octave_value_list::has_magic_colon () const
 {
   octave_idx_type n = length ();
 
@@ -274,7 +274,7 @@
 }
 
 void
-octave_value_list::make_storable_values (void)
+octave_value_list::make_storable_values ()
 {
   octave_idx_type len = length ();
   const std::vector<octave_value>& cdata = m_data;
--- a/libinterp/octave-value/ovl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave-value/ovl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 {
 public:
 
-  octave_value_list (void) = default;
+  octave_value_list () = default;
 
   explicit octave_value_list (octave_idx_type n)
     : m_data (n), m_names () { }
@@ -81,13 +81,13 @@
   octave_value_list (const std::list<octave_value>&);
   octave_value_list (const std::list<octave_value_list>&);
 
-  ~octave_value_list (void) = default;
+  ~octave_value_list () = default;
 
   octave_value_list& operator = (const octave_value_list& obj) = default;
 
   octave_value_list& operator = (octave_value_list&& obj) = default;
 
-  Array<octave_value> array_value (void) const
+  Array<octave_value> array_value () const
   {
     Array<octave_value> retval;
 
@@ -102,7 +102,7 @@
     return retval;
   }
 
-  Cell cell_value (void) const { return array_value (); }
+  Cell cell_value () const { return array_value (); }
 
   // Assignment will resize on range errors.
 
@@ -110,9 +110,9 @@
 
   const octave_value& operator () (octave_idx_type n) const { return elem (n); }
 
-  octave_idx_type length (void) const { return m_data.size (); }
+  octave_idx_type length () const { return m_data.size (); }
 
-  bool empty (void) const { return length () == 0; }
+  bool empty () const { return length () == 0; }
 
   void resize (octave_idx_type n, const octave_value& rfv = octave_value ())
   {
@@ -125,7 +125,7 @@
 
   octave_value_list& append (const octave_value_list& lst);
 
-  octave_value_list& reverse (void);
+  octave_value_list& reverse ();
 
   octave_value_list
   slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const
@@ -152,25 +152,33 @@
   splice (octave_idx_type offset, octave_idx_type len,
           const octave_value_list& lst = octave_value_list ()) const;
 
-  bool all_strings_p (void) const;
+  bool all_strings_p () const;
 
-  bool all_scalars (void) const;
+  bool all_scalars () const;
 
-  bool any_cell (void) const;
+  bool any_cell () const;
 
-  bool has_magic_colon (void) const;
+  bool has_magic_colon () const;
 
   string_vector make_argv (const std::string& = "") const;
 
   void stash_name_tags (const string_vector& nm) { m_names = nm; }
 
-  string_vector name_tags (void) const { return m_names; }
+  string_vector name_tags () const { return m_names; }
 
-  void make_storable_values (void);
+  void make_storable_values ();
 
   octave_value& xelem (octave_idx_type i) { return m_data[i]; }
 
-  void clear (void) { m_data.clear (); }
+  void clear () { m_data.clear (); }
+
+  octave_value first_or_nil_ov () const
+  {
+    if (length ())
+      return m_data.front ();
+
+    return octave_value ();
+  }
 
 private:
 
--- a/libinterp/octave.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -56,7 +56,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-cmdline_options::cmdline_options (void)
+cmdline_options::cmdline_options ()
 {
   m_all_args.resize (1);
   m_all_args[0] = "";
@@ -239,7 +239,7 @@
                                     argc-octave_optind_wrapper ());
 }
 
-octave_value cmdline_options::as_octave_value (void) const
+octave_value cmdline_options::as_octave_value () const
 {
   octave_scalar_map m;
 
@@ -295,7 +295,7 @@
 // an explicit definition of the destructor here is much simpler than
 // including the full declaration of interpreter in the
 // octave.h header file.
-application::~application (void) { }
+application::~application () { }
 
 void
 application::set_program_names (const std::string& pname)
@@ -324,25 +324,25 @@
     }
 }
 
-bool application::forced_interactive (void)
+bool application::forced_interactive ()
 {
   return s_instance ? s_instance->m_options.forced_interactive () : false;
 }
 
 // Provided for convenience.  Will be removed once we eliminate the
 // old terminal widget.
-bool application::experimental_terminal_widget (void) const
+bool application::experimental_terminal_widget () const
 {
   return (s_instance
           ? s_instance->m_options.experimental_terminal_widget () : false);
 }
 
-bool application::interpreter_initialized (void)
+bool application::interpreter_initialized ()
 {
   return m_interpreter ? m_interpreter->initialized () : false;
 }
 
-interpreter& application::create_interpreter (void)
+interpreter& application::create_interpreter ()
 {
   if (! m_interpreter)
     m_interpreter = std::unique_ptr<interpreter> (new interpreter (this));
@@ -350,23 +350,23 @@
   return *m_interpreter;
 }
 
-void application::initialize_interpreter (void)
+void application::initialize_interpreter ()
 {
   if (m_interpreter)
     m_interpreter->initialize ();
 }
 
-int application::execute_interpreter (void)
+int application::execute_interpreter ()
 {
   return m_interpreter ? m_interpreter->execute () : -1;
 }
 
-void application::delete_interpreter (void)
+void application::delete_interpreter ()
 {
   m_interpreter.reset ();
 }
 
-void application::init (void)
+void application::init ()
 {
   if (s_instance)
     throw std::runtime_error
@@ -420,7 +420,7 @@
   sysdep_init ();
 }
 
-int cli_application::execute (void)
+int cli_application::execute ()
 {
   interpreter& interp = create_interpreter ();
 
--- a/libinterp/octave.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/octave.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,49 +44,47 @@
 {
 public:
 
-  cmdline_options (void);
+  cmdline_options ();
 
   cmdline_options (int argc, char **argv);
 
-  cmdline_options (const cmdline_options&) = default;
-
-  cmdline_options& operator = (const cmdline_options&) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (cmdline_options)
 
-  int sys_argc (void) const { return m_all_args.numel (); }
-  char ** sys_argv (void) const { return m_all_args.c_str_vec (); }
+  int sys_argc () const { return m_all_args.numel (); }
+  char ** sys_argv () const { return m_all_args.c_str_vec (); }
 
-  bool echo_commands (void) const { return m_echo_commands; }
+  bool echo_commands () const { return m_echo_commands; }
 
-  bool experimental_terminal_widget (void) const
+  bool experimental_terminal_widget () const
   { return m_experimental_terminal_widget; }
-  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; }
-  bool inhibit_startup_message (void) const
+  bool forced_interactive () const { return m_forced_interactive; }
+  bool forced_line_editing () const { return m_forced_line_editing; }
+  bool gui () const { return m_gui; }
+  bool inhibit_startup_message () const
   { return m_inhibit_startup_message; }
-  bool line_editing (void) const { return m_line_editing; }
+  bool line_editing () const { return m_line_editing; }
 
-  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; }
-  bool read_init_files (void) const { return m_read_init_files; }
-  bool read_site_files (void) const { return m_read_site_files; }
-  bool server (void) const { return m_server; }
-  bool set_initial_path (void) const { return m_set_initial_path; }
-  bool traditional (void) const { return m_traditional; }
-  bool verbose_flag (void) const { return m_verbose_flag; }
-  std::string code_to_eval (void) const { return m_code_to_eval; }
-  std::list<std::string> command_line_path (void) const
+  bool no_window_system () const { return m_no_window_system; }
+  bool persist () const { return m_persist; }
+  bool read_history_file () const { return m_read_history_file; }
+  bool read_init_files () const { return m_read_init_files; }
+  bool read_site_files () const { return m_read_site_files; }
+  bool server () const { return m_server; }
+  bool set_initial_path () const { return m_set_initial_path; }
+  bool traditional () const { return m_traditional; }
+  bool verbose_flag () const { return m_verbose_flag; }
+  std::string code_to_eval () const { return m_code_to_eval; }
+  std::list<std::string> command_line_path () const
   { return m_command_line_path; }
-  std::string docstrings_file (void) const { return m_docstrings_file; }
-  std::string doc_cache_file (void) const { return m_doc_cache_file; }
-  std::string exec_path (void) const { return m_exec_path; }
-  std::string image_path (void) const { return m_image_path; }
-  std::string info_file (void) const { return m_info_file; }
-  std::string info_program (void) const { return m_info_program; }
-  std::string texi_macros_file (void) const {return m_texi_macros_file; }
-  string_vector all_args (void) const { return m_all_args; }
-  string_vector remaining_args (void) const { return m_remaining_args; }
+  std::string docstrings_file () const { return m_docstrings_file; }
+  std::string doc_cache_file () const { return m_doc_cache_file; }
+  std::string exec_path () const { return m_exec_path; }
+  std::string image_path () const { return m_image_path; }
+  std::string info_file () const { return m_info_file; }
+  std::string info_program () const { return m_info_program; }
+  std::string texi_macros_file () const {return m_texi_macros_file; }
+  string_vector all_args () const { return m_all_args; }
+  string_vector remaining_args () const { return m_remaining_args; }
 
   void echo_commands (bool arg) { m_echo_commands = arg; }
 
@@ -120,7 +118,7 @@
   void all_args (const string_vector& arg) { m_all_args = arg; }
   void remaining_args (const string_vector& arg) { m_remaining_args = arg; }
 
-  octave_value as_octave_value (void) const;
+  octave_value as_octave_value () const;
 
 private:
 
@@ -249,42 +247,38 @@
 
   application (int argc, char **argv);
 
-  // No copying, at least not yet...
-
-  application (const application&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (application)
 
-  application& operator = (const application&) = delete;
+  virtual ~application ();
 
-  virtual ~application (void);
-
-  int sys_argc (void) const { return m_options.sys_argc (); }
-  char ** sys_argv (void) const { return m_options.sys_argv (); }
+  int sys_argc () const { return m_options.sys_argc (); }
+  char ** sys_argv () const { return m_options.sys_argv (); }
 
   void set_program_names (const std::string& pname);
 
   void intern_argv (const string_vector& args);
 
-  cmdline_options options (void) const { return m_options; }
+  cmdline_options options () const { return m_options; }
 
-  bool have_eval_option_code (void) const { return m_have_eval_option_code; }
+  bool have_eval_option_code () const { return m_have_eval_option_code; }
 
-  bool have_script_file (void) const { return m_have_script_file; }
+  bool have_script_file () const { return m_have_script_file; }
 
-  bool is_octave_program (void) const { return m_is_octave_program; }
+  bool is_octave_program () const { return m_is_octave_program; }
 
-  bool interpreter_initialized (void);
+  bool interpreter_initialized ();
 
-  virtual interpreter& create_interpreter (void);
+  virtual interpreter& create_interpreter ();
 
-  virtual void initialize_interpreter (void);
+  virtual void initialize_interpreter ();
 
-  virtual int execute_interpreter (void);
+  virtual int execute_interpreter ();
 
-  virtual void delete_interpreter (void);
+  virtual void delete_interpreter ();
 
-  virtual int execute (void) = 0;
+  virtual int execute () = 0;
 
-  virtual bool gui_running (void) const { return false; }
+  virtual bool gui_running () const { return false; }
   virtual void gui_running (bool) { }
 
   void program_invocation_name (const std::string& nm)
@@ -296,40 +290,40 @@
 
   // Provided for convenience.  Will be removed once we eliminate the
   // old terminal widget.
-  bool experimental_terminal_widget (void) const;
+  bool experimental_terminal_widget () const;
 
-  static application * app (void) { return s_instance; }
+  static application * app () { return s_instance; }
 
-  static std::string program_invocation_name (void)
+  static std::string program_invocation_name ()
   {
     return s_instance ? s_instance->m_program_invocation_name : "";
   }
 
-  static std::string program_name (void)
+  static std::string program_name ()
   {
     return s_instance ? s_instance->m_program_name : "";
   }
 
-  static string_vector argv (void)
+  static string_vector argv ()
   {
     return s_instance ? s_instance->m_argv : string_vector ();
   }
 
-  static bool is_gui_running (void)
+  static bool is_gui_running ()
   {
     return s_instance ? s_instance->gui_running () : false;
   }
 
   // Convenience functions.
 
-  static bool forced_interactive (void);
+  static bool forced_interactive ();
 
 private:
 
   // The application instance;  There should be only one.
   static application *s_instance;
 
-  void init (void);
+  void init ();
 
 protected:
 
@@ -374,15 +368,11 @@
     : application (argc, argv)
   { }
 
-  // No copying, at least not yet...
-
-  cli_application (const cli_application&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (cli_application)
 
-  cli_application& operator = (const cli_application&) = delete;
+  ~cli_application () = default;
 
-  ~cli_application (void) = default;
-
-  int execute (void);
+  int execute ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/operators/op-b-b.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-b-b.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -65,14 +65,14 @@
 static octave_value
 oct_unop_uplus (const octave_base_value& a)
 {
-  const octave_bool& v = dynamic_cast<const octave_bool&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);
   return octave_value (v.double_value ());
 }
 
 static octave_value
 oct_unop_uminus (const octave_base_value& a)
 {
-  const octave_bool& v = dynamic_cast<const octave_bool&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);
   return octave_value (- v.double_value ());
 }
 
--- a/libinterp/operators/op-b-bm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-b-bm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -61,7 +61,7 @@
 
 DEFCONV (bool_matrix_conv, bool, bool_matrix)
 {
-  const octave_bool& v = dynamic_cast<const octave_bool&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);
 
   return new octave_bool_matrix (v.bool_matrix_value ());
 }
--- a/libinterp/operators/op-b-sbm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-b-sbm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,9 +51,8 @@
 
 DEFCATOP (b_sbm, bool, sparse_bool_matrix)
 {
-  const octave_bool& v1 = dynamic_cast<const octave_bool&> (a1);
-  const octave_sparse_bool_matrix& v2
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);
   SparseBoolMatrix tmp (1, 1, v1.bool_value ());
   return octave_value (tmp. concat (v2.sparse_bool_matrix_value (),
                                     ra_idx));
@@ -61,24 +60,23 @@
 
 DEFCATOP (b_sm, bool, sparse_matrix)
 {
-  const octave_bool& v1 = dynamic_cast<const octave_bool&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseMatrix tmp (1, 1, v1.scalar_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCATOP (s_sbm, scalar, sparse_bool_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_bool_matrix& v2
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);
   SparseMatrix tmp (1, 1, v1.scalar_value ());
   return octave_value(tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCONV (sparse_bool_matrix_conv, bool, sparse_bool_matrix)
 {
-  const octave_bool& v = dynamic_cast<const octave_bool&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v, a);
 
   return new octave_sparse_bool_matrix
          (SparseBoolMatrix (1, 1, v.bool_value ()));
--- a/libinterp/operators/op-bm-b.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-bm-b.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -74,7 +74,7 @@
                               const octave_value_list& idx,
                               const octave_base_value& a2)
 {
-  octave_bool_matrix& v1 = dynamic_cast<octave_bool_matrix&> (a1);
+  OCTAVE_CAST_BASE_VALUE (octave_bool_matrix&, v1, a1);
 
   // FIXME: perhaps add a warning for this conversion
   //        if the values are not all 0 or 1?
--- a/libinterp/operators/op-bm-bm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-bm-bm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -63,7 +63,7 @@
 
 DEFUNOP (transpose, bool_matrix)
 {
-  const octave_bool_matrix& v = dynamic_cast<const octave_bool_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -115,7 +115,7 @@
                               const octave_value_list& idx,
                               const octave_base_value& a2)
 {
-  octave_bool_matrix& v1 = dynamic_cast<octave_bool_matrix&> (a1);
+  OCTAVE_CAST_BASE_VALUE (octave_bool_matrix&, v1, a1);
 
   // FIXME: perhaps add a warning for this conversion
   //        if the values are not all 0 or 1?
--- a/libinterp/operators/op-bm-sbm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-bm-sbm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,9 +53,8 @@
 
 DEFCATOP (bm_sbm, bool_matrix, sparse_bool_matrix)
 {
-  const octave_bool_matrix& v1 = dynamic_cast<const octave_bool_matrix&> (a1);
-  const octave_sparse_bool_matrix& v2
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);
   SparseBoolMatrix tmp (v1.bool_matrix_value ());
   return octave_value (tmp. concat (v2.sparse_bool_matrix_value (),
                                     ra_idx));
@@ -63,24 +62,23 @@
 
 DEFCATOP (m_sbm, matrix, sparse_bool_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_bool_matrix& v2
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v2, a2);
   SparseMatrix tmp (v1.matrix_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCATOP (bm_sm, bool_matrix, sparse_matrix)
 {
-  const octave_bool_matrix& v1 = dynamic_cast<const octave_bool_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseMatrix tmp (v1.matrix_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCONV (sparse_bool_matrix_conv, bool_matrix, sparse_bool_matrix)
 {
-  const octave_bool_matrix& v = dynamic_cast<const octave_bool_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v, a);
   return new octave_sparse_bool_matrix
          (SparseBoolMatrix (v.bool_matrix_value ()));
 }
--- a/libinterp/operators/op-cdm-cdm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cdm-cdm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,15 +47,13 @@
 
 DEFUNOP (transpose, complex_diag_matrix)
 {
-  const octave_complex_diag_matrix& v
-    = dynamic_cast<const octave_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);
   return octave_value (v.complex_diag_matrix_value ().transpose ());
 }
 
 DEFUNOP (hermitian, complex_diag_matrix)
 {
-  const octave_complex_diag_matrix& v
-    = dynamic_cast<const octave_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);
   return octave_value (v.complex_diag_matrix_value ().hermitian ());
 }
 
@@ -67,10 +65,8 @@
 
 DEFBINOP (div, complex_diag_matrix, complex_diag_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   return xdiv (v1.complex_diag_matrix_value (),
                v2.complex_diag_matrix_value ());
@@ -78,10 +74,8 @@
 
 DEFBINOP (ldiv, complex_diag_matrix, complex_diag_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   return xleftdiv (v1.complex_diag_matrix_value (),
                    v2.complex_diag_matrix_value ());
@@ -89,8 +83,7 @@
 
 CONVDECL (complex_diag_matrix_to_complex_matrix)
 {
-  const octave_complex_diag_matrix& v
-    = dynamic_cast<const octave_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v, a);
 
   return new octave_complex_matrix (v.complex_matrix_value ());
 }
--- a/libinterp/operators/op-cell.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cell.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 
 DEFUNOP (transpose, cell)
 {
-  const octave_cell& v = dynamic_cast<const octave_cell&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_cell&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
--- a/libinterp/operators/op-chm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-chm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 
 DEFUNOP (transpose, char_matrix)
 {
-  const octave_char_matrix& v = dynamic_cast<const octave_char_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v, a);
 
   return octave_value (v.matrix_value ().transpose ());
 }
@@ -54,8 +54,8 @@
 
 DEFCATOP (chm_s, char_matrix, scalar)
 {
-  const octave_char_matrix& v1 = dynamic_cast<const octave_char_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   warn_implicit_conversion ("Octave:num-to-str",
                             v2.type_name (), v1.type_name ());
@@ -66,8 +66,8 @@
 
 DEFCATOP (chm_m, char_matrix, matrix)
 {
-  const octave_char_matrix& v1 = dynamic_cast<const octave_char_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   warn_implicit_conversion ("Octave:num-to-str",
                             v2.type_name (), v1.type_name ());
@@ -78,8 +78,8 @@
 
 DEFCATOP (s_chm, scalar, char_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_char_matrix& v2 = dynamic_cast<const octave_char_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v2, a2);
 
   warn_implicit_conversion ("Octave:num-to-str",
                             v1.type_name (), v2.type_name ());
@@ -90,8 +90,8 @@
 
 DEFCATOP (m_chm, matrix, char_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_char_matrix& v2 = dynamic_cast<const octave_char_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix&, v2, a2);
 
   warn_implicit_conversion ("Octave:num-to-str",
                             v1.type_name (), v2.type_name ());
--- a/libinterp/operators/op-class.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-class.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,6 +34,7 @@
 
 #include "errwarn.h"
 #include "interpreter-private.h"
+#include "interpreter.h"
 #include "load-path.h"
 #include "ovl.h"
 #include "ov.h"
@@ -41,7 +42,6 @@
 #include "ov-typeinfo.h"
 #include "ops.h"
 #include "symtab.h"
-#include "parse.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -55,15 +55,17 @@
 {
   std::string class_name = a.class_name ();
 
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   octave_value meth = symtab.find_method (opname, class_name);
 
   if (meth.is_defined ())
     {
       // Call overloaded unary class operator.
-      octave_value_list tmp = octave::feval (meth.function_value (),
-                                             ovl (a), 1);
+      octave_value_list tmp
+        = interp.feval (meth.function_value (), ovl (a), 1);
 
       // Return first element if present.
       if (tmp.length () > 0)
@@ -91,8 +93,7 @@
         }
       else
         {
-          const octave_class& v
-            = dynamic_cast<const octave_class&> (a.get_rep ());
+          OCTAVE_CAST_BASE_VALUE (const octave_class&, v, a.get_rep ());
 
           return octave_value (v.map_value ().transpose (),
                                v.class_name (),
@@ -140,7 +141,9 @@
 oct_binop_default (const octave_value& a1, const octave_value& a2,
                    const std::string& opname)
 {
-  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
+  octave::interpreter& interp = octave::__get_interpreter__ ();
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
 
   // Dispatch to first (leftmost) operand by default.
   std::string dispatch_type = a1.class_name ();
@@ -157,8 +160,8 @@
     error ("%s method not defined for %s class", opname.c_str (),
            dispatch_type.c_str ());
 
-  octave_value_list tmp = octave::feval (meth.function_value (),
-                                         ovl (a1, a2), 1);
+  octave_value_list tmp
+    = interp.feval (meth.function_value (), ovl (a1, a2), 1);
 
   if (tmp.length () > 0)
     return tmp(0);
--- a/libinterp/operators/op-cm-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,7 @@
 
 DEFUNOP (transpose, complex_matrix)
 {
-  const octave_complex_matrix& v
-    = dynamic_cast<const octave_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -59,8 +58,7 @@
 
 DEFUNOP (hermitian, complex_matrix)
 {
-  const octave_complex_matrix& v
-    = dynamic_cast<const octave_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("complex-conjugate transpose not defined for N-D objects");
@@ -83,10 +81,8 @@
 
 DEFBINOP (div, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.complex_matrix_value (),
@@ -103,10 +99,8 @@
 
 DEFBINOP (ldiv, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -118,10 +112,8 @@
 
 DEFBINOP (trans_mul, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.complex_matrix_value (),
                              v2.complex_matrix_value (),
                              blas_trans, blas_no_trans));
@@ -129,10 +121,8 @@
 
 DEFBINOP (mul_trans, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.complex_matrix_value (),
                              v2.complex_matrix_value (),
                              blas_no_trans, blas_trans));
@@ -140,10 +130,8 @@
 
 DEFBINOP (herm_mul, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.complex_matrix_value (),
                              v2.complex_matrix_value (),
                              blas_conj_trans, blas_no_trans));
@@ -151,10 +139,8 @@
 
 DEFBINOP (mul_herm, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.complex_matrix_value (),
                              v2.complex_matrix_value (),
                              blas_no_trans, blas_conj_trans));
@@ -162,10 +148,8 @@
 
 DEFBINOP (trans_ldiv, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -177,10 +161,8 @@
 
 DEFBINOP (herm_ldiv, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -213,10 +195,8 @@
 
 DEFBINOP (el_ldiv, complex_matrix, complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.complex_array_value (),
                                  v1.complex_array_value ()));
--- a/libinterp/operators/op-cm-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,9 +47,8 @@
 
 DEFBINOP (div, complex_matrix, complex)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.complex_array_value () / v2.complex_value ());
 }
@@ -58,9 +57,8 @@
 
 DEFBINOP (ldiv, complex_matrix, complex)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   ComplexMatrix m1 = v1.complex_matrix_value ();
   ComplexMatrix m2 = v2.complex_matrix_value ();
@@ -88,9 +86,8 @@
 
 DEFBINOP (el_div, complex_matrix, complex)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.complex_array_value () / v2.complex_value ());
 }
@@ -100,9 +97,8 @@
 
 DEFBINOP (el_ldiv, complex_matrix, complex)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return elem_xdiv (v2.complex_value (), v1.complex_array_value ());
 }
--- a/libinterp/operators/op-cm-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,9 +53,8 @@
 
 DEFBINOP (mul_trans, complex_matrix, matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   ComplexMatrix m1 = v1.complex_matrix_value ();
   Matrix m2 = v2.matrix_value ();
@@ -66,9 +65,8 @@
 
 DEFBINOP (div, complex_matrix, matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.complex_matrix_value (),
@@ -85,9 +83,8 @@
 
 DEFBINOP (ldiv, complex_matrix, matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -110,9 +107,8 @@
 
 DEFBINOP (el_ldiv, complex_matrix, matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return quotient (v2.array_value (), v1.complex_array_value ());
 }
--- a/libinterp/operators/op-cm-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,9 +50,8 @@
 
 DEFBINOP (div, complex_matrix, scalar)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.complex_array_value () / v2.double_value ());
 }
@@ -61,9 +60,8 @@
 
 DEFBINOP (ldiv, complex_matrix, scalar)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   ComplexMatrix m1 = v1.complex_matrix_value ();
   Matrix m2 = v2.matrix_value ();
@@ -86,9 +84,8 @@
 
 DEFBINOP (el_div, complex_matrix, scalar)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.complex_array_value () / v2.double_value ());
 }
@@ -97,9 +94,8 @@
 
 DEFBINOP (el_ldiv, complex_matrix, scalar)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return elem_xdiv (v2.double_value (), v1.complex_array_value ());
 }
--- a/libinterp/operators/op-cm-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,10 +51,8 @@
 
 DEFBINOP (div, complex_matrix, sparse_complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.complex_array_value () / v2.complex_value ());
@@ -77,10 +75,8 @@
 
 DEFBINOP (ldiv, complex_matrix, sparse_complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -105,10 +101,8 @@
 
 DEFBINOP (el_pow, complex_matrix, sparse_complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),
@@ -117,10 +111,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.sparse_complex_matrix_value (),
                                  v1.complex_matrix_value ()));
@@ -131,10 +123,8 @@
 
 DEFCATOP (cm_scm, complex_matrix, sparse_complex_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   SparseComplexMatrix tmp (v1.complex_matrix_value ());
   return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),
                                     ra_idx));
@@ -143,8 +133,7 @@
 DEFCONV (sparse_complex_matrix_conv, complex_matrix,
          sparse_complex_matrix)
 {
-  const octave_complex_matrix& v
-    = dynamic_cast<const octave_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v, a);
   return new octave_sparse_complex_matrix
          (SparseComplexMatrix (v.complex_matrix_value ()));
 }
--- a/libinterp/operators/op-cm-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cm-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,10 +51,8 @@
 
 DEFBINOP (div, complex_matrix, sparse_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.complex_array_value () / v2.scalar_value ());
@@ -77,10 +75,8 @@
 
 DEFBINOP (ldiv, complex_matrix, sparse_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.complex_matrix_value (),
@@ -102,10 +98,8 @@
 
 DEFBINOP (el_pow, complex_matrix, sparse_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),
@@ -114,10 +108,8 @@
 
 DEFBINOP (el_ldiv, complex_matrix, sparse_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   return octave_value
          (quotient (v2.sparse_matrix_value (), v1.complex_matrix_value ()));
 }
@@ -127,10 +119,8 @@
 
 DEFCATOP (cm_sm, complex_matrix, sparse_matrix)
 {
-  const octave_complex_matrix& v1
-    = dynamic_cast<const octave_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseComplexMatrix tmp (v1.complex_matrix_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
--- a/libinterp/operators/op-cs-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,9 +46,8 @@
 
 DEFBINOP (div, complex, complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   ComplexMatrix m1 = v1.complex_matrix_value ();
   ComplexMatrix m2 = v2.complex_matrix_value ();
@@ -64,9 +63,8 @@
 
 DEFBINOP (ldiv, complex, complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (v2.complex_array_value () / v1.complex_value ());
 }
@@ -92,9 +90,8 @@
 
 DEFBINOP (el_ldiv, complex, complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (v2.complex_array_value () / v1.complex_value ());
 }
@@ -109,7 +106,7 @@
 
 DEFCONV (complex_matrix_conv, complex, complex_matrix)
 {
-  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);
 
   return new octave_complex_matrix (v.complex_matrix_value ());
 }
--- a/libinterp/operators/op-cs-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 
 DEFUNOP (not, complex)
 {
-  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);
   Complex x = v.complex_value ();
   if (octave::math::isnan (x))
     octave::err_nan_to_logical_conversion ();
@@ -60,7 +60,7 @@
 
 DEFUNOP (hermitian, complex)
 {
-  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);
 
   return octave_value (conj (v.complex_value ()));
 }
@@ -76,8 +76,8 @@
 
 DEFBINOP (div, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.complex_value () / v2.complex_value ());
 }
@@ -86,8 +86,8 @@
 
 DEFBINOP (ldiv, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v2.complex_value () / v1.complex_value ());
 }
@@ -103,8 +103,8 @@
 
 DEFBINOP (el_div, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.complex_value () / v2.complex_value ());
 }
@@ -113,24 +113,24 @@
 
 DEFBINOP (el_ldiv, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v2.complex_value () / v1.complex_value ());
 }
 
 DEFBINOP (el_and, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return v1.complex_value () != 0.0 && v2.complex_value () != 0.0;
 }
 
 DEFBINOP (el_or, complex, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return v1.complex_value () != 0.0 || v2.complex_value () != 0.0;
 }
--- a/libinterp/operators/op-cs-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,8 +52,8 @@
 
 DEFBINOP (div, complex, matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   ComplexMatrix m1 = v1.complex_matrix_value ();
   Matrix m2 = v2.matrix_value ();
@@ -69,8 +69,8 @@
 
 DEFBINOP (ldiv, complex, matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (v2.array_value () / v1.complex_value ());
 }
@@ -88,8 +88,8 @@
 
 DEFBINOP (el_ldiv, complex, matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (v2.array_value () / v1.complex_value ());
 }
--- a/libinterp/operators/op-cs-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,8 +47,8 @@
 
 DEFBINOP (div, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.complex_value () / v2.double_value ());
 }
@@ -57,8 +57,8 @@
 
 DEFBINOP (ldiv, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v2.double_value () / v1.complex_value ());
 }
@@ -74,8 +74,8 @@
 
 DEFBINOP (el_div, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.complex_value () / v2.double_value ());
 }
@@ -84,24 +84,24 @@
 
 DEFBINOP (el_ldiv, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v2.double_value () / v1.complex_value ());
 }
 
 DEFBINOP (el_and, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return v1.complex_value () != 0.0 && v2.double_value ();
 }
 
 DEFBINOP (el_or, complex, scalar)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return v1.complex_value () != 0.0 || v2.double_value ();
 }
--- a/libinterp/operators/op-cs-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,9 +49,8 @@
 
 DEFBINOP (div, complex, sparse_complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v1.complex_value ()
@@ -69,17 +68,15 @@
 
 DEFBINOP (pow, complex, sparse_complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   return xpow (v1.complex_value (), v2.complex_matrix_value ());
 }
 
 DEFBINOP (ldiv, complex, sparse_complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
 }
@@ -98,9 +95,8 @@
 
 DEFBINOP (el_ldiv, complex, sparse_complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
 }
@@ -110,9 +106,8 @@
 
 DEFCATOP (cs_scm, complex, sparse_complex_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   SparseComplexMatrix tmp (1, 1, v1.complex_value ());
   return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),
                                     ra_idx));
@@ -120,7 +115,7 @@
 
 DEFCONV (sparse_complex_matrix_conv, complex, sparse_complex_matrix)
 {
-  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);
 
   return new octave_sparse_complex_matrix
          (SparseComplexMatrix (v.complex_matrix_value ()));
--- a/libinterp/operators/op-cs-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-cs-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,8 +51,8 @@
 
 DEFBINOP (div, complex, sparse_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () / v2.scalar_value ()));
@@ -69,15 +69,15 @@
 
 DEFBINOP (pow, complex, sparse_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   return xpow (v1.complex_value (), v2.matrix_value ());
 }
 
 DEFBINOP (ldiv, complex, sparse_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
 }
@@ -95,8 +95,8 @@
 
 DEFBINOP (el_ldiv, complex, sparse_matrix)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
 }
@@ -106,16 +106,15 @@
 
 DEFCATOP (cs_sm, sparse_matrix, complex)
 {
-  const octave_complex& v1 = dynamic_cast<const octave_complex&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseComplexMatrix tmp (1, 1, v1.complex_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCONV (sparse_matrix_conv, complex, sparse_matrix)
 {
-  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v, a);
 
   return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));
 }
--- a/libinterp/operators/op-dm-dm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-dm-dm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 
 DEFUNOP (transpose, diag_matrix)
 {
-  const octave_diag_matrix& v = dynamic_cast<const octave_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v, a);
   return octave_value (v.diag_matrix_value ().transpose ());
 }
 
@@ -59,8 +59,8 @@
 
 DEFBINOP (div, diag_matrix, diag_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   return xdiv (v1.diag_matrix_value (),
                v2.diag_matrix_value ());
@@ -68,8 +68,8 @@
 
 DEFBINOP (ldiv, diag_matrix, diag_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   return xleftdiv (v1.diag_matrix_value (),
                    v2.diag_matrix_value ());
@@ -77,7 +77,7 @@
 
 CONVDECL (diag_matrix_to_matrix)
 {
-  const octave_diag_matrix& v = dynamic_cast<const octave_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v, a);
 
   return new octave_matrix (v.matrix_value ());
 }
--- a/libinterp/operators/op-dm-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-dm-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,9 +54,8 @@
 
 DEFBINOP (mul_dm_scm, diag_matrix, sparse_complex_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -80,10 +79,8 @@
 
 DEFBINOP (mul_cdm_sm, complex_diag_matrix, sparse_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -107,10 +104,8 @@
 
 DEFBINOP (mul_cdm_scm, complex_diag_matrix, sparse_complex_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -134,9 +129,8 @@
 
 DEFBINOP (ldiv_dm_scm, diag_matrix, sparse_complex_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   MatrixType typ = v2.matrix_type ();
   return xleftdiv (v1.diag_matrix_value (), v2.sparse_complex_matrix_value (),
@@ -145,10 +139,8 @@
 
 DEFBINOP (ldiv_cdm_sm, complex_diag_matrix, sparse_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   MatrixType typ = v2.matrix_type ();
   return xleftdiv (v1.complex_diag_matrix_value (), v2.sparse_matrix_value (),
@@ -157,10 +149,8 @@
 
 DEFBINOP (ldiv_cdm_scm, complex_diag_matrix, sparse_complex_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   MatrixType typ = v2.matrix_type ();
   return xleftdiv (v1.complex_diag_matrix_value (),
@@ -170,9 +160,8 @@
 
 DEFBINOP (add_dm_scm, diag_matrix, sparse_complex_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -188,10 +177,8 @@
 
 DEFBINOP (add_cdm_sm, complex_diag_matrix, sparse_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -207,10 +194,8 @@
 
 DEFBINOP (add_cdm_scm, complex_diag_matrix, sparse_complex_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -226,9 +211,8 @@
 
 DEFBINOP (sub_dm_scm, diag_matrix, sparse_complex_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -244,10 +228,8 @@
 
 DEFBINOP (sub_cdm_sm, complex_diag_matrix, sparse_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -263,10 +245,8 @@
 
 DEFBINOP (sub_cdm_scm, complex_diag_matrix, sparse_complex_matrix)
 {
-  const octave_complex_diag_matrix& v1
-    = dynamic_cast<const octave_complex_diag_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -284,9 +264,8 @@
 
 DEFBINOP (mul_scm_dm, sparse_complex_matrix, diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
@@ -310,10 +289,8 @@
 
 DEFBINOP (mul_sm_cdm, sparse_matrix, complex_diag_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
@@ -337,10 +314,8 @@
 
 DEFBINOP (mul_scm_cdm, sparse_complex_matrix, complex_diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
@@ -371,9 +346,8 @@
 
 DEFBINOP (div_scm_dm, sparse_complex_matrix, diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());
@@ -387,10 +361,8 @@
 
 DEFBINOP (div_sm_cdm, sparse_matrix, complex_diag_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
@@ -404,10 +376,8 @@
 
 DEFBINOP (div_scm_cdm, sparse_complex_matrix, complex_diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
@@ -421,10 +391,8 @@
 
 DEFBINOP (add_sm_cdm, sparse_matrix, complex_diag_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -440,9 +408,8 @@
 
 DEFBINOP (add_scm_dm, sparse_complex_matrix, diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -458,10 +425,8 @@
 
 DEFBINOP (add_scm_cdm, sparse_complex_matrix, complex_diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -477,10 +442,8 @@
 
 DEFBINOP (sub_sm_cdm, sparse_matrix, complex_diag_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -496,9 +459,8 @@
 
 DEFBINOP (sub_scm_dm, sparse_complex_matrix, diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -514,10 +476,8 @@
 
 DEFBINOP (sub_scm_cdm, sparse_complex_matrix, complex_diag_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_diag_matrix& v2
-    = dynamic_cast<const octave_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
--- a/libinterp/operators/op-dm-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-dm-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,8 +43,8 @@
 
 DEFBINOP (mul_dm_sm, diag_matrix, sparse_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -67,8 +67,8 @@
 
 DEFBINOP (ldiv_dm_sm, diag_matrix, sparse_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   MatrixType typ = v2.matrix_type ();
   return xleftdiv (v1.diag_matrix_value (), v2.sparse_matrix_value (), typ);
@@ -76,8 +76,8 @@
 
 DEFBINOP (add_dm_sm, diag_matrix, sparse_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -93,8 +93,8 @@
 
 DEFBINOP (sub_dm_sm, diag_matrix, sparse_matrix)
 {
-  const octave_diag_matrix& v1 = dynamic_cast<const octave_diag_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     // If v2 is a scalar in disguise, return a diagonal matrix rather than
@@ -112,8 +112,8 @@
 
 DEFBINOP (mul_sm_dm, sparse_matrix, diag_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
@@ -136,8 +136,8 @@
 
 DEFBINOP (div_sm_dm, sparse_matrix, diag_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());
@@ -150,8 +150,8 @@
 
 DEFBINOP (add_sm_dm, sparse_matrix, diag_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
@@ -167,8 +167,8 @@
 
 DEFBINOP (sub_sm_dm, sparse_matrix, diag_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_diag_matrix& v2 = dynamic_cast<const octave_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_diag_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     // If v1 is a scalar in disguise, return a diagonal matrix rather than
--- a/libinterp/operators/op-dm-template.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-dm-template.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -66,8 +66,8 @@
 #if defined (DEFINEDIV)
 DEFBINOP (div, LMATRIX, RMATRIX)
 {
-  const OCTAVE_LMATRIX& v1 = dynamic_cast<const OCTAVE_LMATRIX&> (a1);
-  const OCTAVE_RMATRIX& v2 = dynamic_cast<const OCTAVE_RMATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);
 
   return xdiv (v1.LDMATRIX_VALUE (), v2.RMATRIX_VALUE ());
 }
@@ -76,8 +76,8 @@
 #if defined (DEFINELDIV)
 DEFBINOP (ldiv, LMATRIX, RMATRIX)
 {
-  const OCTAVE_LMATRIX& v1 = dynamic_cast<const OCTAVE_LMATRIX&> (a1);
-  const OCTAVE_RMATRIX& v2 = dynamic_cast<const OCTAVE_RMATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);
 
   return xleftdiv (v1.LMATRIX_VALUE (), v2.RDMATRIX_VALUE ());
 }
--- a/libinterp/operators/op-dms-template.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-dms-template.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,24 +54,24 @@
 
 DEFBINOP (dmsdiv, MATRIX, SCALAR)
 {
-  const OCTAVE_MATRIX& v1 = dynamic_cast<const OCTAVE_MATRIX&> (a1);
-  const OCTAVE_SCALAR& v2 = dynamic_cast<const OCTAVE_SCALAR&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_MATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v2, a2);
 
   return v1.MATRIX_VALUE () / v2.SCALAR_VALUE ();
 }
 
 DEFBINOP (sdmldiv, SCALAR, MATRIX)
 {
-  const OCTAVE_SCALAR& v1 = dynamic_cast<const OCTAVE_SCALAR&> (a1);
-  const OCTAVE_MATRIX& v2 = dynamic_cast<const OCTAVE_MATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_MATRIX&, v2, a2);
 
   return v2.MATRIX_VALUE () / v1.SCALAR_VALUE ();
 }
 
 DEFBINOP (dmspow, MATRIX, SCALAR)
 {
-  const OCTAVE_MATRIX& v1 = dynamic_cast<const OCTAVE_MATRIX&> (a1);
-  const OCTAVE_SCALAR& v2 = dynamic_cast<const OCTAVE_SCALAR&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_MATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_SCALAR&, v2, a2);
 
   return xpow (v1.MATRIX_VALUE (), v2.SCALAR_VALUE ());
 }
--- a/libinterp/operators/op-fcdm-fcdm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcdm-fcdm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,15 +47,13 @@
 
 DEFUNOP (transpose, float_complex_diag_matrix)
 {
-  const octave_float_complex_diag_matrix& v
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);
   return octave_value (v.float_complex_diag_matrix_value ().transpose ());
 }
 
 DEFUNOP (hermitian, float_complex_diag_matrix)
 {
-  const octave_float_complex_diag_matrix& v
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);
   return octave_value (v.float_complex_diag_matrix_value ().hermitian ());
 }
 
@@ -67,10 +65,8 @@
 
 DEFBINOP (div, float_complex_diag_matrix, float_complex_diag_matrix)
 {
-  const octave_float_complex_diag_matrix& v1
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a1);
-  const octave_float_complex_diag_matrix& v2
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v2, a2);
 
   return xdiv (v1.float_complex_diag_matrix_value (),
                v2.float_complex_diag_matrix_value ());
@@ -78,10 +74,8 @@
 
 DEFBINOP (ldiv, float_complex_diag_matrix, float_complex_diag_matrix)
 {
-  const octave_float_complex_diag_matrix& v1
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a1);
-  const octave_float_complex_diag_matrix& v2
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v2, a2);
 
   return xleftdiv (v1.float_complex_diag_matrix_value (),
                    v2.float_complex_diag_matrix_value ());
@@ -89,8 +83,7 @@
 
 CONVDECL (float_complex_diag_matrix_to_complex_diag_matrix)
 {
-  const octave_float_complex_diag_matrix& v
-    = dynamic_cast<const octave_float_complex_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_diag_matrix&, v, a);
 
   return new octave_complex_diag_matrix (v.complex_diag_matrix_value ());
 }
--- a/libinterp/operators/op-fcm-fcm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcm-fcm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,7 @@
 
 DEFUNOP (transpose, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v
-    = dynamic_cast<const octave_float_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -59,8 +58,7 @@
 
 DEFUNOP (hermitian, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v
-    = dynamic_cast<const octave_float_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("complex-conjugate transpose not defined for N-D objects");
@@ -83,10 +81,8 @@
 
 DEFBINOP (div, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   FloatComplexMatrix ret = xdiv (v1.float_complex_matrix_value (),
@@ -103,10 +99,8 @@
 
 DEFBINOP (ldiv, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),
@@ -118,10 +112,8 @@
 
 DEFBINOP (trans_mul, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_complex_matrix_value (),
                              v2.float_complex_matrix_value (),
                              blas_trans, blas_no_trans));
@@ -129,10 +121,8 @@
 
 DEFBINOP (mul_trans, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_complex_matrix_value (),
                              v2.float_complex_matrix_value (),
                              blas_no_trans, blas_trans));
@@ -140,10 +130,8 @@
 
 DEFBINOP (herm_mul, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_complex_matrix_value (),
                              v2.float_complex_matrix_value (),
                              blas_conj_trans, blas_no_trans));
@@ -151,10 +139,8 @@
 
 DEFBINOP (mul_herm, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_complex_matrix_value (),
                              v2.float_complex_matrix_value (),
                              blas_no_trans, blas_conj_trans));
@@ -162,10 +148,8 @@
 
 DEFBINOP (trans_ldiv, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),
@@ -178,10 +162,8 @@
 
 DEFBINOP (herm_ldiv, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),
@@ -214,10 +196,8 @@
 
 DEFBINOP (el_ldiv, float_complex_matrix, float_complex_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.float_complex_array_value (),
                                  v1.float_complex_array_value ()));
--- a/libinterp/operators/op-fcm-fcs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcm-fcs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,10 +51,8 @@
 
 DEFBINOP (div, float_complex_matrix, float_complex)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex& v2
-    = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());
 }
@@ -63,10 +61,8 @@
 
 DEFBINOP (ldiv, float_complex_matrix, float_complex)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex& v2
-    = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   FloatComplexMatrix m1 = v1.float_complex_matrix_value ();
   FloatComplexMatrix m2 = v2.float_complex_matrix_value ();
@@ -95,10 +91,8 @@
 
 DEFBINOP (el_div, float_complex_matrix, float_complex)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex& v2
-    = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_complex_array_value () / v2.float_complex_value ());
 }
@@ -108,10 +102,8 @@
 
 DEFBINOP (el_ldiv, float_complex_matrix, float_complex)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_complex& v2
-    = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return elem_xdiv (v2.float_complex_value (), v1.float_complex_array_value ());
 }
--- a/libinterp/operators/op-fcm-fm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcm-fm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,10 +57,8 @@
 
 DEFBINOP (mul_trans, float_complex_matrix, float_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_matrix& v2
-    = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   FloatComplexMatrix m1 = v1.float_complex_matrix_value ();
   FloatMatrix m2 = v2.float_matrix_value ();
@@ -71,10 +69,8 @@
 
 DEFBINOP (div, float_complex_matrix, float_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_matrix& v2
-    = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   FloatComplexMatrix ret = xdiv (v1.float_complex_matrix_value (),
@@ -91,10 +87,8 @@
 
 DEFBINOP (ldiv, float_complex_matrix, float_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_matrix& v2
-    = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_complex_matrix_value (),
@@ -126,10 +120,8 @@
 
 DEFBINOP (el_ldiv, float_complex_matrix, float_matrix)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_matrix& v2
-    = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return quotient (v2.float_array_value (), v1.float_complex_array_value ());
 }
--- a/libinterp/operators/op-fcm-fs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcm-fs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,10 +54,8 @@
 
 DEFBINOP (div, float_complex_matrix, float)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_scalar& v2
-    = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_complex_array_value () / v2.float_value ());
 }
@@ -66,10 +64,8 @@
 
 DEFBINOP (ldiv, float_complex_matrix, float)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_scalar& v2
-    = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   FloatComplexMatrix m1 = v1.float_complex_matrix_value ();
   FloatMatrix m2 = v2.float_matrix_value ();
@@ -99,10 +95,8 @@
 
 DEFBINOP (el_div, float_complex_matrix, float)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_scalar& v2
-    = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_complex_array_value () / v2.float_value ());
 }
@@ -112,10 +106,8 @@
 
 DEFBINOP (el_ldiv, float_complex_matrix, float)
 {
-  const octave_float_complex_matrix& v1
-    = dynamic_cast<const octave_float_complex_matrix&> (a1);
-  const octave_float_scalar& v2
-    = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return elem_xdiv (v2.float_value (), v1.float_complex_array_value ());
 }
--- a/libinterp/operators/op-fcn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,16 +39,16 @@
 
 DEFBINOP (eq, fcn_handle, fcn_handle)
 {
-  const octave_fcn_handle& v1 = dynamic_cast<const octave_fcn_handle&> (a1);
-  const octave_fcn_handle& v2 = dynamic_cast<const octave_fcn_handle&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v2, a2);
 
   return is_equal_to (v1, v2);
 }
 
 DEFBINOP (ne, fcn_handle, fcn_handle)
 {
-  const octave_fcn_handle& v1 = dynamic_cast<const octave_fcn_handle&> (a1);
-  const octave_fcn_handle& v2 = dynamic_cast<const octave_fcn_handle&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_fcn_handle&, v2, a2);
 
   return ! is_equal_to (v1, v2);
 }
--- a/libinterp/operators/op-fcs-fcm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcs-fcm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,10 +51,8 @@
 
 DEFBINOP (div, float_complex, float_complex_matrix)
 {
-  const octave_float_complex& v1
-    = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   FloatComplexMatrix m1 = v1.float_complex_matrix_value ();
   FloatComplexMatrix m2 = v2.float_complex_matrix_value ();
@@ -70,10 +68,8 @@
 
 DEFBINOP (ldiv, float_complex, float_complex_matrix)
 {
-  const octave_float_complex& v1
-    = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());
 }
@@ -100,10 +96,8 @@
 
 DEFBINOP (el_ldiv, float_complex, float_complex_matrix)
 {
-  const octave_float_complex& v1
-    = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return octave_value (v2.float_complex_array_value () / v1.float_complex_value ());
 }
@@ -124,8 +118,7 @@
 
 DEFCONV (float_complex_matrix_conv, float_complex, float_complex_matrix)
 {
-  const octave_float_complex& v
-    = dynamic_cast<const octave_float_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);
 
   return new octave_float_complex_matrix (v.float_complex_matrix_value ());
 }
--- a/libinterp/operators/op-fcs-fcs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcs-fcs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 
 DEFUNOP (not, float_complex)
 {
-  const octave_float_complex& v = dynamic_cast<const octave_float_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);
   FloatComplex x = v.float_complex_value ();
   if (octave::math::isnan (x))
     octave::err_nan_to_logical_conversion ();
@@ -58,7 +58,7 @@
 
 DEFUNOP (hermitian, float_complex)
 {
-  const octave_float_complex& v = dynamic_cast<const octave_float_complex&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v, a);
 
   return octave_value (conj (v.float_complex_value ()));
 }
@@ -74,8 +74,8 @@
 
 DEFBINOP (div, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_complex_value () / v2.float_complex_value ());
 }
@@ -84,8 +84,8 @@
 
 DEFBINOP (ldiv, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v2.float_complex_value () / v1.float_complex_value ());
 }
@@ -101,8 +101,8 @@
 
 DEFBINOP (el_div, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_complex_value () / v2.float_complex_value ());
 }
@@ -111,16 +111,16 @@
 
 DEFBINOP (el_ldiv, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v2.float_complex_value () / v1.float_complex_value ());
 }
 
 DEFBINOP (el_and, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return (v1.float_complex_value () != 0.0f
           && v2.float_complex_value () != 0.0f);
@@ -128,8 +128,8 @@
 
 DEFBINOP (el_or, float_complex, float_complex)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return (v1.float_complex_value () != 0.0f
           || v2.float_complex_value () != 0.0f);
--- a/libinterp/operators/op-fcs-fm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcs-fm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,8 +53,8 @@
 
 DEFBINOP (div, float_complex, float_matrix)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   FloatComplexMatrix m1 = v1.float_complex_matrix_value ();
   FloatMatrix m2 = v2.float_matrix_value ();
@@ -70,8 +70,8 @@
 
 DEFBINOP (ldiv, float_complex, float_matrix)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return octave_value (v2.float_array_value () / v1.float_complex_value ());
 }
@@ -98,8 +98,8 @@
 
 DEFBINOP (el_ldiv, float_complex, float_matrix)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return octave_value (v2.float_array_value () / v1.float_complex_value ());
 }
--- a/libinterp/operators/op-fcs-fs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fcs-fs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,8 +50,8 @@
 
 DEFBINOP (div, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_complex_value () / v2.float_value ());
 }
@@ -60,8 +60,8 @@
 
 DEFBINOP (ldiv, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v2.float_value () / v1.float_complex_value ());
 }
@@ -77,8 +77,8 @@
 
 DEFBINOP (el_div, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_complex_value () / v2.float_value ());
 }
@@ -87,24 +87,24 @@
 
 DEFBINOP (el_ldiv, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v2.float_value () / v1.float_complex_value ());
 }
 
 DEFBINOP (el_and, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return (v1.float_complex_value () != 0.0f && v2.float_value ());
 }
 
 DEFBINOP (el_or, float_complex, float)
 {
-  const octave_float_complex& v1 = dynamic_cast<const octave_float_complex&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return (v1.float_complex_value () != 0.0f || v2.float_value ());
 }
--- a/libinterp/operators/op-fdm-fdm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fdm-fdm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,8 +47,7 @@
 
 DEFUNOP (transpose, float_diag_matrix)
 {
-  const octave_float_diag_matrix& v
-    = dynamic_cast<const octave_float_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v, a);
   return octave_value (v.float_diag_matrix_value ().transpose ());
 }
 
@@ -60,10 +59,8 @@
 
 DEFBINOP (div, float_diag_matrix, float_diag_matrix)
 {
-  const octave_float_diag_matrix& v1
-    = dynamic_cast<const octave_float_diag_matrix&> (a1);
-  const octave_float_diag_matrix& v2
-    = dynamic_cast<const octave_float_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v2, a2);
 
   return xdiv (v1.float_diag_matrix_value (),
                v2.float_diag_matrix_value ());
@@ -71,10 +68,8 @@
 
 DEFBINOP (ldiv, float_diag_matrix, float_diag_matrix)
 {
-  const octave_float_diag_matrix& v1
-    = dynamic_cast<const octave_float_diag_matrix&> (a1);
-  const octave_float_diag_matrix& v2
-    = dynamic_cast<const octave_float_diag_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v2, a2);
 
   return xleftdiv (v1.float_diag_matrix_value (),
                    v2.float_diag_matrix_value ());
@@ -82,8 +77,7 @@
 
 CONVDECL (float_diag_matrix_to_float_matrix)
 {
-  const octave_float_diag_matrix& v
-    = dynamic_cast<const octave_float_diag_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_diag_matrix&, v, a);
 
   return new octave_float_matrix (v.float_matrix_value ());
 }
--- a/libinterp/operators/op-fm-fcm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fm-fcm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,10 +57,8 @@
 
 DEFBINOP (trans_mul, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v1
-    = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   FloatMatrix m1 = v1.float_matrix_value ();
   FloatComplexMatrix m2 = v2.float_complex_matrix_value ();
@@ -71,10 +69,8 @@
 
 DEFBINOP (div, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v1
-    = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   FloatComplexMatrix ret = xdiv (v1.float_matrix_value (),
@@ -91,10 +87,8 @@
 
 DEFBINOP (ldiv, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v1
-    = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_matrix_value (),
@@ -106,10 +100,8 @@
 
 DEFBINOP (trans_ldiv, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v1
-    = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatComplexMatrix ret = xleftdiv (v1.float_matrix_value (),
@@ -142,10 +134,8 @@
 
 DEFBINOP (el_ldiv, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v1
-    = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return quotient (v2.float_complex_array_value (), v1.float_array_value ());
 }
@@ -166,7 +156,7 @@
 
 DEFCONV (float_complex_matrix_conv, float_matrix, float_complex_matrix)
 {
-  const octave_float_matrix& v = dynamic_cast<const octave_float_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v, a);
 
   return new octave_float_complex_matrix (FloatComplexNDArray
                                           (v.float_array_value ()));
--- a/libinterp/operators/op-fm-fcs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fm-fcs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -55,8 +55,8 @@
 
 DEFBINOP (div, float_matrix, float_complex)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_array_value () / v2.float_complex_value ());
 }
@@ -65,8 +65,8 @@
 
 DEFBINOP (ldiv, float_matrix, float_complex)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   FloatMatrix m1 = v1.float_matrix_value ();
   FloatComplexMatrix m2 = v2.float_complex_matrix_value ();
@@ -96,8 +96,8 @@
 
 DEFBINOP (el_div, float_matrix, float_complex)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_array_value () / v2.float_complex_value ());
 }
@@ -107,8 +107,8 @@
 
 DEFBINOP (el_ldiv, float_matrix, flaot_complex)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return elem_xdiv (v2.float_complex_value (), v1.float_array_value ());
 }
--- a/libinterp/operators/op-fm-fm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fm-fm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 
 DEFUNOP (transpose, float_matrix)
 {
-  const octave_float_matrix& v = dynamic_cast<const octave_float_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -69,8 +69,8 @@
 
 DEFBINOP (div, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   FloatMatrix ret = xdiv (v1.float_matrix_value (),
@@ -87,8 +87,8 @@
 
 DEFBINOP (ldiv, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatMatrix ret = xleftdiv (v1.float_matrix_value (),
@@ -100,8 +100,8 @@
 
 DEFBINOP (trans_mul, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_matrix_value (),
                              v2.float_matrix_value (),
                              blas_trans, blas_no_trans));
@@ -109,8 +109,8 @@
 
 DEFBINOP (mul_trans, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   return octave_value(xgemm (v1.float_matrix_value (),
                              v2.float_matrix_value (),
                              blas_no_trans, blas_trans));
@@ -118,8 +118,8 @@
 
 DEFBINOP (trans_ldiv, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   FloatMatrix ret = xleftdiv (v1.float_matrix_value (),
@@ -151,8 +151,8 @@
 
 DEFBINOP (el_ldiv, float_matrix, float_matrix)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return octave_value (quotient (v2.float_array_value (),
                                  v1.float_array_value ()));
--- a/libinterp/operators/op-fm-fs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fm-fs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,8 +47,8 @@
 
 DEFBINOP (div, float_matrix, float)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_array_value () / v2.float_value ());
 }
@@ -57,8 +57,8 @@
 
 DEFBINOP (ldiv, float_matrix, float)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   FloatMatrix m1 = v1.float_matrix_value ();
   FloatMatrix m2 = v2.float_matrix_value ();
@@ -87,8 +87,8 @@
 
 DEFBINOP (el_div, float_matrix, float)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_array_value () / v2.float_value ());
 }
@@ -98,8 +98,8 @@
 
 DEFBINOP (el_ldiv, float_matrix, float)
 {
-  const octave_float_matrix& v1 = dynamic_cast<const octave_float_matrix&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return elem_xdiv (v2.float_value (), v1.float_array_value ());
 }
--- a/libinterp/operators/op-fs-fcm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fs-fcm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,10 +57,8 @@
 
 DEFBINOP (div, float_scalar, float_complex_matrix)
 {
-  const octave_float_scalar& v1
-    = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   FloatMatrix m1 = v1.float_matrix_value ();
   FloatComplexMatrix m2 = v2.float_complex_matrix_value ();
@@ -76,10 +74,8 @@
 
 DEFBINOP (ldiv, float_scalar, float_complex_matrix)
 {
-  const octave_float_scalar& v1
-    = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return octave_value (v2.float_complex_array_value () / v1.float_value ());
 }
@@ -106,10 +102,8 @@
 
 DEFBINOP (el_ldiv, float_scalar, float_complex_matrix)
 {
-  const octave_float_scalar& v1
-    = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex_matrix& v2
-    = dynamic_cast<const octave_float_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex_matrix&, v2, a2);
 
   return octave_value (v2.float_complex_array_value () / v1.float_value ());
 }
@@ -130,7 +124,7 @@
 
 DEFCONV (float_complex_matrix_conv, float_scalar, float_complex_matrix)
 {
-  const octave_float_scalar& v = dynamic_cast<const octave_float_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);
 
   return new octave_float_complex_matrix (FloatComplexMatrix
                                           (v.float_matrix_value ()));
--- a/libinterp/operators/op-fs-fcs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fs-fcs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,8 +50,8 @@
 
 DEFBINOP (div, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_value () / v2.float_complex_value ());
 }
@@ -60,8 +60,8 @@
 
 DEFBINOP (ldiv, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v2.float_complex_value () / v1.float_value ());
 }
@@ -77,8 +77,8 @@
 
 DEFBINOP (el_div, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_value () / v2.float_complex_value ());
 }
@@ -87,16 +87,16 @@
 
 DEFBINOP (el_ldiv, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v2.float_complex_value () / v1.float_value ());
 }
 
 DEFBINOP (el_and, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_scalar_value ()
                        && (v2.float_complex_value () != 0.0f));
@@ -104,8 +104,8 @@
 
 DEFBINOP (el_or, float_scalar, float_complex)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_complex& v2 = dynamic_cast<const octave_float_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_complex&, v2, a2);
 
   return octave_value (v1.float_scalar_value ()
                        || (v2.float_complex_value () != 0.0f));
--- a/libinterp/operators/op-fs-fm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fs-fm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,8 @@
 
 DEFBINOP (div, float_scalar, float_matrix)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   FloatMatrix m1 = v1.float_matrix_value ();
   FloatMatrix m2 = v2.float_matrix_value ();
@@ -65,8 +65,8 @@
 
 DEFBINOP (ldiv, float_scalar, float_matrix)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return octave_value (v2.float_array_value () / v1.float_value ());
 }
@@ -93,8 +93,8 @@
 
 DEFBINOP (el_ldiv, float_scalar, float_matrix)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_matrix& v2 = dynamic_cast<const octave_float_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_matrix&, v2, a2);
 
   return octave_value (v2.float_array_value () / v1.float_value ());
 }
@@ -113,7 +113,7 @@
 
 DEFCONV (matrix_conv, float_scalar, float_matrix)
 {
-  const octave_float_scalar& v = dynamic_cast<const octave_float_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);
 
   return new octave_float_matrix (v.float_matrix_value ());
 }
--- a/libinterp/operators/op-fs-fs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-fs-fs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 
 DEFUNOP (not, float_scalar)
 {
-  const octave_float_scalar& v = dynamic_cast<const octave_float_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v, a);
   float x = v.float_value ();
   if (octave::math::isnan (x))
     octave::err_nan_to_logical_conversion ();
@@ -70,8 +70,8 @@
 
 DEFBINOP (div, float_scalar, float_scalar)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_value () / v2.float_value ());
 }
@@ -80,8 +80,8 @@
 
 DEFBINOP (ldiv, float_scalar, float_scalar)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v2.float_value () / v1.float_value ());
 }
@@ -97,8 +97,8 @@
 
 DEFBINOP (el_div, float_scalar, float_scalar)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v1.float_value () / v2.float_value ());
 }
@@ -107,8 +107,8 @@
 
 DEFBINOP (el_ldiv, float_scalar, float_scalar)
 {
-  const octave_float_scalar& v1 = dynamic_cast<const octave_float_scalar&> (a1);
-  const octave_float_scalar& v2 = dynamic_cast<const octave_float_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_float_scalar&, v2, a2);
 
   return octave_value (v2.float_value () / v1.float_value ());
 }
--- a/libinterp/operators/op-int.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-int.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,8 +36,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \
-    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \
     octave_value retval = octave_value                                  \
       (v1.t1 ## _value () op v2.t2 ## _value ());                       \
     return retval;                                                      \
@@ -48,8 +48,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \
-    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \
     octave_value retval = octave_value                                  \
       (v1.e1 ## _value () op v2.e2 ## _value ());                       \
     return retval;                                                      \
@@ -60,8 +60,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \
-    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \
     octave_value retval = octave_value (f (v1.t1 ## _value (), v2.t2 ## _value ())); \
     return retval;                                                      \
   }
@@ -71,8 +71,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \
-    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \
     octave_value retval = octave_value (f (v1.e1 ## _value (), v2.e2 ## _value ())); \
     return retval;                                                      \
   }
@@ -179,7 +179,7 @@
   DEFUNOP_OP (s_uplus, TYPE ## _scalar, /* no-op */)                    \
   DEFUNOP (s_uminus, TYPE ## _scalar)                                   \
   {                                                                     \
-    const octave_ ## TYPE ## _scalar & v = dynamic_cast<const octave_ ## TYPE ## _scalar &> (a); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _scalar&, v, a);   \
     octave_value retval = octave_value (- v. TYPE ## _scalar_value ()); \
     return retval;                                                      \
   }                                                                     \
@@ -198,8 +198,8 @@
                                                                         \
   DEFBINOP (PFX ## _div, T1 ## scalar, T2 ## scalar)                    \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
   }                                                                     \
@@ -208,8 +208,8 @@
                                                                         \
   DEFBINOP (PFX ## _ldiv, T1 ## scalar, T2 ## scalar)                   \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
   }                                                                     \
@@ -218,8 +218,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_div, T1 ## scalar, T2 ## scalar)                 \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \
   }                                                                     \
@@ -228,8 +228,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_ldiv, T1 ## scalar, T2 ## scalar)                \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \
   }
@@ -237,16 +237,16 @@
 #define OCTAVE_SS_INT_BOOL_OPS(PFX, T1, T2, Z1, Z2)                     \
   DEFBINOP (PFX ## _el_and, T2, T2)                                     \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return v1.T1 ## scalar_value () != Z1 && v2.T2 ## scalar_value () != Z2; \
   }                                                                     \
                                                                         \
   DEFBINOP (PFX ## _el_or, T1, T2)                                      \
   {                                                                     \
-    const octave_ ## T1 ## scalar& v1 = dynamic_cast<const octave_ ## T1 ## scalar&> (a1); \
-    const octave_ ## T2 ## scalar& v2 = dynamic_cast<const octave_ ## T2 ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## scalar&, v2, a2);    \
                                                                         \
     return v1.T1 ## scalar_value () != Z1 || v2.T2 ## scalar_value () != Z2; \
   }
@@ -318,8 +318,8 @@
                                                                         \
   /* DEFBINOP (PFX ## _div, TS ## scalar, TM ## matrix) */              \
   /* { */                                                               \
-  /* const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); */ \
-  /* const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); */ \
+  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1); */ \
+  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2); */ \
   /* */                                                                 \
   /* Matrix m1 = v1.TM ## matrix_value (); */                           \
   /* Matrix m2 = v2.TM ## matrix_value (); */                           \
@@ -331,8 +331,8 @@
                                                                         \
   DEFBINOP (PFX ## _ldiv, TS ## scalar, TM ## matrix)                   \
   {                                                                     \
-   const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); \
-   const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \
                                                                         \
    return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
    }                                                                    \
@@ -340,8 +340,8 @@
   DEFINTNDBINOP_OP (PFX ## _el_mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \
   DEFBINOP (PFX ## _el_div, TS ## scalar, TM ## matrix)                 \
   {                                                                     \
-   const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); \
-   const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \
                                                                         \
    octave_value retval = octave_value (v1.TS ## scalar_value () / v2.TM ## array_value ()); \
    return retval;                                                       \
@@ -351,8 +351,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_ldiv, TS ## scalar, TM ## matrix)                \
   {                                                                     \
-   const octave_ ## TS ## scalar& v1 = dynamic_cast<const octave_ ## TS ## scalar&> (a1); \
-   const octave_ ## TM ## matrix& v2 = dynamic_cast<const octave_ ## TM ## matrix&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v2, a2);    \
                                                                         \
    return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \
    }
@@ -435,7 +435,7 @@
 #define OCTAVE_SM_CONV(TS, TM)                                          \
   DEFCONV (TS ## s_ ## TM ## m_conv, TM ## scalar, TM ## matrix)        \
   {                                                                     \
-    const octave_ ## TS ## scalar& v = dynamic_cast<const octave_ ## TS ## scalar&> (a); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v, a);      \
                                                                         \
     return new octave_ ## TM ## matrix (v.TM ## array_value ());        \
   }
@@ -470,8 +470,8 @@
                                                                         \
   DEFBINOP (PFX ## _div, TM ## matrix, TS ## scalar)                    \
   {                                                                     \
-    const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); \
-    const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
   }                                                                     \
@@ -480,8 +480,8 @@
                                                                         \
   /* DEFBINOP (PFX ## _ldiv, TM ## matrix, TS ## scalar) */             \
   /* { */                                                               \
-  /* const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); */ \
-  /* const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); */ \
+  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1); */ \
+  /* OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2); */ \
   /* */                                                                 \
   /* Matrix m1 = v1.TM ## matrix_value (); */                           \
   /* Matrix m2 = v2.TM ## matrix_value (); */                           \
@@ -493,8 +493,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_div, TM ## matrix, TS ## scalar)                 \
   {                                                                     \
-    const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); \
-    const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \
                                                                         \
     return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \
   }                                                                     \
@@ -503,8 +503,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_ldiv, TM ## matrix, TS ## scalar)                \
   {                                                                     \
-    const octave_ ## TM ## matrix& v1 = dynamic_cast<const octave_ ## TM ## matrix&> (a1); \
-    const octave_ ## TS ## scalar& v2 = dynamic_cast<const octave_ ## TS ## scalar&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TM ## matrix&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TS ## scalar&, v2, a2);    \
                                                                         \
     octave_value retval = v2.TS ## scalar_value () / v1.TM ## array_value (); \
     return retval;                                                      \
@@ -623,14 +623,14 @@
   DEFNDUNOP_OP (m_uplus, TYPE ## _matrix, TYPE ## _array, /* no-op */)  \
   DEFUNOP (m_uminus, TYPE ## _matrix)                                   \
   {                                                                     \
-    const octave_ ## TYPE ## _matrix & v = dynamic_cast<const octave_ ## TYPE ## _matrix &> (a); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _matrix&, v, a);   \
     octave_value retval = octave_value (- v. TYPE ## _array_value ());  \
     return retval;                                                      \
   }                                                                     \
                                                                         \
   DEFUNOP (m_transpose, TYPE ## _matrix)                                \
   {                                                                     \
-    const octave_ ## TYPE ## _matrix& v = dynamic_cast<const octave_ ## TYPE ## _matrix&> (a); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## TYPE ## _matrix&, v, a);   \
                                                                         \
     if (v.ndims () > 2)                                                 \
       error ("transpose not defined for N-D objects");                  \
@@ -666,8 +666,8 @@
                                                                         \
   DEFBINOP (PFX ## _el_ldiv, T1 ## matrix, T2 ## matrix)                \
   {                                                                     \
-    const octave_ ## T1 ## matrix& v1 = dynamic_cast<const octave_ ## T1 ## matrix&> (a1); \
-    const octave_ ## T2 ## matrix& v2 = dynamic_cast<const octave_ ## T2 ## matrix&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## matrix&, v1, a1);    \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T2 ## matrix&, v2, a2);    \
                                                                         \
     octave_value retval = octave_value (quotient (v2.T2 ## array_value (), v1.T1 ## array_value ())); \
     return retval;                                                      \
@@ -807,7 +807,7 @@
 #define OCTAVE_MM_CONV(T1, T2)                                          \
   DEFCONV (T1 ## m_ ## T2 ## m_conv, T1 ## matrix, T2 ## matrix)        \
   {                                                                     \
-    const octave_ ## T1 ## matrix& v = dynamic_cast<const octave_ ## T1 ## matrix&> (a); \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## T1 ## matrix&, v, a);      \
                                                                         \
     return new octave_ ## T2 ## matrix (v.T2 ## array_value ());        \
   }
--- a/libinterp/operators/op-m-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -55,9 +55,8 @@
 
 DEFBINOP (trans_mul, matrix, complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   Matrix m1 = v1.matrix_value ();
   ComplexMatrix m2 = v2.complex_matrix_value ();
@@ -68,9 +67,8 @@
 
 DEFBINOP (div, matrix, complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.matrix_value (),
@@ -87,9 +85,8 @@
 
 DEFBINOP (ldiv, matrix, complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.matrix_value (),
@@ -101,9 +98,8 @@
 
 DEFBINOP (trans_ldiv, matrix, complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.matrix_value (),
@@ -126,9 +122,8 @@
 
 DEFBINOP (el_ldiv, matrix, complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return quotient (v2.complex_array_value (), v1.array_value ());
 }
@@ -140,7 +135,7 @@
 
 DEFCONV (complex_matrix_conv, matrix, complex_matrix)
 {
-  const octave_matrix& v = dynamic_cast<const octave_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);
 
   return new octave_complex_matrix (ComplexNDArray (v.array_value ()));
 }
--- a/libinterp/operators/op-m-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,8 +54,8 @@
 
 DEFBINOP (div, matrix, complex)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.array_value () / v2.complex_value ());
 }
@@ -64,8 +64,8 @@
 
 DEFBINOP (ldiv, matrix, complex)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   Matrix m1 = v1.matrix_value ();
   ComplexMatrix m2 = v2.complex_matrix_value ();
@@ -88,8 +88,8 @@
 
 DEFBINOP (el_div, matrix, complex)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.array_value () / v2.complex_value ());
 }
@@ -98,8 +98,8 @@
 
 DEFBINOP (el_ldiv, matrix, complex)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return elem_xdiv (v2.complex_value (), v1.array_value ());
 }
--- a/libinterp/operators/op-m-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 
 DEFUNOP (transpose, matrix)
 {
-  const octave_matrix& v = dynamic_cast<const octave_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -69,8 +69,8 @@
 
 DEFBINOP (div, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   Matrix ret = xdiv (v1.matrix_value (), v2.matrix_value (), typ);
@@ -86,8 +86,8 @@
 
 DEFBINOP (ldiv, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (), typ);
@@ -98,24 +98,24 @@
 
 DEFBINOP (trans_mul, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   return octave_value(xgemm (v1.matrix_value (), v2.matrix_value (),
                              blas_trans, blas_no_trans));
 }
 
 DEFBINOP (mul_trans, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   return octave_value(xgemm (v1.matrix_value (), v2.matrix_value (),
                              blas_no_trans, blas_trans));
 }
 
 DEFBINOP (trans_ldiv, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (),
@@ -138,8 +138,8 @@
 
 DEFBINOP (el_ldiv, matrix, matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (quotient (v2.array_value (), v1.array_value ()));
 }
--- a/libinterp/operators/op-m-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,8 @@
 
 DEFBINOP (div, matrix, scalar)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.array_value () / v2.double_value ());
 }
@@ -58,8 +58,8 @@
 
 DEFBINOP (ldiv, matrix, scalar)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   Matrix m1 = v1.matrix_value ();
   Matrix m2 = v2.matrix_value ();
@@ -82,8 +82,8 @@
 
 DEFBINOP (el_div, matrix, scalar)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.array_value () / v2.double_value ());
 }
@@ -92,8 +92,8 @@
 
 DEFBINOP (el_ldiv, matrix, scalar)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return elem_xdiv (v2.double_value (), v1.array_value ());
 }
--- a/libinterp/operators/op-m-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,9 +52,8 @@
 
 DEFBINOP (div, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.array_value () / v2.complex_value ());
@@ -77,9 +76,8 @@
 
 DEFBINOP (ldiv, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   ComplexMatrix ret = xleftdiv (v1.matrix_value (),
@@ -101,9 +99,8 @@
 
 DEFBINOP (el_pow, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (SparseMatrix (v1.matrix_value ()),
@@ -112,9 +109,8 @@
 
 DEFBINOP (el_ldiv, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   return octave_value
          (quotient (v2.sparse_complex_matrix_value (), v1.matrix_value ()));
 }
@@ -124,9 +120,8 @@
 
 DEFCATOP (m_scm, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   SparseMatrix tmp (v1.matrix_value ());
   return octave_value (tmp. concat (v2.sparse_complex_matrix_value (),
                                     ra_idx));
@@ -134,7 +129,7 @@
 
 DEFCONV (sparse_complex_matrix_conv, matrix, sparse_complex_matrix)
 {
-  const octave_matrix& v = dynamic_cast<const octave_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);
   return new octave_sparse_complex_matrix
          (SparseComplexMatrix (v.complex_matrix_value ()));
 }
--- a/libinterp/operators/op-m-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-m-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -51,8 +51,8 @@
 
 DEFBINOP (div, matrix, sparse_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.array_value () / v2.scalar_value ());
@@ -74,8 +74,8 @@
 
 DEFBINOP (ldiv, matrix, sparse_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   MatrixType typ = v1.matrix_type ();
 
   Matrix ret = xleftdiv (v1.matrix_value (), v2.matrix_value (), typ);
@@ -98,8 +98,8 @@
 
 DEFBINOP (el_pow, matrix, sparse_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (elem_xpow (SparseMatrix (v1.matrix_value ()),
                                   v2.sparse_matrix_value ()));
@@ -107,8 +107,8 @@
 
 DEFBINOP (el_ldiv, matrix, sparse_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value
          (quotient (v2.sparse_matrix_value (), v1.matrix_value ()));
@@ -119,15 +119,15 @@
 
 DEFCATOP (m_sm, matrix, sparse_matrix)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseMatrix tmp (v1.matrix_value ());
   return octave_value (tmp. concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCONV (sparse_matrix_conv, matrix, sparse_matrix)
 {
-  const octave_matrix& v = dynamic_cast<const octave_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v, a);
   return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));
 }
 
--- a/libinterp/operators/op-mi.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-mi.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 static octave_value
 oct_unop_unsigned_uplus (const octave_base_value& a)
 {
-  const octave_magic_uint& v = dynamic_cast<const octave_magic_uint&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_magic_uint&, v, a);
   // no-op.
   // FIXME: but can we do this just by incrementing the reference count?
   return octave_value (v.clone ());
@@ -56,7 +56,7 @@
 static octave_value
 oct_unop_unsigned_uminus (const octave_base_value& a)
 {
-  const octave_magic_uint& v = dynamic_cast<const octave_magic_uint&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_magic_uint&, v, a);
 
   // We are storing a uint64 value, so some fakery is needed here.
   // Is there a better way?
@@ -96,7 +96,7 @@
 static octave_value
 oct_unop_signed_uplus (const octave_base_value& a)
 {
-  const octave_magic_int& v = dynamic_cast<const octave_magic_int&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_magic_int&, v, a);
   // no-op.
   // FIXME: but can we do this just by incrementing the reference count?
   return octave_value (v.clone ());
@@ -105,7 +105,7 @@
 static octave_value
 oct_unop_signed_uminus (const octave_base_value& a)
 {
-  const octave_magic_int& v = dynamic_cast<const octave_magic_int&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_magic_int&, v, a);
 
   // FIXME: Maybe there should also be octave_magic_int::as_TYPE_value
   // functions?
--- a/libinterp/operators/op-pm-pm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-pm-pm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 
 DEFUNOP (transpose, perm_matrix)
 {
-  const octave_perm_matrix& v = dynamic_cast<const octave_perm_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v, a);
   return octave_value (v.perm_matrix_value ().transpose ());
 }
 
@@ -49,31 +49,31 @@
 
 DEFBINOP (div, perm_matrix, perm_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   return (v1.perm_matrix_value () * v2.perm_matrix_value ().inverse ());
 }
 
 DEFBINOP (ldiv, perm_matrix, perm_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   return (v1.perm_matrix_value ().inverse () * v2.perm_matrix_value ());
 }
 
 DEFBINOP (pow, perm_matrix, scalar)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return xpow (v1.perm_matrix_value (), v2.scalar_value ());
 }
 
 CONVDECL (perm_matrix_to_matrix)
 {
-  const octave_perm_matrix& v = dynamic_cast<const octave_perm_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v, a);
 
   return new octave_matrix (v.matrix_value ());
 }
--- a/libinterp/operators/op-pm-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-pm-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,9 +42,8 @@
 
 DEFBINOP (mul_pm_scm, perm_matrix, sparse_complex_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     {
@@ -60,9 +59,8 @@
 
 DEFBINOP (ldiv_pm_scm, perm_matrix, sparse_complex_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return v1.perm_matrix_value ().inverse () * v2.sparse_complex_matrix_value ();
 }
@@ -71,9 +69,8 @@
 
 DEFBINOP (mul_scm_pm, sparse_complex_matrix, perm_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     {
@@ -89,9 +86,8 @@
 
 DEFBINOP (div_scm_pm, sparse_complex_matrix, perm_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   return v1.sparse_complex_matrix_value () * v2.perm_matrix_value ().inverse ();
 }
--- a/libinterp/operators/op-pm-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-pm-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,8 +42,8 @@
 
 DEFBINOP (mul_pm_sm, perm_matrix, sparse_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     {
@@ -59,8 +59,8 @@
 
 DEFBINOP (ldiv_pm_sm, perm_matrix, sparse_matrix)
 {
-  const octave_perm_matrix& v1 = dynamic_cast<const octave_perm_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return v1.perm_matrix_value ().inverse () * v2.sparse_matrix_value ();
 }
@@ -69,8 +69,8 @@
 
 DEFBINOP (mul_sm_pm, sparse_matrix, perm_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     {
@@ -86,8 +86,8 @@
 
 DEFBINOP (div_sm_pm, sparse_matrix, perm_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_perm_matrix& v2 = dynamic_cast<const octave_perm_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_perm_matrix&, v2, a2);
 
   return v1.sparse_matrix_value () * v2.perm_matrix_value ().inverse ();
 }
--- a/libinterp/operators/op-pm-template.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-pm-template.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,8 +57,8 @@
 
 DEFBINOP (mul, LMATRIX, RMATRIX)
 {
-  const OCTAVE_LMATRIX& v1 = dynamic_cast<const OCTAVE_LMATRIX&> (a1);
-  const OCTAVE_RMATRIX& v2 = dynamic_cast<const OCTAVE_RMATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);
 
   return v1.LMATRIX_VALUE () * v2.RMATRIX_VALUE ();
 }
@@ -66,16 +66,16 @@
 #if defined (LEFT)
 DEFBINOP (ldiv, LMATRIX, RMATRIX)
 {
-  const OCTAVE_LMATRIX& v1 = dynamic_cast<const OCTAVE_LMATRIX&> (a1);
-  const OCTAVE_RMATRIX& v2 = dynamic_cast<const OCTAVE_RMATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);
 
   return v1.perm_matrix_value ().inverse () * v2.RMATRIX_VALUE ();
 }
 #else
 DEFBINOP (div, LMATRIX, RMATRIX)
 {
-  const OCTAVE_LMATRIX& v1 = dynamic_cast<const OCTAVE_LMATRIX&> (a1);
-  const OCTAVE_RMATRIX& v2 = dynamic_cast<const OCTAVE_RMATRIX&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_LMATRIX&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const OCTAVE_RMATRIX&, v2, a2);
 
   return v1.LMATRIX_VALUE () * v2.perm_matrix_value ().inverse ();
 }
--- a/libinterp/operators/op-range.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-range.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 
 CONVDECL (range_to_matrix)
 {
-  const octave_range& v = dynamic_cast<const octave_range&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_range&, v, a);
 
   return new octave_matrix (v.array_value ());
 }
--- a/libinterp/operators/op-s-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,9 +54,8 @@
 
 DEFBINOP (div, scalar, complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   Matrix m1 = v1.matrix_value ();
   ComplexMatrix m2 = v2.complex_matrix_value ();
@@ -72,9 +71,8 @@
 
 DEFBINOP (ldiv, scalar, complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (v2.complex_array_value () / v1.double_value ());
 }
@@ -92,9 +90,8 @@
 
 DEFBINOP (el_ldiv, scalar, complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (v2.complex_array_value () / v1.double_value ());
 }
@@ -106,7 +103,7 @@
 
 DEFCONV (complex_matrix_conv, scalar, complex_matrix)
 {
-  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);
 
   return new octave_complex_matrix (ComplexMatrix (v.matrix_value ()));
 }
--- a/libinterp/operators/op-s-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,8 +49,8 @@
 
 DEFBINOP (div, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.double_value () / v2.complex_value ());
 }
@@ -59,8 +59,8 @@
 
 DEFBINOP (ldiv, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v2.complex_value () / v1.double_value ());
 }
@@ -76,8 +76,8 @@
 
 DEFBINOP (el_div, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.double_value () / v2.complex_value ());
 }
@@ -86,24 +86,24 @@
 
 DEFBINOP (el_ldiv, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v2.complex_value () / v1.double_value ());
 }
 
 DEFBINOP (el_and, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.double_value () && (v2.complex_value () != 0.0));
 }
 
 DEFBINOP (el_or, scalar, complex)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.double_value () || (v2.complex_value () != 0.0));
 }
--- a/libinterp/operators/op-s-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,8 @@
 
 DEFBINOP (div, scalar, matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   Matrix m1 = v1.matrix_value ();
   Matrix m2 = v2.matrix_value ();
@@ -65,8 +65,8 @@
 
 DEFBINOP (ldiv, scalar, matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (v2.array_value () / v1.double_value ());
 }
@@ -84,8 +84,8 @@
 
 DEFBINOP (el_ldiv, scalar, matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (v2.array_value () / v1.double_value ());
 }
@@ -97,7 +97,7 @@
 
 DEFCONV (matrix_conv, scalar, matrix)
 {
-  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);
 
   return new octave_matrix (v.matrix_value ());
 }
--- a/libinterp/operators/op-s-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 
 DEFUNOP (not, scalar)
 {
-  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);
   double x = v.scalar_value ();
   if (octave::math::isnan (x))
     octave::err_nan_to_logical_conversion ();
@@ -71,8 +71,8 @@
 
 DEFBINOP (div, scalar, scalar)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.double_value () / v2.double_value ());
 }
@@ -81,8 +81,8 @@
 
 DEFBINOP (ldiv, scalar, scalar)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v2.double_value () / v1.double_value ());
 }
@@ -98,8 +98,8 @@
 
 DEFBINOP (el_div, scalar, scalar)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.double_value () / v2.double_value ());
 }
@@ -108,8 +108,8 @@
 
 DEFBINOP (el_ldiv, scalar, scalar)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v2.double_value () / v1.double_value ());
 }
--- a/libinterp/operators/op-s-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,9 +52,8 @@
 
 DEFBINOP (div, scalar, sparse_complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v1.scalar_value ()
@@ -72,17 +71,15 @@
 
 DEFBINOP (pow, scalar, sparse_complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   return xpow (v1.scalar_value (), v2.complex_matrix_value ());
 }
 
 DEFBINOP (ldiv, scalar, sparse_complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());
 }
@@ -100,9 +97,8 @@
 
 DEFBINOP (el_ldiv, scalar, sparse_complex_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (v2.sparse_complex_matrix_value () / v1.double_value ());
 }
@@ -112,9 +108,8 @@
 
 DEFCATOP (s_scm, scalar, sparse_compelx_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
   SparseMatrix tmp (1, 1, v1.scalar_value ());
   return octave_value
          (tmp.concat (v2.sparse_complex_matrix_value (), ra_idx));
@@ -122,7 +117,7 @@
 
 DEFCONV (sparse_complex_matrix_conv, scalar, sparse_complex_matrix)
 {
-  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);
 
   return new octave_sparse_complex_matrix
          (SparseComplexMatrix (v.complex_matrix_value ()));
--- a/libinterp/operators/op-s-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-s-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,8 +48,8 @@
 
 DEFBINOP (div, scalar, sparse_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (SparseMatrix (1, 1, v1.scalar_value () / v2.scalar_value ()));
@@ -66,15 +66,15 @@
 
 DEFBINOP (pow, scalar, sparse_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   return xpow (v1.scalar_value (), v2.matrix_value ());
 }
 
 DEFBINOP (ldiv, scalar, sparse_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (v2.sparse_matrix_value () / v1.double_value ());
 }
@@ -92,8 +92,8 @@
 
 DEFBINOP (el_ldiv, scalar, sparse_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (v2.sparse_matrix_value () / v1.double_value ());
 }
@@ -103,15 +103,15 @@
 
 DEFCATOP (s_sm, scalar, sparse_matrix)
 {
-  const octave_scalar& v1 = dynamic_cast<const octave_scalar&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseMatrix tmp (1, 1, v1.scalar_value ());
   return octave_value (tmp.concat (v2.sparse_matrix_value (), ra_idx));
 }
 
 DEFCONV (sparse_matrix_conv, scalar, sparse_matrix)
 {
-  const octave_scalar& v = dynamic_cast<const octave_scalar&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v, a);
 
   return new octave_sparse_matrix (SparseMatrix (v.matrix_value ()));
 }
--- a/libinterp/operators/op-sbm-b.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sbm-b.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -58,8 +58,8 @@
 
 DEFCATOP (sbm_b, sparse_bool_matrix, bool)
 {
-  const octave_sparse_bool_matrix& v1 = dynamic_cast<const octave_sparse_bool_matrix&> (a1);
-  const octave_bool& v2 = dynamic_cast<const octave_bool&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);
 
   SparseBoolMatrix tmp (1, 1, v2.bool_value ());
   return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx));
@@ -67,8 +67,8 @@
 
 DEFCATOP (sm_b, sparse_matrix, bool)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_bool& v2 = dynamic_cast<const octave_bool&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);
 
   SparseMatrix tmp (1, 1, v2.scalar_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
@@ -76,8 +76,8 @@
 
 DEFCATOP (sbm_s, sparse_bool_matrix, scalar)
 {
-  const octave_sparse_bool_matrix& v1 = dynamic_cast<const octave_sparse_bool_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   SparseMatrix tmp (1, 1, v2.scalar_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
@@ -85,8 +85,8 @@
 
 DEFASSIGNOP (assign, sparse_bool_matrix, bool)
 {
-  octave_sparse_bool_matrix& v1 = dynamic_cast<octave_sparse_bool_matrix&> (a1);
-  const octave_bool& v2 = dynamic_cast<const octave_bool&> (a2);
+  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool&, v2, a2);
 
   SparseBoolMatrix tmp (1, 1, v2.bool_value ());
   v1.assign (idx, tmp);
@@ -98,7 +98,7 @@
                               const octave_value_list& idx,
                               const octave_base_value& a2)
 {
-  octave_sparse_bool_matrix& v1 = dynamic_cast<octave_sparse_bool_matrix&> (a1);
+  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);
 
   // FIXME: perhaps add a warning for this conversion if the values
   // are not all 0 or 1?
--- a/libinterp/operators/op-sbm-bm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sbm-bm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -63,8 +63,8 @@
 
 DEFCATOP (sbm_bm, sparse_bool_matrix, bool_matrix)
 {
-  const octave_sparse_bool_matrix& v1 = dynamic_cast<const octave_sparse_bool_matrix&> (a1);
-  const octave_bool_matrix& v2 = dynamic_cast<const octave_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);
 
   SparseBoolMatrix tmp (v2.bool_matrix_value ());
   return octave_value (v1.sparse_bool_matrix_value (). concat (tmp, ra_idx));
@@ -72,8 +72,8 @@
 
 DEFCATOP (sbm_m, sparse_bool_matrix, matrix)
 {
-  const octave_sparse_bool_matrix& v1 = dynamic_cast<const octave_sparse_bool_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   SparseMatrix tmp (v2.matrix_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
@@ -81,8 +81,8 @@
 
 DEFCATOP (sm_bm, sparse_matrix, bool_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_bool_matrix& v2 = dynamic_cast<const octave_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);
 
   SparseMatrix tmp (v2.matrix_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
@@ -90,8 +90,8 @@
 
 DEFASSIGNOP (assign, sparse_bool_matrix, bool_matrix)
 {
-  octave_sparse_bool_matrix& v1 = dynamic_cast<octave_sparse_bool_matrix&> (a1);
-  const octave_bool_matrix& v2 = dynamic_cast<const octave_bool_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_bool_matrix&, v2, a2);
 
   v1.assign (idx, SparseBoolMatrix (v2.bool_matrix_value ()));
   return octave_value ();
@@ -104,7 +104,7 @@
                               const octave_value_list& idx,
                               const octave_base_value& a2)
 {
-  octave_sparse_bool_matrix& v1 = dynamic_cast<octave_sparse_bool_matrix&> (a1);
+  OCTAVE_CAST_BASE_VALUE (octave_sparse_bool_matrix&, v1, a1);
 
   // FIXME: perhaps add a warning for this conversion if the values
   // are not all 0 or 1?
--- a/libinterp/operators/op-sbm-sbm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sbm-sbm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,22 +46,19 @@
 
 DEFUNOP (uplus, sparse_bool_matrix)
 {
-  const octave_sparse_bool_matrix& v
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);
   return octave_value (v.sparse_matrix_value ());
 }
 
 DEFUNOP (uminus, sparse_bool_matrix)
 {
-  const octave_sparse_bool_matrix& v
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);
   return octave_value (- v.sparse_matrix_value ());
 }
 
 DEFUNOP (transpose, sparse_bool_matrix)
 {
-  const octave_sparse_bool_matrix& v
-    = dynamic_cast<const octave_sparse_bool_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_bool_matrix&, v, a);
   return octave_value (v.sparse_bool_matrix_value ().transpose ());
 }
 
--- a/libinterp/operators/op-scm-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,10 +52,8 @@
 
 DEFBINOP (div, sparse_complex_matrix, complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.complex_matrix_value (),
@@ -72,10 +70,8 @@
 
 DEFBINOP (ldiv, sparse_complex_matrix, complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.complex_array_value () / v1.complex_value ());
@@ -106,10 +102,8 @@
 
 DEFBINOP (el_pow, sparse_complex_matrix, complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (v1.sparse_complex_matrix_value (), SparseComplexMatrix
@@ -118,10 +112,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.complex_matrix_value (),
                                  v1.sparse_complex_matrix_value ()));
@@ -132,10 +124,8 @@
 
 DEFCATOP (scm_cm, sparse_complex_matrix, complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   SparseComplexMatrix tmp (v2.complex_matrix_value ());
   return octave_value
          (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));
--- a/libinterp/operators/op-scm-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,26 +50,23 @@
 
 DEFBINOP (div, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP (pow, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
   return xpow (v1.complex_matrix_value (), v2.complex_value ());
 }
 
 DEFBINOP (ldiv, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()
@@ -96,9 +93,8 @@
 
 DEFBINOP (el_div, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
 }
@@ -107,9 +103,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value
          (elem_xdiv (v2.complex_value (), v1.sparse_complex_matrix_value ()));
@@ -120,9 +115,8 @@
 
 DEFCATOP (scm_cs, sparse_complex_matrix, complex)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
   SparseComplexMatrix tmp (1, 1, v2.complex_value ());
   return octave_value
          (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));
--- a/libinterp/operators/op-scm-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,9 +53,8 @@
 
 DEFBINOP (div, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.complex_matrix_value (),
@@ -72,9 +71,8 @@
 
 DEFBINOP (ldiv, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.array_value () / v1.complex_value ());
@@ -102,9 +100,8 @@
 
 DEFBINOP (el_pow, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (v1.sparse_complex_matrix_value (), SparseMatrix
@@ -113,9 +110,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value
          (quotient (v2.matrix_value (), v1.sparse_complex_matrix_value ()));
@@ -126,9 +122,8 @@
 
 DEFCATOP (scm_m, sparse_complex_matrix, matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   SparseMatrix tmp (v2.matrix_value ());
   return octave_value
          (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));
--- a/libinterp/operators/op-scm-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,18 +53,16 @@
 
 DEFBINOP (div, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP (pow, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   double tmp = v2.scalar_value ();
   if (static_cast<int> (tmp) == tmp)
@@ -75,9 +73,8 @@
 
 DEFBINOP (ldiv, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v2.scalar_value ()
@@ -104,9 +101,8 @@
 
 DEFBINOP (el_div, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.sparse_complex_matrix_value () / v2.double_value ());
 }
@@ -115,9 +111,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value
          (elem_xdiv (v2.double_value (), v1.sparse_complex_matrix_value ()));
@@ -128,9 +123,8 @@
 
 DEFCATOP (scm_s, sparse_complex_matrix, scalar)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
   SparseComplexMatrix tmp (1, 1, v2.complex_value ());
   return octave_value
          (v1.sparse_complex_matrix_value ().concat (tmp, ra_idx));
--- a/libinterp/operators/op-scm-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,8 +52,7 @@
 
 DEFUNOP (transpose, sparse_complex_matrix)
 {
-  const octave_sparse_complex_matrix& v
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v, a);
   return octave_value
          (v.sparse_complex_matrix_value ().transpose (),
           v.matrix_type ().transpose ());
@@ -61,8 +60,7 @@
 
 DEFUNOP (hermitian, sparse_complex_matrix)
 {
-  const octave_sparse_complex_matrix& v
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v, a);
   return octave_value
          (v.sparse_complex_matrix_value ().hermitian (),
           v.matrix_type ().transpose ());
@@ -77,10 +75,8 @@
 
 DEFBINOP (div, sparse_complex_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_complex_matrix_value () / v2.complex_value ());
@@ -102,10 +98,8 @@
 
 DEFBINOP (ldiv, sparse_complex_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.sparse_complex_matrix_value () / v1.complex_value ());
@@ -135,10 +129,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.sparse_complex_matrix_value (),
                                  v1.sparse_complex_matrix_value ()));
--- a/libinterp/operators/op-scm-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-scm-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,10 +50,8 @@
 
 DEFBINOP (div, sparse_complex_matrix, sparse_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_complex_matrix_value () / v2.scalar_value ());
@@ -75,10 +73,8 @@
 
 DEFBINOP (ldiv, sparse_complex_matrix, sparse_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.sparse_matrix_value () / v1.complex_value ());
@@ -107,10 +103,8 @@
 
 DEFBINOP (el_ldiv, sparse_complex_matrix, sparse_matrix)
 {
-  const octave_sparse_complex_matrix& v1
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   return octave_value (quotient (v2.sparse_matrix_value (),
                                  v1.sparse_complex_matrix_value ()));
--- a/libinterp/operators/op-sm-cm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-cm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,10 +52,8 @@
 
 DEFBINOP (div, sparse_matrix, complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   ComplexMatrix ret = xdiv (v1.matrix_value (),
@@ -72,10 +70,8 @@
 
 DEFBINOP (ldiv, sparse_matrix, complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.complex_array_value () / v1.scalar_value ());
@@ -103,10 +99,8 @@
 
 DEFBINOP (el_pow, sparse_matrix, complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value
          (elem_xpow (v1.sparse_matrix_value (), SparseComplexMatrix
@@ -115,10 +109,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
 
   return octave_value
          (quotient (v2.complex_matrix_value (), v1.sparse_matrix_value ()));
@@ -129,17 +121,15 @@
 
 DEFCATOP (sm_cm, sparse_matrix, complex_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex_matrix& v2
-    = dynamic_cast<const octave_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex_matrix&, v2, a2);
   SparseComplexMatrix tmp (v2.complex_matrix_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
 }
 
 DEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_matrix& v
-    = dynamic_cast<const octave_sparse_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);
   return new octave_complex_matrix (v.complex_matrix_value ());
 }
 
--- a/libinterp/operators/op-sm-cs.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-cs.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,23 +52,23 @@
 
 DEFBINOP (div, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
 }
 
 DEFBINOP (pow, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
   return xpow (v1.matrix_value (), v2.complex_value ());
 }
 
 DEFBINOP (ldiv, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (SparseComplexMatrix (1, 1, v2.complex_value ()
@@ -95,8 +95,8 @@
 
 DEFBINOP (el_div, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
 }
@@ -105,8 +105,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
 
   return octave_value (elem_xdiv (v2.complex_value (),
                                   v1.sparse_matrix_value ()));
@@ -117,8 +117,8 @@
 
 DEFCATOP (sm_cs, sparse_matrix, complex)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_complex& v2 = dynamic_cast<const octave_complex&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_complex&, v2, a2);
   SparseComplexMatrix tmp (1, 1, v2.complex_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
 }
--- a/libinterp/operators/op-sm-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,8 +52,8 @@
 
 DEFBINOP (div, sparse_matrix, matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   MatrixType typ = v2.matrix_type ();
 
   Matrix ret = xdiv (v1.matrix_value (), v2.matrix_value (), typ);
@@ -69,8 +69,8 @@
 
 DEFBINOP (ldiv, sparse_matrix, matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.array_value () / v1.scalar_value ());
@@ -100,8 +100,8 @@
 
 DEFBINOP (el_pow, sparse_matrix, matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value (elem_xpow (v1.sparse_matrix_value (),
                                   SparseMatrix (v2.matrix_value ())));
@@ -109,8 +109,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   return octave_value
          (quotient (v2.matrix_value (), v1.sparse_matrix_value ()));
@@ -121,8 +121,8 @@
 
 DEFCATOP (sm_m, sparse_matrix, matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
   SparseMatrix tmp (v2.matrix_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
 }
--- a/libinterp/operators/op-sm-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -49,16 +49,16 @@
 
 DEFBINOP (div, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.sparse_matrix_value () / v2.double_value ());
 }
 
 DEFBINOP (pow, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   double tmp = v2.scalar_value ();
   if (static_cast<int> (tmp) == tmp)
@@ -69,8 +69,8 @@
 
 DEFBINOP (ldiv, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (SparseMatrix(1, 1, v2.scalar_value () / v1.scalar_value ()));
@@ -96,8 +96,8 @@
 
 DEFBINOP (el_div, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value (v1.sparse_matrix_value () / v2.double_value ());
 }
@@ -106,8 +106,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   return octave_value
          (elem_xdiv (v2.complex_value (), v1.sparse_matrix_value ()));
@@ -118,8 +118,8 @@
 
 DEFCATOP (sm_s, sparse_matrix, scalar)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
   SparseMatrix tmp (1, 1, v2.scalar_value ());
   return octave_value (v1.sparse_matrix_value (). concat (tmp, ra_idx));
 }
--- a/libinterp/operators/op-sm-scm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-scm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,10 +50,8 @@
 
 DEFBINOP (div, sparse_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_matrix_value () / v2.complex_value ());
@@ -75,10 +73,8 @@
 
 DEFBINOP (ldiv, sparse_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.sparse_complex_matrix_value () / v1.scalar_value ());
@@ -108,10 +104,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_complex_matrix& v2
-    = dynamic_cast<const octave_sparse_complex_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_complex_matrix&, v2, a2);
 
   return octave_value (quotient (v2.sparse_complex_matrix_value (),
                                  v1.sparse_matrix_value ()));
@@ -124,8 +118,7 @@
 
 DEFCONV (sparse_complex_matrix_conv, sparse_matrix, sparse_complex_matrix)
 {
-  const octave_sparse_matrix& v
-    = dynamic_cast<const octave_sparse_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);
   return new octave_sparse_complex_matrix (v.sparse_complex_matrix_value ());
 }
 
--- a/libinterp/operators/op-sm-sm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-sm-sm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 
 DEFUNOP (transpose, sparse_matrix)
 {
-  const octave_sparse_matrix& v = dynamic_cast<const octave_sparse_matrix&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v, a);
   return octave_value (v.sparse_matrix_value ().transpose (),
                        v.matrix_type ().transpose ());
 }
@@ -62,10 +62,8 @@
 static octave_value
 oct_binop_sub (const octave_base_value& a1, const octave_base_value& a2)
 {
-  const octave_sparse_matrix& v1
-    = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_matrix& v2
-    = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   SparseMatrix m = v1.sparse_matrix_value () - v2.sparse_matrix_value ();
 
   return octave_value (m);
@@ -75,8 +73,8 @@
 
 DEFBINOP (div, sparse_matrix, sparse_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v2.rows () == 1 && v2.columns () == 1)
     return octave_value (v1.sparse_matrix_value () / v2.scalar_value ());
@@ -98,8 +96,8 @@
 
 DEFBINOP (ldiv, sparse_matrix, sparse_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
 
   if (v1.rows () == 1 && v1.columns () == 1)
     return octave_value (v2.sparse_matrix_value () / v1.double_value ());
@@ -129,8 +127,8 @@
 
 DEFBINOP (el_ldiv, sparse_matrix, sparse_matrix)
 {
-  const octave_sparse_matrix& v1 = dynamic_cast<const octave_sparse_matrix&> (a1);
-  const octave_sparse_matrix& v2 = dynamic_cast<const octave_sparse_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_sparse_matrix&, v2, a2);
   return octave_value
          (quotient (v2.sparse_matrix_value (), v1.sparse_matrix_value ()));
 }
--- a/libinterp/operators/op-str-m.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-str-m.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,8 +39,8 @@
 
 DEFASSIGNOP (assign, char_matrix_str, octave_matrix)
 {
-  octave_char_matrix_str& v1 = dynamic_cast<octave_char_matrix_str&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   octave_value tmp
     = v2.convert_to_str_internal (false, false,
--- a/libinterp/operators/op-str-s.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-str-s.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,8 +39,8 @@
 
 DEFASSIGNOP (assign, char_matrix_str, octave_scalar)
 {
-  octave_char_matrix_str& v1 = dynamic_cast<octave_char_matrix_str&> (a1);
-  const octave_scalar& v2 = dynamic_cast<const octave_scalar&> (a2);
+  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar&, v2, a2);
 
   octave_value tmp
     = v2.convert_to_str_internal (false, false,
--- a/libinterp/operators/op-str-str.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-str-str.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,8 +41,7 @@
 
 DEFUNOP (transpose, char_matrix_str)
 {
-  const octave_char_matrix_str& v
-    = dynamic_cast<const octave_char_matrix_str&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix_str&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -64,8 +63,8 @@
     bool a1_is_scalar = a1_dims.all_ones ();                            \
     bool a2_is_scalar = a2_dims.all_ones ();                            \
                                                                         \
-    const octave_ ## t1& v1 = dynamic_cast<const octave_ ## t1&> (a1);  \
-    const octave_ ## t2& v2 = dynamic_cast<const octave_ ## t2&> (a2);  \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t1&, v1, a1);              \
+    OCTAVE_CAST_BASE_VALUE (const octave_ ## t2&, v2, a2);              \
                                                                         \
     if (a1_is_scalar)                                                   \
       {                                                                 \
@@ -102,9 +101,8 @@
 
 DEFASSIGNOP (assign, char_matrix_str, char_matrix_str)
 {
-  octave_char_matrix_str& v1 = dynamic_cast<octave_char_matrix_str&> (a1);
-  const octave_char_matrix_str& v2
-    = dynamic_cast<const octave_char_matrix_str&> (a2);
+  OCTAVE_CAST_BASE_VALUE (octave_char_matrix_str&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_char_matrix_str&, v2, a2);
 
   v1.assign (idx, v2.char_array_value ());
   return octave_value ();
--- a/libinterp/operators/op-struct.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/op-struct.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 
 DEFUNOP (transpose, struct)
 {
-  const octave_struct& v = dynamic_cast<const octave_struct&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v, a);
 
   if (v.ndims () > 2)
     error ("transpose not defined for N-D objects");
@@ -51,7 +51,7 @@
 
 DEFUNOP (scalar_transpose, scalar_struct)
 {
-  const octave_scalar_struct& v = dynamic_cast<const octave_scalar_struct&> (a);
+  OCTAVE_CAST_BASE_VALUE (const octave_scalar_struct&, v, a);
 
   return octave_value (v.scalar_map_value ());
 }
@@ -66,8 +66,8 @@
                          const octave_base_value& a2,
                          const Array<octave_idx_type>&)
 {
-  const octave_struct& v1 = dynamic_cast<const octave_struct&> (a1);
-  const octave_matrix& v2 = dynamic_cast<const octave_matrix&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   NDArray tmp = v2.array_value ();
   dim_vector dv = tmp.dims ();
@@ -83,8 +83,8 @@
                          const octave_base_value& a2,
                          const Array<octave_idx_type>&)
 {
-  const octave_matrix& v1 = dynamic_cast<const octave_matrix&> (a1);
-  const octave_struct& v2 = dynamic_cast<const octave_struct&> (a2);
+  OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v1, a1);
+  OCTAVE_CAST_BASE_VALUE (const octave_struct&, v2, a2);
 
   NDArray tmp = v1.array_value ();
   dim_vector dv = tmp.dims ();
--- a/libinterp/operators/ops.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/operators/ops.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,6 +37,21 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
+// NOTE: If OCTAVE_ENABLE_INTERNAL_CHECKS is defined, then
+// OCTAVE_DYNAMIC_CAST is only safe if you can ensure that the cast will
+// succeed.  Using static_cast disables the RTTI checks used by
+// dynamic_cast that ensure an unsuccesful cast will either throw an
+// error for reference types or or return nullptr for pointer types.
+
+#if defined (OCTAVE_ENABLE_INTERNAL_CHECKS)
+#  define OCTAVE_DYNAMIC_CAST dynamic_cast
+#else
+#  define OCTAVE_DYNAMIC_CAST static_cast
+#endif
+
+#define OCTAVE_CAST_BASE_VALUE(T, T_VAL, BASE_VAL)      \
+  T T_VAL = OCTAVE_DYNAMIC_CAST<T> (BASE_VAL)
+
 // Concatenation macros that enforce argument prescan
 #define CONCAT2X(x, y) x ## y
 #define CONCAT2(x, y) CONCAT2X (x, y)
@@ -90,23 +105,23 @@
                                  const octave_value_list& idx,          \
                                  const octave_base_value& a2)           \
   {                                                                     \
-    CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     v1.f (idx, v2.CONCAT2 (t1, _value) ());                             \
     return octave_value ();                                             \
   }
 
-#define DEFNULLASSIGNOP_FN(name, t, f)                                  \
-  static octave_value                                                   \
-  CONCAT2 (oct_assignop_, name) (octave_base_value& a,                  \
-                                 const octave_value_list& idx,          \
-                                 const octave_base_value&)              \
-  {                                                                     \
-    CONCAT2 (octave_, t)& v = dynamic_cast<CONCAT2 (octave_, t)&> (a);  \
-                                                                        \
-    v.f (idx);                                                          \
-    return octave_value ();                                             \
+#define DEFNULLASSIGNOP_FN(name, t, f)                          \
+  static octave_value                                           \
+  CONCAT2 (oct_assignop_, name) (octave_base_value& a,          \
+                                 const octave_value_list& idx,  \
+                                 const octave_base_value&)      \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a);       \
+                                                                \
+    v.f (idx);                                                  \
+    return octave_value ();                                     \
   }
 
 #define DEFNDASSIGNOP_FN(name, t1, t2, e, f)                            \
@@ -115,8 +130,8 @@
                                  const octave_value_list& idx,          \
                                  const octave_base_value& a2)           \
   {                                                                     \
-    CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     v1.f (idx, v2.CONCAT2 (e, _value) ());                              \
     return octave_value ();                                             \
@@ -129,8 +144,8 @@
                                  const octave_value_list& idx,          \
                                  const octave_base_value& a2)           \
   {                                                                     \
-    CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     error_unless (idx.empty ());                                        \
     v1.matrix_ref () op v2.CONCAT2 (f, _value) ();                      \
@@ -144,8 +159,8 @@
                                  const octave_value_list& idx,          \
                                  const octave_base_value& a2)           \
   {                                                                     \
-    CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     error_unless (idx.empty ());                                        \
     fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ());                 \
@@ -153,16 +168,16 @@
     return octave_value ();                                             \
   }
 
-#define DEFASSIGNANYOP_FN(name, t1, f)                                  \
-  static octave_value                                                   \
-  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                 \
-                                 const octave_value_list& idx,          \
-                                 const octave_value& a2)                \
-  {                                                                     \
-    CONCAT2 (octave_, t1)& v1 = dynamic_cast<CONCAT2 (octave_, t1)&> (a1); \
-                                                                        \
-    v1.f (idx, a2);                                                     \
-    return octave_value ();                                             \
+#define DEFASSIGNANYOP_FN(name, t1, f)                          \
+  static octave_value                                           \
+  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,         \
+                                 const octave_value_list& idx,  \
+                                 const octave_value& a2)        \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);    \
+                                                                \
+    v1.f (idx, a2);                                             \
+    return octave_value ();                                     \
   }
 
 #define CONVDECL(name)                                          \
@@ -180,46 +195,46 @@
   static octave_value                                           \
   CONCAT2 (oct_unop_, name) (const octave_base_value& a)
 
-#define DEFUNOP_OP(name, t, op)                                         \
-  static octave_value                                                   \
-  CONCAT2 (oct_unop_, name) (const octave_base_value& a)                \
-  {                                                                     \
-    const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
-    return octave_value (op v.CONCAT2 (t, _value) ());                  \
+#define DEFUNOP_OP(name, t, op)                                 \
+  static octave_value                                           \
+  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
+    return octave_value (op v.CONCAT2 (t, _value) ());          \
   }
 
-#define DEFNDUNOP_OP(name, t, e, op)                                    \
-  static octave_value                                                   \
-  CONCAT2 (oct_unop_, name) (const octave_base_value& a)                \
-  {                                                                     \
-    const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
-    return octave_value (op v.CONCAT2 (e, _value) ());                  \
+#define DEFNDUNOP_OP(name, t, e, op)                            \
+  static octave_value                                           \
+  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
+    return octave_value (op v.CONCAT2 (e, _value) ());          \
   }
 
 // FIXME: in some cases, the constructor isn't necessary.
 
-#define DEFUNOP_FN(name, t, f)                                          \
-  static octave_value                                                   \
-  CONCAT2 (oct_unop_, name) (const octave_base_value& a)                \
-  {                                                                     \
-    const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
-    return octave_value (f (v.CONCAT2 (t, _value) ()));                 \
+#define DEFUNOP_FN(name, t, f)                                  \
+  static octave_value                                           \
+  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
+    return octave_value (f (v.CONCAT2 (t, _value) ()));         \
   }
 
-#define DEFNDUNOP_FN(name, t, e, f)                                     \
-  static octave_value                                                   \
-  CONCAT2 (oct_unop_, name) (const octave_base_value& a)                \
-  {                                                                     \
-    const CONCAT2 (octave_, t)& v = dynamic_cast<const CONCAT2 (octave_, t)&> (a); \
-    return octave_value (f (v.CONCAT2 (e, _value) ()));                 \
+#define DEFNDUNOP_FN(name, t, e, f)                             \
+  static octave_value                                           \
+  CONCAT2 (oct_unop_, name) (const octave_base_value& a)        \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t)&, v, a); \
+    return octave_value (f (v.CONCAT2 (e, _value) ()));         \
   }
 
-#define DEFNCUNOP_METHOD(name, t, method)                               \
-  static void                                                           \
-  CONCAT2 (oct_unop_, name) (octave_base_value& a)                      \
-  {                                                                     \
-    CONCAT2 (octave_, t)& v = dynamic_cast<CONCAT2 (octave_, t)&> (a);  \
-    v.method ();                                                        \
+#define DEFNCUNOP_METHOD(name, t, method)                       \
+  static void                                                   \
+  CONCAT2 (oct_unop_, name) (octave_base_value& a)              \
+  {                                                             \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t)&, v, a);       \
+    v.method ();                                                \
   }
 
 #define DEFBINOPX(name, t1, t2)                         \
@@ -237,8 +252,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value                                                 \
       (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ());       \
@@ -249,8 +264,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     warn_complex_cmp ();                                                \
                                                                         \
@@ -263,11 +278,11 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     if (octave::math::isnan (v1.CONCAT2 (t1, _value) ()) || octave::math::isnan (v2.CONCAT2 (t2, _value) ())) \
-      octave::err_nan_to_logical_conversion ();                                 \
+      octave::err_nan_to_logical_conversion ();                         \
                                                                         \
     return octave_value                                                 \
       (v1.CONCAT2 (t1, _value) () op v2.CONCAT2 (t2, _value) ());       \
@@ -278,8 +293,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value                                                 \
       (v1.CONCAT2 (e1, _value) () op v2.CONCAT2 (e2, _value) ());       \
@@ -292,8 +307,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (f (v1.CONCAT2 (t1, _value) (), v2.CONCAT2 (t2, _value) ())); \
   }
@@ -303,8 +318,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
   }
@@ -314,8 +329,8 @@
   CONCAT2 (oct_binop_, name) (const octave_base_value& a1,              \
                               const octave_base_value& a2)              \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (f (v1.CONCAT2 (e1, _value) (), v2.CONCAT2 (e2, _value) ())); \
   }
@@ -340,8 +355,8 @@
                               const octave_base_value& a2,              \
                               const Array<octave_idx_type>& ra_idx)     \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (v1.CONCAT2 (t1, _value) () . f (v2.CONCAT2 (t2, _value) (), ra_idx)); \
   }
@@ -352,8 +367,8 @@
                               const octave_base_value& a2,              \
                               const Array<octave_idx_type>& ra_idx)     \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (v1.CONCAT2 (e1, _value) () . f (v2.CONCAT2 (e2, _value) (), ra_idx)); \
   }
@@ -364,8 +379,8 @@
                               const octave_base_value& a2,              \
                               const Array<octave_idx_type>& ra_idx)     \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
                          ((a1.is_sq_string () || a2.is_sq_string ())    \
@@ -381,8 +396,8 @@
                               const octave_base_value& a2,              \
                               const Array<octave_idx_type>& ra_idx)     \
   {                                                                     \
-    const CONCAT2 (octave_, t1)& v1 = dynamic_cast<const CONCAT2 (octave_, t1)&> (a1); \
-    const CONCAT2 (octave_, t2)& v2 = dynamic_cast<const CONCAT2 (octave_, t2)&> (a2); \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t1)&, v1, a1);      \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);      \
                                                                         \
     return octave_value (tc1 (v1.CONCAT2 (e1, _value) ()) . f (tc2 (v2.CONCAT2 (e2, _value) ()), ra_idx)); \
   }
--- a/libinterp/parse-tree/anon-fcn-validator.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/anon-fcn-validator.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,13 +45,9 @@
 
   anon_fcn_validator (tree_parameter_list *, tree_expression *expr);
 
-  // No copying!
-
-  anon_fcn_validator (const anon_fcn_validator&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (anon_fcn_validator)
 
-  anon_fcn_validator& operator = (const anon_fcn_validator&) = delete;
-
-  ~anon_fcn_validator (void) = default;
+  ~anon_fcn_validator () = default;
 
   void visit_postfix_expression (tree_postfix_expression&);
 
@@ -61,12 +57,12 @@
 
   void visit_simple_assignment (tree_simple_assignment&);
 
-  bool ok (void) const { return m_ok; }
+  bool ok () const { return m_ok; }
 
-  int line (void) const { return m_line; }
-  int column (void) const { return m_column; }
+  int line () const { return m_line; }
+  int column () const { return m_column; }
 
-  std::string message (void) const { return m_message; }
+  std::string message () const { return m_message; }
 
 private:
 
--- a/libinterp/parse-tree/bp-table.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/bp-table.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -96,12 +96,12 @@
       m_ok = true;
   }
 
-  std::string file (void) const { return m_file; }
-  std::string dir (void) const { return m_fcn; }
-  std::string fcn (void) const { return m_fcn; }
-  std::string class_name (void) const { return m_class_name; }
+  std::string file () const { return m_file; }
+  std::string dir () const { return m_fcn; }
+  std::string fcn () const { return m_fcn; }
+  std::string class_name () const { return m_class_name; }
 
-  bool ok (void) const { return m_ok; }
+  bool ok () const { return m_ok; }
 
 private:
 
@@ -114,7 +114,7 @@
 
 // Clear all reasons to stop, other than breakpoints.
 
-void bp_table::dbclear_all_signals (void)
+void bp_table::dbclear_all_signals ()
 {
   interpreter& interp = m_evaluator.get_interpreter ();
   error_system& es = interp.get_error_system ();
@@ -941,7 +941,7 @@
   return remove_all_breakpoints_from_function (info.fcn (), silent);
 }
 
-void bp_table::remove_all_breakpoints (void)
+void bp_table::remove_all_breakpoints ()
 {
   // Odd loop structure required because delete will invalidate
   // m_bp_set iterators.
--- a/libinterp/parse-tree/bp-table.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/bp-table.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,9 @@
       m_caught_that_stop (), m_warnings_that_stop ()
   { }
 
-  ~bp_table (void) = default;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (bp_table)
+
+  ~bp_table () = default;
 
   // Set of breakpoint lines.
   typedef std::set<int> bp_lines;
@@ -79,26 +81,6 @@
   typedef fname_bp_map::const_iterator const_fname_bp_map_iterator;
   typedef fname_bp_map::iterator fname_bp_map_iterator;
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead")
-  int add_breakpoint (const std::string& fname = "",
-                      const std::string& class_name = "",
-                      int line = 1,
-                      const std::string& condition = "")
-  {
-    return add_breakpoint_in_function (fname, class_name, line, condition);
-  }
-
-  OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead")
-  bp_lines add_breakpoint (const std::string& fname = "",
-                           const std::string& class_name = "",
-                           const bp_lines& lines = bp_lines (),
-                           const std::string& condition = "")
-  {
-    return add_breakpoints_in_function (fname, class_name, lines, condition);
-  }
-#endif
-
   // Add a breakpoint at the nearest executable line in a function.
   int add_breakpoint_in_function (const std::string& fname = "",
                                   const std::string& class_name = "",
@@ -123,22 +105,6 @@
                                     const bp_lines& lines = bp_lines (),
                                     const std::string& condition = "");
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoint_from_function' instead")
-  int remove_breakpoint (const std::string& fname = "",
-                         int line = 1)
-  {
-    return remove_breakpoint_from_function (fname, line);
-  }
-
-  OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoints_from_function' instead")
-  int remove_breakpoint (const std::string& fname = "",
-                         const bp_lines& lines = bp_lines ())
-  {
-    return remove_breakpoints_from_function (fname, lines);
-  }
-#endif
-
   // Remove a breakpoint from the given line in file.
   int remove_breakpoint_from_function (const std::string& fname = "",
                                        int line = 1);
@@ -149,7 +115,7 @@
 
   // Remove all the breakpoints in a specified function.
   bp_lines remove_all_breakpoints_from_function (const std::string& fname,
-      bool silent = false);
+                                                 bool silent = false);
 
   // Remove a breakpoint from the given line in file.
   int remove_breakpoint_from_file (const std::string& file = "",
@@ -160,27 +126,18 @@
                                     const bp_lines& lines = bp_lines ());
 
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'bp_table::remove_all_breakpoints_from_function' instead")
-  bp_lines remove_all_breakpoints_in_file (const std::string& fname,
-      bool silent = false)
-  {
-    return remove_all_breakpoints_from_function (fname, silent);
-  }
-#endif
-
   // Remove all the breakpoints from a file.
   bp_lines remove_all_breakpoints_from_file (const std::string& file,
-      bool silent = false);
+                                             bool silent = false);
 
   // Remove all the breakpoints registered with octave.
-  void remove_all_breakpoints (void);
+  void remove_all_breakpoints ();
 
   // Return all breakpoints.  Each element of the map is a vector
   // containing the breakpoints corresponding to a given function name.
   fname_bp_map get_breakpoint_list (const octave_value_list& fname_list);
 
-  bool have_breakpoints (void) { return (! m_bp_set.empty ()); }
+  bool have_breakpoints () { return (! m_bp_set.empty ()); }
 
   // Should we enter debugging for this particular error identifier?
   bool debug_on_err (const std::string& id)
@@ -204,7 +161,7 @@
 
   void dbstop_process_map_args (const octave_map& mv);
 
-  void dbclear_all_signals (void);
+  void dbclear_all_signals ();
 
   bool condition_valid (const std::string& cond);
 
@@ -248,7 +205,7 @@
                            const bp_lines& lines);
 
   bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn,
-      const std::string& fname);
+                                             const std::string& fname);
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/comment-list.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/comment-list.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 comment_list *
-comment_list::dup (void) const
+comment_list::dup () const
 {
   comment_list *new_cl = new comment_list ();
 
--- a/libinterp/parse-tree/comment-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/comment-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,9 +34,9 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-extern std::string get_comment_text (void);
+extern std::string get_comment_text ();
 
-extern char * get_comment_text_c_str (void);
+extern char * get_comment_text_c_str ();
 
 extern void save_comment_text (const std::string& text);
 
@@ -72,17 +72,17 @@
     return *this;
   }
 
-  std::string text (void) const { return m_text; }
+  std::string text () const { return m_text; }
 
-  comment_type type (void) const { return m_type; }
+  comment_type type () const { return m_type; }
 
-  bool is_block (void) const { return m_type == block; }
-  bool is_full_line (void) const { return m_type == full_line; }
-  bool is_end_of_line (void) const { return m_type == end_of_line; }
-  bool is_doc_string (void) const { return m_type == doc_string; }
-  bool is_copyright (void) const { return m_type == copyright; }
+  bool is_block () const { return m_type == block; }
+  bool is_full_line () const { return m_type == full_line; }
+  bool is_end_of_line () const { return m_type == end_of_line; }
+  bool is_doc_string () const { return m_type == doc_string; }
+  bool is_copyright () const { return m_type == copyright; }
 
-  ~comment_elt (void) = default;
+  ~comment_elt () = default;
 
 private:
 
@@ -98,7 +98,7 @@
 {
 public:
 
-  comment_list (void) { }
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (comment_list)
 
   void append (const comment_elt& elt)
   { base_list<comment_elt>::append (elt); }
@@ -107,7 +107,7 @@
                comment_elt::comment_type t = comment_elt::unknown)
   { append (comment_elt (s, t)); }
 
-  comment_list * dup (void) const;
+  comment_list * dup () const;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/filepos.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/filepos.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 {
 public:
 
-  filepos (void) : m_line (0), m_column (0) { }
+  filepos () : m_line (0), m_column (0) { }
 
   filepos (int l, int c) : m_line (l), m_column (c) { }
 
@@ -42,15 +42,15 @@
 
   filepos& operator = (const filepos&) = default;
 
-  ~filepos (void) = default;
+  ~filepos () = default;
 
   operator bool () { return m_line > 0 && m_column > 0; }
 
   void line (int l) { m_line = l; }
   void column (int c) { m_column = c; }
 
-  int line (void) const { return m_line; }
-  int column (void) const { return m_column; }
+  int line () const { return m_line; }
+  int column () const { return m_column; }
 
   void increment_line (int val = 1) { m_line += val; }
   void increment_column (int val = 1) { m_column += val; }
@@ -58,7 +58,7 @@
   void decrement_line (int val = 1) { m_line -= val; }
   void decrement_column (int val = 1) { m_column -= val; }
 
-  void next_line (void)
+  void next_line ()
   {
     m_line++;
     m_column = 1;
--- a/libinterp/parse-tree/lex.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/lex.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,23 +62,25 @@
     symbol_table_context (interpreter& interp)
       : m_interpreter (interp), m_frame_stack () { }
 
-    ~symbol_table_context (void) { clear (); }
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (symbol_table_context)
 
-    void clear (void);
+    ~symbol_table_context () { clear (); }
+
+    void clear ();
 
-    bool empty (void) const { return m_frame_stack.empty (); }
+    bool empty () const { return m_frame_stack.empty (); }
 
-    std::size_t size (void) const { return m_frame_stack.size (); }
+    std::size_t size () const { return m_frame_stack.size (); }
 
-    void pop (void);
+    void pop ();
 
     void push (const symbol_scope& scope)
     {
       m_frame_stack.push_front (scope);
     }
 
-    symbol_scope curr_scope (void) const;
-    symbol_scope parent_scope (void) const;
+    symbol_scope curr_scope () const;
+    symbol_scope parent_scope () const;
 
   private:
 
@@ -103,7 +105,7 @@
 
   public:
 
-    bbp_nesting_level (void) : m_context () { }
+    bbp_nesting_level () : m_context () { }
 
     bbp_nesting_level (const bbp_nesting_level& nl)
       : m_context (nl.m_context)
@@ -117,54 +119,54 @@
       return *this;
     }
 
-    ~bbp_nesting_level (void) = default;
+    ~bbp_nesting_level () = default;
 
     // Alias for clear function.
-    void reset (void) { clear (); }
+    void reset () { clear (); }
 
-    void bracket (void) { m_context.push (BRACKET); }
+    void bracket () { m_context.push (BRACKET); }
 
-    bool is_bracket (void)
+    bool is_bracket ()
     {
       return ! m_context.empty () && m_context.top () == BRACKET;
     }
 
-    void brace (void) { m_context.push (BRACE); }
+    void brace () { m_context.push (BRACE); }
 
-    bool is_brace (void)
+    bool is_brace ()
     {
       return ! m_context.empty () && m_context.top () == BRACE;
     }
 
-    void paren (void) { m_context.push (PAREN); }
+    void paren () { m_context.push (PAREN); }
 
-    bool is_paren (void)
+    bool is_paren ()
     {
       return ! m_context.empty () && m_context.top () == PAREN;
     }
 
-    void anon_fcn_body (void) { m_context.push (ANON_FCN_BODY); }
+    void anon_fcn_body () { m_context.push (ANON_FCN_BODY); }
 
-    bool is_anon_fcn_body (void)
+    bool is_anon_fcn_body ()
     {
       return ! m_context.empty () && m_context.top () == ANON_FCN_BODY;
     }
 
-    bool is_bracket_or_brace (void)
+    bool is_bracket_or_brace ()
     {
       return (! m_context.empty ()
               && (m_context.top () == BRACKET || m_context.top () == BRACE));
     }
 
-    bool none (void) { return m_context.empty (); }
+    bool none () { return m_context.empty (); }
 
-    void remove (void)
+    void remove ()
     {
       if (! m_context.empty ())
         m_context.pop ();
     }
 
-    void clear (void)
+    void clear ()
     {
       while (! m_context.empty ())
         m_context.pop ();
@@ -191,22 +193,18 @@
     // elements that it stores.  Another reason is that it makes it
     // easier to change the implementation later if needed.
 
-    token_cache (void) : m_buffer () { }
-
-    // No copying!
+    token_cache () : m_buffer () { }
 
-    token_cache (const token_cache&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (token_cache)
 
-    token_cache& operator = (const token_cache&) = delete;
-
-    ~token_cache (void) { clear (); }
+    ~token_cache () { clear (); }
 
     void push (token *tok)
     {
       m_buffer.push_front (tok);
     }
 
-    void pop (void)
+    void pop ()
     {
       if (! empty ())
         {
@@ -227,32 +225,32 @@
     }
 
     // Most recently pushed.
-    token * front (void)
+    token * front ()
     {
       return empty () ? nullptr : m_buffer.front ();
     }
 
-    const token * front (void) const
+    const token * front () const
     {
       return empty () ? nullptr : m_buffer.front ();
     }
 
-    token * back (void)
+    token * back ()
     {
       return empty () ? nullptr : m_buffer.back ();
     }
 
-    const token * back (void) const
+    const token * back () const
     {
       return empty () ? nullptr : m_buffer.back ();
     }
 
     // Number of elements currently in the buffer.
-    std::size_t size (void) const { return m_buffer.size (); }
+    std::size_t size () const { return m_buffer.size (); }
 
-    bool empty (void) const { return m_buffer.empty (); }
+    bool empty () const { return m_buffer.empty (); }
 
-    void clear (void)
+    void clear ()
     {
       while (! empty ())
         pop ();
@@ -320,31 +318,27 @@
     init ();
   }
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (lexical_feedback)
 
-  lexical_feedback (const lexical_feedback&) = delete;
-
-  lexical_feedback& operator = (const lexical_feedback&) = delete;
+  ~lexical_feedback ();
 
-  ~lexical_feedback (void);
-
-  void init (void);
+  void init ();
 
-  void reset (void);
+  void reset ();
 
-  int previous_token_value (void) const;
+  int previous_token_value () const;
 
   bool previous_token_value_is (int tok_val) const;
 
-  void mark_previous_token_trailing_space (void);
+  void mark_previous_token_trailing_space ();
 
-  bool space_follows_previous_token (void) const;
+  bool space_follows_previous_token () const;
 
-  bool previous_token_is_binop (void) const;
+  bool previous_token_is_binop () const;
 
-  bool previous_token_is_keyword (void) const;
+  bool previous_token_is_keyword () const;
 
-  bool previous_token_may_be_command (void) const;
+  bool previous_token_may_be_command () const;
 
   void mark_as_variable (const std::string& nm);
   void mark_as_variables (const std::list<std::string>& lst);
@@ -539,18 +533,20 @@
   {
   public:
 
-    input_buffer (void)
+    input_buffer ()
       : m_buffer (), m_offset (0), m_chars_left (0), m_eof (false)
     { }
 
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (input_buffer)
+
     void fill (const std::string& input, bool eof_arg);
 
     // Copy at most max_size characters to buf.
     int copy_chunk (char *buf, std::size_t max_size, bool by_lines = false);
 
-    bool empty (void) const { return m_chars_left == 0; }
+    bool empty () const { return m_chars_left == 0; }
 
-    bool at_eof (void) const { return m_eof; }
+    bool at_eof () const { return m_eof; }
 
   private:
 
@@ -567,9 +563,11 @@
   {
   public:
 
-    comment_buffer (void) : m_comment_list (nullptr) { }
+    comment_buffer () : m_comment_list (nullptr) { }
 
-    ~comment_buffer (void) { delete m_comment_list; }
+    OCTAVE_DISABLE_COPY_MOVE (comment_buffer)
+
+    ~comment_buffer () { delete m_comment_list; }
 
     void append (const std::string& s, comment_elt::comment_type t)
     {
@@ -581,7 +579,7 @@
 
     // Caller is expected to delete the returned value.
 
-    comment_list * get_comment (void)
+    comment_list * get_comment ()
     {
       comment_list *retval = m_comment_list;
 
@@ -590,7 +588,7 @@
       return retval;
     }
 
-    void reset (void)
+    void reset ()
     {
       delete m_comment_list;
 
@@ -609,37 +607,33 @@
     init ();
   }
 
-  // No copying!
-
-  base_lexer (const base_lexer&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_lexer)
 
-  base_lexer& operator = (const base_lexer&) = delete;
+  virtual ~base_lexer ();
 
-  virtual ~base_lexer (void);
+  void init ();
 
-  void init (void);
-
-  virtual bool is_push_lexer (void) const { return false; }
+  virtual bool is_push_lexer () const { return false; }
 
-  virtual void reset (void);
+  virtual void reset ();
 
-  void prep_for_file (void);
+  void prep_for_file ();
 
   void begin_string (int state);
 
   virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0;
 
-  bool at_end_of_buffer (void) const { return m_input_buf.empty (); }
+  bool at_end_of_buffer () const { return m_input_buf.empty (); }
 
-  bool at_end_of_file (void) const { return m_input_buf.at_eof (); }
+  bool at_end_of_file () const { return m_input_buf.at_eof (); }
 
-  int handle_end_of_input (void);
+  int handle_end_of_input ();
 
-  char * flex_yytext (void);
+  char * flex_yytext ();
 
-  int flex_yyleng (void);
+  int flex_yyleng ();
 
-  int text_yyinput (void);
+  int text_yyinput ();
 
   void xunput (char c, char *buf);
 
@@ -647,37 +641,37 @@
 
   void update_token_positions (int tok_len);
 
-  bool looking_at_space (void);
+  bool looking_at_space ();
 
-  bool inside_any_object_index (void);
+  bool inside_any_object_index ();
 
   int make_keyword_token (const std::string& s);
 
   bool fq_identifier_contains_keyword (const std::string& s);
 
-  bool whitespace_is_significant (void);
+  bool whitespace_is_significant ();
 
   // We only provide specializations with base equal to 2, 10, or 16.
   template <int base>
-  int handle_number (void);
+  int handle_number ();
 
-  void handle_continuation (void);
+  void handle_continuation ();
 
   void finish_comment (comment_elt::comment_type typ);
 
-  comment_list * get_comment (void) { return m_comment_buf.get_comment (); }
+  comment_list * get_comment () { return m_comment_buf.get_comment (); }
 
   int handle_close_bracket (int bracket_type);
 
-  bool looks_like_command_arg (void);
+  bool looks_like_command_arg ();
 
-  int handle_superclass_identifier (void);
+  int handle_superclass_identifier ();
 
-  int handle_meta_identifier (void);
+  int handle_meta_identifier ();
 
-  int handle_fq_identifier (void);
+  int handle_fq_identifier ();
 
-  int handle_identifier (void);
+  int handle_identifier ();
 
   void maybe_warn_separator_insert (char sep);
 
@@ -685,31 +679,27 @@
 
   void maybe_warn_language_extension_comment (char c);
 
-  void warn_language_extension_continuation (void);
+  void warn_language_extension_continuation ();
 
   void warn_language_extension_operator (const std::string& op);
 
   void warn_deprecated_syntax (const std::string& msg);
 
-  void warn_deprecated_operator (const std::string& deprecated_op,
-                                 const std::string& recommended_op,
-                                 const std::string& version);
-
   void push_token (token *);
 
-  token * current_token (void);
+  token * current_token ();
 
-  std::size_t pending_token_count (void) const;
+  std::size_t pending_token_count () const;
 
   void display_token (int tok);
 
   void fatal_error (const char *msg);
 
-  bool debug_flag (void) const;
+  bool debug_flag () const;
 
-  bool display_tokens (void) const;
+  bool display_tokens () const;
 
-  void increment_token_count (void);
+  void increment_token_count ();
 
   void lexer_debug (const char *pattern);
 
@@ -722,31 +712,31 @@
   // Object that collects comment text.
   comment_buffer m_comment_buf;
 
-  virtual std::string input_source (void) const { return "unknown"; }
+  virtual std::string input_source () const { return "unknown"; }
 
-  virtual bool input_from_terminal (void) const { return false; }
+  virtual bool input_from_terminal () const { return false; }
 
-  virtual bool input_from_file (void) const { return false; }
+  virtual bool input_from_file () const { return false; }
 
-  virtual bool input_from_eval_string (void) const { return false; }
+  virtual bool input_from_eval_string () const { return false; }
 
-  bool input_from_tmp_history_file (void);
+  bool input_from_tmp_history_file ();
 
   void push_start_state (int state);
 
-  void pop_start_state (void);
+  void pop_start_state ();
 
-  void clear_start_state (void);
+  void clear_start_state ();
 
-  int start_state (void) const { return start_state_stack.top (); }
+  int start_state () const { return start_state_stack.top (); }
 
-  void display_start_state (void) const;
+  void display_start_state () const;
 
   bool maybe_unput_comma_before_unary_op (int tok);
 
   int handle_op (int tok, bool bos = false, bool compat = true);
 
-  int finish_command_arg (void);
+  int finish_command_arg ();
 
   int handle_token (int tok, token *tok_val = nullptr);
 
@@ -784,35 +774,33 @@
       m_initial_input (true)
   { }
 
-  // No copying!
-
-  lexer (const lexer&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (lexer)
 
-  lexer& operator = (const lexer&) = delete;
+  ~lexer () = default;
 
-  void reset (void)
+  void reset ()
   {
     m_initial_input = true;
 
     base_lexer::reset ();
   }
 
-  std::string input_source (void) const
+  std::string input_source () const
   {
     return m_reader.input_source ();
   }
 
-  bool input_from_terminal (void) const
+  bool input_from_terminal () const
   {
     return m_reader.input_from_terminal ();
   }
 
-  bool input_from_file (void) const
+  bool input_from_file () const
   {
     return m_reader.input_from_file ();
   }
 
-  bool input_from_eval_string (void) const
+  bool input_from_eval_string () const
   {
     return m_reader.input_from_eval_string ();
   }
@@ -862,17 +850,15 @@
     append_input (input, eof);
   }
 
-  // No copying!
-
-  push_lexer (const push_lexer&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (push_lexer)
 
-  push_lexer& operator = (const push_lexer&) = delete;
+  ~push_lexer () = default;
 
-  bool is_push_lexer (void) const { return true; }
+  bool is_push_lexer () const { return true; }
 
   void append_input (const std::string& input, bool eof);
 
-  std::string input_source (void) const { return "push buffer"; }
+  std::string input_source () const { return "push buffer"; }
 
   int fill_flex_buffer (char *buf, unsigned int max_size);
 };
--- a/libinterp/parse-tree/lex.ll	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/lex.ll	Fri Jun 23 20:51:51 2023 +0200
@@ -183,28 +183,6 @@
      }                                                                  \
    while (0)
 
-#define CMD_OR_DEPRECATED_OP(PATTERN, REPLACEMENT, VERSION, TOK)        \
-   do                                                                   \
-     {                                                                  \
-       curr_lexer->lexer_debug (PATTERN);                               \
-                                                                        \
-       if (curr_lexer->looks_like_command_arg ())                       \
-         {                                                              \
-           yyless (0);                                                  \
-           curr_lexer->push_start_state (COMMAND_START);                \
-         }                                                              \
-       else                                                             \
-         {                                                              \
-           curr_lexer->warn_deprecated_operator (PATTERN, REPLACEMENT,  \
-                                                 #VERSION);             \
-           /* set COMPAT to true here to avoid warning about            \
-              compatibility since we've already warned about the        \
-              operator being deprecated.  */                            \
-           return curr_lexer->handle_op (TOK, false, true);             \
-         }                                                              \
-     }                                                                  \
-   while (0)
-
 #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT)                           \
    do                                                                   \
      {                                                                  \
@@ -1088,28 +1066,6 @@
     curr_lexer->m_string_text += '\v';
   }
 
-<DQ_STRING_START>(\.\.\.){S}*{NL} {
-    curr_lexer->lexer_debug ("<DQ_STRING_START>(\\.\\.\\.){S}*{NL}");
-
-    /* FIXME: Remove support for '...' continuation in Octave 9 */
-    static const char *msg = "'...' continuations in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave; please use '\\' instead";
-
-    curr_lexer->warn_deprecated_syntax (msg);
-
-    HANDLE_STRING_CONTINUATION;
-  }
-
-<DQ_STRING_START>\\{S}+{NL} {
-    curr_lexer->lexer_debug ("<DQ_STRING_START>\\\\{S}+{NL}");
-
-    /* FIXME: Remove support for WS after line continuation in Octave 9 */
-    static const char *msg = "whitespace after continuation markers in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave";
-
-    curr_lexer->warn_deprecated_syntax (msg);
-
-    HANDLE_STRING_CONTINUATION;
-  }
-
 <DQ_STRING_START>\\{NL} {
     curr_lexer->lexer_debug ("<DQ_STRING_START>\\\\{NL}");
 
@@ -1302,17 +1258,6 @@
 // Deprecated C preprocessor style continuation markers.
 %}
 
-\\{S}*{NL} |
-\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL} {
-    curr_lexer->lexer_debug ("\\\\{S}*{NL}|\\\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL}");
-
-    /* FIXME: Remove support for '\\' line continuation in Octave 9 */
-    static const char *msg = "using continuation marker \\ outside of double quoted strings was deprecated in version 7 and will be removed from a future version of Octave, use ... instead";
-
-    curr_lexer->warn_deprecated_syntax (msg);
-
-    curr_lexer->handle_continuation ();
-  }
 
 %{
 // End of file.
@@ -1644,13 +1589,10 @@
 %}
 
 ":"   { CMD_OR_OP (":", ':', true); }
-".+"  { CMD_OR_DEPRECATED_OP (".+", "+", 7, '+'); }
-".-"  { CMD_OR_DEPRECATED_OP (".-", "-", 7, '-'); }
 ".*"  { CMD_OR_OP (".*", EMUL, true); }
 "./"  { CMD_OR_OP ("./", EDIV, true); }
 ".\\" { CMD_OR_OP (".\\", ELEFTDIV, true); }
 ".^"  { CMD_OR_OP (".^", EPOW, true); }
-".**" { CMD_OR_DEPRECATED_OP (".**", ".^", 7, EPOW); }
 "<="  { CMD_OR_OP ("<=", EXPR_LE, true); }
 "=="  { CMD_OR_OP ("==", EXPR_EQ, true); }
 "!="  { CMD_OR_OP ("!=", EXPR_NE, false); }
@@ -1680,7 +1622,6 @@
   }
 
 "^"   { CMD_OR_OP ("^", POW, true); }
-"**"  { CMD_OR_DEPRECATED_OP ("**", "^", 7, POW); }
 "&&"  { CMD_OR_OP ("&&", EXPR_AND_AND, true); }
 "||"  { CMD_OR_OP ("||", EXPR_OR_OR, true); }
 
@@ -1817,15 +1758,11 @@
 "*="   { CMD_OR_OP ("*=", MUL_EQ, false); }
 "/="   { CMD_OR_OP ("/=", DIV_EQ, false); }
 "\\="  { CMD_OR_OP ("\\=", LEFTDIV_EQ, false); }
-".+="  { CMD_OR_DEPRECATED_OP (".+=", "+=", 7, ADD_EQ); }
-".-="  { CMD_OR_DEPRECATED_OP (".-=", "-=", 7, SUB_EQ); }
 ".*="  { CMD_OR_OP (".*=", EMUL_EQ, false); }
 "./="  { CMD_OR_OP ("./=", EDIV_EQ, false); }
 ".\\=" { CMD_OR_OP (".\\=", ELEFTDIV_EQ, false); }
 "^="   { CMD_OR_OP ("^=", POW_EQ, false); }
-"**="  { CMD_OR_DEPRECATED_OP ("**=", "^=", 7, POW_EQ); }
 ".^="  { CMD_OR_OP (".^=", EPOW_EQ, false); }
-".**=" { CMD_OR_DEPRECATED_OP (".**=", ".^=", 7, EPOW_EQ); }
 "&="   { CMD_OR_OP ("&=", AND_EQ, false); }
 "|="   { CMD_OR_OP ("|=", OR_EQ, false); }
 
@@ -2177,14 +2114,14 @@
 */
 
   void
-  lexical_feedback::symbol_table_context::clear (void)
+  lexical_feedback::symbol_table_context::clear ()
   {
     while (! m_frame_stack.empty ())
       m_frame_stack.pop_front ();
   }
 
   void
-  lexical_feedback::symbol_table_context::pop (void)
+  lexical_feedback::symbol_table_context::pop ()
   {
     if (empty ())
       panic_impossible ();
@@ -2193,7 +2130,7 @@
   }
 
   symbol_scope
-  lexical_feedback::symbol_table_context::curr_scope (void) const
+  lexical_feedback::symbol_table_context::curr_scope () const
   {
     if (empty ())
       return m_interpreter.get_current_scope ();
@@ -2202,7 +2139,7 @@
   }
 
   symbol_scope
-  lexical_feedback::symbol_table_context::parent_scope (void) const
+  lexical_feedback::symbol_table_context::parent_scope () const
   {
     std::size_t sz = size ();
 
@@ -2211,13 +2148,13 @@
             : (sz == 1 ? m_frame_stack[0] : symbol_scope ()));
   }
 
-  lexical_feedback::~lexical_feedback (void)
+  lexical_feedback::~lexical_feedback ()
   {
     m_tokens.clear ();
   }
 
   void
-  lexical_feedback::init (void)
+  lexical_feedback::init ()
   {
     // The closest paren, brace, or bracket nesting is not an object
     // index.
@@ -2225,7 +2162,7 @@
   }
 
   void
-  lexical_feedback::reset (void)
+  lexical_feedback::reset ()
   {
     m_end_of_input = false;
     m_allow_command_syntax = true;
@@ -2285,7 +2222,7 @@
   }
 
   int
-  lexical_feedback::previous_token_value (void) const
+  lexical_feedback::previous_token_value () const
   {
     const token *tok = m_tokens.front ();
     return tok ? tok->token_value () : 0;
@@ -2299,7 +2236,7 @@
   }
 
   void
-  lexical_feedback::mark_previous_token_trailing_space (void)
+  lexical_feedback::mark_previous_token_trailing_space ()
   {
     token *tok = m_tokens.front ();
     if (tok && ! previous_token_value_is ('\n'))
@@ -2307,14 +2244,14 @@
   }
 
   bool
-  lexical_feedback::space_follows_previous_token (void) const
+  lexical_feedback::space_follows_previous_token () const
   {
     const token *tok = m_tokens.front ();
     return tok ? tok->space_follows_token () : false;
   }
 
   bool
-  lexical_feedback::previous_token_is_binop (void) const
+  lexical_feedback::previous_token_is_binop () const
   {
     int tok = previous_token_value ();
 
@@ -2334,7 +2271,7 @@
   }
 
   bool
-  lexical_feedback::previous_token_is_keyword (void) const
+  lexical_feedback::previous_token_is_keyword () const
   {
     const token *tok = m_tokens.front ();
     return tok ? tok->iskeyword () : false;
@@ -2359,7 +2296,7 @@
   }
 
   bool
-  lexical_feedback::previous_token_may_be_command (void) const
+  lexical_feedback::previous_token_may_be_command () const
   {
     if (! m_allow_command_syntax)
       return false;
@@ -2455,13 +2392,13 @@
     return len;
   }
 
-  base_lexer::~base_lexer (void)
+  base_lexer::~base_lexer ()
   {
     yylex_destroy (m_scanner);
   }
 
   void
-  base_lexer::init (void)
+  base_lexer::init ()
   {
     yylex_init (&m_scanner);
 
@@ -2482,7 +2419,7 @@
   struct yyguts_t *yyg = static_cast<struct yyguts_t*> (m_scanner)
 
   void
-  base_lexer::reset (void)
+  base_lexer::reset ()
   {
     // Start off on the right foot.
     clear_start_state ();
@@ -2505,7 +2442,7 @@
   }
 
   void
-  base_lexer::prep_for_file (void)
+  base_lexer::prep_for_file ()
   {
     m_reading_script_file = true;
 
@@ -2521,7 +2458,7 @@
   }
 
   int
-  base_lexer::handle_end_of_input (void)
+  base_lexer::handle_end_of_input ()
   {
     lexer_debug ("<<EOF>>");
 
@@ -2546,19 +2483,19 @@
   }
 
   char *
-  base_lexer::flex_yytext (void)
+  base_lexer::flex_yytext ()
   {
     return yyget_text (m_scanner);
   }
 
   int
-  base_lexer::flex_yyleng (void)
+  base_lexer::flex_yyleng ()
   {
     return yyget_leng (m_scanner);
   }
 
   int
-  base_lexer::text_yyinput (void)
+  base_lexer::text_yyinput ()
   {
     int c = yyinput (m_scanner);
 
@@ -2629,7 +2566,7 @@
   }
 
   bool
-  base_lexer::looking_at_space (void)
+  base_lexer::looking_at_space ()
   {
     int c = text_yyinput ();
     xunput (c);
@@ -2637,7 +2574,7 @@
   }
 
   bool
-  base_lexer::inside_any_object_index (void)
+  base_lexer::inside_any_object_index ()
   {
     bool retval = false;
 
@@ -2964,7 +2901,7 @@
   }
 
   bool
-  base_lexer::whitespace_is_significant (void)
+  base_lexer::whitespace_is_significant ()
   {
     return (m_nesting_level.is_bracket ()
             || (m_nesting_level.is_brace ()
@@ -3035,7 +2972,7 @@
 
   template <>
   int
-  base_lexer::handle_number<2> (void)
+  base_lexer::handle_number<2> ()
   {
     // Skip 0[bB] prefix.
     std::string yytxt (flex_yytext () + 2);
@@ -3121,14 +3058,14 @@
   }
 
   static uint64_t
-  flintmax (void)
+  flintmax ()
   {
     return (static_cast<uint64_t> (1) << std::numeric_limits<double>::digits);
   }
 
   template <>
   int
-  base_lexer::handle_number<10> (void)
+  base_lexer::handle_number<10> ()
   {
     bool imag = false;
     bool digits_only = true;
@@ -3243,7 +3180,7 @@
 
   template <>
   int
-  base_lexer::handle_number<16> (void)
+  base_lexer::handle_number<16> ()
   {
     // Skip 0[xX] prefix.
     std::string yytxt (flex_yytext () + 2);
@@ -3319,7 +3256,7 @@
   }
 
   void
-  base_lexer::handle_continuation (void)
+  base_lexer::handle_continuation ()
   {
     char *yytxt = flex_yytext ();
     int yylng = flex_yyleng ();
@@ -3382,7 +3319,9 @@
   {
     bool copyright = looks_like_copyright (m_comment_text);
 
-    if (m_nesting_level.none () && m_help_text.empty () && ! m_comment_text.empty ()
+    if (typ != octave::comment_elt::end_of_line
+        && m_nesting_level.none ()
+        && m_help_text.empty () && ! m_comment_text.empty ()
         && ! copyright && ! looks_like_shebang (m_comment_text))
       m_help_text = m_comment_text;
 
@@ -3422,7 +3361,7 @@
   }
 
   bool
-  base_lexer::looks_like_command_arg (void)
+  base_lexer::looks_like_command_arg ()
   {
     if (! m_allow_command_syntax)
       return false;
@@ -3435,7 +3374,7 @@
   }
 
   int
-  base_lexer::handle_superclass_identifier (void)
+  base_lexer::handle_superclass_identifier ()
   {
     update_token_positions (flex_yyleng ());
 
@@ -3469,7 +3408,7 @@
   }
 
   int
-  base_lexer::handle_meta_identifier (void)
+  base_lexer::handle_meta_identifier ()
   {
     std::string txt = flex_yytext ();
 
@@ -3500,7 +3439,7 @@
   }
 
   int
-  base_lexer::handle_fq_identifier (void)
+  base_lexer::handle_fq_identifier ()
   {
     std::string txt = flex_yytext ();
 
@@ -3534,7 +3473,7 @@
   // should be ignored.
 
   int
-  base_lexer::handle_identifier (void)
+  base_lexer::handle_identifier ()
   {
     update_token_positions (flex_yyleng ());
 
@@ -3640,7 +3579,7 @@
   }
 
   void
-  base_lexer::warn_language_extension_continuation (void)
+  base_lexer::warn_language_extension_continuation ()
   {
     warn_language_extension ("\\ used as line continuation marker");
   }
@@ -3667,16 +3606,6 @@
   }
 
   void
-  base_lexer::warn_deprecated_operator (const std::string& deprecated_op,
-                                        const std::string& recommended_op,
-                                        const std::string& version)
-  {
-    std::string msg = "the '" + deprecated_op + "' operator was deprecated in version " + version + " and will not be allowed in a future version of Octave; please use '" + recommended_op + "' instead";
-
-    warn_deprecated_syntax (msg);
-  }
-
-  void
   base_lexer::push_token (token *tok)
   {
     YYSTYPE *lval = yyget_lval (m_scanner);
@@ -3685,14 +3614,14 @@
   }
 
   token *
-  base_lexer::current_token (void)
+  base_lexer::current_token ()
   {
     YYSTYPE *lval = yyget_lval (m_scanner);
     return lval->tok_val;
   }
 
   std::size_t
-  base_lexer::pending_token_count (void) const
+  base_lexer::pending_token_count () const
   {
     return m_tokens.size ();
   }
@@ -3832,21 +3761,21 @@
   }
 
   bool
-  base_lexer::debug_flag (void) const
+  base_lexer::debug_flag () const
   {
     settings& stgs = m_interpreter.get_settings ();
     return stgs.lexer_debug_flag ();
   }
 
   bool
-  base_lexer::display_tokens (void) const
+  base_lexer::display_tokens () const
   {
     settings& stgs = m_interpreter.get_settings ();
     return stgs.display_tokens ();
   }
 
   void
-  base_lexer::increment_token_count (void)
+  base_lexer::increment_token_count ()
   {
     settings& stgs = m_interpreter.get_settings ();
     stgs.increment_token_count ();
@@ -3869,7 +3798,7 @@
   }
 
   bool
-  base_lexer::input_from_tmp_history_file (void)
+  base_lexer::input_from_tmp_history_file ()
   {
     history_system& history_sys = m_interpreter.get_history_system ();
 
@@ -3887,7 +3816,7 @@
   }
 
   void
-  base_lexer::pop_start_state (void)
+  base_lexer::pop_start_state ()
   {
     OCTAVE_YYG;
 
@@ -3897,7 +3826,7 @@
   }
 
   void
-  base_lexer::clear_start_state (void)
+  base_lexer::clear_start_state ()
   {
     while (! start_state_stack.empty ())
       start_state_stack.pop ();
@@ -3906,7 +3835,7 @@
   }
 
   void
-  base_lexer::display_start_state (void) const
+  base_lexer::display_start_state () const
   {
     std::cerr << "S: ";
 
@@ -4017,7 +3946,7 @@
   // function call.
 
   int
-  base_lexer::finish_command_arg (void)
+  base_lexer::finish_command_arg ()
   {
     int tok = SQ_STRING;
 
@@ -4083,10 +4012,8 @@
 
     if (m_input_buf.empty ())
       {
-        input_system& input_sys = m_interpreter.get_input_system ();
-
         std::string ps
-          = m_initial_input ? input_sys.PS1 () : input_sys.PS2 ();
+          = m_initial_input ? m_interpreter.PS1 () : m_interpreter.PS2 ();
 
         std::string prompt = command_editor::decode_prompt_string (ps);
 
--- a/libinterp/parse-tree/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -15,6 +15,10 @@
   %reldir%/pt-assign.h \
   %reldir%/pt-binop.h \
   %reldir%/pt-bp.h \
+  %reldir%/pt-bytecode.h \
+  %reldir%/pt-bytecode-walk.h \
+  %reldir%/pt-bytecode-vm.h \
+  %reldir%/pt-bytecode-vm-internal.h \
   %reldir%/pt-cbinop.h \
   %reldir%/pt-cell.h \
   %reldir%/pt-check.h \
@@ -64,6 +68,8 @@
   %reldir%/pt-assign.cc \
   %reldir%/pt-binop.cc \
   %reldir%/pt-bp.cc \
+  %reldir%/pt-bytecode-walk.cc \
+  %reldir%/pt-bytecode-vm.cc \
   %reldir%/pt-cbinop.cc \
   %reldir%/pt-cell.cc \
   %reldir%/pt-check.cc \
@@ -86,7 +92,6 @@
   %reldir%/pt-stmt.cc \
   %reldir%/pt-tm-const.cc \
   %reldir%/pt-unop.cc \
-  %reldir%/pt-vm-eval.cc \
   %reldir%/pt-walk.cc \
   %reldir%/pt.cc \
   %reldir%/token.cc
--- a/libinterp/parse-tree/oct-lvalue.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/oct-lvalue.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,12 +37,12 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-bool octave_lvalue::is_defined (void) const
+bool octave_lvalue::is_defined () const
 {
   return ! is_black_hole () && m_frame->is_defined (m_sym);
 }
 
-bool octave_lvalue::is_undefined (void) const
+bool octave_lvalue::is_undefined () const
 {
   return ! is_defined ();
 }
@@ -59,7 +59,7 @@
     m_frame->assign (op, m_sym, m_type, m_idx, rhs);
 }
 
-octave_idx_type octave_lvalue::numel (void) const
+octave_idx_type octave_lvalue::numel () const
 {
   // Return 1 if there is no index because without an index there
   // should be no way to have a cs-list here.  Cs-lists may be passed
@@ -178,7 +178,7 @@
   m_idx = i;
 }
 
-bool octave_lvalue::index_is_empty (void) const
+bool octave_lvalue::index_is_empty () const
 {
   bool retval = false;
 
@@ -192,7 +192,7 @@
   return retval;
 }
 
-bool octave_lvalue::index_is_colon (void) const
+bool octave_lvalue::index_is_colon () const
 {
   bool retval = false;
 
@@ -212,7 +212,7 @@
     m_frame->non_const_unary_op (op, m_sym, m_type, m_idx);
 }
 
-octave_value octave_lvalue::value (void) const
+octave_value octave_lvalue::value () const
 {
   return (is_black_hole ()
           ? octave_value () : m_frame->value (m_sym, m_type, m_idx));
--- a/libinterp/parse-tree/oct-lvalue.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/oct-lvalue.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,50 +46,38 @@
       m_type (), m_idx ()
   { }
 
-  octave_lvalue (const octave_lvalue&) = default;
-
-  octave_lvalue& operator = (const octave_lvalue&) = delete;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_lvalue)
 
-  ~octave_lvalue (void) = default;
+  bool is_black_hole () const { return m_black_hole; }
 
-  bool is_black_hole (void) const { return m_black_hole; }
+  void mark_black_hole () { m_black_hole = true; }
 
-  void mark_black_hole (void) { m_black_hole = true; }
-
-  bool is_defined (void) const;
+  bool is_defined () const;
 
-  bool is_undefined (void) const;
+  bool is_undefined () const;
 
-  bool isstruct (void) const { return value().isstruct (); }
+  bool isstruct () const { return value().isstruct (); }
 
   void define (const octave_value& v);
 
   void assign (octave_value::assign_op, const octave_value&);
 
-  octave_idx_type numel (void) const;
+  octave_idx_type numel () const;
 
   void set_index (const std::string& t,
                   const std::list<octave_value_list>& i);
 
-  void clear_index (void) { m_type = ""; m_idx.clear (); }
+  void clear_index () { m_type = ""; m_idx.clear (); }
 
-  std::string index_type (void) const { return m_type; }
+  std::string index_type () const { return m_type; }
 
-  bool index_is_empty (void) const;
+  bool index_is_empty () const;
 
-  bool index_is_colon (void) const;
+  bool index_is_colon () const;
 
   void unary_op (octave_value::unary_op op);
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "use 'octave_lvalue::unary_op' instead")
-  void do_unary_op (octave_value::unary_op op)
-  {
-    return unary_op (op);
-  }
-#endif
-
-  octave_value value (void) const;
+  octave_value value () const;
 
 private:
 
--- a/libinterp/parse-tree/oct-parse.yy	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/oct-parse.yy	Fri Jun 23 20:51:51 2023 +0200
@@ -2412,6 +2412,8 @@
   {
   public:
 
+    parse_exception () = delete;
+
     parse_exception (const std::string& message,
                      const std::string& fcn_name = "",
                      const std::string& file_name = "",
@@ -2421,22 +2423,18 @@
         m_line (line), m_column (column)
     { }
 
-    parse_exception (const parse_exception&) = default;
-
-    parse_exception& operator = (const parse_exception&) = default;
-
-    ~parse_exception (void) = default;
-
-    std::string message (void) const { return m_message; }
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (parse_exception)
+
+    std::string message () const { return m_message; }
 
     // Provided for std::exception interface.
-    const char * what (void) const noexcept { return m_message.c_str (); }
-
-    std::string fcn_name (void) const { return m_fcn_name; }
-    std::string file_name (void) const { return m_file_name; }
-
-    int line (void) const { return m_line; }
-    int column (void) const { return m_column; }
+    const char * what () const noexcept { return m_message.c_str (); }
+
+    std::string fcn_name () const { return m_fcn_name; }
+    std::string file_name () const { return m_file_name; }
+
+    int line () const { return m_line; }
+    int column () const { return m_column; }
 
     // virtual void display (std::ostream& os) const;
 
@@ -2454,21 +2452,19 @@
   {
   public:
 
-    parse_tree_validator (void)
+    parse_tree_validator ()
       : m_scope (), m_error_list ()
     { }
 
-    parse_tree_validator (const parse_tree_validator&) = delete;
-
-    parse_tree_validator& operator = (const parse_tree_validator&) = delete;
-
-    ~parse_tree_validator (void) = default;
-
-    symbol_scope get_scope (void) const { return m_scope; }
-
-    bool ok (void) const { return m_error_list.empty (); }
-
-    std::list<parse_exception> error_list (void) const
+    OCTAVE_DISABLE_COPY_MOVE (parse_tree_validator)
+
+    ~parse_tree_validator () = default;
+
+    symbol_scope get_scope () const { return m_scope; }
+
+    bool ok () const { return m_error_list.empty (); }
+
+    std::list<parse_exception> error_list () const
     {
       return m_error_list;
     }
@@ -2542,7 +2538,7 @@
   }
 
   std::size_t
-  base_parser::parent_scope_info::size (void) const
+  base_parser::parent_scope_info::size () const
   {
     return m_info.size ();
   }
@@ -2560,7 +2556,7 @@
   }
 
   void
-  base_parser::parent_scope_info::pop (void)
+  base_parser::parent_scope_info::pop ()
   {
     m_info.pop_back ();
   }
@@ -2616,18 +2612,18 @@
   }
 
   symbol_scope
-  base_parser::parent_scope_info::parent_scope (void) const
+  base_parser::parent_scope_info::parent_scope () const
   {
     return size () > 1 ? m_info[size()-2].first : symbol_scope ();
   }
 
   std::string
-  base_parser::parent_scope_info::parent_name (void) const
+  base_parser::parent_scope_info::parent_name () const
   {
     return m_info[size()-2].second;
   }
 
-  void base_parser::parent_scope_info::clear (void)
+  void base_parser::parent_scope_info::clear ()
   {
     m_info.clear ();
     m_all_names.clear ();
@@ -2643,7 +2639,7 @@
       m_stmt_list (), m_lexer (lxr), m_parser_state (yypstate_new ())
   { }
 
-  base_parser::~base_parser (void)
+  base_parser::~base_parser ()
   {
     delete &m_lexer;
 
@@ -2659,7 +2655,7 @@
   }
 
   void
-  base_parser::reset (void)
+  base_parser::reset ()
   {
     m_endfunction_found = false;
     m_autoloading = false;
@@ -2801,7 +2797,7 @@
   }
 
   bool
-  base_parser::push_fcn_symtab (void)
+  base_parser::push_fcn_symtab ()
   {
     m_curr_fcn_depth++;
 
@@ -2893,7 +2889,7 @@
   }
 
   tree_black_hole *
-  base_parser::make_black_hole (void)
+  base_parser::make_black_hole ()
   {
     return new tree_black_hole ();
   }
@@ -3006,7 +3002,7 @@
     if (base->is_constant () && limit->is_constant ()
         && (! incr || incr->is_constant ()))
       {
-        interpreter& interp = __get_interpreter__ ();
+        interpreter& interp = m_lexer.m_interpreter;
 
         try
           {
@@ -4306,7 +4302,7 @@
   }
 
   void
-  base_parser::recover_from_parsing_function (void)
+  base_parser::recover_from_parsing_function ()
   {
     m_lexer.m_symtab_context.pop ();
 
@@ -4884,7 +4880,9 @@
 
     if (local_fcns)
       {
-        symbol_table& symtab = __get_symbol_table__ ();
+        interpreter& interp = m_lexer.m_interpreter;
+
+        symbol_table& symtab = interp.get_symbol_table ();
 
         for (tree_statement *elt : *local_fcns)
           {
@@ -5174,7 +5172,9 @@
 
     if (e->is_constant ())
       {
-        tree_evaluator& tw = __get_evaluator__ ();
+        interpreter& interp = m_lexer.m_interpreter;
+
+        tree_evaluator& tw = interp.get_evaluator ();
 
         octave_value ov = e->evaluate (tw);
 
@@ -5237,7 +5237,7 @@
 
     if (array_list->all_elements_are_constant ())
       {
-        interpreter& interp = __get_interpreter__ ();
+        interpreter& interp = m_lexer.m_interpreter;
 
         try
           {
@@ -5494,7 +5494,7 @@
   }
 
   void
-  base_parser::disallow_command_syntax (void)
+  base_parser::disallow_command_syntax ()
   {
     m_lexer.m_allow_command_syntax = false;
   }
@@ -5615,7 +5615,7 @@
   }
 
   int
-  parser::run (void)
+  parser::run ()
   {
     int status = -1;
 
@@ -5732,17 +5732,15 @@
   }
 
   int
-  push_parser::run (void)
+  push_parser::run ()
   {
     if (! m_reader)
       error ("push_parser::run requires valid input_reader");
 
     int exit_status = 0;
 
-    input_system&  input_sys = m_interpreter.get_input_system ();
-
     std::string prompt
-      = command_editor::decode_prompt_string (input_sys.PS1 ());
+      = command_editor::decode_prompt_string (m_interpreter.PS1 ());
 
     do
       {
@@ -5764,7 +5762,7 @@
 
         exit_status = run (input_line, false);
 
-        prompt = command_editor::decode_prompt_string (input_sys.PS2 ());
+        prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());
       }
     while (exit_status < 0);
 
@@ -5806,7 +5804,7 @@
         return octave_value ();
       }
 
-    unwind_action act ([=] (void) { ::fclose (ffile); });
+    unwind_action act ([=] () { ::fclose (ffile); });
 
     // get the encoding for this folder
     input_system& input_sys = interp.get_input_system ();
@@ -5900,7 +5898,7 @@
 
   // Check script or function for semantic errors.
   bool
-  base_parser::validate_primary_fcn (void)
+  base_parser::validate_primary_fcn ()
   {
     octave_user_code *code = m_primary_fcn.user_code_value ();
 
@@ -6412,16 +6410,6 @@
   return retval;
 }
 
-  void
-  cleanup_statement_list (tree_statement_list **lst)
-  {
-    if (*lst)
-      {
-        delete *lst;
-        *lst = nullptr;
-      }
-  }
-
 DEFMETHOD (eval, interp, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} eval (@var{try})
@@ -6648,7 +6636,7 @@
   // the eval, then the message is stored in the exception object and we
   // will display it later, after the buffers have been restored.
 
-  unwind_action act ([=] (void)
+  unwind_action act ([=] ()
                              {
                                octave_stdout.rdbuf (old_out_buf);
                                std::cerr.rdbuf (old_err_buf);
--- a/libinterp/parse-tree/parse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/parse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -122,37 +122,33 @@
     typedef std::deque<value_type>::reverse_iterator reverse_iterator;
     typedef std::deque<value_type>::const_reverse_iterator const_reverse_iterator;
 
-    parent_scope_info (void) = delete;
+    parent_scope_info () = delete;
 
     parent_scope_info (base_parser& parser)
       : m_parser (parser), m_info (), m_all_names ()
     { }
 
-    // No copying!
-
-    parent_scope_info (const parent_scope_info&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (parent_scope_info)
 
-    parent_scope_info& operator = (const parent_scope_info&) = delete;
+    ~parent_scope_info () = default;
 
-    ~parent_scope_info (void) = default;
-
-    OCTINTERP_API std::size_t size (void) const;
+    OCTINTERP_API std::size_t size () const;
 
     OCTINTERP_API void push (const value_type& elt);
 
     OCTINTERP_API void push (const symbol_scope& id);
 
-    OCTINTERP_API void pop (void);
+    OCTINTERP_API void pop ();
 
     OCTINTERP_API bool name_ok (const std::string& name);
 
     OCTINTERP_API bool name_current_scope (const std::string& name);
 
-    OCTINTERP_API symbol_scope parent_scope (void) const;
+    OCTINTERP_API symbol_scope parent_scope () const;
 
-    OCTINTERP_API std::string parent_name (void) const;
+    OCTINTERP_API std::string parent_name () const;
 
-    OCTINTERP_API void clear (void);
+    OCTINTERP_API void clear ();
 
   private:
 
@@ -165,33 +161,29 @@
 
   OCTINTERP_API base_parser (base_lexer& lxr);
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (base_parser)
 
-  base_parser (const base_parser&) = delete;
-
-  base_parser& operator = (const base_parser&) = delete;
+  virtual ~base_parser ();
 
-  virtual ~base_parser (void);
-
-  base_lexer& get_lexer (void) const { return m_lexer; }
+  base_lexer& get_lexer () const { return m_lexer; }
 
-  bool at_end_of_input (void) const { return m_lexer.m_end_of_input; }
+  bool at_end_of_input () const { return m_lexer.m_end_of_input; }
 
-  OCTINTERP_API void reset (void);
+  OCTINTERP_API void reset ();
 
   void classdef_object (const std::shared_ptr<tree_classdef>& obj)
   {
     m_classdef_object = obj;
   }
 
-  std::shared_ptr<tree_classdef> classdef_object (void) const
+  std::shared_ptr<tree_classdef> classdef_object () const
   {
     return m_classdef_object;
   }
 
   OCTINTERP_API void statement_list (std::shared_ptr<tree_statement_list>& lst);
 
-  std::shared_ptr<tree_statement_list> statement_list (void) const
+  std::shared_ptr<tree_statement_list> statement_list () const
   {
     return m_stmt_list;
   }
@@ -201,7 +193,7 @@
     m_parsing_subfunctions = flag;
   }
 
-  bool parsing_subfunctions (void) const
+  bool parsing_subfunctions () const
   {
     return m_parsing_subfunctions;
   }
@@ -211,12 +203,12 @@
     m_parsing_local_functions = flag;
   }
 
-  bool parsing_local_functions (void) const
+  bool parsing_local_functions () const
   {
     return m_parsing_local_functions;
   }
 
-  int curr_fcn_depth (void) const
+  int curr_fcn_depth () const
   {
     return m_curr_fcn_depth;
   }
@@ -226,7 +218,7 @@
     m_endfunction_found = flag;
   }
 
-  bool endfunction_found (void) const
+  bool endfunction_found () const
   {
     return m_endfunction_found;
   }
@@ -239,12 +231,12 @@
   OCTINTERP_API bool end_token_ok (token *tok, token::end_tok_type expected);
 
   // Handle pushing symbol table for new function scope.
-  OCTINTERP_API bool push_fcn_symtab (void);
+  OCTINTERP_API bool push_fcn_symtab ();
 
   // Build a constant.
   OCTINTERP_API tree_constant * make_constant (token *tok_val);
 
-  OCTINTERP_API tree_black_hole * make_black_hole (void);
+  OCTINTERP_API tree_black_hole * make_black_hole ();
 
   OCTINTERP_API tree_matrix * make_matrix (tree_argument_list *row);
 
@@ -458,7 +450,7 @@
 
   // Reset state after parsing function.
   OCTINTERP_API void
-  recover_from_parsing_function (void);
+  recover_from_parsing_function ();
 
   OCTINTERP_API tree_classdef *
   make_classdef (token *tok_val, tree_classdef_attribute_list *a,
@@ -701,7 +693,7 @@
   // Don't allow parsing command syntax.  If the parser/lexer is
   // reset, this setting is also reset to the default (allow command
   // syntax).
-  OCTINTERP_API void disallow_command_syntax (void);
+  OCTINTERP_API void disallow_command_syntax ();
 
   // Generic error messages.
   OCTINTERP_API void bison_error (const std::string& s);
@@ -723,18 +715,18 @@
   // use a separate run method and completely separate input from
   // lexical analysis and parsing.
 
-  virtual int run (void) = 0;
+  virtual int run () = 0;
 
   // Check primary script or function generated by the parser for
   // semantic errors.
-  OCTINTERP_API bool validate_primary_fcn (void);
+  OCTINTERP_API bool validate_primary_fcn ();
 
   OCTINTERP_API bool finish_input (tree_statement_list *lst,
                                    bool at_eof = false);
 
 protected:
 
-  // Contains error message if Bison-generated parser returns non-zero
+  // Contains error message if Bison-generated parser returns nonzero
   // status.
   std::string m_parse_error_msg;
 
@@ -853,15 +845,11 @@
     : base_parser (*lxr)
   { }
 
-  // No copying!
-
-  parser (const parser&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (parser)
 
-  parser& operator = (const parser&) = delete;
+  ~parser () = default;
 
-  ~parser (void) = default;
-
-  OCTINTERP_API int run (void);
+  OCTINTERP_API int run ();
 };
 
 class push_parser : public base_parser
@@ -881,19 +869,15 @@
       m_interpreter (interp), m_reader (reader)
   { }
 
-  // No copying!
-
-  push_parser (const push_parser&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (push_parser)
 
-  push_parser& operator = (const push_parser&) = delete;
-
-  ~push_parser (void) = default;
+  ~push_parser () = default;
 
   // Use the push parser in the same way as the pull parser.  The
   // parser arranges for input through the M_READER object.  See, for
   // example, interpreter::main_loop.
 
-  OCTINTERP_API int run (void);
+  OCTINTERP_API int run ();
 
   // Parse INPUT.  M_READER is not used.  The user is responsible for
   // collecting input.
@@ -950,9 +934,6 @@
 extern OCTINTERP_API octave_value_list
 feval (const octave_value_list& args, int nargout = 0);
 
-extern OCTINTERP_API void
-cleanup_statement_list (tree_statement_list **lst);
-
 OCTAVE_END_NAMESPACE(octave)
 
 #endif
--- a/libinterp/parse-tree/profiler.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/profiler.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-profiler::stats::stats (void)
+profiler::stats::stats ()
   : m_time (0.0), m_calls (0), m_recursive (false),
     m_parents (), m_children ()
 { }
@@ -172,13 +172,13 @@
   return retval;
 }
 
-profiler::profiler (void)
+profiler::profiler ()
   : m_known_functions (), m_fcn_index (),
     m_enabled (false), m_call_tree (new tree_node (nullptr, 0)),
     m_active_fcn (nullptr), m_last_time (-1.0)
 { }
 
-profiler::~profiler (void)
+profiler::~profiler ()
 {
   delete m_call_tree;
 }
@@ -253,7 +253,7 @@
 }
 
 void
-profiler::reset (void)
+profiler::reset ()
 {
   if (enabled ())
     error ("profile: can't reset active profiler");
@@ -272,7 +272,7 @@
 }
 
 octave_value
-profiler::get_flat (void) const
+profiler::get_flat () const
 {
   octave_value retval;
 
@@ -334,7 +334,7 @@
 }
 
 octave_value
-profiler::get_hierarchical (void) const
+profiler::get_hierarchical () const
 {
   octave_value retval;
 
@@ -360,7 +360,7 @@
 }
 
 double
-profiler::query_time (void) const
+profiler::query_time () const
 {
   sys::time now;
 
@@ -372,7 +372,7 @@
 }
 
 void
-profiler::add_current_time (void)
+profiler::add_current_time ()
 {
   if (m_active_fcn)
     {
--- a/libinterp/parse-tree/profiler.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/profiler.h	Fri Jun 23 20:51:51 2023 +0200
@@ -76,36 +76,28 @@
         }
     }
 
-    // No copying!
-
-    enter (const enter&) = delete;
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (enter)
 
-    enter& operator = (const enter&) = delete;
-
-    ~enter (void)
+    ~enter ()
     {
       if (m_enabled)
         m_profiler.exit_function (m_fcn);
     }
   };
 
-  profiler (void);
+  profiler ();
 
-  // No copying!
-
-  profiler (const profiler&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (profiler)
 
-  profiler& operator = (const profiler&) = delete;
+  virtual ~profiler ();
 
-  virtual ~profiler (void);
-
-  bool enabled (void) const { return m_enabled; }
+  bool enabled () const { return m_enabled; }
   void set_active (bool);
 
-  void reset (void);
+  void reset ();
 
-  octave_value get_flat (void) const;
-  octave_value get_hierarchical (void) const;
+  octave_value get_flat () const;
+  octave_value get_hierarchical () const;
 
 private:
 
@@ -115,7 +107,10 @@
   struct stats
   {
   public:
-    stats (void);
+
+    stats ();
+
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (stats)
 
     typedef std::set<octave_idx_type> function_set;
 
@@ -143,13 +138,9 @@
 
     tree_node (tree_node *, octave_idx_type);
 
-    virtual ~tree_node (void);
-
-    // No copying!
+    virtual ~tree_node ();
 
-    tree_node (const tree_node&) = delete;
-
-    tree_node& operator = (const tree_node&) = delete;
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_node)
 
     void add_time (double dt) { m_time += dt; }
 
@@ -212,12 +203,12 @@
   // This is not static because in the future, maybe we want a flag
   // in the profiler or something to choose between cputime, wall-time,
   // user-time, system-time, ...
-  double query_time (void) const;
+  double query_time () const;
 
   // Add the time elapsed since last_time to the function we're currently in.
   // This is called from two different positions, thus it is useful to have
   // it as a separate function.
-  void add_current_time (void);
+  void add_current_time ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-anon-scopes.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-anon-scopes.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,21 +41,17 @@
 {
 public:
 
-  tree_anon_scopes (void) = delete;
+  tree_anon_scopes () = delete;
 
   tree_anon_scopes (tree_anon_fcn_handle& anon_fh);
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_anon_scopes)
 
-  tree_anon_scopes (const tree_anon_scopes&) = delete;
-
-  tree_anon_scopes& operator = (const tree_anon_scopes&) = delete;
+  ~tree_anon_scopes () = default;
 
-  ~tree_anon_scopes (void) = default;
+  std::set<std::string> fcn_parameters () const { return m_params; }
 
-  std::set<std::string> fcn_parameters (void) const { return m_params; }
-
-  std::set<std::string> free_variables (void) const { return m_vars; }
+  std::set<std::string> free_variables () const { return m_vars; }
 
   // The following methods, though public, don't belong to the
   // intended user interface of this class.
--- a/libinterp/parse-tree/pt-arg-list.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-arg-list.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 
 // Argument lists.
 
-tree_argument_list::~tree_argument_list (void)
+tree_argument_list::~tree_argument_list ()
 {
   while (! empty ())
     {
@@ -66,7 +66,7 @@
 }
 
 bool
-tree_argument_list::all_elements_are_constant (void) const
+tree_argument_list::all_elements_are_constant () const
 {
   for (const tree_expression *elt : *this)
     {
@@ -78,7 +78,7 @@
 }
 
 bool
-tree_argument_list::is_valid_lvalue_list (void) const
+tree_argument_list::is_valid_lvalue_list () const
 {
   bool retval = true;
 
@@ -98,7 +98,7 @@
 }
 
 string_vector
-tree_argument_list::get_arg_names (void) const
+tree_argument_list::get_arg_names () const
 {
   int len = length ();
 
@@ -113,7 +113,7 @@
 }
 
 std::list<std::string>
-tree_argument_list::variable_names (void) const
+tree_argument_list::variable_names () const
 {
   std::list<std::string> retval;
 
--- a/libinterp/parse-tree/pt-arg-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-arg-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 
   typedef tree_expression *element_type;
 
-  tree_argument_list (void)
+  tree_argument_list ()
     : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false)
   { }
 
@@ -61,25 +61,21 @@
     : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false)
   { append (t); }
 
-  // No copying!
-
-  tree_argument_list (const tree_argument_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_argument_list)
 
-  tree_argument_list& operator = (const tree_argument_list&) = delete;
+  ~tree_argument_list ();
 
-  ~tree_argument_list (void);
-
-  bool has_magic_tilde (void) const
+  bool has_magic_tilde () const
   {
     return m_list_includes_magic_tilde;
   }
 
-  bool includes_magic_tilde (void) const
+  bool includes_magic_tilde () const
   {
     return m_list_includes_magic_tilde;
   }
 
-  tree_expression * remove_front (void)
+  tree_expression * remove_front ()
   {
     auto p = begin ();
     tree_expression *retval = *p;
@@ -89,17 +85,17 @@
 
   void append (const element_type& s);
 
-  void mark_as_simple_assign_lhs (void) { m_simple_assign_lhs = true; }
+  void mark_as_simple_assign_lhs () { m_simple_assign_lhs = true; }
 
-  bool is_simple_assign_lhs (void) { return m_simple_assign_lhs; }
+  bool is_simple_assign_lhs () { return m_simple_assign_lhs; }
 
-  bool all_elements_are_constant (void) const;
+  bool all_elements_are_constant () const;
 
-  bool is_valid_lvalue_list (void) const;
+  bool is_valid_lvalue_list () const;
 
-  string_vector get_arg_names (void) const;
+  string_vector get_arg_names () const;
 
-  std::list<std::string> variable_names (void) const;
+  std::list<std::string> variable_names () const;
 
   tree_argument_list * dup (symbol_scope& scope) const;
 
--- a/libinterp/parse-tree/pt-args-block.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-args-block.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -31,7 +31,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-tree_args_block_validation_list::~tree_args_block_validation_list (void)
+tree_args_block_validation_list::~tree_args_block_validation_list ()
 {
   while (! empty ())
     {
--- a/libinterp/parse-tree/pt-args-block.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-args-block.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,18 +49,14 @@
     : m_size_args (size_args)
   { }
 
-  // No copying!
-
-  tree_arg_size_spec (const tree_arg_size_spec&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_size_spec)
 
-  tree_arg_size_spec& operator = (const tree_arg_size_spec&) = delete;
-
-  ~tree_arg_size_spec (void)
+  ~tree_arg_size_spec ()
   {
     delete m_size_args;
   }
 
-  tree_argument_list * size_args (void) { return m_size_args; }
+  tree_argument_list * size_args () { return m_size_args; }
 
   void accept (tree_walker& tw)
   {
@@ -80,18 +76,14 @@
     : m_fcn_args (fcn_args)
   { }
 
-  // No copying!
-
-  tree_arg_validation_fcns (const tree_arg_validation_fcns&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_validation_fcns)
 
-  tree_arg_validation_fcns& operator = (const tree_arg_validation_fcns&) = delete;
-
-  ~tree_arg_validation_fcns (void)
+  ~tree_arg_validation_fcns ()
   {
     delete m_fcn_args;
   }
 
-  tree_argument_list * fcn_args (void) { return m_fcn_args; }
+  tree_argument_list * fcn_args () { return m_fcn_args; }
 
   void accept (tree_walker& tw)
   {
@@ -116,13 +108,9 @@
       m_default_value (default_value)
   { }
 
-  // No copying!
-
-  tree_arg_validation (const tree_arg_validation&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_validation)
 
-  tree_arg_validation& operator = (const tree_arg_validation&) = delete;
-
-  ~tree_arg_validation (void)
+  ~tree_arg_validation ()
   {
     delete m_arg_name;
     delete m_size_spec;
@@ -136,17 +124,17 @@
     m_arg_name = name;
   }
 
-  tree_expression * identifier_expression (void) { return m_arg_name; }
+  tree_expression * identifier_expression () { return m_arg_name; }
 
-  tree_arg_size_spec * size_spec (void) { return m_size_spec; }
+  tree_arg_size_spec * size_spec () { return m_size_spec; }
 
-  tree_identifier * class_name (void) { return m_class_name; }
+  tree_identifier * class_name () { return m_class_name; }
 
   tree_arg_validation_fcns *
-  validation_fcns (void) { return m_validation_fcns; }
+  validation_fcns () { return m_validation_fcns; }
 
   tree_expression *
-  initializer_expression (void) { return m_default_value; }
+  initializer_expression () { return m_default_value; }
 
   void accept (tree_walker& tw)
   {
@@ -169,7 +157,7 @@
 {
 public:
 
-  tree_args_block_validation_list (void) { }
+  tree_args_block_validation_list () { }
 
   tree_args_block_validation_list (tree_arg_validation *a) { append (a); }
 
@@ -177,13 +165,9 @@
     : base_list<tree_arg_validation *> (a)
   { }
 
-  // No copying!
-
-  tree_args_block_validation_list (const tree_args_block_validation_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_args_block_validation_list)
 
-  tree_args_block_validation_list& operator = (const tree_args_block_validation_list&) = delete;
-
-  ~tree_args_block_validation_list (void);
+  ~tree_args_block_validation_list ();
 
   void accept (tree_walker& tw)
   {
@@ -202,18 +186,14 @@
     : m_attr (attr)
   { }
 
-  // No copying!
-
-  tree_args_block_attribute_list (const tree_args_block_attribute_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_args_block_attribute_list)
 
-  tree_args_block_attribute_list& operator = (const tree_args_block_attribute_list&) = delete;
-
-  ~tree_args_block_attribute_list (void)
+  ~tree_args_block_attribute_list ()
   {
     delete m_attr;
   }
 
-  tree_identifier * attribute (void) { return m_attr; }
+  tree_identifier * attribute () { return m_attr; }
 
   void accept (tree_walker& tw)
   {
@@ -239,13 +219,9 @@
       m_lead_comm (nullptr), m_trail_comm (nullptr)
   { }
 
-  // No copying!
-
-  tree_arguments_block (const tree_arguments_block&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arguments_block)
 
-  tree_arguments_block& operator = (const tree_arguments_block&) = delete;
-
-  ~tree_arguments_block (void)
+  ~tree_arguments_block ()
   {
     delete m_attr_list;
     delete m_validation_list;
@@ -254,19 +230,19 @@
     delete m_trail_comm;
   }
 
-  tree_args_block_attribute_list * attribute_list (void)
+  tree_args_block_attribute_list * attribute_list ()
   {
     return m_attr_list;
   }
 
-  tree_args_block_validation_list * validation_list (void)
+  tree_args_block_validation_list * validation_list ()
   {
     return m_validation_list;
   }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-array-list.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-array-list.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-tree_array_list::~tree_array_list (void)
+tree_array_list::~tree_array_list ()
 {
   while (! empty ())
     {
@@ -45,7 +45,7 @@
 }
 
 bool
-tree_array_list::all_elements_are_constant (void) const
+tree_array_list::all_elements_are_constant () const
 {
   for (const tree_argument_list *elt : *this)
     {
--- a/libinterp/parse-tree/pt-array-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-array-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -58,15 +58,11 @@
 
 public:
 
-  // No copying!
-
-  tree_array_list (const tree_array_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_array_list)
 
-  tree_array_list& operator = (const tree_array_list&) = delete;
+  ~tree_array_list ();
 
-  ~tree_array_list (void);
-
-  bool all_elements_are_constant (void) const;
+  bool all_elements_are_constant () const;
 
   // 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
--- a/libinterp/parse-tree/pt-assign.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-assign.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -30,9 +30,9 @@
 #include <string>
 
 #include "error.h"
+#include "interpreter.h"
 #include "oct-lvalue.h"
 #include "ov.h"
-#include "parse.h"
 #include "pt-arg-list.h"
 #include "pt-assign.h"
 
@@ -48,7 +48,7 @@
     m_ans_assign (), m_etype (t)
 { }
 
-tree_simple_assignment::~tree_simple_assignment (void)
+tree_simple_assignment::~tree_simple_assignment ()
 {
   if (! m_preserve)
     delete m_lhs;
@@ -57,7 +57,7 @@
 }
 
 std::string
-tree_simple_assignment::oper (void) const
+tree_simple_assignment::oper () const
 {
   return octave_value::assign_op_as_string (m_etype);
 }
@@ -134,7 +134,10 @@
 
               octave_value_list args = ovl (lhs_val);
               args.stash_name_tags (string_vector (m_lhs->name ()));
-              feval ("display", args);
+
+              interpreter& interp = tw.get_interpreter ();
+
+              interp.feval ("display", args);
             }
         }
       catch (index_exception& ie)
@@ -156,7 +159,7 @@
   : tree_expression (l, c), m_lhs (lst), m_rhs (r), m_preserve (plhs)
 { }
 
-tree_multi_assignment::~tree_multi_assignment (void)
+tree_multi_assignment::~tree_multi_assignment ()
 {
   if (! m_preserve)
     delete m_lhs;
@@ -165,7 +168,7 @@
 }
 
 std::string
-tree_multi_assignment::oper (void) const
+tree_multi_assignment::oper () const
 {
   return octave_value::assign_op_as_string (op_type ());
 }
@@ -339,7 +342,10 @@
 
               octave_value_list args = ovl (lhs_val);
               args.stash_name_tags (string_vector (lhs_elt->name ()));
-              feval ("display", args);
+
+              interpreter& interp = tw.get_interpreter ();
+
+              interp.feval ("display", args);
             }
         }
 
--- a/libinterp/parse-tree/pt-assign.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-assign.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,23 +60,19 @@
                           bool plhs = false, int l = -1, int c = -1,
                           octave_value::assign_op t = octave_value::op_asn_eq);
 
-  // No copying!
-
-  tree_simple_assignment (const tree_simple_assignment&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_simple_assignment)
 
-  tree_simple_assignment& operator = (const tree_simple_assignment&) = delete;
+  ~tree_simple_assignment ();
 
-  ~tree_simple_assignment (void);
+  bool rvalue_ok () const { return true; }
 
-  bool rvalue_ok (void) const { return true; }
+  bool is_assignment_expression () const { return true; }
 
-  bool is_assignment_expression (void) const { return true; }
+  std::string oper () const;
 
-  std::string oper (void) const;
+  tree_expression * left_hand_side () { return m_lhs; }
 
-  tree_expression * left_hand_side (void) { return m_lhs; }
-
-  tree_expression * right_hand_side (void) { return m_rhs; }
+  tree_expression * right_hand_side () { return m_rhs; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -92,7 +88,7 @@
     tw.visit_simple_assignment (*this);
   }
 
-  octave_value::assign_op op_type (void) const { return m_etype; }
+  octave_value::assign_op op_type () const { return m_etype; }
 
 private:
 
@@ -131,23 +127,19 @@
   tree_multi_assignment (tree_argument_list *lst, tree_expression *r,
                          bool plhs = false, int l = -1, int c = -1);
 
-  // No copying!
-
-  tree_multi_assignment (const tree_multi_assignment&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_multi_assignment)
 
-  tree_multi_assignment& operator = (const tree_multi_assignment&) = delete;
+  ~tree_multi_assignment ();
 
-  ~tree_multi_assignment (void);
+  bool is_assignment_expression () const { return true; }
 
-  bool is_assignment_expression (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
-  bool rvalue_ok (void) const { return true; }
+  std::string oper () const;
 
-  std::string oper (void) const;
+  tree_argument_list * left_hand_side () { return m_lhs; }
 
-  tree_argument_list * left_hand_side (void) { return m_lhs; }
-
-  tree_expression * right_hand_side (void) { return m_rhs; }
+  tree_expression * right_hand_side () { return m_rhs; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -165,7 +157,7 @@
     tw.visit_multi_assignment (*this);
   }
 
-  octave_value::assign_op op_type (void) const
+  octave_value::assign_op op_type () const
   {
     return octave_value::op_asn_eq;
   }
--- a/libinterp/parse-tree/pt-binop.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-binop.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 }
 
 std::string
-tree_binary_expression::oper (void) const
+tree_binary_expression::oper () const
 {
   return octave_value::binary_op_as_string (m_etype);
 }
@@ -166,7 +166,7 @@
 // Boolean expressions.
 
 std::string
-tree_boolean_expression::oper (void) const
+tree_boolean_expression::oper () const
 {
   std::string retval = "<unknown>";
 
--- a/libinterp/parse-tree/pt-binop.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-binop.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,13 +62,9 @@
       m_preserve_operands (false)
   { }
 
-  // No copying!
-
-  tree_binary_expression (const tree_binary_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_binary_expression)
 
-  tree_binary_expression& operator = (const tree_binary_expression&) = delete;
-
-  ~tree_binary_expression (void)
+  ~tree_binary_expression ()
   {
     if (! m_preserve_operands)
       {
@@ -77,18 +73,18 @@
       }
   }
 
-  void preserve_operands (void) { m_preserve_operands = true; }
+  void preserve_operands () { m_preserve_operands = true; }
 
-  bool is_binary_expression (void) const { return true; }
+  bool is_binary_expression () const { return true; }
 
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
-  std::string oper (void) const;
+  std::string oper () const;
 
-  octave_value::binary_op op_type (void) const { return m_etype; }
+  octave_value::binary_op op_type () const { return m_etype; }
 
-  tree_expression * lhs (void) { return m_lhs; }
-  tree_expression * rhs (void) { return m_rhs; }
+  tree_expression * lhs () { return m_lhs; }
+  tree_expression * rhs () { return m_rhs; }
 
   void lhs (tree_expression *expr) { m_lhs = expr; }
   void rhs (tree_expression *expr) { m_rhs = expr; }
@@ -107,10 +103,11 @@
     tw.visit_binary_expression (*this);
   }
 
-  std::string profiler_name (void) const { return "binary " + oper (); }
+  std::string profiler_name () const { return "binary " + oper (); }
 
   void matlab_style_short_circuit_warning (const char *op);
 
+  virtual bool is_braindead () const { return false; }
 protected:
 
   // The operands for the expression.
@@ -132,27 +129,23 @@
 public:
 
   tree_braindead_shortcircuit_binary_expression (tree_expression *a,
-      tree_expression *b,
-      int l, int c,
-      octave_value::binary_op t)
+                                                 tree_expression *b,
+                                                 int l, int c,
+                                                 octave_value::binary_op t)
     : tree_binary_expression (a, b, l, c, t)
   { }
 
-  // No copying!
-
-  tree_braindead_shortcircuit_binary_expression
-  (const tree_braindead_shortcircuit_binary_expression&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_braindead_shortcircuit_binary_expression)
 
-  tree_braindead_shortcircuit_binary_expression&
-  operator = (const tree_braindead_shortcircuit_binary_expression&) = delete;
-
-  ~tree_braindead_shortcircuit_binary_expression (void) = default;
+  ~tree_braindead_shortcircuit_binary_expression () = default;
 
   tree_expression * dup (symbol_scope& scope) const;
 
   octave_value evaluate (tree_evaluator&, int nargout = 1);
 
   using tree_binary_expression::evaluate_n;
+
+  bool is_braindead () const { return true; }
 };
 
 // Boolean expressions.
@@ -175,21 +168,17 @@
                            int l = -1, int c = -1, type t = unknown)
     : tree_binary_expression (a, b, l, c), m_etype (t) { }
 
-  // No copying!
-
-  tree_boolean_expression (const tree_boolean_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_boolean_expression)
 
-  tree_boolean_expression& operator = (const tree_boolean_expression&) = delete;
+  ~tree_boolean_expression () = default;
 
-  ~tree_boolean_expression (void) = default;
+  bool is_boolean_expression () const { return true; }
 
-  bool is_boolean_expression (void) const { return true; }
-
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
-  std::string oper (void) const;
+  std::string oper () const;
 
-  type op_type (void) const { return m_etype; }
+  type op_type () const { return m_etype; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
--- a/libinterp/parse-tree/pt-bp.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-bp.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,15 +50,11 @@
       m_bp_list (), m_bp_cond_list ()
   { }
 
-  // No copying!
-
-  tree_breakpoint (const tree_breakpoint&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_breakpoint)
 
-  tree_breakpoint& operator = (const tree_breakpoint&) = delete;
+  ~tree_breakpoint () = default;
 
-  ~tree_breakpoint (void) = default;
-
-  bool success (void) const { return m_found; }
+  bool success () const { return m_found; }
 
   void visit_argument_list (tree_argument_list&);
 
@@ -147,11 +143,11 @@
 
   void visit_unwind_protect_command (tree_unwind_protect_command&);
 
-  octave_value_list get_list (void) { return m_bp_list; }
+  octave_value_list get_list () { return m_bp_list; }
 
-  octave_value_list get_cond_list (void) { return m_bp_cond_list; }
+  octave_value_list get_cond_list () { return m_bp_cond_list; }
 
-  int get_line (void) { return m_found ? m_line : 0; }
+  int get_line () { return m_found ? m_line : 0; }
 
 private:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode-vm-internal.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,416 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_pt_bytecode_vm_internal_h)
+#define octave_pt_bytecode_vm_internal_h 1
+
+#include "octave-config.h"
+
+#define EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK(ovl,n) \
+do {\
+  if (nargout <= 1)\
+    PUSH_OV (ovl.first_or_nil_ov());\
+else /* TODO: Should be function call to keep code shorter. */\
+  {\
+    int actual_nargout = 0;\
+\
+    int n_retval = std::min (static_cast<int> (ovl.length ()), static_cast<int> (nargout));\
+    /* We want to push the ovl backwards */\
+    for (int i = n_retval - 1; i >= 0 && actual_nargout < nargout; i--)\
+    {\
+      octave_value &arg = ovl (i);\
+\
+      if (arg.is_cs_list ())\
+        {\
+          /* cs-list are also pushed backwards */\
+          octave_value_list args = arg.list_value ();\
+          /* We might need to skip the elements in the cs-list's end */ \
+          int n_left = nargout - actual_nargout;\
+          for (int j = std::min (static_cast<int> (args.length () - 1), n_left - 1);\
+                j >= 0 && actual_nargout < nargout; \
+                j--)\
+            {\
+              PUSH_OV (args (j));\
+              actual_nargout++;\
+            }\
+        }\
+      else\
+        {\
+          PUSH_OV (std::move (arg));\
+          actual_nargout++;\
+        }\
+    }\
+\
+    /* TODO: Need errors here for missing arguments in assignment somehow */ \
+    if (actual_nargout != nargout)\
+      {\
+        int diff = nargout - actual_nargout;\
+        stack_element *start = sp - actual_nargout;\
+        stack_lift (start, actual_nargout, diff);\
+        sp += diff;\
+      }\
+  }\
+} while (0)
+
+
+#define MAKE_BINOP(op) \
+{                                       \
+  octave_value &rhs = TOP_OV ();        \
+  octave_value &lhs = SEC_OV ();        \
+                                        \
+  try                                   \
+    {                                   \
+      octave_value ans =                \
+        binary_op (*m_ti,               \
+                    octave_value::op,   \
+                    lhs, rhs);          \
+      STACK_DESTROY (2);                \
+      PUSH_OV (std::move (ans));        \
+    }                                   \
+  CATCH_INTERRUPT_EXCEPTION             \
+  CATCH_INDEX_EXCEPTION                 \
+  CATCH_EXECUTION_EXCEPTION             \
+  CATCH_BAD_ALLOC                       \
+}                                       \
+
+#define MAKE_BINOP_SPECIALIZED(op_fn,jmp_target,op_target,target_type) \
+{                                                                                        \
+  octave_value &rhs = TOP_OV ();                                                         \
+  octave_value_vm &lhs = SEC_OV_VM ();                                                   \
+                                                                                         \
+  int rhs_type = rhs.type_id ();                                                         \
+  int lhs_type = lhs.type_id ();                                                         \
+  int t_type = target_type;                                                              \
+  if (OCTAVE_UNLIKELY (rhs_type != lhs_type || rhs_type != t_type))                      \
+    {                                                                                    \
+      ip[-2] = static_cast<unsigned char> (INSTR::op_target);                            \
+      goto jmp_target;                                                                   \
+    }                                                                                    \
+                                                                                         \
+  try                                                                                    \
+    {                                                                                    \
+      lhs = op_fn (lhs.get_rep (), rhs.get_rep ());                                      \
+      rhs.~octave_value ();                                                              \
+      STACK_SHRINK (1);                                                                  \
+    }                                                                                    \
+  CATCH_INTERRUPT_EXCEPTION                                                              \
+  CATCH_INDEX_EXCEPTION                                                                  \
+  CATCH_EXECUTION_EXCEPTION                                                              \
+  CATCH_BAD_ALLOC                                                                        \
+}                                                                                        \
+
+#define MAKE_UNOP_SPECIALIZED(op_fn, jmp_target, op_target, target_type) \
+{                                                                                        \
+  octave_value &ov = TOP_OV ();                                                          \
+                                                                                         \
+  if (OCTAVE_UNLIKELY (ov.type_id () != target_type))                                    \
+    {                                                                                    \
+      /* Change the specialized opcode to the generic one */                             \
+      ip[-2] = static_cast<unsigned char> (INSTR::op_target);                            \
+      goto jmp_target;                                                                   \
+    }                                                                                    \
+                                                                                         \
+  try                                                                                    \
+    {                                                                                    \
+      ov = op_fn (ov.get_rep ());                                          \
+    }                                                                                    \
+  CATCH_INTERRUPT_EXCEPTION                                                              \
+  CATCH_INDEX_EXCEPTION                                                                  \
+  CATCH_EXECUTION_EXCEPTION                                                              \
+  CATCH_BAD_ALLOC                                                                        \
+}                                                                                        \
+
+#define MAKE_BINOP_SELFMODIFYING(op, jmp_target, op_target) \
+{                                                                                          \
+  octave_value &rhs = TOP_OV ();                                                           \
+  octave_value &lhs = SEC_OV ();                                                           \
+                                                                                           \
+  int rhs_type = rhs.type_id ();                                                           \
+  int lhs_type = lhs.type_id ();                                                           \
+  if (rhs_type == lhs_type && rhs_type == m_scalar_typeid)                                 \
+    {                                                                                      \
+      ip[-2] = static_cast<unsigned char> (INSTR::op_target);                              \
+      goto jmp_target;                                                                     \
+    }                                                                                      \
+                                                                                           \
+  try                                                                                      \
+    {                                                                                      \
+      octave_value ans =                                                                   \
+        binary_op (*m_ti,                                                                  \
+                    octave_value::op,                                                      \
+                    lhs, rhs);                                                             \
+      STACK_DESTROY (2);                                                                   \
+      PUSH_OV (std::move (ans));                                                           \
+    }                                                                                      \
+  CATCH_INTERRUPT_EXCEPTION                                                                \
+  CATCH_INDEX_EXCEPTION                                                                    \
+  CATCH_EXECUTION_EXCEPTION                                                                \
+  CATCH_BAD_ALLOC                                                                          \
+}                                                                                          \
+
+#define CATCH_INDEX_EXCEPTION \
+catch (index_exception& ie)                              \
+{                                                        \
+  (*sp++).pee = ie.dup ();                               \
+  (*sp++).i = static_cast<int> (error_type::INDEX_ERROR);\
+  goto unwind;                                           \
+}                                                        \
+
+#define CATCH_INDEX_EXCEPTION_WITH_NAME \
+catch (index_exception& ie)                              \
+{                                                        \
+  ie.set_var (name_data [slot]);                         \
+  (*sp++).pee = ie.dup ();                               \
+  (*sp++).i = static_cast<int> (error_type::INDEX_ERROR);\
+  goto unwind;                                           \
+}                                                        \
+
+#define CATCH_INDEX_EXCEPTION_WITH_MAYBE_NAME(has_name)  \
+catch (index_exception& ie)                              \
+{                                                        \
+  if (has_name)                                          \
+    ie.set_var (name_data [slot]);                       \
+  (*sp++).pee = ie.dup ();                               \
+  (*sp++).i = static_cast<int> (error_type::INDEX_ERROR);\
+  goto unwind;                                           \
+}                                                        \
+
+#define CATCH_INTERRUPT_EXCEPTION \
+catch (interrupt_exception& e)                                          \
+  {                                                                     \
+    (*sp++).i = static_cast<int>(error_type::INTERRUPT_EXC);            \
+    goto unwind;                                                        \
+  }                                                                     \
+
+#define CATCH_EXECUTION_EXCEPTION \
+catch (execution_exception& e)                                          \
+  {                                                                     \
+    /* TODO: Id? */                                                     \
+    (*sp++).pee = new execution_exception {e};                          \
+    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);           \
+                                                                        \
+    goto unwind;                                                        \
+  }                                                                     \
+
+#define CATCH_STACKPUSH_EXECUTION_EXCEPTION \
+catch (execution_exception& e)                                          \
+  {                                                                     \
+    m_could_not_push_frame = true;                                      \
+    (*sp++).pee = new execution_exception {e};                          \
+    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);           \
+                                                                        \
+    goto unwind;                                                        \
+  }                                                                     \
+
+#define CATCH_STACKPUSH_BAD_ALLOC \
+catch (const std::bad_alloc&)                                           \
+{                                                                       \
+  m_could_not_push_frame = true;                                        \
+  (*sp++).i = static_cast<int> (error_type::BAD_ALLOC);                 \
+                                                                        \
+  goto unwind;                                                          \
+}
+
+#define CATCH_EXIT_EXCEPTION \
+catch (const exit_exception& e)                                         \
+{                                                                       \
+  (*sp++).i = e.exit_status ();                                         \
+  (*sp++).i = e.safe_to_return ();                                      \
+  (*sp++).i = static_cast<int> (error_type::EXIT_EXCEPTION);            \
+                                                                        \
+  goto unwind;                                                          \
+}
+
+#define CATCH_BAD_ALLOC \
+catch (const std::bad_alloc&)                                           \
+{                                                                       \
+  (*sp++).i = static_cast<int> (error_type::BAD_ALLOC);                 \
+                                                                        \
+  goto unwind;                                                          \
+}
+
+#define MAKE_BYTECODE_CALL \
+if (sp + stack_min_for_new_call >= m_stack + stack_size)                                          \
+  {                                                                                               \
+    (*sp++).pee = new execution_exception {"error","","VM is running out of stack space"};        \
+    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);                                     \
+    goto unwind;                                                                                  \
+  }                                                                                               \
+/* We are now going to call another function */                                                   \
+/* compiled to bytecode */                                                                        \
+                                                                                                  \
+m_tw->set_active_bytecode_ip (ip - code);                                                         \
+stack_element *first_arg = sp - n_args_on_stack;                                                  \
+                                                                                                  \
+/* Push address to first arg (or would one would have been */                                     \
+/* if there are no args), so we can restore the sp at return */                                   \
+(*sp++).pse = first_arg;                                                                          \
+                                                                                                  \
+/* Push unwind data */                                                                            \
+(*sp++).pud = unwind_data;                                                                        \
+                                                                                                  \
+/* Push code */                                                                                   \
+(*sp++).puc = code;                                                                               \
+                                                                                                  \
+/* Push data */                                                                                   \
+(*sp++).pov = data;                                                                               \
+                                                                                                  \
+/* Push id names */                                                                               \
+(*sp++).ps = name_data;                                                                           \
+                                                                                                  \
+/* Push bsp */                                                                                    \
+(*sp++).pse = bsp;                                                                                \
+                                                                                                  \
+/* Push the instruction pointer */                                                                \
+/* (last on caller stack) */                                                                      \
+(*sp++).puc = ip;                                                                                 \
+                                                                                                  \
+/* set callee bsp */                                                                              \
+m_sp = bsp = sp;                                                                                  \
+                                                                                                  \
+/* Push nargout (first on callee stack) */                                                        \
+(*sp++).u = nargout;                                                                              \
+                                                                                                  \
+/* Set the new data, code etc */                                                                  \
+bytecode &bc = usr_fcn->get_bytecode ();                                                          \
+if (OCTAVE_UNLIKELY (m_profiler_enabled))                                                         \
+  {                                                                                               \
+    auto p = vm::m_vm_profiler;                                                                   \
+    if (p)                                                                                        \
+      {                                                                                           \
+        std::string caller_name = data[2].string_value (); /* profiler_name () querried at compile time */ \
+        p->enter_fn (caller_name, bc);                                                            \
+      }                                                                                           \
+  }                                                                                               \
+m_data = data = bc.m_data.data ();                                                                \
+m_code = code = bc.m_code.data ();                                                                \
+m_name_data = name_data = bc.m_ids.data ();                                                       \
+m_unwind_data = unwind_data = &bc.m_unwind_data;                                                  \
+                                                                                                  \
+                                                                                                  \
+/* Set the ip to 0 */                                                                             \
+ip = code;                                                                                        \
+int n_returns_callee = static_cast<signed char> (*ip++); /* Negative for varargout */             \
+n_returns_callee = n_returns_callee >= 0 ? n_returns_callee : -n_returns_callee;                  \
+int n_args_callee = static_cast<signed char> (*ip++); /* Negative for varargin */                 \
+int n_locals_callee = POP_CODE_USHORT ();                                                         \
+                                                                                                  \
+if (n_args_callee < 0)                                                                            \
+{                                                                                                 \
+  sp[0].pv = static_cast<void*> (usr_fcn);                                                        \
+  goto varargin_call;                                                                             \
+}                                                                                                 \
+                                                                                                  \
+/* Construct return values - note nargout */                                                      \
+/* is allready pushed as a uint64 */                                                              \
+for (int i = 1; i < n_returns_callee; i++)                                                        \
+  PUSH_OV ();                                                                                     \
+                                                                                                  \
+int ii;                                                                                           \
+int n_args_on_callee_stack = 0;                                                                   \
+/* Move the args to the new stack */                                                              \
+if (!has_cs_list_arg) /* TODO: Kludge. Move to beginning. */                                      \
+ {                                                                                                \
+    n_args_on_callee_stack = n_args_on_stack;                                                     \
+    for (ii = 0; ii < n_args_on_stack; ii++)                                                      \
+      {                                                                                           \
+        PUSH_OV (std::move (first_arg[ii].ov));                                                   \
+        /* Destroy the args */                                                                    \
+        first_arg[ii].ov.~octave_value ();                                                        \
+      }                                                                                           \
+  }                                                                                               \
+else                                                                                              \
+  {                                                                                               \
+    for (ii = 0; ii < n_args_on_stack; ii++)                                                      \
+      {                                                                                           \
+        octave_value &arg = first_arg[ii].ov;                                                     \
+                                                                                                  \
+        if (arg.is_cs_list ())                                                                    \
+          {                                                                                       \
+            /* TODO: Use opcode instead? */                                                       \
+            octave_value_list args = arg.list_value ();                                           \
+            for (int j = 0; j < args.length (); j++)                                              \
+              {                                                                                   \
+                PUSH_OV (args (j));                                                               \
+                n_args_on_callee_stack++;                                                         \
+              }                                                                                   \
+        }                                                                                         \
+      else                                                                                        \
+        {                                                                                         \
+          PUSH_OV (std::move (arg));                                                              \
+          n_args_on_callee_stack++;                                                               \
+        }                                                                                         \
+      /* Destroy the args */                                                                      \
+      arg.~octave_value ();                                                                       \
+    }                                                                                             \
+  }                                                                                               \
+/* Construct missing args */                                                                      \
+for (int i = n_args_on_callee_stack; i < n_args_callee; i++)                                      \
+  PUSH_OV ();                                                                                     \
+                                                                                                  \
+/* Construct locals */                                                                            \
+int n_locals_to_ctor =                                                                            \
+  n_locals_callee - n_args_callee - n_returns_callee;                                             \
+for (int i = 0; i < n_locals_to_ctor; i++)                                                        \
+  PUSH_OV ();                                                                                     \
+                                                                                                  \
+                                                                                                  \
+try                                                                                               \
+  {                                                                                               \
+    m_tw->push_stack_frame(*this, usr_fcn, nargout, n_args_on_callee_stack);                      \
+  }                                                                                               \
+CATCH_STACKPUSH_EXECUTION_EXCEPTION /* Sets m_could_not_push_frame to true */                     \
+CATCH_STACKPUSH_BAD_ALLOC                                                                         \
+                                                                                                  \
+/* "auto var" in the frame object. This is needed if nargout() etc are called */                  \
+set_nargout (nargout);                                                                            \
+/* Called fn needs to know about ignored outputs .e.g. [~, a] = foo() */                          \
+if (m_output_ignore_data)                                                                         \
+  {                                                                                               \
+    if (m_output_ignore_data->is_pending ())                                                      \
+      m_tw->set_auto_fcn_var (stack_frame::IGNORED, m_output_ignore_data->get_ignore_matrix ());  \
+    else                                                                                          \
+      m_tw->set_auto_fcn_var (stack_frame::IGNORED, {});                                          \
+    m_output_ignore_data->m_v_lvalue_list.push_back (m_tw->lvalue_list ());                       \
+    m_tw->set_lvalue_list (nullptr);                                                              \
+  }                                                                                               \
+                                                                                                  \
+if (n_args_on_callee_stack > n_args_callee)                                                       \
+  {                                                                                               \
+    (*sp++).pee = new execution_exception {"error","","function called with too many inputs"};    \
+    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);                                     \
+    goto unwind;                                                                                  \
+  }                                                                                               \
+/* N_RETURNS is negative for varargout */                                                         \
+int n_returns = N_RETURNS () - 1; /* %nargout in N_RETURNS */                                     \
+if (n_returns >= 0 && nargout > n_returns)                                                        \
+  {                                                                                               \
+    (*sp++).pee = new execution_exception {"error","","function called with too many outputs"};   \
+    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);                                     \
+    goto unwind;                                                                                  \
+  }                                                                                               \
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,6766 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <iostream>
+
+#include "time-wrappers.h"
+
+#include "pt-bytecode-vm.h"
+#include "pt-bytecode-vm-internal.h"
+#include "ov.h"
+#include "error.h"
+#include "symtab.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "pt-eval.h"
+#include "pt-tm-const.h"
+#include "pt-stmt.h"
+#include "ov-classdef.h"
+#include "ov-ref.h"
+#include "ov-range.h"
+#include "ov-inline.h"
+
+#include "ov-vm.h"
+
+//#pragma GCC optimize("O0")
+
+extern "C" void vm_debug_print_ovl (void *p);
+extern "C" void vm_debug_print_ov (void *p);
+static bool ov_need_stepwise_subsrefs (octave_value &ov);
+static void copy_many_args_to_caller (octave::stack_element *sp, octave::stack_element *caller_stack_end,
+                                      int n_args_to_move, int n_args_caller_expects);
+static int lhs_assign_numel (octave_value &ov, const std::string& type, const std::list<octave_value_list>& idx);
+
+#define TODO(msg) error("Not done yet %d: " msg, __LINE__)
+#define ERR(msg) error("VM error %d: " msg, __LINE__)
+#define CHECK(cond)                                                            \
+  do {                                                                         \
+    if (!(cond))                                                               \
+      ERR("Internal VM conistency check failed, " #cond);                      \
+  } while ((0))
+#define PANIC(msg) error("VM panic %d: " msg, __LINE__)
+
+using namespace octave;
+
+static unsigned
+chars_to_uint (unsigned char *p)
+{
+  unsigned u = 0;
+  u |= *p++;
+  u |= *p++ << 8;
+  u |= *p++ << 16;
+  u |= *p << 24;
+
+  return u;
+}
+
+std::vector<std::pair<int, std::string>>
+octave::opcodes_to_strings (bytecode &bc)
+{
+  return opcodes_to_strings (bc.m_code, bc.m_ids);
+}
+
+std::vector<std::pair<int, std::string>>
+octave::opcodes_to_strings (std::vector<unsigned char> &v_code, std::vector<std::string> &names)
+{
+  unsigned char *p = v_code.data ();
+  unsigned char *code = p;
+  int n = v_code.size ();
+  bool wide_opext_active = false;
+
+  // Skip some framedata
+  p += 4;
+
+  std::vector<std::pair<int, std::string>> v_pair_row_str;
+
+#define CASE_START(type) \
+  case INSTR::type:                     \
+  { /* Line stored in s */              \
+  std::string s;                        \
+  /* Code offset */                     \
+  int ip = static_cast<int> (p - code); \
+  s += #type;                           \
+  /* vec for id names */                \
+  std::vector<std::string> v_ids;       \
+
+#define CASE_END()        \
+    if (v_ids.size ())                  \
+      {                                 \
+        s += " #";                      \
+        for (auto ss : v_ids)           \
+          s += " " + ss;                \
+      }                                 \
+    v_pair_row_str.push_back ({ip, s}); \
+    break;}                             \
+
+#define PRINT_OP(type)    \
+  CASE_START (type)       \
+  CASE_END ()             \
+
+#define PCHAR() \
+    {p++;                               \
+    CHECK_END ();                       \
+    s += " " + std::to_string (*p);}
+
+#define PCHAR_AS_CHAR() \
+    {p++;                                     \
+    CHECK_END ();                             \
+    s += std::string {" '"} + static_cast<char> (*p) + "'";}
+
+#define PSHORT() \
+    {p++;                           \
+    CHECK_END ();                   \
+    unsigned char b0 = *p;          \
+    p++;                            \
+    CHECK_END ();                   \
+    unsigned char b1 = *p;          \
+    unsigned u = b0 | (b1 << 8);    \
+    s += " " + std::to_string (u);}
+
+#define PSSLOT() \
+    {p++;                                                            \
+    CHECK_END ();                                                    \
+    s += " " + std::to_string (*p);                                  \
+    v_ids.push_back (std::string {*p < names.size() ?                \
+                                      names[*p].c_str() :            \
+                                      "INVALID SLOT"});}
+
+#define PSLOT() \
+    {if (wide_opext_active)                                         \
+      PWSLOT ()                                                     \
+    else                                                            \
+      PSSLOT ()                                                     \
+    wide_opext_active = false;}
+
+#define PWSLOT() \
+    {p++;                                                           \
+    CHECK_END ();                                                   \
+    unsigned char b0 = *p;                                          \
+    p++;                                                            \
+    CHECK_END ();                                                   \
+    unsigned char b1 = *p;                                          \
+    unsigned u = b0 | (b1 << 8);                                    \
+    s += " " + std::to_string (u);                                  \
+    v_ids.push_back (std::string {u < names.size() ?                \
+                                      names[u].c_str() :            \
+                                      "INVALID SLOT"});}
+
+#define CHECK_END() \
+  do {if (p >= v_code.data () + v_code.size ()) { error ("Invalid bytecode\n");}} while((0))
+
+#define PINT() \
+  do {\
+    unsigned u = 0;\
+    p++;\
+    CHECK_END ();\
+    u |= *p++;\
+    CHECK_END ();\
+    u |= *p++ << 8;\
+    CHECK_END ();\
+    u |= *p++ << 16;\
+    CHECK_END ();\
+    u |= *p << 24;\
+    s += " " + std::to_string (u);\
+  } while (0);
+
+  while (p < code + n)
+    {
+      switch (static_cast<INSTR> (*p))
+        {
+
+          PRINT_OP (POP)
+          PRINT_OP (DUP)
+          PRINT_OP (MUL)
+          PRINT_OP (MUL_DBL)
+          PRINT_OP (ADD)
+          PRINT_OP (ADD_DBL)
+          PRINT_OP (SUB)
+          PRINT_OP (SUB_DBL)
+          PRINT_OP (DIV)
+          PRINT_OP (DIV_DBL)
+          PRINT_OP (RET)
+          PRINT_OP (LE)
+          PRINT_OP (LE_DBL)
+          PRINT_OP (LE_EQ)
+          PRINT_OP (LE_EQ_DBL)
+          PRINT_OP (GR)
+          PRINT_OP (GR_DBL)
+          PRINT_OP (GR_EQ)
+          PRINT_OP (GR_EQ_DBL)
+          PRINT_OP (EQ)
+          PRINT_OP (EQ_DBL)
+          PRINT_OP (NEQ)
+          PRINT_OP (NEQ_DBL)
+          PRINT_OP (TRANS_MUL)
+          PRINT_OP (MUL_TRANS)
+          PRINT_OP (HERM_MUL)
+          PRINT_OP (MUL_HERM)
+          PRINT_OP (INCR_PREFIX)
+          PRINT_OP (ROT)
+          PRINT_OP (TRANS_LDIV)
+          PRINT_OP (HERM_LDIV)
+          PRINT_OP (PUSH_CELL)
+          PRINT_OP (PUSH_OV_U64)
+          PRINT_OP (EXPAND_CS_LIST)
+          PRINT_OP (POW_DBL)
+          PRINT_OP (POW)
+          PRINT_OP (LDIV)
+          PRINT_OP (EL_MUL)
+          PRINT_OP (EL_DIV)
+          PRINT_OP (EL_POW)
+          PRINT_OP (EL_AND)
+          PRINT_OP (EL_OR)
+          PRINT_OP (EL_LDIV)
+          PRINT_OP (NOT_DBL)
+          PRINT_OP (NOT_BOOL)
+          PRINT_OP (NOT)
+          PRINT_OP (UADD)
+          PRINT_OP (USUB)
+          PRINT_OP (USUB_DBL)
+          PRINT_OP (TRANS)
+          PRINT_OP (HANDLE_SIGNALS)
+          PRINT_OP (HERM)
+          PRINT_OP (UNARY_TRUE)
+          PRINT_OP (PUSH_TRUE)
+          PRINT_OP (PUSH_FALSE)
+          PRINT_OP (COLON2)
+          PRINT_OP (COLON3)
+          PRINT_OP (COLON2_CMD)
+          PRINT_OP (COLON3_CMD)
+          PRINT_OP (FOR_SETUP)
+          PRINT_OP (PUSH_NIL);
+          PRINT_OP (THROW_IFERROBJ);
+          PRINT_OP (BRAINDEAD_PRECONDITION);
+          PRINT_OP (PUSH_DBL_0);
+          PRINT_OP (PUSH_DBL_1);
+          PRINT_OP (PUSH_DBL_2);
+
+          CASE_START (WIDE)
+            wide_opext_active = true;
+          CASE_END ()
+
+          CASE_START (PUSH_FOLDED_CST) PSLOT () PSHORT () CASE_END ()
+          CASE_START (SET_FOLDED_CST) PSLOT () CASE_END ()
+
+          CASE_START (LOAD_CST)       PCHAR () CASE_END ()
+          CASE_START (LOAD_CST_ALT2)  PCHAR () CASE_END ()
+          CASE_START (LOAD_CST_ALT3)  PCHAR () CASE_END ()
+          CASE_START (LOAD_CST_ALT4)  PCHAR () CASE_END ()
+          CASE_START (LOAD_2_CST)     PCHAR () CASE_END ()
+          CASE_START (POP_N_INTS)     PCHAR () CASE_END ()
+
+          CASE_START (ASSIGN)                     PSLOT() CASE_END ()
+          CASE_START (BIND_ANS)                   PSLOT() CASE_END ()
+          CASE_START (INCR_ID_PREFIX)             PSLOT() CASE_END ()
+          CASE_START (INCR_ID_POSTFIX)            PSLOT() CASE_END ()
+          CASE_START (DECR_ID_PREFIX)             PSLOT() CASE_END ()
+          CASE_START (DECR_ID_POSTFIX)            PSLOT() CASE_END ()
+          CASE_START (INCR_ID_PREFIX_DBL)         PSLOT() CASE_END ()
+          CASE_START (INCR_ID_POSTFIX_DBL)        PSLOT() CASE_END ()
+          CASE_START (DECR_ID_PREFIX_DBL)         PSLOT() CASE_END ()
+          CASE_START (DECR_ID_POSTFIX_DBL)        PSLOT() CASE_END ()
+          CASE_START (FORCE_ASSIGN)               PSLOT() CASE_END ()
+          CASE_START (PUSH_SLOT_NARGOUT1)         PSLOT() CASE_END ()
+          CASE_START (PUSH_PI)                    PSLOT() CASE_END ()
+          CASE_START (PUSH_SLOT_NARGOUT1_SPECIAL) PSLOT() CASE_END ()
+          CASE_START (PUSH_SLOT_INDEXED)          PSLOT() CASE_END ()
+          CASE_START (PUSH_FCN_HANDLE)            PSLOT() CASE_END ()
+          CASE_START (PUSH_SLOT_NARGOUT0)         PSLOT() CASE_END ()
+          CASE_START (SET_SLOT_TO_STACK_DEPTH)    PSLOT() CASE_END ()
+
+          CASE_START (DISP)           PSLOT() PWSLOT() CASE_END ()
+          CASE_START (PUSH_SLOT_DISP) PSLOT() PWSLOT() CASE_END ()
+
+          CASE_START (JMP_IFDEF)                PSHORT() CASE_END ()
+          CASE_START (JMP_IFNCASEMATCH)         PSHORT() CASE_END ()
+          CASE_START (JMP)                      PSHORT() CASE_END ()
+          CASE_START (JMP_IF)                   PSHORT() CASE_END ()
+          CASE_START (JMP_IFN)                  PSHORT() CASE_END ()
+          CASE_START (JMP_IF_BOOL)              PSHORT() CASE_END ()
+          CASE_START (JMP_IFN_BOOL)             PSHORT() CASE_END ()
+          CASE_START (FOR_COMPLEX_SETUP)        PSHORT() CASE_END ()
+
+          CASE_START (ASSIGN_COMPOUND)        PSLOT () PCHAR () CASE_END ()
+
+          CASE_START (INDEX_ID_NARGOUT0)      PSLOT () PCHAR () CASE_END ()
+          CASE_START (INDEX_ID_NARGOUT1)      PSLOT () PCHAR () CASE_END ()
+          CASE_START (INDEX_ID1_MAT_2D)       PSLOT () PCHAR () CASE_END ()
+          CASE_START (INDEX_ID1_MAT_1D)       PSLOT () PCHAR () CASE_END ()
+
+          CASE_START (INDEX_CELL_ID_NARGOUT0) PSLOT () PCHAR () CASE_END ()
+          CASE_START (INDEX_CELL_ID_NARGOUT1) PSLOT () PCHAR () CASE_END ()
+
+          CASE_START (INDEX_CELL_ID_NARGOUTN) PSLOT () PCHAR () PCHAR () CASE_END ()
+          CASE_START (INDEX_IDN)              PSLOT () PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (SUBASSIGN_OBJ)          PCHAR () PCHAR () CASE_END ()
+          CASE_START (MATRIX)                 PCHAR () PCHAR () CASE_END ()
+          CASE_START (DUPN)                   PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (INDEX_ID1_MATHY_UFUN)   PCHAR () PSLOT () PCHAR () CASE_END ()
+
+          CASE_START (INDEX_OBJ)              PCHAR () PCHAR () PWSLOT () PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (FOR_COND) PSLOT () PSHORT () CASE_END ()
+
+          CASE_START (FOR_COMPLEX_COND) PSHORT () PWSLOT () PWSLOT () CASE_END ()
+
+          CASE_START (INDEX_STRUCT_NARGOUTN)  PCHAR () PWSLOT () PWSLOT () CASE_END ()
+          CASE_START (END_ID)                 PSLOT () PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (PUSH_SLOT_NARGOUTN)     PSLOT () PCHAR () CASE_END ()
+          CASE_START (BRAINDEAD_WARNING)      PSLOT () PCHAR () CASE_END ()
+          CASE_START (SUBASSIGN_STRUCT)       PSLOT () PWSLOT () CASE_END ()
+
+          CASE_START (SUBASSIGN_ID)         PSLOT () PCHAR () CASE_END ()
+          CASE_START (SUBASSIGN_ID_MAT_1D)  PSLOT () PCHAR () CASE_END ()
+          CASE_START (SUBASSIGN_CELL_ID)    PSLOT () PCHAR () CASE_END ()
+
+          CASE_START (EVAL) PCHAR () PINT () CASE_END ()
+
+          CASE_START (PUSH_ANON_FCN_HANDLE) PINT () CASE_END ()
+
+          CASE_START (INDEX_STRUCT_CALL)
+            PCHAR ()
+            PCHAR ()
+            PCHAR ()
+            PCHAR ()
+            int nn = *p;
+            s += " {";
+            for (int i = 0; i < nn; i++)
+              {
+                PCHAR ()
+                PCHAR_AS_CHAR ()
+                if (i + 1 != nn)
+                  s += ", ";
+              }
+            s += "} ";
+          CASE_END ()
+
+          CASE_START (LOAD_FAR_CST) PINT () CASE_END ()
+
+          CASE_START (END_OBJ) PSLOT () PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (WORDCMD) PSLOT () PCHAR () PCHAR () CASE_END ()
+
+          CASE_START (SET_IGNORE_OUTPUTS)
+            PCHAR ()
+            int nn = *p;
+            PCHAR ()
+            for (int i = 0; i < nn; i++)
+              PCHAR ()
+          CASE_END ()
+
+          CASE_START (CLEAR_IGNORE_OUTPUTS)
+            PCHAR ()
+            int nn = *p;
+            for (int i = 0; i < nn; i++)
+              {
+                PWSLOT ()
+              }
+          CASE_END ()
+
+          CASE_START (END_X_N)
+            PCHAR ()
+
+            int nn = *p;
+            for (int i = 0; i < nn; i++)
+              {
+                PCHAR ()
+                PCHAR ()
+                PCHAR ()
+                PWSLOT ()
+              }
+          CASE_END ()
+
+          CASE_START (MATRIX_UNEVEN)
+            s += " TYPE";
+            PCHAR ()
+            int type = *p;
+
+            if (type == 1)
+              {
+                s += " ROWS"; PINT ();
+                s += " COLS"; PINT ();
+              }
+            else
+              {
+                if (p + 3 >= code + n)
+                  error ("Invalid bytecode\n");
+                int i = chars_to_uint (p);
+                s += " ROWS"; PINT ();
+                s += " COLS";
+                for (int j = 0; j < i; j++)
+                  PINT ();
+              }
+          CASE_END ()
+
+          CASE_START (SUBASSIGN_CHAINED)
+            PCHAR (); // op
+            PCHAR (); // nchained
+            int nn = *p;
+            for (int i = 0; i < nn; i++)
+              {
+                PCHAR ();
+                PCHAR ();
+              }
+          CASE_END ()
+
+          CASE_START (GLOBAL_INIT)
+              p++;
+              CHECK_END ();
+              if (static_cast<global_type> (*p) == global_type::GLOBAL)
+                s += " 'GLOBAL'";
+              else if (static_cast<global_type> (*p) == global_type::PERSISTENT)
+                s += " 'PERSISTENT'";
+
+              PWSLOT ()
+              PWSLOT ()
+
+              s += " HAS-TARGET";
+              PCHAR ()
+              int has_target = *p;
+              if (has_target)
+                {
+                  s += " AFTER INIT";
+                  PSHORT ();
+                }
+          CASE_END ()
+
+          CASE_START (ASSIGNN)
+            PCHAR ()
+            int n_slots = *p;
+            for (int i = 0; i < n_slots; i++)
+              PWSLOT ()
+          CASE_END ()
+
+          default:
+            CHECK_END ();
+            error ("Unknown op: %d\n", *p);
+            break;
+        }
+      p++;
+    }
+
+  return v_pair_row_str;
+}
+
+void
+octave::print_bytecode(bytecode &bc)
+{
+  unsigned char *p = bc.m_code.data ();
+  int n = bc.m_code.size ();
+
+  CHECK (bc.m_data.size () >= 2);
+  printf ("metadata:\n");
+  printf ("\t%s\n", bc.m_data[0].string_value ().c_str ()); // function name
+  printf ("\t%s\n\n", bc.m_data[1].string_value ().c_str ()); // function type
+
+  printf("frame:\n");
+  printf("\t.n_return %d\n", *p++);
+  printf("\t.n_args %d\n", *p++);
+  printf("\t.n_locals %d\n\n", *p++);
+
+  printf("slots:\n");
+  int idx = 0;
+  for (std::string local : bc.m_ids)
+    printf("%5d: %s\n", idx++, local.c_str ());
+  printf ("\n");
+
+  printf ("source code lut:\n");
+  for (auto it : bc.m_unwind_data.m_loc_entry)
+    {
+      printf ("\tl:%5d c:%5d ip0:%5d ip1:%5d\n", it.m_line, it.m_col, it.m_ip_start, it.m_ip_end);
+    }
+
+  printf ("dbg tree object:\n");
+  for (auto it : bc.m_unwind_data.m_ip_to_tree)
+    {
+      printf ("\tip:%5d obj=%p\n", it.first, it.second);
+    }
+
+  printf("code: (n=%d)\n", n);
+  auto v_ls = opcodes_to_strings (bc);
+  for (auto ls : v_ls)
+    {
+      printf ("\t%5d: %s\n", ls.first, ls.second.c_str ());
+    }
+}
+
+static int pop_code_int (unsigned char *ip)
+{
+  unsigned int ans;
+  ip -= 4;
+  ans = *ip++;
+  ans |= *ip++ << 8;
+  ans |= *ip++ << 16;
+  ans |= *ip++ << 24;
+
+  return ans;
+}
+
+static int pop_code_ushort (unsigned char *ip)
+{
+  unsigned int ans;
+  ip -= 2;
+  ans = *ip++;
+  ans |= *ip++ << 8;
+
+  return ans;
+}
+
+
+
+// Debug functions easy to break out into in gdb. Called by __dummy_mark_1() in Octave
+extern "C" void dummy_mark_1 (void);
+extern "C" void dummy_mark_2 (void);
+
+#define POP_CODE() *ip++
+#define POP_CODE_INT() (ip++,ip++,ip++,ip++,pop_code_int (ip))
+#define POP_CODE_USHORT() (ip++, ip++, pop_code_ushort (ip))
+
+#define PUSH_OV(ov) \
+  do {                           \
+    new (sp++) octave_value (ov);  \
+  } while ((0))
+
+#define PUSH_OVB(ovb) \
+  do {                           \
+    new (sp++) octave_value_vm (ovb);  \
+  } while ((0))
+
+#define PUSH_OV_VM(ov) \
+  do {                           \
+    new (sp++) octave_value_vm (ov);  \
+  } while ((0))
+
+#define POP() (*--sp)
+
+#define TOP_OVB() (sp[-1]).ovb
+#define SEC_OVB() (sp[-2]).ovb
+
+#define TOP_OV_VM() (sp[-1]).ov_vm
+#define SEC_OV_VM() (sp[-2]).ov_vm
+
+#define TOP_OV() (sp[-1]).ov
+#define SEC_OV() (sp[-2]).ov
+#define THIRD_OV() (sp[-3]).ov
+#define FOURTH_OV() (sp[-4]).ov
+
+#define TOP() (sp[-1])
+#define SEC() (sp[-2])
+#define THIRD() (sp[-3])
+
+#define STACK_SHRINK(n) sp -= n
+#define STACK_GROW(n) sp += n
+#define STACK_DESTROY(n)               \
+  do {                                 \
+    for (int iii = 0; iii < n; iii++)  \
+      (*--sp).ov.~octave_value ();     \
+  } while ((0))
+
+static void stack_lift (stack_element *start, int n_elem, int n_lift)
+{
+  octave_value_list tmp;
+  for (int i = 0; i < n_elem; i++)
+    tmp.append (std::move (start[i].ov));
+  for (int i = 0; i < n_elem; i++)
+    start[i].ov.~octave_value ();
+  for (int i = 0; i < n_lift; i++)
+    new (start + i) octave_value;
+  for (int i = 0; i < n_elem; i++)
+    new (start + n_lift + i) octave_value (std::move (tmp.xelem (i)));
+}
+
+#define COMMA ,
+#define PRINT_VM_STATE(msg)                                                    \
+  do {                                                                         \
+    printf(msg);                                                               \
+    printf("\n");                                                              \
+    printf("sp  : %p\n", sp);                                                  \
+    printf("bsp : %p\n", bsp);                                                 \
+    printf("sp i: %zu\n", sp - bsp);                                           \
+    printf("sp ii: %zu\n", sp - m_stack);                                      \
+    printf("ip  : %zu\n", ip - code);                                          \
+    printf("code: %p\n", code);                                                \
+    printf("data: %p\n", data);                                                \
+    printf("ids : %p\n", name_data);                                           \
+    printf("fn  : %s\n", m_tw->get_current_stack_frame ()->fcn_name ().c_str ());\
+    printf("Next op: %u\n\n", *ip);\
+  } while ((0))
+
+#define CHECK_STACK(n) \
+  do {\
+    for (unsigned i = 0; i < stack_pad; i++)\
+      {\
+        CHECK (m_stack0[i].u == stack_magic_int);\
+        CHECK (m_stack0[i + stack_size].u == stack_magic_int);\
+      }\
+    CHECK (sp <= m_stack + stack_size);\
+    CHECK (sp + n <= m_stack + stack_size);\
+    CHECK (sp >= m_stack);\
+  } while (0)
+
+#define CHECK_STACK_N(n) CHECK (sp + n <= m_stack + stack_size)
+
+// Access the octave_base_value as subclass type of an octave_value ov
+#define REP(type,ov) static_cast<type&> (const_cast<octave_base_value &> (ov.get_rep()))
+
+#define DISPATCH() do { \
+  /*if (!m_tw->get_current_stack_frame ()->is_bytecode_fcn_frame ()) \
+    { \
+      printf ("Why oh why\n"); \
+      dummy_mark_1 (); \
+    } */ \
+  /* PRINT_VM_STATE ("%d" COMMA __LINE__); */ \
+  /* CHECK_STACK (0); */ \
+\
+  if (OCTAVE_UNLIKELY (m_tw->debug_mode ())) /* Do we need to check for breakpoints? */\
+    goto debug_check;\
+  int opcode = ip[0];\
+  arg0 = ip[1];\
+  ip += 2;\
+  goto *instr [opcode]; /* Dispatch to next instruction */\
+} while ((0))
+
+#define DISPATCH_1BYTEOP() do { \
+  /*if (!m_tw->get_current_stack_frame ()->is_bytecode_fcn_frame ()) \
+    { \
+      printf ("Why oh why\n"); \
+      dummy_mark_1 (); \
+    } */ \
+  /* PRINT_VM_STATE ("%d" COMMA __LINE__); */ \
+  /* CHECK_STACK (0); */ \
+\
+  if (OCTAVE_UNLIKELY (m_tw->debug_mode ())) /* Do we need to check for breakpoints? */\
+    goto debug_check_1b;\
+  int opcode = arg0;\
+  arg0 = *ip++;\
+  goto *instr [opcode]; /* Dispatch to next instruction */\
+} while ((0))
+
+std::shared_ptr<vm_profiler> vm::m_vm_profiler;
+bool vm::m_profiler_enabled;
+bool vm::m_trace_enabled;
+
+// These two are used for pushing true and false ov:s to the
+// operand stack.
+static octave_value ov_true {true};
+static octave_value ov_false {false};
+#if defined (M_PI)
+  static octave_value ov_pi {M_PI};
+#else
+  // Initialized in vm::vm()
+  static octave_value ov_pi;
+#endif
+static octave_value ov_dbl_0 {0.0};
+static octave_value ov_dbl_1 {1.0};
+static octave_value ov_dbl_2 {2.0};
+
+// TODO: Push non-nil and nil ov instead of true false to make some checks
+//       faster? Would they be faster?
+
+octave_value_list
+vm::execute_code (const octave_value_list &root_args, int root_nargout)
+{
+  // This field is set to true at each return from this function so we can
+  // assure in the caller that no exception escapes the VM in some way.
+  this->m_dbg_proper_return = false;
+
+  // Array of label pointers, corresponding to opcodes by position in
+  // the array. "&&" is label address, not rvalue reference.
+  static const void* instr[] =
+    {
+      &&pop,                                               // POP,
+      &&dup,                                               // DUP,
+      &&load_cst,                                          // LOAD_CST,
+      &&mul,                                               // MUL,
+      &&div,                                               // DIV,
+      &&add,                                               // ADD,
+      &&sub,                                               // SUB,
+      &&ret,                                               // RET,
+      &&assign,                                            // ASSIGN,
+      &&jmp_if,                                            // JMP_IF,
+      &&jmp,                                               // JMP,
+      &&jmp_ifn,                                           // JMP_IFN,
+      &&push_slot_nargout0,                                // PUSH_SLOT_NARGOUT0,
+      &&le,                                                // LE,
+      &&le_eq,                                             // LE_EQ,
+      &&gr,                                                // GR,
+      &&gr_eq,                                             // GR_EQ,
+      &&eq,                                                // EQ,
+      &&neq,                                               // NEQ,
+      &&index_id_nargout0,                                 // INDEX_ID_NARGOUT0,
+      &&push_slot_indexed,                                 // PUSH_SLOT_INDEXED,
+      &&pow,                                               // POW,
+      &&ldiv,                                              // LDIV,
+      &&el_mul,                                            // EL_MUL,
+      &&el_div,                                            // EL_DIV,
+      &&el_pow,                                            // EL_POW,
+      &&el_and,                                            // EL_AND,
+      &&el_or,                                             // EL_OR,
+      &&el_ldiv,                                           // EL_LDIV,
+      &&op_not,                                            // NOT,
+      &&uadd,                                              // UADD,
+      &&usub,                                              // USUB,
+      &&trans,                                             // TRANS,
+      &&herm,                                              // HERM,
+      &&incr_id_prefix,                                    // INCR_ID_PREFIX,
+      &&decr_id_prefix,                                    // DECR_ID_PREFIX,
+      &&incr_id_postfix,                                   // INCR_ID_POSTFIX,
+      &&decr_id_postfix,                                   // DECR_ID_POSTFIX,
+      &&for_setup,                                         // FOR_SETUP,
+      &&for_cond,                                          // FOR_COND,
+      &&pop_n_ints,                                        // POP_N_INTS,
+      &&push_slot_nargout1,                                // PUSH_SLOT_NARGOUT1,
+      &&index_id1,                                         // INDEX_ID_NARGOUT1,
+      &&push_fcn_handle,                                   // PUSH_FCN_HANDLE,
+      &&colon,                                             // COLON3,
+      &&colon,                                             // COLON2,
+      &&colon_cmd,                                         // COLON3_CMD,
+      &&colon_cmd,                                         // COLON2_CMD,
+      &&push_true,                                         // PUSH_TRUE,
+      &&push_false,                                        // PUSH_FALSE,
+      &&unary_true,                                        // UNARY_TRUE,
+      &&index_idn,                                         // INDEX_IDN,
+      &&assign_n,                                          // ASSIGNN,
+      &&push_slot_nargoutn,                                // PUSH_SLOT_NARGOUTN,
+      &&subassign_id,                                      // SUBASSIGN_ID,
+      &&end_id,                                            // END_ID,
+      &&matrix,                                            // MATRIX,
+      &&trans_mul,                                         // TRANS_MUL,
+      &&mul_trans,                                         // MUL_TRANS,
+      &&herm_mul,                                          // HERM_MUL,
+      &&mul_herm,                                          // MUL_HERM,
+      &&trans_ldiv,                                        // TRANS_LDIV,
+      &&herm_ldiv,                                         // HERM_LDIV,
+      &&wordcmd,                                           // WORDCMD,
+      &&handle_signals,                                    // HANDLE_SIGNALS,
+      &&push_cell,                                         // PUSH_CELL,
+      &&push_ov_u64,                                       // PUSH_OV_U64,
+      &&expand_cs_list,                                    // EXPAND_CS_LIST,
+      &&index_cell_id0,                                    // INDEX_CELL_ID_NARGOUT0,
+      &&index_cell_id1,                                    // INDEX_CELL_ID_NARGOUT1,
+      &&index_cell_idn,                                    // INDEX_CELL_ID_NARGOUTN,
+      &&incr_prefix,                                       // INCR_PREFIX,
+      &&rot,                                               // ROT,
+      &&init_global,                                       // GLOBAL_INIT,
+      &&assign_compound,                                   // ASSIGN_COMPOUND,
+      &&jmp_ifdef,                                         // JMP_IFDEF,
+      &&switch_cmp,                                        // JMP_IFNCASEMATCH,
+      &&braindead_precond,                                 // BRAINDEAD_PRECONDITION,
+      &&braindead_warning,                                 // BRAINDEAD_WARNING,
+      &&force_assign,                                      // FORCE_ASSIGN, // Accepts undefined rhs
+      &&push_nil,                                          // PUSH_NIL,
+      &&throw_iferrorobj,                                  // THROW_IFERROBJ,
+      &&index_struct_n,                                    // INDEX_STRUCT_NARGOUTN,
+      &&subasgn_struct,                                    // SUBASSIGN_STRUCT,
+      &&subasgn_cell_id,                                   // SUBASSIGN_CELL_ID,
+      &&index_obj,                                         // INDEX_OBJ,
+      &&subassign_obj,                                     // SUBASSIGN_OBJ,
+      &&matrix_big,                                        // MATRIX_UNEVEN,
+      &&load_far_cst,                                      // LOAD_FAR_CST,
+      &&end_obj,                                           // END_OBJ,
+      &&set_ignore_outputs,                                // SET_IGNORE_OUTPUTS,
+      &&clear_ignore_outputs,                              // CLEAR_IGNORE_OUTPUTS,
+      &&subassign_chained,                                 // SUBASSIGN_CHAINED,
+      &&set_slot_to_stack_depth,                           // SET_SLOT_TO_STACK_DEPTH,
+      &&dupn,                                              // DUPN,
+      &&debug,                                             // DEBUG,
+      &&index_struct_call,                                 // INDEX_STRUCT_CALL,
+      &&end_x_n,                                           // END_X_N,
+      &&eval,                                              // EVAL,
+      &&bind_ans,                                          // BIND_ANS,
+      &&push_anon_fcn_handle,                              // PUSH_ANON_FCN_HANDLE,
+      &&for_complex_setup,                                 // FOR_COMPLEX_SETUP, // opcode
+      &&for_complex_cond,                                  // FOR_COMPLEX_COND,
+      &&push_slot1_special,                                // PUSH_SLOT_NARGOUT1_SPECIAL,
+      &&disp,                                              // DISP,
+      &&push_slot_disp,                                    // PUSH_SLOT_DISP,
+      &&load_cst_alt2,                                     // LOAD_CST_ALT2,
+      &&load_cst_alt3,                                     // LOAD_CST_ALT3,
+      &&load_cst_alt4,                                     // LOAD_CST_ALT4,
+      &&load_2_cst,                                        // LOAD_2_CST,
+      &&mul_dbl,                                           // MUL_DBL,
+      &&add_dbl,                                           // ADD_DBL,
+      &&sub_dbl,                                           // SUB_DBL,
+      &&div_dbl,                                           // DIV_DBL,
+      &&pow_dbl,                                           // POW_DBL,
+      &&le_dbl,                                            // LE_DBL,
+      &&le_eq_dbl,                                         // LE_EQ_DBL,
+      &&gr_dbl,                                            // GR_DBL,
+      &&gr_eq_dbl,                                         // GR_EQ_DBL,
+      &&eq_dbl,                                            // EQ_DBL,
+      &&neq_dbl,                                           // NEQ_DBL,
+      &&index_id1_mat_1d,                                  // INDEX_ID1_MAT_1D,
+      &&index_id1_mat_2d,                                  // INDEX_ID1_MAT_2D,
+      &&push_pi,                                           // PUSH_PI,
+      &&index_math_ufun_id1,                               // INDEX_ID1_MATHY_UFUN,
+      &&subassign_id_mat_1d,                               // SUBASSIGN_ID_MAT_1D,
+      &&incr_id_prefix_dbl,                                // INCR_ID_PREFIX_DBL,
+      &&decr_id_prefix_dbl,                                // DECR_ID_PREFIX_DBL,
+      &&incr_id_postfix_dbl,                               // INCR_ID_POSTFIX_DBL,
+      &&decr_id_postfix_dbl,                               // DECR_ID_POSTFIX_DBL,
+      &&push_cst_dbl_0,                                    // PUSH_DBL_0,
+      &&push_cst_dbl_1,                                    // PUSH_DBL_1,
+      &&push_cst_dbl_2,                                    // PUSH_DBL_2,
+      &&jmp_if_bool,                                       // JMP_IF_BOOL,
+      &&jmp_ifn_bool,                                      // JMP_IFN_BOOL,
+      &&usub_dbl,                                          // USUB_DBL,
+      &&not_dbl,                                           // NOT_DBL,
+      &&not_bool,                                          // NOT_BOOL,
+      &&push_folded_cst,                                   // PUSH_FOLDED_CST,
+      &&set_folded_cst,                                    // SET_FOLDED_CST,
+      &&wide,                                              // WIDE
+    };
+
+  if (OCTAVE_UNLIKELY (m_profiler_enabled))
+    {
+      auto p = vm::m_vm_profiler;
+      if (p)
+        {
+          std::string fn_name = m_data[2].string_value (); // profiler_name () querried at compile time
+          p->enter_fn (fn_name, "", m_unwind_data, m_name_data, m_code);
+        }
+    }
+
+#if defined (__GNUC__) && defined (__x86_64__)
+  // We strongly suggest to GCC to put sp, ip and bsp in actual registers with
+  // the "local register variable" extension.
+  //
+  // If GCC is not nudged to put these in registers, its register allocator
+  // might make the VM spend quite some time pushing and popping of the C-stack.
+  register int arg0 asm("r12");
+  register stack_element *sp asm("r14");    // Stack pointer register
+  register unsigned char *ip asm("r15");    // The instruction pointer register
+  register stack_element *bsp asm("r13");   // Base stack pointer
+#else
+  int arg0;
+  stack_element *sp;
+  unsigned char *ip;
+  stack_element *bsp;
+#endif
+
+  unsigned char *code; // The instruction base register
+
+  stack_element *rsp; // Root stack pointer. Marks the beginning of the VM stack
+
+  octave_value *data = m_data;
+  std::string *name_data = m_name_data;
+  unwind_data *unwind_data = m_unwind_data;
+
+  code = m_code;
+  ip = code;
+
+  sp = bsp = rsp = m_stack;
+
+  // Read the meta data for constructing a stack frame.
+  {
+#define N_RETURNS() static_cast<signed char>(code[0])
+#define N_ARGS() static_cast<signed char>(code[1])
+#define N_LOCALS() (code[2] | (code [3] << 8))
+
+    int n_returns = static_cast<signed char> (*ip++);
+    // n_args is negative for varargin calls
+    int n_args = static_cast<signed char> (*ip++);
+    int n_locals = POP_CODE_USHORT (); // Note: An arg and return can share slot
+
+    bool is_varargin = n_args < 0;
+    bool is_varargout = n_returns < 0;
+
+    int n_root_args = root_args.length ();
+
+    if (is_varargin)
+      n_args = -n_args;
+    if (n_returns < 0)  // Negative for varargout
+      n_returns = -n_returns;
+
+    // The first return is always nargout, as a uint64
+    (*sp++).u = 0; //TODO: nargout as arg to this func
+
+    // Construct nil octave_values for the return slots
+    for (int i = 1; i < n_returns; i++)
+      PUSH_OV (); // TODO: Might be an arg i.e "[a,i] = foo (i,b)"
+
+    // Push the args onto the stack, filling their local slots
+    if (!is_varargin)
+      {
+        int i = 0;
+        for (i = 0; i < n_root_args; i++)
+          PUSH_OV (root_args (i));
+        // If not all args are given, fill up with nil objects
+        for (; i < n_args; i++)
+          PUSH_OV ();
+
+        set_nargin (n_root_args);   // Needed for nargin function
+      }
+    else
+      {
+        // Dont push varargin arguments
+        int n_args_to_push = std::min (n_args - 1, n_root_args);
+        int ii = 0;
+        for (ii = 0; ii < n_args_to_push; ii++)
+          PUSH_OV (root_args (ii));
+
+        // Construct missing args (if any)
+        for (; ii < n_args - 1; ii++)
+          PUSH_OV ();
+
+        // The rest of the args are to be put in a cell and be put
+        // in the last argument slot
+        int n_varargin = n_root_args - n_args_to_push;
+
+        if (n_varargin > 0)
+          {
+            Cell cell(1, n_varargin);
+            int i;
+            for (i = 0; i < n_varargin; i++)
+              {
+                cell (0, i) = root_args (ii + i);
+              }
+            PUSH_OV (cell);
+          }
+        else
+          PUSH_OV (Cell (0,0)); // Empty cell into varargin's slot
+
+        set_nargin (n_args_to_push + n_varargin);
+      }
+    // Construct nil octave_values for locals in their slots
+    for (int i = 0; i < n_locals - n_args - n_returns; i++)
+      PUSH_OV ();
+
+    /* We do the number of args check after frame init so that the unwind is easier. */
+    if (!is_varargin && n_args < n_root_args)
+      {
+        (*sp++).pee = new execution_exception {"error","","function called with too many inputs"};
+        (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+        ip++; // unwind expects ip to point to two after the opcode being executed
+        goto unwind;
+      }
+    if (!is_varargout && root_nargout > n_returns - 1) // n_returns includes %nargout, so subtract one
+      {
+        (*sp++).pee = new execution_exception {"error","","function called with too many outputs"};
+        (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+        ip++;
+        goto unwind;
+      }
+
+    m_original_lvalue_list = m_tw->lvalue_list ();
+    m_tw->set_lvalue_list (nullptr);
+  }
+
+  // Go go go
+  DISPATCH ();
+
+pop:
+  {
+    (*--sp).ov.~octave_value ();
+    DISPATCH_1BYTEOP ();
+  }
+dup:
+  {
+    new (sp) octave_value ((sp[-1]).ov);
+    sp++;
+    DISPATCH_1BYTEOP ();
+  }
+load_cst:
+  {
+    // The next instruction is the offset in the data.
+    int offset = arg0;
+
+    // Copy construct it into the top of the stack
+    new (sp++) octave_value (data [offset]);
+
+    DISPATCH ();
+  }
+mul_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_mul, mul, MUL, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+mul:
+  MAKE_BINOP_SELFMODIFYING (binary_op::op_mul, mul_dbl, MUL_DBL)
+  DISPATCH_1BYTEOP();
+div_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_div, div, DIV, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+div:
+  MAKE_BINOP_SELFMODIFYING (binary_op::op_div, div_dbl, DIV_DBL)
+  DISPATCH_1BYTEOP();
+add_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_add, add, ADD, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+add:
+  MAKE_BINOP_SELFMODIFYING (binary_op::op_add, add_dbl, ADD_DBL)
+  DISPATCH_1BYTEOP();
+sub_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_sub, sub, SUB, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+sub:
+  MAKE_BINOP_SELFMODIFYING (binary_op::op_sub, sub_dbl, SUB_DBL)
+  DISPATCH_1BYTEOP();
+ret:
+  {
+    // We need to tell the bytecode frame we are unwinding so that it can save
+    // variables on the VM stack if it is referenced from somewhere else.
+    m_tw->get_current_stack_frame ()->vm_unwinds ();
+
+    // Assert that the stack pointer is back where it should be
+    assert (bsp + N_LOCALS() == sp);
+
+    int n_returns_callee = N_RETURNS ();
+
+    bool is_varargout = n_returns_callee < 0;
+    if (n_returns_callee < 0)
+      n_returns_callee = -n_returns_callee;
+
+    assert (n_returns_callee > 0);
+    int n_locals_callee = N_LOCALS ();
+
+    // Destroy locals
+    //
+    // Note that we destroy from the bottom towards
+    // the top of the stack to calls ctors in the same
+    // order as the treewalker.
+    int n_dtor = n_locals_callee - n_returns_callee;
+
+    stack_element *first = sp - n_dtor;
+    while (first != sp)
+      {
+        (*first++).ov.~octave_value ();
+      }
+    sp -= n_dtor;
+
+    if (is_varargout)
+      {
+        n_returns_callee--; // Assume empty varargout
+
+        // Expand the cell array and push the elements to the stack
+        octave_value ov_vararg = std::move (sp[-1].ov);
+        STACK_DESTROY (1);
+
+        bool vararg_defined = ov_vararg.is_defined ();
+        if (vararg_defined && !ov_vararg.iscell ())
+          {
+            (*sp++).pee = new execution_exception {"error","","varargout must be a cell array object"};
+            (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+            goto unwind;
+          }
+        if (vararg_defined)
+          {
+            // Push the cell array elements to the stack
+            Cell cell_vararg = ov_vararg.cell_value ();
+            for (int i = 0; i < cell_vararg.numel (); i++)
+              {
+                octave_value &arg = cell_vararg(i);
+                PUSH_OV (std::move (arg));
+                n_returns_callee++;
+              }
+          }
+        // Only push an empty varargout if we are returning to another bytecode function
+        else if (bsp != rsp)
+          {
+            n_returns_callee++;
+            PUSH_OV ();
+          }
+      }
+
+    if (OCTAVE_UNLIKELY (m_profiler_enabled))
+      {
+        auto p = vm::m_vm_profiler;
+        if (p)
+          {
+            std::string fn_name = data[2].string_value (); // profiler_name () querried at compile time
+            p->exit_fn (fn_name);
+          }
+      }
+
+    // Are we at the root routine?
+    if (bsp == rsp)
+      {
+        CHECK (m_output_ignore_data == nullptr); // This can't be active
+
+        octave_value_list ret;
+
+        // Skip nargout, the first value, which is an integer
+        for (int i = 1; i < n_returns_callee; i++)
+        {
+          ret.append(std::move (bsp[i].ov));
+          bsp[i].ov.~octave_value ();
+        }
+
+        //Note: Stack frame object popped by caller
+        CHECK_STACK (0);
+        this->m_dbg_proper_return = true;
+
+        m_tw->set_lvalue_list (m_original_lvalue_list);
+        return ret;
+      }
+
+    // If the root stack pointer is not the same as the base pointer,
+    // we are returning from a bytecode routine to another bytecode routine,
+    // so we have to restore the caller stack frame and cleanup the callee's.
+    //
+    // Essentially do the same thing as in the call but in reverse order.
+
+    // If we have any active ~/"black hole", e.g. [~] = foo() in the stack
+    // the m_output_ignore_data pointer is live. We need to pop and reset
+    // lvalue lists for the tree walker.
+    if (m_output_ignore_data)
+      {
+        delete m_tw->lvalue_list ();
+        CHECK (!m_output_ignore_data->m_v_lvalue_list.empty ());
+
+        m_tw->set_lvalue_list (m_output_ignore_data->m_v_lvalue_list.back ());
+        m_output_ignore_data->m_v_lvalue_list.pop_back ();
+      }
+
+    // The sp now points one past the last return value
+    stack_element *caller_stack_end = sp - n_returns_callee;
+    sp = caller_stack_end; // sp points to one past caller stack
+
+    int callee_nargout = caller_stack_end[0].i;
+    //TODO: Check nargout
+
+    // Restore ip
+    ip = (*--sp).puc;
+
+    // Restore bsp
+    bsp = (*--sp).pse;
+
+    // Restore id names
+    name_data = (*--sp).ps;
+
+    // Restore data
+    data = (*--sp).pov;
+
+    // Restore code
+    code = (*--sp).puc;
+
+    // Restore unwind data
+    unwind_data = (*--sp).pud;
+
+    // Restore the stack pointer. The stored address is the first arg
+    // on the caller stack, or where it would have been if there are no args.
+    // The args were moved to the callee stack and destroyed on the caller
+    // stack in the call.
+    sp = sp[-1].pse;
+
+    // We now have the object that was called on the stack, destroy it
+    STACK_DESTROY (1);
+
+    // Move the callee's return values to the top of the stack of the caller.
+    // Renaming variables to keep my sanity.
+    int n_args_caller_expects = callee_nargout;
+    int n_args_callee_has = n_returns_callee - 1; // Exclude %nargout
+    int n_args_to_move = std::min (n_args_caller_expects, n_args_callee_has);
+    int n_args_actually_moved = 0;
+
+    // If no return values is requested but there exists return values,
+    // we need to push one to be able to write it to ans.
+    if (n_args_caller_expects == 0 && n_args_callee_has)
+      {
+        n_args_actually_moved++;
+        PUSH_OV (std::move (caller_stack_end[1].ov));
+      }
+    // If the callee aint returning anything, we need to push a
+    // nil object, since the caller always anticipates atleast
+    // one object, even for nargout == 0.
+    else if (n_args_caller_expects == 0 && !n_args_callee_has)
+      PUSH_OV();
+    // If the stacks will overlap due to many returns, do copy via container
+    else if (sp + n_args_caller_expects >= caller_stack_end)
+      {
+        // This pushes 'n_args_to_move' number of return values and 'n_args_caller_expects - n_args_to_move'
+        // number of nils.
+        copy_many_args_to_caller (sp, caller_stack_end + 1, n_args_to_move, n_args_caller_expects);
+        n_args_actually_moved = n_args_caller_expects;
+        sp += n_args_actually_moved;
+      }
+    // Move 'n_args_to_move' return value from callee to caller
+    else
+      {
+        // If the caller wants '[a, b, ~]' and the callee has 'd e'
+        // we need to push 'nil' 'd' 'e'
+        for (int i = n_args_to_move; i < n_args_caller_expects; i++)
+          PUSH_OV ();
+        for (int i = 0; i < n_args_to_move; i++)
+          {
+            // Move into caller stack. Note that the order is reversed, such that
+            // a b c on the callee stack becomes c b a on the caller stack.
+            int idx = n_args_to_move - 1 - i;
+            octave_value &arg = caller_stack_end[1 + idx].ov;
+
+            PUSH_OV (std::move (arg));
+          }
+        n_args_actually_moved = n_args_caller_expects;
+      }
+
+    // Destroy the unused return values on the callee stack
+    for (int i = 0; i < n_args_callee_has; i++)
+      {
+        int idx = n_args_callee_has - 1 - i;
+        caller_stack_end[1 + idx].ov.~octave_value (); // Destroy ov in callee
+      }
+
+    // Pop the current dynamic stack frame
+    std::shared_ptr<stack_frame> fp = m_tw->pop_return_stack_frame ();
+    // If the pointer is not shared, stash it in a cache which is used
+    // to avoid having to allocate shared pointers each frame push.
+    if (fp.unique () && m_frame_ptr_cache.size () < 8)
+      {
+        fp->vm_clear_for_cache ();
+        m_frame_ptr_cache.push_back (std::move (fp));
+      }
+
+    // Continue execution back in the caller
+  }
+  DISPATCH ();
+assign:
+  {
+    // The next instruction is the slot number
+    int slot = arg0;
+
+    octave_value_vm &ov_rhs = TOP_OV_VM ();
+    octave_value_vm &ov_lhs = bsp[slot].ov_vm;
+
+    // Handle undefined, cs-lists, objects that need an unique call etc
+    // in a separate code block to keep assign short.
+    if (OCTAVE_UNLIKELY (ov_rhs.vm_need_dispatch_assign_rhs () ||
+                         ov_lhs.vm_need_dispatch_assign_lhs ()))
+        goto assign_dispath;
+
+    ov_lhs = std::move (ov_rhs); // Note move
+
+    ov_rhs.~octave_value_vm (); // Destroy the top of the stack.
+    STACK_SHRINK (1);
+  }
+  DISPATCH();
+
+// Note: Not an op-code. Only jumped to from assign above.
+assign_dispath:
+{
+  // Extract the slot number again
+  int slot = arg0;
+
+  octave_value &ov_rhs = TOP_OV ();
+  octave_value &ov_lhs = bsp[slot].ov;
+
+  // If rhs is a "comma separated list" we just assign the first one.
+  // E.g.:
+  // a = {1,2,3};
+  // b = a{:}; % This assignment
+  //
+  // TODO: Do some smart function in ov for this?
+  //       Combine with undefined check?
+  if (ov_rhs.is_cs_list ())
+    {
+      const octave_value_list lst = ov_rhs.list_value ();
+
+      if (lst.empty ())
+        {
+          // TODO: Need id, name
+          (*sp++).i = static_cast<int>(error_type::INVALID_N_EL_RHS_IN_ASSIGNMENT);
+          goto unwind;
+        }
+
+      ov_rhs = lst(0);
+    }
+
+  if (ov_rhs.is_undefined ())
+    {
+      // TODO: Need id, name
+      (*sp++).i = static_cast<int>(error_type::RHS_UNDEF_IN_ASSIGNMENT);
+      goto unwind;
+    }
+
+  // If the object in the slot is the last one of it, we need
+  // to call its object dtor.
+  // TODO: Probably not needed since the Octave dtor will be called
+  //       by the C++ dtor of ov_lhs's m_count is 0??? The assign
+  //       function calls this function though ...
+  ov_lhs.maybe_call_dtor ();
+
+  if (ov_rhs.vm_need_storable_call ())
+    ov_rhs.make_storable_value (); // Some types have lazy copy
+
+  if (OCTAVE_LIKELY (!ov_lhs.is_ref ()))
+    ov_lhs = std::move (ov_rhs); // Note move
+  else
+    ov_lhs.ref_rep ()->set_value (std::move (ov_rhs));
+
+  STACK_DESTROY (1);
+}
+DISPATCH();
+
+jmp_if_bool:
+{
+  octave_value_vm &ov_1 = TOP_OV_VM ();
+
+  if (OCTAVE_UNLIKELY (ov_1.type_id () != m_bool_typeid))
+    {
+      // Change the specialized opcode to the generic one
+      ip[-2] = static_cast<unsigned char> (INSTR::JMP_IF);
+      goto jmp_if;
+    }
+
+  unsigned char b0 = arg0;
+  unsigned char b1 = *ip++;
+
+  int target = b0 | (b1 << 8);
+
+  octave_bool &ovb_bool = REP (octave_bool, ov_1);
+
+  bool is_true = ovb_bool.octave_bool::is_true ();
+
+  ov_1.~octave_value_vm ();
+  STACK_SHRINK (1);
+
+  if (is_true)
+    ip = code + target;
+}
+DISPATCH ();
+
+jmp_if:
+  {
+    octave_value &ov_1 = TOP_OV ();
+
+    if (OCTAVE_UNLIKELY (ov_1.type_id () == m_bool_typeid))
+      {
+        // Change the generic opcode to the specialized one
+        ip[-2] = static_cast<unsigned char> (INSTR::JMP_IF_BOOL);
+        goto jmp_if_bool;
+      }
+
+    unsigned char b0 = arg0;
+    unsigned char b1 = *ip++;
+
+    int target = b0 | (b1 << 8);
+
+    bool is_true;
+    if (ov_1.is_defined ())
+      {
+        try
+          {
+            is_true = ov_1.is_true ();
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+    else
+      {
+        (*sp++).i = static_cast<int>(error_type::IF_UNDEFINED);
+        goto unwind;
+      }
+
+    STACK_DESTROY (1);
+
+    if (is_true)
+      ip = code + target;
+  }
+  DISPATCH();
+jmp:
+  {
+    unsigned char b0 = arg0;
+    unsigned char b1 = *ip++;
+
+    int target = b0 | (b1 << 8);
+    ip = code + target;
+  }
+  DISPATCH ();
+jmp_ifn_bool:
+{
+  octave_value_vm &ov_1 = TOP_OV_VM ();
+
+  if (OCTAVE_UNLIKELY (ov_1.type_id () != m_bool_typeid))
+    {
+      // Change the specialized opcode to the generic one
+      ip[-2] = static_cast<unsigned char> (INSTR::JMP_IFN);
+      goto jmp_ifn;
+    }
+
+  unsigned char b0 = arg0;
+  unsigned char b1 = *ip++;
+
+  int target = b0 | (b1 << 8);
+
+  octave_bool &ovb_bool = REP (octave_bool, ov_1);
+
+  bool is_true = ovb_bool.octave_bool::is_true ();
+
+  ov_1.~octave_value_vm ();
+  STACK_SHRINK (1);
+
+  if (!is_true)
+    ip = code + target;
+}
+DISPATCH ();
+
+jmp_ifn:
+  {
+    octave_value &ov_1 = TOP_OV ();
+
+    if (OCTAVE_UNLIKELY (ov_1.type_id () == m_bool_typeid))
+      {
+        // Change the generic opcode to the specialized one
+        ip[-2] = static_cast<unsigned char> (INSTR::JMP_IFN_BOOL);
+        goto jmp_ifn_bool;
+      }
+
+    unsigned char b0 = arg0;
+    unsigned char b1 = *ip++;
+
+    int target = b0 | (b1 << 8);
+
+    bool is_true;
+    if (ov_1.is_defined ()) //10
+      {
+        try
+          {
+            is_true = ov_1.is_true ();
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+    else
+      {
+        (*sp++).i = static_cast<int> (error_type::IF_UNDEFINED);
+        goto unwind;
+      }
+
+    STACK_DESTROY (1);
+
+    if (!is_true)
+      ip = code + target;
+  }
+  DISPATCH ();
+push_slot_nargoutn:
+  {
+    // The next instruction is the slot number
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    // Handle undefined (which might be an error or function
+    // call on command form) or a function object.
+    if (ov.is_maybe_function ())
+      goto cmd_fcn_or_undef_error;
+
+    ip++; // nargout not needed
+
+    // Push the value in the slot to the stack
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      PUSH_OV (ov);
+    else
+      PUSH_OV (ov.ref_rep ()->deref ()); // global, persistent ... need dereferencing
+  }
+  DISPATCH();
+set_folded_cst:
+{
+  int slot = arg0;
+  octave_cached_value *ovb = static_cast<octave_cached_value*> (bsp[slot].ovb);
+  ovb->set_cached_obj (std::move (TOP_OV ()));
+  STACK_DESTROY (1);
+}
+DISPATCH();
+push_folded_cst:
+  {
+    int slot = arg0;
+    unsigned char b0 = *ip++;
+    unsigned char b1 = *ip++;
+
+    octave_cached_value *ovb = static_cast<octave_cached_value*> (bsp[slot].ovb);
+    if (ovb->is_defined () && ovb->cache_is_valid ())
+      {
+        PUSH_OV (ovb->get_cached_value ());
+        int target = b0 | (b1 << 8);
+        ip = code + target;
+      }
+    else
+      {
+        bsp[slot].ov = octave_value {new octave_cached_value};
+      }
+  }
+  DISPATCH();
+
+push_slot_nargout0:
+push_slot_nargout1:
+push_slot1_special:
+  {
+    int slot = arg0;
+
+    octave_base_value *ovb = bsp[slot].ovb;
+
+    // Some ov:s need some checks before pushing
+    if (OCTAVE_UNLIKELY (ovb->vm_need_dispatch_push ()))
+      goto push_slot_dispatch;
+
+    PUSH_OVB (ovb);
+  }
+  DISPATCH();
+// This is not an op-code and is only jumped to from above opcode.
+push_slot_dispatch:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    // Handle some special cases separately.
+    // I.e. cmd fn calls or classdef metas.
+    // Also error if no function-ish thing is found
+    // in lookups.
+    if (ov.is_maybe_function ())
+      goto cmd_fcn_or_undef_error;
+
+    // Push the value in the slot to the stack
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      PUSH_OV (ov);
+    else
+      PUSH_OV (ov.ref_rep ()->deref ()); // global, persistent ... need dereferencing
+  }
+  DISPATCH();
+
+disp:
+  {
+    octave_value &ov = TOP_OV ();
+    // 0 is magic slot number that indicates no name or always not a command
+    // for this opcode.
+    int slot = arg0;
+    int slot_was_cmd = POP_CODE_USHORT (); // Marker for if the preceding call was a command call
+
+    bool call_was_cmd = false;
+    if (slot_was_cmd)
+      {
+        octave_value &ov_call_was_cmd = bsp[slot_was_cmd].ov;
+        if (ov_call_was_cmd.is_defined ())
+          call_was_cmd = true;
+      }
+
+    if (m_tw->statement_printing_enabled () && ov.is_defined ())
+      {
+        interpreter& interp = m_tw->get_interpreter ();
+
+        if (ov.is_cs_list ())
+          {
+            octave_value_list ovl = ov.list_value ();
+
+            for (int i = 0; i < ovl.length (); i++)
+              {
+                octave_value_list el_ovl = octave_value_list {ovl(i)};
+                el_ovl.stash_name_tags (string_vector ("ans"));
+                m_tw->set_active_bytecode_ip (ip - code); // Needed if display calls inputname()
+
+                try
+                  {
+                    interp.feval ("display", el_ovl);
+                  }
+                CATCH_INTERRUPT_EXCEPTION
+                CATCH_INDEX_EXCEPTION
+                CATCH_EXECUTION_EXCEPTION
+                CATCH_BAD_ALLOC
+                CATCH_EXIT_EXCEPTION
+              }
+          }
+        else
+          {
+            octave_value_list ovl;
+            ovl.append (ov);
+
+            if (call_was_cmd)
+              ovl.stash_name_tags (string_vector ("ans"));
+            else if (slot != 0)
+              ovl.stash_name_tags (string_vector (name_data[slot]));
+            else
+              ovl.stash_name_tags (string_vector {});
+
+            m_tw->set_active_bytecode_ip (ip - code); // Needed if display calls inputname()
+
+            try
+              {
+                interp.feval ("display", ovl);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+      }
+
+    STACK_DESTROY (1);
+  }
+  DISPATCH ();
+
+push_slot_disp:
+  {
+    int slot = arg0;
+    int slot_was_cmd = POP_CODE_USHORT ();
+    octave_value &ov = bsp[slot].ov;
+    octave_value &ov_was_cmd = bsp[slot_was_cmd].ov;
+
+    // Handle some special cases separately.
+    // I.e. cmd fn calls or classdef metas.
+    // Also error if no function-ish thing is found
+    // in lookups.
+
+    // Assume that the pushed slot will not be a cmd.
+    // disp will later use the ov_was_cmd slot to choose between printing
+    // 'ans = ...' or 'foo = ...'
+    ov_was_cmd = octave_value ();
+
+    if (ov.is_maybe_function ())
+      {
+        if (ov.is_undefined ()) // class objects are defined
+          ov_was_cmd = true;
+        ip -= 2; // Rewind to slot so the state matches 'push_slot_nargoutn' and 'push_slot_dispatch'.
+        goto cmd_fcn_or_undef_error;
+      }
+
+    // Push the value in the slot to the stack
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      PUSH_OV (ov);
+    else
+      PUSH_OV (ov.ref_rep ()->deref ()); // global, persistent ... need dereferencing
+  }
+  DISPATCH();
+
+// Some kludge to handle the possibility of command form function calls.
+cmd_fcn_or_undef_error:
+  {
+    int slot = arg0;
+    octave_value ov = bsp[slot].ov;
+    bool is_ref = ov.is_ref ();
+    if (is_ref)
+      ov = ov.ref_rep ()->deref ();
+
+    // Check to opcode to see how many nargout there are.
+    // Also skip ip to the end of the opcode.
+    int nargout;
+    bool push_classdef_metas = false;
+    INSTR opcode = static_cast<INSTR> (*(ip - 2));
+    if (opcode == INSTR::PUSH_SLOT_NARGOUT1 ||
+        opcode == INSTR::PUSH_PI)
+      nargout = 1;
+    else if (opcode == INSTR::PUSH_SLOT_NARGOUT0)
+      nargout = 0;
+    else if (opcode == INSTR::PUSH_SLOT_NARGOUTN)
+      nargout = *ip++;
+    else if (opcode == INSTR::PUSH_SLOT_NARGOUT1_SPECIAL)
+      {
+        push_classdef_metas = true;
+        nargout = 1;
+      }
+    else if (opcode == INSTR::PUSH_SLOT_DISP)
+      {
+        nargout = 0;
+        ip += 2; // Skip the maybe command slot
+      }
+    else
+      PANIC ("Invalid opcode");
+
+    // A global or persistent var should not be undefined but whatever check anyway
+    bool ov_defined1 = ov.is_defined ();
+    if (is_ref && !ov_defined1)
+      {
+        (*sp++).ps = new std::string {name_data[slot]};
+        (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+        goto unwind;
+      }
+
+    if (!ov_defined1 && ov.is_nil ())
+      {
+        ov = bsp[slot].ov =
+          octave_value (new octave_fcn_cache (name_data[slot]));
+      }
+
+    if (!ov_defined1 && ov.is_function_cache ())
+      {
+        try
+          {
+            octave_fcn_cache *ovb_cache = ov.fcn_cache_value ();
+            ov = ovb_cache->get_cached_obj ({});
+          }
+        CATCH_EXECUTION_EXCEPTION
+      }
+
+    if (! ov.is_defined ())
+      {
+        (*sp++).ps = new std::string {name_data[slot]};
+        (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+        goto unwind;
+      }
+
+    // When executing op-code PUSH_SLOT_NARGOUT1_SPECIAL ...
+    // Essentially if we have a foo{1} where foo is a classdef
+    // we need to push it for the {1} indexing.
+    if (push_classdef_metas && ov.is_classdef_meta ())
+      PUSH_OV (ov);
+    else if (ov.is_function ())
+      {
+        octave_function *fcn = ov.function_value (true); //TODO: Unwind on error?
+
+        // TODO: Bytecode call
+        if (fcn)
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                octave_value_list ovl = fcn->call (*m_tw, nargout);
+
+                EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (ovl, nargout);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+        else
+          PUSH_OV (ov); // TODO: The walker does this. Sane?
+      }
+    else
+      PUSH_OV (ov); // TODO: The walker does this. Sane?
+  }
+  DISPATCH ();
+le_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_le, le, LE, m_scalar_typeid)
+  DISPATCH_1BYTEOP ();
+le:
+  MAKE_BINOP_SELFMODIFYING (binary_op::op_lt, le_dbl, LE_DBL)
+  DISPATCH_1BYTEOP ();
+le_eq_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_le_eq, le_eq, LE_EQ, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+le_eq:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_le, le_eq_dbl, LE_EQ_DBL)
+  DISPATCH_1BYTEOP();
+gr_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_gr, gr, GR, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+gr:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_gt, gr_dbl, GR_DBL)
+  DISPATCH_1BYTEOP();
+gr_eq_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_gr_eq, gr_eq, GR_EQ, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+gr_eq:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_ge, gr_eq_dbl, GR_EQ_DBL)
+  DISPATCH_1BYTEOP();
+eq_dbl:
+  MAKE_BINOP_SPECIALIZED(m_fn_dbl_eq, eq, EQ, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+eq:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_eq, eq_dbl, EQ_DBL)
+  DISPATCH_1BYTEOP();
+neq_dbl:
+  MAKE_BINOP_SPECIALIZED(m_fn_dbl_neq, neq, NEQ, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+neq:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_ne, neq_dbl, NEQ_DBL)
+  DISPATCH_1BYTEOP();
+
+
+index_id1_mat_1d:
+{
+  int slot = arg0;
+  ip++; // n_args_on_stack ignored
+
+  octave_base_value *arg1 = TOP_OVB ();
+  octave_value &mat = SEC_OV ();
+
+  bool is_scalar = arg1->type_id () == m_scalar_typeid; // scalar is C "double"
+  bool is_mat = mat.is_full_num_matrix ();
+  // If the args have change types we need to use the generic index opcode
+  if (OCTAVE_UNLIKELY (!is_scalar || !is_mat))
+    {
+      // Rewind ip ton_args_on_stack
+      ip -= 1;
+      int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+      // Change the specialized opcode to the generic one
+      ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INDEX_ID_NARGOUT1);
+      goto index_id1;
+    }
+
+  try
+    {
+      octave_scalar *arg1_double = static_cast<octave_scalar*> (arg1);
+
+      double idx_double = arg1_double->double_value ();
+      octave_idx_type idx = static_cast<octave_idx_type> (idx_double);
+
+      if (static_cast<double> (idx) != idx_double)
+        err_invalid_index (idx_double - 1, // Expects zero-indexed index
+                           1,  // The 1st index has the wrong dimension
+                           1); // Total amount of dimensions
+      if (idx <= 0)
+        err_invalid_index (idx - 1, 1, 1);
+
+      // Arguments are one-indexed but checked_full_matrix_elem() is 0-indexed.
+      octave_value ans = mat.checked_full_matrix_elem (idx - 1);
+      STACK_DESTROY (2);
+      PUSH_OV (std::move (ans));
+    }
+  CATCH_INTERRUPT_EXCEPTION
+  CATCH_INDEX_EXCEPTION_WITH_NAME
+  CATCH_EXECUTION_EXCEPTION
+  CATCH_BAD_ALLOC
+  CATCH_EXIT_EXCEPTION
+}
+DISPATCH();
+
+index_id1_mat_2d:
+{
+  int slot = arg0;
+  ip++; // n_args_on_stack ignored
+
+  octave_base_value *arg2 = TOP_OVB (); // Collumn index
+  octave_base_value *arg1 = SEC_OVB (); // Row index
+  octave_value &mat = THIRD_OV ();
+
+  bool is_scalar; // scalar as in C "double"
+  is_scalar = arg1->type_id () == m_scalar_typeid;
+  is_scalar = arg2->type_id () == m_scalar_typeid && is_scalar;
+
+  bool is_mat = mat.is_full_num_matrix ();
+  // If the args have change types we need to use the generic index opcode
+  if (OCTAVE_UNLIKELY (!is_scalar || !is_mat))
+    {
+      // Rewind ip to n_args_on_stack
+      ip -= 1;
+      int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+      // Change the specialized opcode to the generic one
+      ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INDEX_ID_NARGOUT1);
+      goto index_id1;
+    }
+
+  try
+    {
+      octave_scalar *arg1_double = static_cast<octave_scalar*> (arg1);
+
+      double idx1_double = arg1_double->double_value ();
+      octave_idx_type idx1 = static_cast<octave_idx_type> (idx1_double);
+
+      if (static_cast<double> (idx1) != idx1_double)
+        err_invalid_index (idx1_double - 1, // Expects zero-indexed index
+                           1,  // The 1st index has the wrong dimension
+                           2); // Total amount of dimensions
+      if (idx1 <= 0)
+        err_invalid_index (idx1 - 1, 1, 2);
+
+      octave_scalar *arg2_double = static_cast<octave_scalar*> (arg2);
+
+      double idx2_double = arg2_double->double_value ();
+      octave_idx_type idx2 = static_cast<octave_idx_type> (idx2_double);
+
+      if (static_cast<double> (idx2) != idx2_double)
+        err_invalid_index (idx2_double - 1, // Expects zero-indexed index
+                           2,  // The 1st index has the wrong dimension
+                           2); // Total amount of dimensions
+      if (idx2 <= 0)
+        err_invalid_index (idx2 - 1, 2, 2);
+
+      // Arguments are one-indexed but checked_full_matrix_elem() is 0-indexed.
+      octave_value ans = mat.checked_full_matrix_elem (idx1 - 1, idx2 - 1);
+      STACK_DESTROY (3);
+      PUSH_OV (std::move (ans));
+    }
+  CATCH_INTERRUPT_EXCEPTION
+  CATCH_INDEX_EXCEPTION_WITH_NAME
+  CATCH_EXECUTION_EXCEPTION
+  CATCH_BAD_ALLOC
+  CATCH_EXIT_EXCEPTION
+}
+DISPATCH();
+
+index_math_ufun_id1:
+{
+  auto ufn = static_cast<octave_base_value::unary_mapper_t> (arg0);
+  ip++; // slot number ignored
+  ip++; // "n_args_on_stack" ignored. Always 1
+
+  // The object to index is before the arg on the stack
+  octave_value &arg = TOP_OV ();
+  octave_value &ov = SEC_OV ();
+
+  if (OCTAVE_UNLIKELY (arg.type_id () != m_scalar_typeid ||
+      !ov.is_function_cache ()))
+    {
+      ip -= 1; // Rewind ip to n_args_on_stack
+      arg0 = ip[-1]; // set arg0 to slot
+      goto index_math_ufun_id1_dispatch;
+    }
+
+  // We need to check so the user has not defined some function
+  // that overrides the builtin ones.
+  octave_function *fcn;
+  try
+    {
+      fcn = ov.get_cached_fcn ({arg});
+    }
+  CATCH_EXECUTION_EXCEPTION // parse errors might throw in classdefs
+
+  if (OCTAVE_UNLIKELY (!fcn->is_builtin_function ()))
+    {
+      ip -= 1; // Rewind ip to n_args_on_stack
+      arg0 = ip[-1]; // set arg0 to slot
+      goto index_math_ufun_id1_dispatch;
+    }
+
+  octave_scalar *ovb_arg = static_cast<octave_scalar*> (TOP_OVB ());
+
+  SEC_OV () = ovb_arg->octave_scalar::map (ufn);
+  STACK_DESTROY (1);
+}
+DISPATCH ();
+
+push_pi:
+// Specialization to push pi fast as a scalar.
+//
+// If the user have messed up 'pi' opcode PUSH_SLOT_NARGOUT1
+// is used instead.
+{
+  // The next instruction is the slot number
+  int slot = arg0;
+
+  octave_value &ov = bsp[slot].ov;
+  // If the slot value is not a function cache we do a
+  // PUSH_SLOT_NARGOUT1 which will most likely put a
+  // function cache in the slot (unless the user has done a
+  // "pi = 123;" or whatever).
+  if (OCTAVE_UNLIKELY (!ov.is_function_cache ()))
+    {
+      goto push_slot_nargout1;
+    }
+
+  // We need to check so the user has not defined some pi function
+  octave_function *fcn;
+  try
+    {
+      fcn = ov.get_cached_fcn ({});
+    }
+  CATCH_EXECUTION_EXCEPTION // parse errors might throw in classdefs
+
+  if (OCTAVE_UNLIKELY (fcn != m_pi_builtin_fn))
+    {
+      goto push_slot_nargout1;
+    }
+
+  // The user wanna push 3.1415...
+  PUSH_OV (ov_pi);
+}
+DISPATCH();
+
+  {
+    // TODO: Too much code. Should be broken out?
+
+    // Note: Beutifully interleaved if branches and goto labels
+    int nargout, slot;
+    bool specialization_ok;
+    if (0)
+      {
+index_idn:
+        slot = arg0; // Needed if we need a function lookup
+        nargout = *ip++;
+        specialization_ok = false;
+      }
+    else if (0)
+      {
+index_id1:
+        slot = arg0;
+        nargout = 1;
+        specialization_ok = true;
+      }
+    else if (0)
+      {
+index_id_nargout0:
+        slot = arg0;
+        nargout = 0;
+        specialization_ok = false;
+      }
+    else
+      {
+index_math_ufun_id1_dispatch: // Escape dispatch for index_math_ufun_id1 specialization
+        slot = arg0;
+        nargout = 1;
+        specialization_ok = false;
+      }
+
+    int n_args_on_stack = *ip++;
+
+    // The object to index is before the args on the stack
+    octave_value &ov = (sp[-1 - n_args_on_stack]).ov;
+
+    // TODO: The ovl should not be needed
+    // Make an ovl with the args
+    // TODO: Should be inplace moves
+    octave_value_list ovl;
+    bool has_cs_list_arg = false;
+    // The operands are on the top of the stack
+
+    bool all_args_double = true;
+    for (int i = n_args_on_stack - 1; i >= 0; i--)
+      {
+        octave_value &arg = sp[-1 - i].ov;
+        if (arg.type_id () != m_scalar_typeid)
+          all_args_double = false;
+        // If the operand arg is a cs list we need to expand it
+        if (arg.is_cs_list ())
+          {
+            has_cs_list_arg = true;
+            ovl.append (arg.list_value ());
+          }
+        else
+          ovl.append (sp[-1 - i].ov); // TODO: copied, not moved
+      }
+
+    // If the ov is a "full matrix", i.e. based on octave_base_matrix,
+    // and the arguments are all scalar, we modify this opcode to a
+    // specialized opcode for matrix scalar indexing.
+    if (nargout == 1 && all_args_double && ov.is_full_num_matrix () && specialization_ok)
+      {
+        if (n_args_on_stack == 1)
+          {
+            ip -= 1;
+            int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+
+            CHECK (ip[-2 + wide_opcode_offset] == static_cast<unsigned char> (INSTR::INDEX_ID_NARGOUT1));
+            ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INDEX_ID1_MAT_1D);
+
+            goto index_id1_mat_1d;
+          }
+        else if (n_args_on_stack == 2)
+          {
+            ip -= 1;
+            int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+
+            CHECK (ip[-2 + wide_opcode_offset] == static_cast<unsigned char> (INSTR::INDEX_ID_NARGOUT1));
+            ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INDEX_ID1_MAT_2D);
+
+            goto index_id1_mat_2d;
+          }
+      }
+
+    //TODO: Are the args really destroyed in all paths? Remember cell too
+
+    // octave_fcn_cache and some octave_fcn_handle have caches
+    bool has_function_cache = ov.has_function_cache ();
+
+    if (! has_function_cache && ov.is_defined ())
+      {
+        // It is probably a variable
+        octave_value_list retval;
+
+        if (OCTAVE_LIKELY (! ov.is_function ()
+                           || ov.is_classdef_meta ()))
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                retval = ov.simple_subsref ('(', ovl, nargout);
+                ovl.clear ();
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION_WITH_NAME
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+        else
+          TODO ("Silly state");
+
+        ov = octave_value ();
+
+        STACK_DESTROY (n_args_on_stack + 1);
+        EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+      }
+    else if (has_function_cache)
+      {
+// The else clause bellow jumps to here
+querry_fcn_cache:
+
+        octave_function *fcn;
+        try
+          {
+            fcn = ov.get_cached_fcn (ovl);
+          }
+        CATCH_EXECUTION_EXCEPTION // parse errors might throw in classdefs
+
+        if (! fcn)
+          {
+            (*sp++).ps = new std::string {name_data[slot]};
+            (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+            goto unwind;
+          }
+        else if (fcn->is_compiled ())
+          {
+            octave_user_function *usr_fcn = static_cast<octave_user_function *> (fcn);
+
+            // Alot of code in this define
+            MAKE_BYTECODE_CALL
+
+            // Now dispatch to first instruction in the
+            // called function
+          }
+        else
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                octave_value_list ret = fcn->call (*m_tw, nargout, ovl);
+
+                STACK_DESTROY (n_args_on_stack + 1);
+                EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (ret, nargout);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+          }
+      }
+    else
+      {
+        // It is probably a function call
+        if (! ov.is_nil ())
+          {
+            PRINT_VM_STATE("err %s" COMMA name_data[slot].c_str ());
+            TODO ("Not nil object for fcn cache replacement");
+          }
+
+        // Put a function cache object in the slot and in the local ov
+        ov = bsp[slot].ov =
+          octave_value (new octave_fcn_cache (name_data[slot]));
+        goto querry_fcn_cache; // Jump into the if clause above
+      }
+  }
+  DISPATCH ();
+
+push_slot_indexed:
+  {
+    // The next instruction is the slot number
+    int slot = arg0;
+    octave_value &ov = bsp[slot].ov;
+
+    // Unlike push_slot this can't be a command function call
+    // so we don't need to check if this is a function.
+
+    // Push the value in the slot to the stack
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      PUSH_OV (ov);
+    else
+      PUSH_OV (ov.ref_rep ()->deref ()); // global, persistent ... need dereferencing
+
+  }
+  DISPATCH();
+
+pow_dbl:
+  MAKE_BINOP_SPECIALIZED (m_fn_dbl_pow, pow, POW, m_scalar_typeid)
+  DISPATCH_1BYTEOP();
+pow:
+  MAKE_BINOP_SELFMODIFYING(binary_op::op_pow, pow_dbl, POW_DBL)
+  DISPATCH_1BYTEOP();
+ldiv:
+  MAKE_BINOP(binary_op::op_ldiv)
+  DISPATCH_1BYTEOP();
+el_mul:
+  MAKE_BINOP(binary_op::op_el_mul)
+  DISPATCH_1BYTEOP();
+el_div:
+  MAKE_BINOP(binary_op::op_el_div)
+  DISPATCH_1BYTEOP();
+el_pow:
+  MAKE_BINOP(binary_op::op_el_pow)
+  DISPATCH_1BYTEOP();
+el_and:
+  MAKE_BINOP(binary_op::op_el_and)
+  DISPATCH_1BYTEOP();
+el_or:
+  MAKE_BINOP(binary_op::op_el_or)
+  DISPATCH_1BYTEOP();
+el_ldiv:
+  MAKE_BINOP(binary_op::op_el_ldiv)
+  DISPATCH_1BYTEOP();
+
+not_dbl:
+MAKE_UNOP_SPECIALIZED (m_fn_dbl_not, op_not, NOT, m_scalar_typeid);
+DISPATCH_1BYTEOP ();
+
+not_bool:
+MAKE_UNOP_SPECIALIZED (m_fn_bool_not, op_not, NOT, m_bool_typeid);
+DISPATCH_1BYTEOP ();
+
+op_not:
+  {
+    octave_value &ov = TOP_OV ();
+
+    int type_id = ov.type_id ();
+    if (OCTAVE_UNLIKELY (type_id == m_scalar_typeid))
+      {
+        // Change the generic opcode to the specialized one
+        ip[-2] = static_cast<unsigned char> (INSTR::NOT_DBL);
+        goto not_dbl;
+      }
+    else if (OCTAVE_UNLIKELY (type_id == m_bool_typeid))
+      {
+        // Change the generic opcode to the specialized one
+        ip[-2] = static_cast<unsigned char> (INSTR::NOT_BOOL);
+        goto not_bool;
+      }
+
+    try
+      {
+        octave_value ans = unary_op (*m_ti, octave_value::unary_op::op_not,
+                                     ov);
+        ov.~octave_value ();
+
+        STACK_SHRINK (1);
+
+        new (sp++) octave_value (std::move (ans));
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP();
+uadd:
+  {
+    octave_value &ov = TOP_OV ();
+
+    try
+      {
+        octave_value ans = unary_op (*m_ti, octave_value::unary_op::op_uplus,
+                                     ov);
+        ov.~octave_value ();
+
+        STACK_SHRINK (1);
+
+        new (sp++) octave_value (std::move (ans));
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP();
+
+usub_dbl:
+MAKE_UNOP_SPECIALIZED (m_fn_dbl_usub, usub, USUB, m_scalar_typeid);
+DISPATCH_1BYTEOP ();
+usub:
+  {
+    octave_value &ov = TOP_OV ();
+
+    if (OCTAVE_UNLIKELY (ov.type_id () == m_scalar_typeid))
+      {
+        // Change the generic opcode to the specialized one
+        ip[-2] = static_cast<unsigned char> (INSTR::USUB_DBL);
+        goto usub_dbl;
+      }
+
+    try
+      {
+        octave_value ans = unary_op (*m_ti, octave_value::unary_op::op_uminus,
+                                     ov);
+        ov.~octave_value ();
+
+        STACK_SHRINK (1);
+
+        new (sp++) octave_value (std::move (ans));
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP();
+trans:
+  {
+    octave_value &ov = TOP_OV ();
+
+    try
+      {
+        octave_value ans = unary_op (*m_ti,
+                                     octave_value::unary_op::op_transpose,
+                                     ov);
+        ov.~octave_value ();
+
+        STACK_SHRINK (1);
+
+        new (sp++) octave_value (std::move (ans));
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP();
+herm:
+  {
+    octave_value &ov = TOP_OV ();
+
+    try
+      {
+        octave_value ans = unary_op (*m_ti,
+                                     octave_value::unary_op::op_hermitian,
+                                     ov);
+        ov.~octave_value ();
+
+        STACK_SHRINK (1);
+
+        new (sp++) octave_value (std::move (ans));
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP();
+
+incr_id_prefix_dbl:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () != m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        // Change the specialized opcode to the generic one
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INCR_ID_PREFIX);
+        goto incr_id_prefix;
+      }
+
+    octave_scalar &scalar = REP (octave_scalar, ov);
+    double val = scalar.octave_scalar::double_value ();
+
+    if (!scalar.octave_scalar::maybe_update_double (val + 1))
+      ov = octave_value_factory::make (val + 1);
+
+    PUSH_OV (ov);
+  }
+  DISPATCH();
+incr_id_prefix:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () == m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        // Change the generic opcode to the specialized one
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INCR_ID_PREFIX_DBL);
+        goto incr_id_prefix_dbl;
+      }
+
+    try
+      {
+        if (OCTAVE_LIKELY (!ov.is_ref ()))
+          {
+            ov.non_const_unary_op (octave_value::unary_op::op_incr);
+            PUSH_OV (ov);
+          }
+        else
+          {
+            octave_value &ov_glb = ov.ref_rep ()->ref ();
+            ov_glb.non_const_unary_op (octave_value::unary_op::op_incr);
+            PUSH_OV (ov_glb);
+          }
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH();
+
+decr_id_prefix_dbl:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () != m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::DECR_ID_PREFIX);
+        goto decr_id_prefix;
+      }
+
+    octave_scalar &scalar = REP (octave_scalar, ov);
+    double val = scalar.octave_scalar::double_value ();
+
+    if (!scalar.octave_scalar::maybe_update_double (val - 1))
+      ov = octave_value_factory::make (val - 1);
+
+    PUSH_OV (ov);
+  }
+  DISPATCH();
+decr_id_prefix:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () == m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::DECR_ID_PREFIX_DBL);
+        goto decr_id_prefix_dbl;
+      }
+
+    try
+      {
+        if (OCTAVE_LIKELY (!ov.is_ref ()))
+          {
+            ov.non_const_unary_op (octave_value::unary_op::op_decr);
+            PUSH_OV (ov);
+          }
+        else
+          {
+            octave_value &ov_glb = ov.ref_rep ()->ref ();
+            ov_glb.non_const_unary_op (octave_value::unary_op::op_decr);
+            PUSH_OV (ov_glb);
+          }
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH();
+incr_id_postfix_dbl:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () != m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INCR_ID_POSTFIX);
+        goto incr_id_postfix;
+      }
+
+    octave_scalar &scalar = REP (octave_scalar, ov);
+    double val = scalar.octave_scalar::double_value ();
+
+    PUSH_OV (std::move (ov));
+    ov = octave_value_factory::make (val + 1);
+  }
+  DISPATCH();
+incr_id_postfix:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () == m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::INCR_ID_POSTFIX_DBL);
+        goto incr_id_postfix_dbl;
+      }
+
+    try
+      {
+        if (OCTAVE_LIKELY (!ov.is_ref ()))
+          {
+            octave_value copy = ov;
+            ov.non_const_unary_op (octave_value::unary_op::op_incr);
+            PUSH_OV (std::move (copy));
+          }
+        else
+          {
+            octave_value &ov_glb = ov.ref_rep ()->ref ();
+            octave_value copy = ov_glb;
+            ov_glb.non_const_unary_op (octave_value::unary_op::op_incr);
+            PUSH_OV (std::move (copy));
+          }
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH();
+decr_id_postfix_dbl:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () != m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::DECR_ID_POSTFIX);
+        goto decr_id_postfix;
+      }
+
+    octave_scalar &scalar = REP (octave_scalar, ov);
+    double val = scalar.octave_scalar::double_value ();
+
+    PUSH_OV (std::move (ov));
+    ov = octave_value_factory::make (val - 1);
+  }
+  DISPATCH();
+decr_id_postfix:
+  {
+    int slot = arg0;
+
+    octave_value &ov = bsp[slot].ov;
+
+    if (ov.type_id () == m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+        ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::DECR_ID_POSTFIX_DBL);
+        goto decr_id_postfix_dbl;
+      }
+
+    try
+      {
+        if (OCTAVE_LIKELY (!ov.is_ref ()))
+          {
+            octave_value copy = ov;
+            ov.non_const_unary_op (octave_value::unary_op::op_decr);
+            PUSH_OV (std::move (copy));
+          }
+        else
+          {
+            octave_value &ov_glb = ov.ref_rep ()->ref ();
+            octave_value copy = ov_glb;
+            ov_glb.non_const_unary_op (octave_value::unary_op::op_decr);
+            PUSH_OV (std::move (copy));
+          }
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH();
+for_setup:
+  {
+    octave_value &ov_range = TOP_OV ();
+
+    octave_idx_type n = ov_range.numel();
+
+    bool is_range = ov_range.is_range ();
+    //TODO: Kludge galore. Should be refactored into some virtual call.
+    if (is_range &&
+        (
+         ov_range.is_double_type () ||
+         ov_range.is_int64_type () ||
+         ov_range.is_uint64_type () ||
+         ov_range.is_int32_type () ||
+         ov_range.is_uint32_type () ||
+         ov_range.is_int16_type () ||
+         ov_range.is_uint16_type () ||
+         ov_range.is_int16_type () ||
+         ov_range.is_int8_type () ||
+         ov_range.is_int8_type () ||
+         ov_range.is_uint8_type () ||
+         ov_range.is_single_type()))
+      {
+        ov_range = ov_range.maybe_as_trivial_range ();
+      }
+    else if (is_range ||
+             ov_range.is_matrix_type () ||
+             ov_range.iscell () ||
+             ov_range.is_string () ||
+             ov_range.isstruct ())
+      {
+        // The iteration is column wise for these, so change
+        // n to the amount of columns rather then elements.
+        dim_vector dv = ov_range.dims ().redim (2);
+        int n_rows = dv (0);
+        if (n_rows)
+          n = dv(1);
+        else
+          n = 0; // A e.g. 0x3 sized Cell gives no iterations, not 3
+      }
+    else if (ov_range.is_scalar_type ())
+      ;
+    else
+      TODO ("Unsupported for rhs type");
+
+    // TODO: Kludgy classes.
+
+    if (!ov_range.is_trivial_range () && is_range)
+      {
+        // TODO: Wasteful copy of range.
+        auto range = ov_range.range_value ();
+        if (math::isinf (range.limit ()) || math::isinf (range.base ()))
+            warning_with_id ("Octave:infinite-loop",
+                     "FOR loop limit is infinite, will stop after %"
+                     OCTAVE_IDX_TYPE_FORMAT " steps", range.numel ());
+      }
+
+
+    // Push n to the stack
+    (*sp++).i = n;
+    // Push a counter to the stack, initialized so that it will
+    // increment to 0.
+    (*sp++).i = -1;
+
+    // For empty rhs just assign it to lhs
+    if (! n)
+      {
+        // Slot from the for_cond that always follow a for_setup
+        int slot;
+        if (arg0 == static_cast<int> (INSTR::WIDE))
+          slot = ip[1];
+        else
+          slot = ip[0];
+        try
+        {
+          octave_value &lhs_ov = bsp[slot].ov;
+          if (!lhs_ov.is_ref ())
+            lhs_ov = ov_range.storable_value ();
+          else
+            lhs_ov.ref_rep ()->set_value (ov_range.storable_value ());
+        }
+        CATCH_EXECUTION_EXCEPTION
+      }
+  }
+DISPATCH_1BYTEOP ();
+
+for_cond:
+  {
+    // Check if we should exit the loop due to e.g. ctrl-c, or handle
+    // any other signals.
+    try
+      {
+        octave_quit ();
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    // Increase counter
+    TOP ().i++; // Wraps to zero first iteration
+
+    // Check if we done all iterations
+    // n is second element on the stack
+    if (TOP ().i == SEC ().i)
+      {
+        // The after address
+        unsigned char b0 = *ip++;
+        unsigned char b1 = *ip++;
+
+        int after = b0 | (b1 << 8);
+
+        // goto after block
+        ip = code + after;
+      }
+    else
+      {
+        // Write the iteration's value to the for loop variable
+        int slot = arg0;
+        ip +=2; // Skip the after address
+
+        octave_idx_type counter = TOP ().i;
+
+        octave_value &ov_range = THIRD_OV ();
+        octave_value &ov_it = bsp[slot].ov;
+
+        if (ov_range.is_trivial_range ())
+          {
+            double val = REP (octave_trivial_range, ov_range).octave_trivial_range::vm_extract_forloop_double (counter);
+            if (!ov_it.maybe_update_double (val))
+              {
+                if (OCTAVE_LIKELY (!ov_it.is_ref ()))
+                  ov_it = octave_value_factory::make (val);
+                else
+                  ov_it.ref_rep ()->set_value (val);
+              }
+          }
+        else if (OCTAVE_LIKELY (!ov_it.is_ref ()))
+          ov_it = ov_range.vm_extract_forloop_value (counter);
+        else
+          ov_it.ref_rep ()->set_value (ov_range.vm_extract_forloop_value (counter));
+
+        // The next opcode is the start of the body
+      }
+  }
+  DISPATCH ();
+pop_n_ints:
+  {
+    sp -= arg0;
+    DISPATCH();
+  }
+push_fcn_handle:
+  {
+    int slot = arg0;
+
+    //octave_value &fcn_cache = bsp[slot].ov;
+
+    std::string handle_name = name_data[slot];
+
+    if (!handle_name.size () || handle_name[0] != '@')
+      TODO ("Strange handle name");
+
+    handle_name = handle_name.substr(1);
+
+    octave_value fcn_handle = m_tw->make_fcn_handle (handle_name);
+
+    PUSH_OV (std::move (fcn_handle));
+  }
+  DISPATCH ();
+colon:
+  {
+    bool is_for_cmd;
+
+    // Yes, we are doing this
+    if (0)
+      {
+colon_cmd:
+        is_for_cmd = true;
+      }
+    else
+      {
+        is_for_cmd = false;
+      }
+
+    bool has_incr = false;
+    if (ip[-2] == static_cast<int> (INSTR::COLON3) ||
+        ip[-2] == static_cast<int> (INSTR::COLON3_CMD))
+      has_incr = true;
+
+    octave_value ret;
+
+    if (has_incr)
+      {
+        octave_value &base = THIRD_OV ();
+        octave_value &incr = SEC_OV ();
+        octave_value &limit = TOP_OV ();
+
+        try
+        {
+          ret = colon_op(base, incr, limit, is_for_cmd);
+        }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+
+        STACK_DESTROY (3);
+      }
+    else
+      {
+        octave_value &base = SEC_OV ();
+        octave_value &limit = TOP_OV ();
+
+        try
+        {
+          ret = colon_op(base, limit, is_for_cmd);
+        }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+
+        STACK_DESTROY (2);
+      }
+
+    PUSH_OV (std::move (ret));
+  }
+  DISPATCH_1BYTEOP ();
+
+push_true:
+  {
+    PUSH_OV(ov_true);
+  }
+  DISPATCH_1BYTEOP ();
+push_false:
+  {
+    PUSH_OV(ov_false);
+  }
+  DISPATCH_1BYTEOP ();
+unary_true:
+  {
+    octave_value &op1 = TOP_OV ();
+
+    bool is_true;
+
+    try
+      {
+        is_true = op1.is_true ();
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    STACK_DESTROY (1);
+
+    if (is_true)
+      PUSH_OV (ov_true);
+    else
+      PUSH_OV (ov_false);
+
+  }
+  DISPATCH_1BYTEOP ();
+assign_n:
+  {
+    int n_slots = arg0;
+
+    int n_actual = 0;
+    do
+      {
+        // Move operand to the local at slot in relation to base stack pointer
+
+        octave_value &arg = (*--sp).ov;
+        int slot = POP_CODE_USHORT ();
+        octave_value &lhs_ov = bsp[slot].ov;
+
+
+        /* Expand cs_lists */
+        if (arg.is_cs_list ())
+          {
+            octave_value_list args = arg.list_value ();
+            for (int i = 0; i < args.length (); i++)
+              {
+                octave_value &ov_1 = args (i);
+
+                lhs_ov.maybe_call_dtor ();
+
+                if (ov_1.vm_need_storable_call ())
+                  ov_1.make_storable_value (); // Some types have lazy copy
+
+                if (ov_1.is_undefined ())
+                  {
+                    std::string &name = name_data[slot];
+
+                    // If the return value is ignored, undefined is OK
+                    bool is_ignored = false;
+                    if (name.size () >= 2 && name[0] == '%' && name[1] == '~')
+                      is_ignored = true;
+
+                    Matrix ignored;
+                    octave_value tmp = m_tw->get_auto_fcn_var (stack_frame::auto_var_type::IGNORED);
+                    if (tmp.is_defined ())
+                      {
+                        ignored = tmp.matrix_value ();
+
+                        if (slot < N_RETURNS ())
+                          {
+                            int outputnum = N_RETURNS () - 1 - slot;
+
+                            octave_idx_type idx = ignored.lookup (outputnum);
+                            is_ignored = idx > 0 && ignored (idx - 1) == outputnum;
+                          }
+                      }
+
+                    if (!is_ignored)
+                      {
+                        (*sp++).pee = new execution_exception {"error", "", "element number " + std::to_string (n_actual + 1) + " undefined in return list"};
+                        (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+                        goto unwind;
+                      }
+                  }
+
+                if (OCTAVE_LIKELY (!lhs_ov.is_ref ()))
+                  lhs_ov = std::move (ov_1); // Note move
+                else
+                  lhs_ov.ref_rep ()->set_value (ov_1);
+                n_actual++;
+              }
+          }
+        else
+          {
+            lhs_ov.maybe_call_dtor ();
+
+            if (arg.vm_need_storable_call ())
+              arg.make_storable_value (); // Some types have lazy copy
+
+            if (arg.is_undefined ())
+              {
+                std::string &name = name_data[slot];
+
+                // If the return value is ignored, undefined is OK
+                bool is_ignored = false;
+                if (name.size () >= 2 && name[0] == '%' && name[1] == '~')
+                  is_ignored = true;
+
+                Matrix ignored;
+                octave_value tmp = m_tw->get_auto_fcn_var (stack_frame::auto_var_type::IGNORED);
+                if (tmp.is_defined ())
+                  {
+                    ignored = tmp.matrix_value ();
+
+                    if (slot < N_RETURNS ())
+                      {
+                        int outputnum = N_RETURNS () - 1 - slot;
+
+                        octave_idx_type idx = ignored.lookup (outputnum);
+                        is_ignored = idx > 0 && ignored (idx - 1) == outputnum;
+                      }
+                  }
+                if (!is_ignored)
+                  {
+                    (*sp++).pee = new execution_exception {"error", "", "element number " + std::to_string (n_actual + 1) + " undefined in return list"};
+                    (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+                    goto unwind;
+                  }
+              }
+
+            if (OCTAVE_LIKELY (!lhs_ov.is_ref ()))
+              lhs_ov = std::move (arg); // Note move
+            else
+              lhs_ov.ref_rep ()->set_value (arg);
+
+            n_actual++;
+          }
+
+          arg.~octave_value (); // Destroy the operand
+      }
+    while (n_actual < n_slots);
+  }
+  DISPATCH ();
+
+subassign_id_mat_1d:
+{
+  int slot = arg0;
+  ip++; // nargs always one
+
+  // The top of the stack is the rhs value
+  octave_value &rhs = TOP_OV ();
+  octave_value &arg = SEC_OV ();
+  // The ov to subassign to
+  octave_value &mat_ov = bsp[slot].ov;
+
+  int rhs_type_id = rhs.type_id ();
+  int arg_type_id = arg.type_id ();
+  int mat_type_id = mat_ov.type_id ();
+
+  if (rhs_type_id != m_scalar_typeid || mat_type_id != m_matrix_typeid ||
+    arg_type_id != m_scalar_typeid)
+  {
+    // Rewind ip to the 2nd byte of the opcode
+    ip -= 1;
+    int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+    // Change the specialized opcode to the general one
+    ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::SUBASSIGN_ID);
+    goto subassign_id;
+  }
+
+  try
+    {
+      mat_ov.make_unique ();
+
+      octave_scalar &rhs_scalar = REP (octave_scalar, rhs);
+      octave_scalar &arg_scalar = REP (octave_scalar, arg);
+
+      double idx_dbl = arg_scalar.octave_scalar::double_value ();
+      octave_idx_type idx = idx_dbl - 1;
+      double val = rhs_scalar.octave_scalar::double_value ();
+
+      octave_matrix &mat_ovb = REP (octave_matrix, mat_ov);
+      NDArray &arr = mat_ovb.matrix_ref ();
+      // Handle out-of-bound or non-integer index in the generic opcode
+      if (idx >= arr.numel () || idx < 0 ||
+          idx != idx_dbl - 1)
+        {
+          // Rewind ip to the 2nd byte of the opcode
+          ip -= 1;
+          goto subassign_id;
+        }
+
+      // The NDArray got its own m_rep that might be shared
+      arr.make_unique ();
+
+      arr.xelem (idx) = val;
+    }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+  STACK_DESTROY (2);
+}
+DISPATCH ();
+
+subassign_id:
+  {
+    // The args to the subassign are on the operand stack
+    int slot = arg0;
+    int nargs = *ip++;
+
+    // The top of the stack is the rhs value
+    octave_value &rhs = TOP_OV ();
+    // First argument
+    stack_element *parg = sp - 1 - nargs;
+
+    // Move the args to an ovl
+    // TODO: Should actually be a move
+    bool all_args_are_scalar = true;
+    octave_value_list args;
+    for (int i = 0; i < nargs; i++)
+    {
+      octave_value &arg = parg[i].ov;
+      // We need to expand cs-lists
+      if (arg.type_id () != m_scalar_typeid)
+        all_args_are_scalar = false;
+      if (arg.is_cs_list ())
+        args.append (arg.list_value ());
+      else
+        args.append (arg);
+    }
+
+    // The ov to subassign to
+    octave_value &ov = bsp[slot].ov;
+
+    if (nargs == 1 && all_args_are_scalar && ov.type_id () == m_matrix_typeid &&
+        rhs.type_id () == m_scalar_typeid)
+      {
+        int wide_opcode_offset = slot < 256 ? 0 : -1; // If WIDE is used, we need to look further back
+
+        // If the opcode allready is SUBASSIGN_ID_MAT_1D we were sent back to
+        // SUBASSIGN_ID to handle some error or edgecase, so don't go back.
+        if ( ip[-3 + wide_opcode_offset] != static_cast<unsigned char> (INSTR::SUBASSIGN_ID_MAT_1D))
+          {
+            // Rewind ip to the 2nd byte of the opcode
+            ip -= 1;
+            // Change the general opcode to the specialized one
+            ip[-2 + wide_opcode_offset] = static_cast<unsigned char> (INSTR::SUBASSIGN_ID_MAT_1D);
+            goto subassign_id_mat_1d;
+          }
+      }
+
+    // TODO: Room for performance improvement here maybe
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      ov.make_unique ();
+    else
+      ov.ref_rep ()->ref ().make_unique ();
+
+    if (rhs.is_cs_list ())
+      {
+        const octave_value_list lst = rhs.list_value ();
+
+        if (lst.empty ())
+          {
+            // TODO: Need id, name
+            // TODO: Make execution_exception like the others instead of its own error_type
+            (*sp++).i = static_cast<int>(error_type::INVALID_N_EL_RHS_IN_ASSIGNMENT);
+            goto unwind;
+          }
+
+        rhs = lst(0);
+      }
+
+    // E.g. scalars do not update them self inplace
+    // but create a new octave_value, so we need to
+    // copy the return value to the slot.
+
+    try
+      {
+        ov = ov.simple_subsasgn('(', args, rhs);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    // Destroy the args on the operand stack aswell as rhs
+    STACK_DESTROY (nargs + 1);
+  }
+  DISPATCH ();
+
+end_id:
+  {
+    // Indexed variable
+    int slot = arg0;
+    // Amount of args to the index, i.e. amount of dimensions
+    // being indexed.
+    // E.g. foo (1,2,3) => 3
+    int nargs = *ip++;
+    // Index of the end, in the index, counting from 0.
+    // E.g. foo (1, end, 3) => 1
+    int idx = *ip++;
+
+    octave_value ov = bsp[slot].ov;
+
+    if (ov.is_ref ())
+      ov = ov.ref_rep ()->deref ();
+
+    if (ov.is_undefined ())
+      {
+        (*sp++).pee = new execution_exception {"error","","invalid use of 'end': may only be used to index existing value"};
+        (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+        goto unwind;
+      }
+
+    octave_value end_idx;
+    if (ov.isobject ())
+      {
+        try
+          {
+            end_idx = handle_object_end (ov, idx, nargs);
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+    else
+      end_idx = octave_value (ov.end_index (idx, nargs));
+
+    PUSH_OV (std::move (end_idx));
+  }
+  DISPATCH ();
+end_obj:
+  {
+    // Slot that stores the stack depth of the indexed object
+    int slot = arg0;
+    // Amount of args to the index, i.e. amount of dimensions
+    // being indexed.
+    // E.g. foo (1,2,3) => 3
+    int nargs = *ip++;
+    // Index of the end, in the index, counting from 0.
+    // E.g. foo (1, end, 3) => 1
+    int idx = *ip++;
+
+    octave_value &stack_depth = bsp[slot].ov;
+    // Indexed object
+    octave_value &ov = bsp[stack_depth.int_value () - 1].ov;
+
+    if (ov.is_undefined ())
+      {
+        (*sp++).pee = new execution_exception {"error","","invalid use of 'end': may only be used to index existing value"};
+        (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+        goto unwind;
+      }
+
+    octave_value end_idx;
+    if (ov.isobject ())
+      {
+        try
+          {
+            end_idx = handle_object_end (ov, idx, nargs);
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+    else
+      end_idx = octave_value (ov.end_index (idx, nargs));
+
+    PUSH_OV (std::move (end_idx));
+  }
+  DISPATCH ();
+
+end_x_n:
+  {
+    // Since 'end' in "foo (bar (1, end))" can refer
+    // to the end of 'foo' if 'bar' is a function we
+    // need to scan inner to outer after a defined
+    // object to find the end of.
+
+    int n_ids = arg0;
+    int i;
+
+    for (i = 0; i < n_ids;)
+      {
+        // Amount of args to the index, i.e. amount of dimensions
+        // being indexed.
+        // E.g. foo (1,2,3) => 3
+        int nargs = *ip++;
+        // Index of the end, in the index, counting from 0.
+        // E.g. foo (1, end, 3) => 1
+        int idx = *ip++;
+        // type 0: Like 'end_id:'
+        // type 1: Like 'end_obj:'
+        int type = *ip++;
+        // Slot that stores:
+        //    the object that is being indexed for type 0
+        //    the stack depth of the indexed object for type 1
+        int slot = POP_CODE_USHORT ();
+
+        octave_value ov = bsp[slot].ov;
+
+        if (ov.is_ref ())
+          ov = ov.ref_rep ()->deref ();
+
+        // If the type is 1, the ov in the slot is the stack depth
+        // of the object being indexed.
+        if (type == 1)
+          ov = bsp[ov.int_value () - 1].ov;
+
+        bool is_undef = ov.is_undefined ();
+
+        // If the outer most indexed object is not defined
+        // it is an error.
+        if (is_undef && i + 1 == n_ids)
+          {
+            (*sp++).pee = new execution_exception {"error","","invalid use of 'end': may only be used to index existing value"};
+            (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+            goto unwind;
+          }
+        else if (is_undef)
+          {
+            i++;
+            continue; // Look if the next outer object is defined.
+          }
+
+        octave_value end_idx;
+        if (ov.isobject ())
+          {
+            try
+              {
+                end_idx = handle_object_end (ov, idx, nargs);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+        else
+          end_idx = octave_value (ov.end_index (idx, nargs));
+
+        PUSH_OV (std::move (end_idx));
+        i++;
+        break;
+      }
+
+    // Skip any unread objects to index
+    for (; i < n_ids; i++)
+      ip += 5;
+  }
+  DISPATCH ();
+
+eval:
+  {
+    int nargout = arg0;
+    int tree_idx = POP_CODE_INT ();
+    CHECK (tree_idx < 0); // Should always be negative to mark for eval. Otherwise it is debug data
+
+    auto it = unwind_data->m_ip_to_tree.find (tree_idx);
+    CHECK (it != unwind_data->m_ip_to_tree.end ());
+
+    tree_expression *te = static_cast <tree_expression*> (it->second);
+
+    octave_value_list retval;
+    try
+    {
+      retval = te->evaluate_n (*m_tw, nargout);
+    }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+  }
+  DISPATCH ();
+bind_ans:
+  {
+    int slot = arg0;
+    octave_value &ans_on_stack = TOP_OV ();
+    octave_value &ans_in_slot = bsp [slot].ov;
+
+    if (ans_on_stack.is_defined ())
+      {
+        if (!ans_on_stack.is_cs_list ())
+          {
+            ans_in_slot.maybe_call_dtor ();
+            if (ans_on_stack.vm_need_storable_call ())
+              ans_on_stack.make_storable_value ();
+
+            if (OCTAVE_LIKELY (!ans_in_slot.is_ref ()))
+              ans_in_slot = std::move (ans_on_stack); // Note move
+            else
+              ans_in_slot.ref_rep ()->set_value (ans_on_stack);
+          }
+        else
+          {
+            // We need to recursivly expand any cs-list and assign
+            // the elements one by one to ans.
+            std::vector<octave_value> v_el;
+
+            std::vector<octave_value_list> v_ovl_stack; // "recursive" stacks
+            std::vector<int> v_ovl_idx_stack;
+
+            v_ovl_stack.push_back (ans_on_stack.list_value ());
+            v_ovl_idx_stack.push_back (0);
+
+            while (true)
+              {
+              redo:
+                octave_value_list &lst = v_ovl_stack.back ();
+                int &idx = v_ovl_idx_stack.back (); // Note: reference changes in loop
+
+                for (; idx < lst.length (); idx++)
+                  {
+                    octave_value ov = lst (idx);
+                    if (ov.is_cs_list ())
+                      {
+                        idx++;
+                        v_ovl_stack.push_back (ov.list_value ());
+                        v_ovl_idx_stack.push_back (0);
+                        goto redo;
+                      }
+                    else if (ov.is_defined ())
+                      v_el.push_back (ov);
+                  }
+
+                v_ovl_stack.pop_back ();
+                v_ovl_idx_stack.pop_back ();
+
+                if (v_ovl_stack.size () == 0)
+                  break;
+              }
+
+            // Assign all elements to ans one by one
+            for (auto &ov_rhs : v_el)
+              {
+                ans_in_slot.maybe_call_dtor ();
+                if (ov_rhs.vm_need_storable_call ())
+                  ov_rhs.make_storable_value ();
+
+                if (OCTAVE_LIKELY (!ans_in_slot.is_ref ()))
+                  ans_in_slot = std::move (ov_rhs); // Note move
+                else
+                  ans_in_slot.ref_rep ()->set_value (ov_rhs);
+              }
+          }
+      }
+
+    STACK_DESTROY (1);
+  }
+DISPATCH ();
+
+push_anon_fcn_handle:
+{
+  ip--; // Rewind ip for int macro underneath
+  int tree_idx = POP_CODE_INT ();
+
+  auto it = unwind_data->m_ip_to_tree.find (tree_idx);
+  CHECK (it != unwind_data->m_ip_to_tree.end ());
+
+  tree_anon_fcn_handle *h = reinterpret_cast <tree_anon_fcn_handle*> (it->second);
+
+  octave_value ret = m_tw->evaluate_anon_fcn_handle (*h);
+
+  PUSH_OV (ret);
+}
+DISPATCH ();
+
+for_complex_setup:
+{
+  octave_value &ov_rhs = TOP_OV ();
+  ov_rhs.make_unique (); // TODO: Dunno if needed
+  unsigned char b0 = arg0;
+  unsigned char b1 = *ip++;
+
+  int target = b0 | (b1 << 8);
+
+  if (ov_rhs.is_undefined ())
+    {
+      ip = code + target;
+      DISPATCH ();
+    }
+
+  if (!ov_rhs.isstruct ())
+    {
+      (*sp++).i = 1; // Need two native ints on the stack so they can be poped by the unwind.
+      (*sp++).i = 2;
+      (*sp++).pee = new execution_exception {"error", "", "in statement 'for [X, Y] = VAL', VAL must be a structure"};
+      (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+      goto unwind;
+    }
+
+  octave_map map = ov_rhs.map_value ();
+  string_vector keys = map.keys ();
+  octave_idx_type n = keys.numel ();
+
+  // Push n to the stack
+  (*sp++).i = n;
+  // Push a counter to the stack, initialized so that it will
+  // increment to 0.
+  (*sp++).i = -1;
+}
+DISPATCH ();
+
+for_complex_cond:
+{
+  // Increase counter
+  TOP ().i++; // Wraps to zero first iteration
+
+  // Check if we done all iterations
+  // n is second element on the stack
+  if (TOP ().i == SEC ().i)
+    {
+      // The after address
+      unsigned char b0 = arg0;
+      unsigned char b1 = *ip++;
+
+      int after = b0 | (b1 << 8);
+
+      // goto after block
+      ip = code + after;
+    }
+  else
+    {
+      ip++; // Skip 2nd part of afteraddress
+      int slot_key = POP_CODE_USHORT ();
+      int slot_value = POP_CODE_USHORT ();
+      octave_idx_type counter = TOP ().i;
+
+      octave_value &ov_rhs = THIRD_OV (); // This is always a struct
+      octave_value &ov_key = bsp[slot_key].ov;
+      octave_value &ov_val = bsp[slot_value].ov;
+
+      // TODO: Abit wasteful copying map_value () each time but whatever
+      //       who uses complex for loops anyways.
+      std::string key = ov_rhs.map_value ().keys () [counter];
+      const Cell val_lst = ov_rhs.map_value ().contents (key);
+
+      octave_idx_type n = val_lst.numel ();
+      octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);
+
+      if (counter == 0)
+        {
+          ov_val.maybe_call_dtor (); // The first iteration these could be class objects ...
+          ov_key.maybe_call_dtor ();
+        }
+
+      val.make_unique (); // TODO: Dunno if needed
+
+      if (ov_val.is_ref ())
+        ov_val.ref_rep ()->set_value (val);
+      else
+        ov_val = val;
+
+      if (ov_val.is_ref ())
+        ov_key.ref_rep ()->set_value (key);
+      else
+        ov_key = key;
+    }
+}
+DISPATCH ();
+
+/* For dynamic m*n matrix where m and n < 256 */
+matrix:
+  {
+    int nrows = arg0;
+    int ncols = *ip++;
+    int n_el = nrows * ncols;
+
+    // The first element is down the stack
+    // and the last element is at the top.
+    octave_value *first_arg = &(*sp).ov - n_el;
+
+    // The stack pointer is pointing to the first unused
+    // stack position, so it is the end pointer.
+    octave_value *end_arg = &(*sp).ov;
+
+    try
+      {
+        tm_const tmp (first_arg, end_arg, ncols, *m_tw);
+
+        octave_value &&ov = tmp.concat (' ');
+
+        STACK_DESTROY (n_el);
+
+        PUSH_OV (ov);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH ();
+matrix_big:
+  {
+    int type = arg0;
+
+    /* type 0 indicates a matrix that has unequal length of the rows.
+     *
+     * Any other value than zero indicates a big "rectangle" matrix
+     * with more than 255 elements in a row or column. */
+    if (type == 0)
+      {
+        int nrows = POP_CODE_INT ();
+
+        std::vector<int> length_rows;
+
+        int n_el = 0;
+        for (int i = 0; i < nrows; i++)
+          {
+            int row_length = POP_CODE_INT ();
+            length_rows.push_back (row_length);
+            n_el += row_length;
+          }
+
+        // The first element is down the stack
+        // and the last element is at the top.
+        octave_value *first_arg = &(*sp).ov - n_el;
+
+        // The stack pointer is pointing to the first unused
+        // stack position, so it is the end pointer.
+        octave_value *end_arg = &(*sp).ov;
+
+        try
+          {
+            tm_const tmp (first_arg, end_arg, length_rows, *m_tw);
+
+            octave_value &&ov = tmp.concat (' ');
+
+            STACK_DESTROY (n_el);
+
+            PUSH_OV (ov);
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+    else
+      {
+        int nrows = POP_CODE_INT ();
+        int ncols = POP_CODE_INT ();
+        int n_el = nrows * ncols;
+
+        // The first element is down the stack
+        // and the last element is at the top.
+        octave_value *first_arg = &(*sp).ov - n_el;
+
+        // The stack pointer is pointing to the first unused
+        // stack position, so it is the end pointer.
+        octave_value *end_arg = &(*sp).ov;
+
+        try
+          {
+            tm_const tmp (first_arg, end_arg, ncols, *m_tw);
+
+            octave_value &&ov = tmp.concat (' ');
+
+            STACK_DESTROY (n_el);
+
+            PUSH_OV (ov);
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+  }
+  DISPATCH ();
+trans_mul:
+  MAKE_BINOP(compound_binary_op::op_trans_mul)
+  DISPATCH_1BYTEOP();
+mul_trans:
+  MAKE_BINOP(compound_binary_op::op_mul_trans)
+  DISPATCH_1BYTEOP();
+herm_mul:
+  MAKE_BINOP(compound_binary_op::op_herm_mul)
+  DISPATCH_1BYTEOP();
+mul_herm:
+  MAKE_BINOP(compound_binary_op::op_mul_herm)
+  DISPATCH_1BYTEOP();
+trans_ldiv:
+  MAKE_BINOP(compound_binary_op::op_trans_ldiv)
+  DISPATCH_1BYTEOP();
+herm_ldiv:
+  MAKE_BINOP(compound_binary_op::op_herm_ldiv)
+  DISPATCH_1BYTEOP();
+wordcmd:
+  {
+    int slot = arg0; // Needed if we need a function lookup
+    int nargout = *ip++;
+    int n_args_on_stack = *ip++;
+
+    // The object to index is before the args on the stack
+    octave_value &ov = (sp[-1 - n_args_on_stack]).ov;
+
+    octave_value_list ovl;
+    // The operands are on the top of the stack
+    for (int i = n_args_on_stack - 1; i >= 0; i--)
+      ovl.append (sp[-1 - i].ov); // TODO: copied, not moved
+    // TODO: Expand cs_list? Probably not since strings?
+
+    // octave_fcn_cache and some octave_fcn_handle have caches
+    bool has_function_cache = ov.has_function_cache ();
+
+    if (! has_function_cache && ov.is_defined ())
+      TODO ("Error: word list command defined");
+
+    else if (has_function_cache)
+      {
+// The else clause bellow jumps to here
+// TODO: Should be a shared thing?
+//       Add a "register" for octave_function *fcn?
+querry_fcn_cache2:
+
+        octave_function *fcn;
+        try
+          {
+            fcn = ov.get_cached_fcn (ovl);
+          }
+        CATCH_EXECUTION_EXCEPTION
+
+        if (! fcn)
+          {
+            (*sp++).ps = new std::string {name_data[slot]};
+            (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+            goto unwind;
+          }
+
+        if (fcn->is_compiled ())
+          {
+            octave_user_function *usr_fcn = static_cast<octave_user_function *> (fcn);
+            // Alot of code in this define
+            bool has_cs_list_arg = false;
+            MAKE_BYTECODE_CALL
+
+            // Now dispatch to first instruction in the
+            // called function
+          }
+        else
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                octave_value_list ret = fcn->call (*m_tw, nargout, ovl);
+
+                STACK_DESTROY (n_args_on_stack + 1);
+                EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (ret, nargout);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION_WITH_NAME
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+      }
+    else
+      {
+        // It is probably a function call
+        if (! ov.is_nil ())
+          {
+            PRINT_VM_STATE("err %s" COMMA name_data[slot].c_str ());
+            TODO ("Not nil object for fcn cache replacement");
+          }
+
+        // Put a function cache object in the slot and in the local ov
+        ov = bsp[slot].ov =
+          octave_value (new octave_fcn_cache (name_data[slot]));
+        goto querry_fcn_cache2; // Jump into the if clause above
+      }
+  }
+  DISPATCH ();
+handle_signals:
+  {
+    // Check if there is any signal to handle
+    try
+      {
+        octave_quit ();
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+  }
+  DISPATCH_1BYTEOP ();
+push_cst_dbl_0:
+{
+  PUSH_OV (ov_dbl_0);
+}
+DISPATCH_1BYTEOP ();
+push_cst_dbl_1:
+{
+  PUSH_OV (ov_dbl_1);
+}
+DISPATCH_1BYTEOP ();
+push_cst_dbl_2:
+{
+  PUSH_OV (ov_dbl_2);
+}
+DISPATCH_1BYTEOP ();
+
+push_cell:
+  {
+    // The amount of columns is at the top of the stack as
+    // u64 ov.
+    octave_value &rows_ov = TOP_OV ();
+    octave_value &cols_ov = SEC_OV ();
+    octave_idx_type n_cols = cols_ov.uint64_value ();
+    octave_idx_type n_rows = rows_ov.uint64_value ();
+    STACK_DESTROY (2); // Destroy the cols and rows ov
+
+    // We need to first figure out the size of the Cell
+    // we are creating.
+    // E.g.
+    //      z = cell (1,2,3,0,5);
+    //      {1, z{:}, 2}
+    // Is a 2x1 Cell.
+    // So we can't know the Cell size in advance of the
+    // args are evaluated.
+
+    octave_idx_type n_actual_rows = 0;
+    if (n_cols != 0)
+      n_actual_rows++;
+
+    stack_element *tmp_sp = sp;
+    octave_idx_type n_cols_i = n_cols;
+    for (octave_idx_type i = 0; i < n_rows; i++)
+      {
+        tmp_sp -= n_cols_i;
+
+        if (i != n_rows - 1) // Not last iteration
+          {
+            // We now have a ov with the number of cols on the stack
+            octave_value &cols_i_ov = tmp_sp[-1].ov; tmp_sp--;
+            n_cols_i = cols_i_ov.uint64_value ();
+            if (n_cols_i != 0)
+              n_actual_rows++;
+          }
+      }
+
+    Cell cell(n_actual_rows, n_cols);
+    int n_cols_orig = n_cols;
+
+    int row_idx = 0;
+    n_cols_i = n_cols;
+    for (octave_idx_type i = 0; i < n_rows; i++)
+      {
+        if (n_cols_i != 0) // Only add row to cell if the row "exists", i.e. is not e.g. 0x3 sized
+          {
+            for (octave_idx_type j = 0; j < n_cols_i; j++)
+              {
+                cell (n_actual_rows - 1 - row_idx, n_cols_i - 1 - j) = TOP_OV();
+                STACK_DESTROY (1);
+              }
+            row_idx++;
+          }
+
+        if (i != n_rows - 1) // Not last iteration
+          {
+            // We now have a ov with the number of cols on the stack
+            octave_value &cols_i_ov = TOP_OV ();
+            n_cols_i = cols_i_ov.uint64_value ();
+            if (n_cols_i && n_cols_orig != n_cols_i)
+              TODO ("Wrong number of cols in other row");
+
+            n_cols = n_cols_i;
+            STACK_DESTROY (1);
+          }
+      }
+
+    PUSH_OV (cell);
+  }
+  DISPATCH_1BYTEOP ();
+push_ov_u64:
+  {
+    PUSH_OV (octave_int<uint64_t>{});
+  }
+  DISPATCH_1BYTEOP ();
+expand_cs_list:
+  {
+    octave_value cs = TOP_OV ();
+    octave_value cols_ov = SEC_OV (); // n columns
+    octave_value rows_ov = THIRD_OV (); // n rows
+
+    if (cs.is_cs_list ())
+      {
+        STACK_DESTROY (3);
+
+        octave_value_list tmp_ovl = cs.list_value ();
+
+        for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)
+          {
+            PUSH_OV (tmp_ovl (i));
+            cols_ov.non_const_unary_op (octave_value::unary_op::op_incr);
+          }
+      }
+    else
+      {
+        STACK_DESTROY (3);
+
+        cols_ov.non_const_unary_op (octave_value::unary_op::op_incr);
+
+        PUSH_OV (cs);
+      }
+
+    PUSH_OV (rows_ov);
+    PUSH_OV (cols_ov);
+  }
+  DISPATCH_1BYTEOP ();
+
+  {
+    // TODO: Too much code. Should be broken out?
+    // Something made sp not be in r15.
+
+    int nargout, slot;
+    if (0)
+      {
+index_cell_idn:
+        slot = arg0; // Needed if we need a function lookup
+        nargout = *ip++;
+      }
+    else if (0)
+index_cell_id1:
+      {
+        slot = arg0;
+        nargout = 1;
+      }
+    else if (0)
+index_cell_id0:
+      {
+        slot = arg0;
+        nargout = 0;
+      }
+
+    int n_args_on_stack = *ip++;
+
+    // The object to index is before the args on the stack
+    octave_value &ov = (sp[-1 - n_args_on_stack]).ov;
+
+    // TODO: The ovl should not be needed
+    // Make an ovl with the args
+    // TODO: Should be inplace moves
+    // TODO: cl_lists should expanded inplace on the stack instead.
+    // TODO: Cache lookup should just take pointers to the stack.
+    octave_value_list ovl;
+    bool has_cs_list_arg = false;
+    // The operands are on the top of the stack
+    for (int i = n_args_on_stack - 1; i >= 0; i--)
+      {
+        octave_value &arg = sp[-1 - i].ov;
+        // If the operand arg is a cs list we need to expand it
+        if (arg.is_cs_list ())
+          {
+            has_cs_list_arg = true;
+            ovl.append (arg.list_value ());
+          }
+        else
+          ovl.append (sp[-1 - i].ov); // TODO: copied, not moved
+      }
+
+    // octave_fcn_cache and some octave_fcn_handle have caches
+    bool has_function_cache = ov.has_function_cache ();
+
+    if (! has_function_cache && ov.is_defined ())
+      {
+        // It is probably a variable
+
+        // TODO: subsref should take ovl instead and be chained,
+        // or something smarter
+        std::list<octave_value_list> idx; // TODO: mallocs!
+
+        idx.push_back(ovl);
+
+
+        // TODO: subsref might throw index error
+        octave_value_list retval;
+
+        if (OCTAVE_LIKELY (! ov.is_function ()
+                           || ov.is_classdef_meta ()))
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                retval = ov.subsref("{", idx, nargout);
+                idx.clear ();
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION_WITH_NAME
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+        else
+          {
+            TODO ("Classes not implemented for cell index yet");
+            #if 0
+            retval = handle_superclass (*m_tw,
+                                        ov,
+                                        idx,
+                                        nargout);
+            #endif
+          }
+
+        bool is_fcn = (retval.length () ?
+                         retval(0).is_function() : false);
+
+        // "FIXME: when can the following happen?  In what case does indexing
+        //  result in a value that is a function?  Classdef method calls?
+        //  Something else?"
+
+        if (OCTAVE_LIKELY (!is_fcn))
+          {
+            idx.clear ();
+            // TODO: Necessary? I guess it might trigger dtors
+            // or something?
+            ov = octave_value ();
+          }
+        else
+          {
+            octave_value val = retval(0);
+            octave_function *fcn = val.function_value (true);
+
+            if (fcn)
+              {
+                octave_value_list final_args;
+
+                if (! idx.empty ())
+                  final_args = idx.front ();
+
+                try
+                  {
+                    m_tw->set_active_bytecode_ip (ip - code);
+                    retval = fcn->call (*m_tw, nargout, final_args);
+                  }
+                CATCH_INTERRUPT_EXCEPTION
+                CATCH_INDEX_EXCEPTION
+                CATCH_EXECUTION_EXCEPTION
+                CATCH_BAD_ALLOC
+                CATCH_EXIT_EXCEPTION
+              }
+
+            idx.clear ();
+            ov = octave_value ();
+            val = octave_value ();
+          }
+
+        STACK_DESTROY (n_args_on_stack + 1);
+        EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+      }
+    else if (has_function_cache)
+      {
+// The else clause bellow jumps to here
+querry_fcn_cache3:
+
+        octave_function *fcn;
+        try
+          {
+            fcn = ov.get_cached_fcn (ovl);
+          }
+        CATCH_EXECUTION_EXCEPTION
+
+        if (! fcn)
+          {
+            (*sp++).ps = new std::string {name_data[slot]};
+            (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+            goto unwind;
+          }
+
+        if (fcn->is_compiled ())
+          {
+            octave_user_function *usr_fcn = static_cast<octave_user_function *> (fcn);
+            // Alot of code in this define
+            MAKE_BYTECODE_CALL
+
+            // Now dispatch to first instruction in the
+            // called function
+          }
+        else
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                octave_value_list ret = fcn->call (*m_tw, nargout, ovl);
+
+                STACK_DESTROY (n_args_on_stack + 1);
+                EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (ret, nargout);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION_WITH_NAME
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+      }
+    else
+      {
+        // It is probably a function call
+        if (! ov.is_nil ())
+          {
+            PRINT_VM_STATE("err %s" COMMA name_data[slot].c_str ());
+            TODO ("Not nil object for fcn cache replacement");
+          }
+
+        // Put a function cache object in the slot and in the local ov
+        ov = bsp[slot].ov =
+          octave_value (new octave_fcn_cache (name_data[slot]));
+        goto querry_fcn_cache3; // Jump into the if clause above
+      }
+  }
+  DISPATCH ();
+
+incr_prefix:
+  {
+    octave_value &ov = TOP_OV ();
+    // Inplace
+    ov.non_const_unary_op (octave_value::unary_op::op_incr);
+  }
+  DISPATCH_1BYTEOP ();
+
+rot:
+  {
+    octave_value top_ov = TOP_OV ();
+    octave_value sec_ov = SEC_OV ();
+    STACK_DESTROY (2);
+    PUSH_OV (top_ov);
+    PUSH_OV (sec_ov);
+  }
+  DISPATCH_1BYTEOP ();
+
+varargin_call:
+  {
+    // We jump to here when a bytecode call notices it is
+    // calling a function with varargin.
+    //
+    // Continue where we left off. Restore temp variables from the stack.
+
+    octave_user_function *usr_fcn = static_cast<octave_user_function *> (sp[0].pv);
+
+    int n_returns_callee = static_cast<signed char> (ip[-4]);
+    if (n_returns_callee < 0)
+      n_returns_callee = -n_returns_callee;
+    int n_args_callee = -static_cast<signed char> (ip[-3]); // Note: Minus
+    int n_locals_callee = ip[-2] | (ip[-1] << 8);
+
+    int nargout = sp[-1].i;
+
+    // Recreate first arg and n_args_on_stack
+    // from the stack
+    stack_element *first_arg = sp[-8].pse;
+    int n_args_on_stack = (sp - 8) - first_arg;
+
+    // Construct return values - note nargout
+    // is allready pushed as a uint64
+    for (int i = 1; i < n_returns_callee; i++)
+      PUSH_OV ();
+
+    int n_args_before_varargin =
+      std::min (n_args_callee - 1,
+                n_args_on_stack);
+    // Move the args to the new stack, except varargin
+    //
+    // We need to expand any cs-list, but only until the next
+    // argument would be in varargin. Those need to end up
+    // in the varargin cell array.
+    int ii;
+    int n_args_on_callee_stack = 0;
+    octave_value_list cs_args;
+    int cs_args_idx = 0;
+    for (ii = 0; ii < n_args_before_varargin; ii++)
+      {
+        octave_value &arg = first_arg[ii].ov;
+        if (arg.is_cs_list ())
+          {
+            cs_args = arg.list_value ();
+            cs_args_idx = 0;
+            for (int j = 0; j < cs_args.length () && n_args_on_callee_stack < n_args_before_varargin; j++)
+              {
+                PUSH_OV (cs_args (j));
+                n_args_on_callee_stack++;
+                cs_args_idx++;
+              }
+          }
+        else
+          {
+            PUSH_OV (std::move (arg));
+            n_args_on_callee_stack++;
+          }
+
+        // Destroy the args
+        first_arg[ii].ov.~octave_value ();
+      }
+      // TODO: Expand cl_list? Smarter way? Do it in beginning ...
+
+    // Construct missing args, if any
+    for (int i = n_args_on_callee_stack; i < n_args_callee - 1; i++)
+      PUSH_OV ();
+
+    int n_args_in_varargin = n_args_on_stack - n_args_callee + 1; // "Surplus" args
+    int n_cells_left = cs_args.length () - cs_args_idx; // Amount of leftover cell ellements that need to go into varargin
+
+    int idx_cell = 0;
+    if (n_args_in_varargin > 0 || n_cells_left) // Anything to put in the varargin cell?
+      {
+        // TODO: Preallocate whole cell
+        Cell cell(n_cells_left ? 1 : 0, n_cells_left);
+
+        // Put the leftover objects from the cs-list expansion
+        // in the varargin cell, if any
+        for (int i = 0; i < n_cells_left; i++)
+          cell (0, idx_cell++) = cs_args (cs_args_idx + i);
+
+        // We need to expand cs-lists here too ...
+        for (int i = 0; i < n_args_in_varargin; i++)
+          {
+            // int col = n_args_in_varargin - 1 - i;
+            octave_value &arg = first_arg[ii + i].ov;
+
+            if (arg.is_cs_list ())
+              {
+                octave_value_list cs_args_i = arg.list_value ();
+                for (int j = 0; j < cs_args_i.length (); j++)
+                  {
+                    if (cell.numel () <= idx_cell)
+                      cell.resize (dim_vector {1, idx_cell + 1});
+                    cell (0, idx_cell++) = cs_args_i (j);
+                  }
+              }
+            else
+              {
+                if (cell.numel () <= idx_cell)
+                  cell.resize (dim_vector {1, idx_cell + 1});
+                cell (0, idx_cell++) = std::move (arg);
+              }
+
+            arg.~octave_value ();
+          }
+
+        // Push varargin to the stack
+        PUSH_OV (cell);
+      }
+    else
+      PUSH_OV (Cell (0,0)); // Empty cell into varargin's slot
+
+    // Construct locals
+    int n_locals_to_ctor =
+      n_locals_callee - n_args_callee - n_returns_callee;
+
+    CHECK_STACK (n_locals_to_ctor);
+    for (int i = 0; i < n_locals_to_ctor; i++)
+      PUSH_OV ();
+
+    int nargin = n_args_on_callee_stack + idx_cell; // n_args_callee count includes varargin
+    try
+      {
+        m_tw->push_stack_frame(*this, usr_fcn, nargout, nargin);
+      }
+    CATCH_STACKPUSH_EXECUTION_EXCEPTION // Sets m_could_not_push_frame to true
+    CATCH_STACKPUSH_BAD_ALLOC
+
+    /* Called fn needs to know about ignored outputs .e.g. [~, a] = foo() */
+    if (m_output_ignore_data)
+      {
+        if (m_output_ignore_data->is_pending ())
+          m_tw->set_auto_fcn_var (stack_frame::IGNORED, m_output_ignore_data->get_ignore_matrix ());
+        else
+          m_tw->set_auto_fcn_var (stack_frame::IGNORED, {});
+        m_output_ignore_data->m_v_lvalue_list.push_back (m_tw->lvalue_list ());
+        m_tw->set_lvalue_list (nullptr);
+      }
+
+    /* N_RETURNS is negative for varargout */
+    int n_returns = N_RETURNS () - 1; /* %nargout in N_RETURNS */
+    if (n_returns >= 0 && nargout > n_returns)
+      {
+        (*sp++).pee = new execution_exception {"error","","function called with too many outputs"};
+        (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+        goto unwind;
+      }
+
+    // Now dispatch to first instruction in the
+    // called function
+  }
+  DISPATCH ();
+
+unwind:
+  {
+    ip--; // Rewind ip to after the opcode (i.e. arg0's position in the code)
+    // Push VM state
+    m_sp = sp;
+    m_bsp = bsp;
+    m_rsp = rsp;
+    m_code = code;
+    m_data = data;
+    m_name_data = name_data;
+    m_ip = ip - code;
+    m_unwind_data = unwind_data;
+
+    // Ther error_type is put on the stack before the jump to unwind.
+    error_type et = static_cast<error_type> (m_sp[-1].i);
+    m_sp--;
+
+    // Save current exception to the error system in handle_error ()
+    error_data errdat = handle_error (et);
+
+    // Only run unwind_protect code if the exception is the interrupt or OOM exception.
+    // I.e. no 'throw ... catch' code.
+    bool only_unwind_protect = et == error_type::INTERRUPT_EXC;
+
+    while (1)
+      {
+        // Find unwind entry for current value of the instruction pointer
+        unwind_entry *entry = find_unwind_entry_for_current_state (only_unwind_protect);
+
+        unwind_entry_type type = unwind_entry_type::INVALID;
+        if (entry)
+          type = entry->m_unwind_entry_type;
+
+        // We need to figure out what stack depth we want.
+        // If we are unwinding in a try catch we need to save any
+        // nesting switch or for loop stack objects on the stack.
+        int target_stack_depth = N_LOCALS();
+        if (entry)
+          {
+            target_stack_depth += entry->m_stack_depth;
+          }
+
+        // Unwind the stack down to the locals
+        //
+        // If we got here from return op code we might allready have
+        // destroyed the locals when an error triggered.
+        while (m_sp - m_bsp > target_stack_depth)
+          {
+            // If the stack depth matches a for loop we need to
+            // pop some native ints.
+            //
+            // TODO: Wasteful search for forloop each iteration
+            int current_stack_depth = m_sp - m_bsp - N_LOCALS ();
+            int stack_depth_for_forloop =
+              find_unwind_entry_for_forloop (current_stack_depth);
+
+            if (stack_depth_for_forloop != -1 &&
+                current_stack_depth == stack_depth_for_forloop + 3)
+              {
+                m_sp -= 2; // Pop two ints
+                (*--m_sp).ov.~octave_value (); // Pop ov
+              }
+            else
+              (*--m_sp).ov.~octave_value ();
+          }
+
+        if (type == unwind_entry_type::UNWIND_PROTECT ||
+            type == unwind_entry_type::TRY_CATCH)
+          {
+            // Need to set some stuff for last_error etc and make the
+            // interpreter happy by reseting stuff
+            error_system& es = m_tw->get_interpreter().get_error_system ();
+
+            octave_scalar_map err_map;
+
+            err_map.assign ("message", es.last_error_message ());
+            err_map.assign ("identifier", es.last_error_id ());
+            err_map.assign ("stack", es.last_error_stack ());
+
+            m_tw->get_interpreter().recover_from_exception ();
+
+            // Set stack pointer and ip and dispatch
+            m_ip = entry->m_ip_target;
+            code = m_code;
+            ip = m_code + m_ip;
+            sp = m_sp;
+
+            // Push the error object that is either just poped right
+            // away by a POP instruction or assigned to the catch
+            // clause identifier.
+            PUSH_OV (err_map);
+
+            if (et == error_type::INTERRUPT_EXC)
+              m_unwinding_interrupt = true;
+
+            goto bail_unwind;
+          }
+
+        m_tw->get_current_stack_frame ()->vm_unwinds ();
+
+        // Destroy locals down to nargout
+        while (m_sp != m_bsp + 1)
+          {
+            (*--m_sp).ov.~octave_value ();
+          }
+
+        m_sp--; // nargout
+
+        if (m_sp == m_rsp)
+          break; // Got down to start of root stack frame
+
+        if (OCTAVE_UNLIKELY (m_profiler_enabled))
+          {
+            auto p = vm::m_vm_profiler;
+            if (p)
+              {
+                std::string fn_name = data[2].string_value (); // profiler_name () querried at compile time
+                p->exit_fn (fn_name);
+              }
+          }
+
+        // Restore ip
+        ip = (*--m_sp).puc;
+
+        // Restore bsp
+        bsp = m_bsp = (*--m_sp).pse;
+
+        // Restore id names
+        name_data = m_name_data = (*--m_sp).ps;
+
+        // Restore data
+        data = m_data = (*--m_sp).pov;
+
+        // Restore code
+        code = m_code = (*--m_sp).puc;
+        m_ip = ip - m_code;
+
+        // Restore unwind data
+        unwind_data = m_unwind_data = (*--m_sp).pud;
+
+        // Restore the stack pointer
+        sp = m_sp = m_sp[-1].pse;
+
+        // Pop dynamic stackframe (unless it was never pushed)
+        if (!m_could_not_push_frame)
+          m_tw->pop_stack_frame ();
+        else
+          m_could_not_push_frame = false;
+
+        // If we are messing with the interpreters lvalue_list due to some
+        // ~ we need to restore stuff.
+        if (m_output_ignore_data)
+          {
+            delete m_tw->lvalue_list ();
+            CHECK (!m_output_ignore_data->m_v_lvalue_list.empty ());
+
+            m_tw->set_lvalue_list (m_output_ignore_data->m_v_lvalue_list.back ());
+            m_output_ignore_data->m_v_lvalue_list.pop_back ();
+          }
+      }
+
+    CHECK_STACK (0);
+    this->m_dbg_proper_return = true;
+
+    m_tw->set_lvalue_list (m_original_lvalue_list);
+
+    // Rethrow exceptions out of the VM
+    if (et == error_type::INTERRUPT_EXC)
+      throw interrupt_exception {};
+    else if (et == error_type::EXIT_EXCEPTION)
+      throw exit_exception (errdat.m_exit_status, errdat.m_safe_to_return);
+    else
+      {
+        error_system& es = m_tw->get_interpreter().get_error_system ();
+        es.rethrow_error (es.last_error_id (), es.last_error_message (), es.last_error_stack ());
+      }
+
+  }
+bail_unwind:
+  DISPATCH ();
+
+init_global:
+  {
+    // The next instruction tells whether we should init a global or persistent
+    // variable.
+    global_type type = static_cast<global_type> (arg0);
+
+    // The next instruction is the local slot number for the global variable
+    int slot = POP_CODE_USHORT();
+    POP_CODE_USHORT(); // Not used TODO: Remove. Make this opcode use WIDE
+
+    std::string& name = name_data[slot];
+
+    octave_value &ov_slot = bsp[slot].ov;
+    bool slot_already_live = ov_slot.is_defined ();
+
+    bool is_marked_in_VM = ov_slot.is_ref ();
+
+    // The next instruction is whether the global declare has an
+    // initialization value
+    bool has_init_code = *ip++;
+
+    // If the global was not allready created we need to assign a
+    // empty double matrix to it.
+    // If there already is a defined local in the slot we initialize
+    // the global with the local
+    // TODO: Should be a decrapation warning here for this
+    octave_value ov_default;
+    if (slot_already_live && !is_marked_in_VM)
+      ov_default = std::move (ov_slot);
+    else
+      ov_default = Matrix ();
+
+    if (!is_marked_in_VM)
+      ov_slot = octave_value {};
+
+    bool global_is_new_in_callstack = false;
+
+    if (type == global_type::GLOBAL)
+      {
+        if (is_marked_in_VM && ov_slot.ref_rep ()->is_persistent_ref ())
+          {
+            (*sp++).pee = new execution_exception {"error", "",
+              "can't make persistent variable '" + name + "' global"};
+            (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+            goto unwind;
+          }
+
+        auto sym = m_tw->get_current_stack_frame ()->insert_symbol (name);
+        // Note: Install variable wont override global's value with nil ov from
+        //       the "{}" argument.
+        //
+        //       Also install_variable () will write a true ov to the marker
+        //       ov on the VM stack.
+        m_tw->get_current_stack_frame()->install_variable (sym, {}, 1);
+
+        octave_value &ov_gbl = m_tw->global_varref (name);
+        global_is_new_in_callstack = ov_gbl.is_undefined ();
+
+        // We assign the default before the init
+        if (global_is_new_in_callstack)
+          m_tw->global_assign (name, ov_default);
+
+        if (!is_marked_in_VM)
+          {
+            ov_slot = octave_value {new octave_value_ref_global {name}};
+          }
+
+        // TODO: Assert global_is_new_in_callstack != global_is_marked_in_VM
+        // but does not work until the dynamic stack is implemented.
+
+        // CHECK (global_is_new_in_callstack != global_is_marked_in_VM);
+      }
+    else if (type == global_type::PERSISTENT)
+      {
+        if (is_marked_in_VM && ov_slot.ref_rep ()->is_global_ref ())
+          {
+            (*sp++).pee = new execution_exception {"error", "",
+              "can't make global variable '" + name + "' persistent"};
+            (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+            goto unwind;
+          }
+
+        auto frame = m_tw->get_current_stack_frame();
+
+        symbol_record sym = frame->lookup_symbol(name);
+        try
+          {
+            // Throws if global or formal parameter
+            frame->make_persistent(sym);
+          }
+        CATCH_EXECUTION_EXCEPTION
+
+        auto scope = frame->get_scope ();
+
+        // TODO: Put the offset in the op-code instead?
+        auto it = unwind_data->m_slot_to_persistent_slot.find (slot);
+        CHECK (it != unwind_data->m_slot_to_persistent_slot.end ());
+        int pers_offset = it->second;
+
+        octave_value &ov_gbl = scope.persistent_varref (pers_offset);
+
+        global_is_new_in_callstack = ov_gbl.is_undefined ();
+        if (global_is_new_in_callstack)
+          {
+            ov_gbl = ov_default;
+          }
+
+        if (!is_marked_in_VM)
+          {
+            ov_slot = octave_value {new octave_value_ref_persistent {std::move (scope), pers_offset}};
+          }
+      }
+    else
+      ERR ("Wrong global type");
+
+    // If there is init code, then there is also a offset to the first
+    // instruction after the init code, to where we jump if the global is
+    // alread live.
+    int after;
+    if (has_init_code)
+      {
+        unsigned char b0 = *ip++;
+        unsigned char b1 = *ip++;
+        after = b0 | (b1 << 8);
+
+        if (!global_is_new_in_callstack || slot_already_live)
+          ip = code + after;
+      }
+
+    // Now dispatch to either next instruction if no init, init or after init
+  }
+  DISPATCH ();
+assign_compound:
+  {
+    // The next instruction is the slot number
+    int slot = arg0;
+    // The next instruction is the type of compound operation
+    octave_value::assign_op op =
+      static_cast<octave_value::assign_op> (*ip++);
+
+    octave_value &ov_rhs = TOP_OV ();
+    octave_value &ov_lhs = bsp[slot].ov;
+
+    if (!ov_lhs.is_defined ()) // TODO: Also checked in .assign() ...
+      {
+        (*sp++).pee = new execution_exception {"error", "",
+          "in computed assignment A OP= X, A must be defined first"};
+        (*sp++).i = static_cast<int>(error_type::EXECUTION_EXC);
+        goto unwind;
+      }
+
+    try
+      {
+        // TODO: assign makes some stupid empty list and slows everything down
+        if (OCTAVE_LIKELY (!ov_lhs.is_ref ()))
+          ov_lhs.assign (op, ov_rhs); // Move code into here?
+        else
+          {
+            octave_value &glb_ref = ov_lhs.ref_rep ()->ref ();
+            glb_ref.assign (op, ov_rhs);
+          }
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    STACK_DESTROY (1);
+  }
+  DISPATCH ();
+jmp_ifdef:
+  {
+    octave_value &ov_1 = TOP_OV ();
+    unsigned char b0 = arg0;
+    unsigned char b1 = *ip++;
+
+    int target = b0 | (b1 << 8);
+
+    if (ov_1.is_defined () && !ov_1.is_magic_colon ())
+      ip = code + target;
+
+    STACK_DESTROY (1);
+  }
+  DISPATCH ();
+switch_cmp:
+  {
+    octave_value &ov_label = TOP_OV ();
+    octave_value &ov_switch = SEC_OV ();
+    unsigned char b0 = arg0;
+    unsigned char b1 = *ip++;
+
+    int target = b0 | (b1 << 8);
+
+    bool do_it;
+    if (ov_label.is_undefined ())
+      do_it = false;
+    else if (!ov_label.iscell ())
+      do_it = ov_switch.is_equal (ov_label);
+    else
+      {
+        do_it = false;
+        // Match all cell elements. Any will do
+        Cell cell (ov_label.cell_value ());
+
+        for (octave_idx_type i = 0; i < cell.rows (); i++)
+          {
+            for (octave_idx_type j = 0; j < cell.columns (); j++)
+              {
+                do_it = ov_switch.is_equal (cell(i,j));
+
+                if (do_it)
+                  break;
+              }
+          }
+      }
+
+    STACK_DESTROY (2);
+
+    if (!do_it)
+      ip = code + target;
+  }
+  DISPATCH ();
+
+braindead_precond:
+  {
+    octave_value &ov = TOP_OV();
+
+    bool do_braindead = false;
+    if (ov.ndims () == 2 && ov.rows () == 1 && ov.columns () == 1)
+      do_braindead = true;
+
+    STACK_DESTROY (1);
+
+    if (do_braindead)
+      PUSH_OV (ov_true);
+    else
+      PUSH_OV (ov_false);
+  }
+  DISPATCH_1BYTEOP ();
+
+braindead_warning:
+  {
+    // A slot stores whether we allready printed this warning for a particular
+    // place where there could be a braindead short circuit
+    int slot = arg0;
+    // The next codepoint is the type of warning
+    int type = *ip++; // asci '|' or '&'
+
+    octave_value& ov_warning = bsp[slot].ov;
+
+    if (ov_warning.is_nil ())
+      {
+        ov_warning = ov_true; // Don't print the warning next time
+        m_tw->set_active_bytecode_ip (ip - code); // The warning needs to be able to get line numbers.
+
+        // It is possible to specify that certain warning should be an error, so we need a try here.
+        try
+          {
+            warning_with_id ("Octave:possible-matlab-short-circuit-operator",
+                            "Matlab-style short-circuit operation performed for operator %c",
+                            type);
+          }
+        CATCH_EXECUTION_EXCEPTION
+      }
+  }
+  DISPATCH ();
+force_assign:
+  {
+    // The next instruction is the slot number
+    int slot = arg0;
+
+    octave_value &ov_rhs = TOP_OV ();
+    octave_value &ov_lhs = bsp[slot].ov;
+
+    ov_lhs.maybe_call_dtor ();
+
+    if (ov_rhs.vm_need_storable_call ())
+      ov_rhs.make_storable_value (); // Some types have lazy copy
+
+    if (OCTAVE_LIKELY (!ov_lhs.is_ref ()))
+      ov_lhs = std::move (ov_rhs); // Note move
+    else
+      ov_lhs.ref_rep ()->set_value (std::move (ov_rhs));
+
+    STACK_DESTROY (1);
+  }
+  DISPATCH();
+push_nil:
+  {
+    PUSH_OV(octave_value{});
+  }
+  DISPATCH_1BYTEOP();
+throw_iferrorobj:
+  {
+    octave_value& ov_top = TOP_OV ();
+
+    if (ov_top.is_defined ())
+      {
+        // This "error object" is created by the unwind: code
+        // and e.g. not from a user's error
+        octave_scalar_map map = ov_top.scalar_map_value ();
+
+        bool is_err_obj = map.isfield("message") &&
+                          map.isfield ("identifier") &&
+                          map.isfield ("stack");
+
+        if (!is_err_obj)
+          PANIC ("Strange error object on stack");
+
+        octave_value msg = map.getfield ("message");
+        octave_value id = map.getfield ("identifier");
+
+        STACK_DESTROY (1);
+
+        std::string s_msg  = msg.string_value ();
+        std::string s_id = id.string_value ();
+
+        octave_map err_stack = map.contents ("stack").xmap_value ("ERR.STACK must be a struct");
+
+        // Are we unwinding an interrupt exception?
+        if (m_unwinding_interrupt)
+          {
+            (*sp++).i = static_cast<int>(error_type::INTERRUPT_EXC);
+            goto unwind;
+          }
+
+        // On a rethrow, the C++ exception is always base class execution_exception.
+        // We use rethrow_error() to recreate a stack info object from the octave_map
+        // in an easy way.
+        try
+        {
+          error_system& es = m_tw->get_interpreter().get_error_system ();
+          es.rethrow_error (s_id, s_msg, err_stack);
+        }
+        catch(execution_exception& e)
+        {
+          (*sp++).pee =  new execution_exception {e};
+        }
+
+        (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+        goto unwind;
+      }
+    else
+      STACK_DESTROY (1);
+  }
+  DISPATCH_1BYTEOP();
+
+index_struct_call:
+  {
+    int slot = arg0;
+    bool has_slot = *ip++;
+    int nargout = *ip++;
+
+    int n_subs = POP_CODE ();
+
+    std::list<octave_value_list> idx;
+
+    std::vector<int> v_n_args;
+    std::string types;
+    types.resize (n_subs);
+
+    for (int i = 0; i < n_subs; i++)
+      {
+        v_n_args.push_back (POP_CODE ());
+        types[i] = POP_CODE ();
+      }
+
+    // Add the args of each sub indexing to the idx list
+    for (int i = 0; i < n_subs; i++)
+      {
+        octave_value_list ovl;
+        int n_args = v_n_args[n_subs - 1 - i]; // Note, from end to beginning
+        for (int j = 0; j < n_args; j++)
+          {
+            octave_value &arg = TOP_OV ();
+
+            if (arg.is_cs_list ())
+              ovl.append (arg.list_value ().reverse ());
+            else
+              ovl.append (std::move (arg));
+
+            STACK_DESTROY (1);
+          }
+        // args are pushed left to right to stack, so we need to reverse the ovl
+        ovl.reverse ();
+        idx.push_back (ovl);
+      }
+    idx.reverse (); // expressions was pushed left to right, so we need to reverse
+
+    octave_value &ov = TOP_OV ();
+    octave_value_list retval;
+    try
+      {
+        m_tw->set_active_bytecode_ip (ip - code);
+
+        // TODO: Need to figure out a clean way to do this kind of stuff.
+        //       See tree_index_expression::evaluate_n()
+        //       It should be general, because I don't think this will always work?
+        int cntr = 0;
+        while (ov_need_stepwise_subsrefs(ov) && types.size () > 0)
+          {
+            bool eat_args = true;
+            std::string step_type {types.front ()};
+
+            std::list<octave_value_list> step_idx;
+            step_idx.push_back (idx.front ());
+
+            int step_nargout = types.size () > 1 ? 1 : nargout;
+
+            if (cntr == 0 && ov.is_nil () && has_slot)
+              {
+                // Put a function cache object in the slot and in the local ov
+                ov = bsp[slot].ov =
+                  octave_value (new octave_fcn_cache (name_data[slot]));
+              }
+
+            if (cntr == 0 && ov.has_function_cache () && has_slot)
+              {
+                octave_function *fcn;
+                try
+                  {
+                    if (step_type == "(")
+                      {
+                        fcn = ov.get_cached_fcn (idx.front ());
+                      }
+                    else // { or .
+                      {
+                        fcn = ov.get_cached_fcn ({});
+                        eat_args = false; // The function call has no args
+                      }
+                  }
+                CATCH_EXECUTION_EXCEPTION // parse errors might throw in classdefs
+
+                if (! fcn)
+                  {
+                    (*sp++).ps = new std::string {name_data[slot]};
+                    (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+                    goto unwind;
+                  }
+
+                try
+                  {
+                    m_tw->set_active_bytecode_ip (ip - code);
+                    if (eat_args)
+                      retval = fcn->call (*m_tw, step_nargout, idx.front ());
+                    else
+                      retval = fcn->call (*m_tw, step_nargout, {});
+                    // TODO: Bytecode call.
+                  }
+                CATCH_INTERRUPT_EXCEPTION
+                CATCH_INDEX_EXCEPTION
+                CATCH_EXECUTION_EXCEPTION
+                CATCH_BAD_ALLOC
+                CATCH_EXIT_EXCEPTION
+              }
+            else if (ov.is_function () && !ov.is_classdef_meta ())
+              {
+                octave_function *fcn = ov.function_value (true);
+                if (fcn)
+                  {
+                    octave_value_list args = idx.front ();
+                    retval = fcn->call (*m_tw, step_nargout, args);
+                  }
+                else
+                  PANIC ("Silly state");
+              }
+            else
+              {
+                try
+                  {
+                    retval = ov.subsref (step_type.c_str (), step_idx, step_nargout);
+                  }
+                CATCH_INTERRUPT_EXCEPTION
+                CATCH_INDEX_EXCEPTION_WITH_MAYBE_NAME (has_slot && cntr == 0)
+                CATCH_EXECUTION_EXCEPTION
+                CATCH_BAD_ALLOC
+                CATCH_EXIT_EXCEPTION
+              }
+
+            // If the first retval has zero length and we got more to go, it is an error
+            if (cntr == 0 && step_type.size() > 1 && retval.length () == 0)
+              {
+                (*sp++).pee = new execution_exception {"error","","indexing undefined value"};
+                (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+                goto unwind;
+              }
+
+            ov = retval.first_or_nil_ov ();
+
+            if (cntr != 0 && ov.is_cs_list () && step_type.size() > 1)
+              {
+                (*sp++).pee = new execution_exception {"error","","a cs-list cannot be further indexed"};
+                (*sp++).i = static_cast<int> (error_type::EXECUTION_EXC);
+                goto unwind;
+              }
+
+            if (eat_args)
+              {
+                types = types.substr(1, types.size () - 1);
+                idx.pop_front ();
+              }
+            cntr++;
+          }
+
+        if ((!ov.is_function () || ov.is_classdef_meta ()) && types.size ())
+        {
+          retval = ov.subsref (types.c_str (), idx, nargout);
+          idx.pop_front ();
+        }
+
+        octave_value val = (retval.length () ? retval(0) : octave_value ());
+        if (val.is_function ())
+          {
+            octave_function *fcn = val.function_value (true);
+
+            if (fcn)
+              {
+                octave_value_list args = idx.size () ? idx.front () : (octave_value_list){};
+                retval = fcn->call (*m_tw, nargout, args);
+              }
+          }
+
+        idx.clear ();
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    STACK_DESTROY (1);
+    EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+  }
+  DISPATCH ();
+
+index_struct_n:
+  {
+    int nargout = arg0;
+
+    int slot = POP_CODE_USHORT (); // Needed if we need a function lookup
+    int slot_for_field = POP_CODE_USHORT ();
+
+    octave_value &ov = TOP_OV ();
+
+    std::string field_name = name_data [slot_for_field];
+
+    octave_value ov_field_name {field_name};
+
+    octave_value_list retval;
+
+    // TODO: Should be a "simple_subsref for "{" and "."
+    octave_value_list ovl_idx;
+    ovl_idx.append (ov_field_name);
+
+    std::list<octave_value_list> idx;
+    idx.push_back (ovl_idx);
+
+    try
+      {
+        m_tw->set_active_bytecode_ip (ip - code);
+        retval = ov.subsref(".", idx, nargout);
+
+        // TODO: Kludge for e.g. "m = containsers.Map;" which returns a function.
+        //       Should preferably be done by .subsref?
+        octave_value val = (retval.length () ? retval(0) : octave_value ());
+        if (val.is_function ())
+          {
+            octave_function *fcn = val.function_value (true);
+
+            if (fcn)
+              {
+                retval = fcn->call (*m_tw, nargout, {});
+              }
+          }
+
+        idx.clear ();
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    STACK_DESTROY (1);
+    EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+  }
+  DISPATCH ();
+
+subasgn_struct:
+  {
+    int slot = arg0;
+    int field_slot = POP_CODE_USHORT ();
+
+    // The top of the stack is the rhs value
+    octave_value &rhs = TOP_OV ();
+
+    // The ov to subassign to
+    octave_value &ov = bsp[slot].ov;
+
+    // TODO: Room for performance improvement here maybe
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      ov.make_unique ();
+    else
+      ov.ref_rep ()->ref ().make_unique ();
+
+    // TODO: Uggly containers
+    std::list<octave_value_list> idx;
+    octave_value_list ovl;
+
+    std::string field_name = name_data[field_slot];
+
+    octave_value ov_field_name {field_name};
+
+    ovl.append (ov_field_name);
+
+    idx.push_back (ovl);
+
+    // E.g. scalars do not update them self inplace
+    // but create a new octave_value, so we need to
+    // copy the return value to the slot.
+    try
+      {
+        ov = ov.subsasgn (".", idx, rhs);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    STACK_DESTROY (1);
+  }
+  DISPATCH ();
+
+subasgn_cell_id:
+  {
+    // The args to the subassign are on the operand stack
+    int slot = arg0;
+    int nargs = *ip++;
+
+    // The top of the stack is the rhs value
+    octave_value &rhs = TOP_OV ();
+    // First argument
+    stack_element *parg = sp - 1 - nargs;
+
+    // Move the args to an ovl
+    // TODO: Should actually be a move
+    octave_value_list args;
+    for (int i = 0; i < nargs; i++)
+    {
+      octave_value &arg = parg[i].ov;
+      // We need to expand cs-lists
+      if (arg.is_cs_list ())
+        args.append (arg.list_value ());
+      else
+        args.append (arg);
+    }
+
+    // The ov to subassign to
+    octave_value &ov = bsp[slot].ov;
+    // TODO: Room for performance improvement here maybe
+    if (OCTAVE_LIKELY (!ov.is_ref ()))
+      ov.make_unique ();
+    else
+      ov.ref_rep ()->ref ().make_unique ();
+
+    // TODO: Uggly containers
+    std::list<octave_value_list> idx;
+    idx.push_back (args);
+
+    try
+      {
+        // E.g. scalars do not update them self inplace
+        // but create a new octave_value, so we need to
+        // copy the return value to the slot.
+        ov = ov.subsasgn("{", idx, rhs);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION_WITH_NAME
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    // Destroy the args on the operand stack aswell as rhs
+    STACK_DESTROY (nargs + 1);
+  }
+  DISPATCH ();
+
+subassign_obj:
+  {
+    // The args to the subassign are on the operand stack
+    int nargs = arg0;
+    char type = *ip++;
+
+    // First argument
+    stack_element *parg = sp - nargs;
+    // lhs is under the args -- the target for the subassign
+    octave_value &lhs = (sp - nargs - 1)->ov;
+    lhs.make_unique (); // TODO: Room for performance improvement here maybe
+    // rhs is under the lhs
+    octave_value &rhs = (sp - nargs - 2)->ov; // lhs is written to this stack position
+
+    // Move the args to an ovl
+    // TODO: Should actually be a move
+    octave_value_list args;
+    for (int i = 0; i < nargs; i++)
+    {
+      octave_value &arg = parg[i].ov;
+      // We need to expand cs-lists
+      if (arg.is_cs_list ())
+        args.append (arg.list_value ());
+      else
+        args.append (arg);
+    }
+
+    // TODO: Uggly containers
+    std::list<octave_value_list> idx;
+    idx.push_back (args);
+
+    try
+      {
+        // E.g. scalars do not update them self inplace
+        // but create a new octave_value, so we need to
+        // copy the return value to the slot.
+        lhs = lhs.subsasgn(std::string {type}, idx, rhs);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    // We want lhs on the top of the stack after dropping all
+    // the args to SUBASSIGN_OBJ, so we move it to where rhs is
+    rhs = std::move (lhs);
+
+    // Destroy the args on the operand stack aswell as the
+    // stack position that we moved lhs out of.
+    STACK_DESTROY (nargs + 1);
+
+    // lhs is on the top of the stack now
+  }
+  DISPATCH ();
+
+index_obj:
+  {
+    int nargout = arg0;
+    int has_slot = *ip++;
+    int slot = POP_CODE_USHORT ();
+    int n_args_on_stack = *ip++;
+    char type = *ip++;
+
+    // The object to index is before the args on the stack
+    octave_value &ov = (sp[-1 - n_args_on_stack]).ov;
+
+    // Make an ovl with the args
+    // TODO: Should be inplace moves
+    octave_value_list ovl;
+    bool has_cs_list_arg = false;
+    // The operands are on the top of the stack
+    for (int i = n_args_on_stack - 1; i >= 0; i--)
+      {
+        octave_value &arg = sp[-1 - i].ov;
+
+        // If the operand arg is a cs list we need to expand it
+        if (arg.is_cs_list ())
+          {
+            has_cs_list_arg = true;
+            ovl.append (arg.list_value ());
+          }
+        else
+          ovl.append (sp[-1 - i].ov); // TODO: copied, not moved
+      }
+
+    // octave_fcn_cache and some octave_fcn_handle have caches
+    bool has_function_cache = ov.has_function_cache ();
+
+    if (! has_function_cache && ov.is_defined ())
+      {
+        // It is probably a variable
+
+        // TODO: subsref should take ovl instead and be chained,
+        // or something smarter
+        std::list<octave_value_list> idx; // TODO: mallocs!
+
+        idx.push_back(ovl);
+
+
+        // TODO: subsref might throw index error
+        octave_value_list retval;
+
+        if (OCTAVE_LIKELY (! ov.is_function ()
+                           || ov.is_classdef_meta ()))
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                retval = ov.subsref(std::string {type}, idx, nargout);
+                idx.clear ();
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION_WITH_MAYBE_NAME (has_slot)
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+        else
+          PANIC ("Strange state");
+
+        bool is_fcn = (retval.length () ?
+                         retval(0).is_function() : false);
+
+        // "FIXME: when can the following happen?  In what case does indexing
+        //  result in a value that is a function?  Classdef method calls?
+        //  Something else?"
+
+        if (OCTAVE_LIKELY (!is_fcn))
+          {
+            idx.clear ();
+            // TODO: Necessary? I guess it might trigger dtors
+            // or something?
+            ov = octave_value ();
+          }
+        else
+          {
+            octave_value val = retval(0);
+            octave_function *fcn = val.function_value (true);
+
+            if (fcn)
+              {
+                octave_value_list final_args;
+
+                if (! idx.empty ())
+                  final_args = idx.front ();
+
+                try
+                  {
+                    m_tw->set_active_bytecode_ip (ip - code);
+                    retval = fcn->call (*m_tw, nargout, final_args);
+                  }
+                CATCH_INTERRUPT_EXCEPTION
+                CATCH_INDEX_EXCEPTION_WITH_MAYBE_NAME (has_slot)
+                CATCH_EXECUTION_EXCEPTION
+                CATCH_BAD_ALLOC
+                CATCH_EXIT_EXCEPTION
+              }
+
+            idx.clear ();
+            ov = octave_value ();
+            val = octave_value ();
+          }
+
+        // TODO: Maybe the args should be destroyed before the indexed
+        // variable?
+        STACK_DESTROY (n_args_on_stack + 1);
+        EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (retval, nargout);
+      }
+    else if (has_function_cache)
+      {
+querry_fcn_cache_index_obj:
+
+        octave_function *fcn;
+        try
+          {
+            fcn = ov.get_cached_fcn (ovl);
+          }
+        CATCH_EXECUTION_EXCEPTION
+
+        if (! fcn)
+          {
+            if (has_slot)
+              (*sp++).ps = new std::string {name_data[slot]};
+            else
+              (*sp++).ps = new std::string {"temporary object"};
+            (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+            goto unwind;
+          }
+
+        if (fcn->is_compiled ())
+          {
+            octave_user_function *usr_fcn = static_cast<octave_user_function *> (fcn);
+            // Alot of code in this define
+            MAKE_BYTECODE_CALL
+
+            // Now dispatch to first instruction in the
+            // called function
+          }
+        else
+          {
+            try
+              {
+                m_tw->set_active_bytecode_ip (ip - code);
+                octave_value_list ret = fcn->call (*m_tw, nargout, ovl);
+
+                STACK_DESTROY (n_args_on_stack + 1);
+                EXPAND_CSLIST_PUSH_N_OVL_ELEMENTS_TO_STACK (ret, nargout);
+              }
+            CATCH_INTERRUPT_EXCEPTION
+            CATCH_INDEX_EXCEPTION
+            CATCH_EXECUTION_EXCEPTION
+            CATCH_BAD_ALLOC
+            CATCH_EXIT_EXCEPTION
+
+          }
+      }
+    else
+      {
+        // If the first object is not an identifier we can't look it up for
+        // a function call.
+        if (!has_slot)
+          {
+            (*sp++).ps = new std::string {"temporary object"};
+            (*sp++).i = static_cast<int>(error_type::ID_UNDEFINED);
+            goto unwind;
+          }
+
+        if (! ov.is_nil ())
+          {
+            TODO ("Not nil object for fcn cache replacement");
+          }
+
+        // It is probably a function call.
+        // Put a function cache object in the slot and in the local ov
+        // and jump into the if clause above to search for some function
+        // to call.
+        ov = bsp[slot].ov =
+          octave_value (new octave_fcn_cache (name_data[slot]));
+        goto querry_fcn_cache_index_obj;
+      }
+  }
+  DISPATCH ();
+load_far_cst:
+  {
+    ip--;
+    int offset = POP_CODE_INT ();
+
+    // Copy construct it into the top of the stack
+    new (sp++) octave_value (data [offset]);
+
+    DISPATCH();
+  }
+
+set_ignore_outputs:
+  {
+    if (!m_output_ignore_data)
+      {
+        m_output_ignore_data = new output_ignore_data;
+      }
+
+    int n_ignored = arg0;
+    int n_total = POP_CODE ();
+    auto *M = new Matrix {};
+    m_output_ignore_data->m_v_matrixes.push_back (M);
+    M->resize (1, n_ignored);
+
+    std::set<int> set_ignored;
+
+    for (int i = 0; i < n_ignored; i++)
+      {
+        int ignore_idx = POP_CODE ();
+        (*M) (i) = ignore_idx;
+        set_ignored.insert (ignore_idx);
+      }
+
+    // For calls into m-functions etc
+    auto *active_lvalue_list = new std::list<octave_lvalue> {};
+
+    auto *saved_lvalue_list = m_tw->lvalue_list ();
+    m_output_ignore_data->m_v_lvalue_list.push_back (saved_lvalue_list);
+
+    for (int i = 0; i < n_total; i++)
+      {
+        octave_lvalue lval ({}, m_tw->get_current_stack_frame ());
+        if (set_ignored.find (i + 1) != set_ignored.end ())
+          lval.mark_black_hole ();
+        active_lvalue_list->push_back (lval);
+      }
+
+    m_tw->set_lvalue_list (active_lvalue_list);
+  }
+  DISPATCH();
+
+clear_ignore_outputs:
+  {
+    CHECK (m_output_ignore_data);
+
+    auto *active_lvalue_list = m_tw->lvalue_list ();
+    delete active_lvalue_list;
+
+    // Restore the evaluators lvalue list
+    m_tw->set_lvalue_list (m_output_ignore_data->pop_lvalue_list ());
+
+    // Delete the matrix we used to set the autovar (if it has not been used an nulled)
+    delete m_output_ignore_data->m_v_matrixes.back ();
+    m_output_ignore_data->m_v_matrixes.pop_back ();
+
+    // We want to null m_output_ignore_data if it is empty
+    if (m_output_ignore_data->m_v_matrixes.empty ())
+      {
+        CHECK (m_output_ignore_data->m_v_lvalue_list.empty ());
+        delete m_output_ignore_data;
+        m_output_ignore_data = nullptr;
+      }
+
+    // Clear any value written to the %~X slot(s)
+    int n_slots = arg0;
+    for (int i = 0; i < n_slots; i++)
+      {
+        int slot = POP_CODE_USHORT ();
+
+        octave_value &ov = bsp[slot].ov;
+
+        if (ov.get_count () == 1)
+          ov.call_object_destructor ();
+
+        ov = octave_value{};
+      }
+  }
+  DISPATCH();
+
+subassign_chained:
+  {
+    octave_value::assign_op op = static_cast<octave_value::assign_op> (arg0);
+    int n_chained = POP_CODE ();
+    std::vector<int> v_n_args;
+    std::string type (n_chained, 0);
+
+    for (int i = 0; i < n_chained; i++)
+      {
+        v_n_args.push_back (POP_CODE ());
+        type [i] = POP_CODE ();
+      }
+
+    std::list<octave_value_list> idx;
+    for (int i = 0; i < n_chained; i++)
+      {
+        octave_value_list ovl;
+        // foo (a1, a2).bar (a3, a4)
+        // are:
+        // TOP a4, a3, a2, a1
+        // on the stack now.
+        int n_args = v_n_args [n_chained - i - 1];
+        for (int j = 0; j < n_args; j++)
+          {
+            octave_value &arg = TOP_OV ();
+            ovl.append (std::move (arg));
+            STACK_DESTROY (1);
+          }
+        ovl.reverse ();
+        idx.push_back (ovl);
+      }
+
+    idx.reverse ();
+
+    octave_value lhs = std::move (TOP_OV ());
+    STACK_DESTROY (1);
+    octave_value rhs = std::move (TOP_OV ());
+    STACK_DESTROY (1);
+
+    try
+      {
+        if (type.size () && type.back () != '(' && lhs_assign_numel (lhs, type, idx) != 1)
+          err_invalid_structure_assignment ();
+
+        lhs.assign (op, type, idx, rhs);
+      }
+    CATCH_INTERRUPT_EXCEPTION
+    CATCH_INDEX_EXCEPTION
+    CATCH_EXECUTION_EXCEPTION
+    CATCH_BAD_ALLOC
+    CATCH_EXIT_EXCEPTION
+
+    PUSH_OV (lhs);
+  }
+  DISPATCH ();
+
+set_slot_to_stack_depth:
+  {
+    int slot = arg0;
+    int stack_depth = sp - bsp;
+    bsp[slot].ov = octave_value {stack_depth};
+  }
+  DISPATCH ();
+dupn:
+  {
+    int offset = arg0;
+    int n = POP_CODE ();
+    stack_element *first = sp - n - offset;
+    for (int i = 0; i < n; i++)
+      PUSH_OV (first[i].ov);
+  }
+  DISPATCH ();
+load_cst_alt2:
+  {
+    int offset = arg0;
+
+    // Copy construct it into the top of the stack
+    new (sp++) octave_value (data [offset]);
+
+    DISPATCH ();
+  }
+load_cst_alt3:
+  {
+    int offset = arg0;
+
+    // Copy construct it into the top of the stack
+    new (sp++) octave_value (data [offset]);
+
+    DISPATCH ();
+  }
+load_cst_alt4:
+  {
+    int offset = arg0;
+
+    // Copy construct it into the top of the stack
+    new (sp++) octave_value (data [offset]);
+
+    DISPATCH ();
+  }
+load_2_cst:
+{
+  // We are pushing two constants to the stack. E.g. for "3 * 2".
+  // The next instruction is the offset in the data of the lhs.
+  // rhs is right after.
+  int offset = arg0;
+
+  // Copy construct the two constants onto the top of the stack
+  new (sp++) octave_value (data [offset]);     // lhs in a binop
+  new (sp++) octave_value (data [offset + 1]); // rhs
+
+  DISPATCH ();
+}
+/* Check whether we should enter the debugger on the next ip */
+{
+  bool onebyte_op;
+  if (0)
+    debug_check:
+    onebyte_op = false;
+  else if (0)
+    debug_check_1b:
+    onebyte_op = true;
+
+  {
+    int tmp_ip = ip - code;
+    if (onebyte_op)
+      tmp_ip--;
+
+    if (OCTAVE_UNLIKELY (m_trace_enabled))
+      {
+        PRINT_VM_STATE ("Trace: ");
+      }
+
+    if (OCTAVE_UNLIKELY (m_profiler_enabled))
+      {
+        int64_t t1 = vm_profiler::unow ();
+
+        auto p = m_vm_profiler;
+        if (!p) // Only happens as a race between m_profiler_enabled and m_vm_profiler
+          goto debug_check_end;
+
+        std::string fn_name = data[2].string_value (); // profiler_name () querried at compile time
+        vm_profiler::vm_profiler_fn_stats &stat = p->m_map_fn_stats[fn_name];
+
+        if (!stat.m_v_t.size ())
+          {
+            // The profiler got enabled after the current function was called.
+            p->enter_fn (fn_name, "", unwind_data, name_data, code);
+            stat.m_v_t.back () = -1;
+            stat.m_v_ip.back () = ip - code; // We are not at function start, so set ip to proper value.
+          }
+        else if (stat.m_v_t.back () != -1)
+          {
+            int64_t t0 = stat.m_v_t.back ();
+            int64_t dt = t1 - t0;
+
+            stat.add_t (dt);
+            p->add_t (dt);
+          }
+      }
+
+    // TODO: Check all trees one time and cache the result somewhere?
+    //       Until another bp is set? Debugging will be quite slow
+    //       with one check for each op-code.
+
+    auto it = unwind_data->m_ip_to_tree.find (tmp_ip);
+
+    if (it == unwind_data->m_ip_to_tree.end ())
+      goto debug_check_end;
+
+    bool is_ret = *ip == static_cast<unsigned char> (INSTR::RET);
+
+    m_sp = sp;
+    m_bsp = bsp;
+    m_rsp = rsp;
+    m_code = code;
+    m_data = data;
+    m_name_data = name_data;
+    m_ip = tmp_ip;
+    m_unwind_data = unwind_data;
+    m_tw->set_active_bytecode_ip (tmp_ip);
+
+    tree *t = it->second;
+
+    // do_breakpoint will check if there is a breakpoint attached
+    // to the relevant code and escape to the debugger repl
+    // if neccessary.
+    if (t)
+      {
+        try
+          {
+            m_tw->do_breakpoint (t->is_active_breakpoint (*m_tw), is_ret);
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+  }
+  debug_check_end:
+  {
+    if (OCTAVE_UNLIKELY (m_profiler_enabled))
+      {
+        auto p = m_vm_profiler;
+
+        if (p)
+          {
+            std::string fn_name = data[2].string_value (); // profiler_name () querried at compile time
+            vm_profiler::vm_profiler_fn_stats &stat = m_vm_profiler->m_map_fn_stats[fn_name];
+
+            // If someone enabled profiling in the debugger we need to wait until
+            // the debug_check: block is ran next time.
+            if (stat.m_v_t.size())
+              {
+                int tmp_ip = ip - code;
+                if (onebyte_op)
+                  tmp_ip--;
+                stat.m_v_ip.back () = tmp_ip; // Sets a new 'currently running ip'
+                stat.m_v_t.back () = vm_profiler::unow (); // Sets a new timestamp for the current ip
+              }
+          }
+      }
+  }
+  if (onebyte_op)
+    {
+      int opcode = ip[-1];
+      arg0 = ip[0];
+      ip++;
+      goto *instr [opcode];
+    }
+  else
+    {
+      int opcode = ip[0];
+      arg0 = ip[1];
+      ip += 2;
+      goto *instr [opcode];
+    }
+}
+
+debug: // TODO: Remove
+  {
+    if (m_tw->debug_mode ())
+      {
+        m_ip = ip - code;
+        m_sp = sp;
+        m_tw->set_active_bytecode_ip (ip - code);
+
+        try
+          {
+            m_tw->enter_debugger ();
+          }
+        CATCH_INTERRUPT_EXCEPTION
+        CATCH_INDEX_EXCEPTION
+        CATCH_EXECUTION_EXCEPTION
+        CATCH_BAD_ALLOC
+        CATCH_EXIT_EXCEPTION
+      }
+  }
+  DISPATCH ();
+
+  wide:
+  {
+    int opcode = arg0; // The opcode to execute next is in arg0, i.e. ip[-1]
+    // The next opcode needs its arg0, which is a unsigned short instead of the usual byte
+    // that DISPATCH() writes to arg0.
+    arg0 = (ip[1] << 8) | ip[0];
+    ip += 2; // Forward ip so it points to after the widened argument
+    goto *instr [opcode];
+  }
+
+  __builtin_unreachable ();
+}
+
+octave_value
+vm::handle_object_end (octave_value ov, int idx, int nargs)
+{
+  // See tree_evaluator::evaluate_end_expression()
+  octave_value ans;
+
+  auto &interpreter = m_tw->get_interpreter ();
+  std::string dispatch_class = ov.class_name ();
+  symbol_table& symtab = interpreter.get_symbol_table ();
+
+  octave_value meth = symtab.find_method ("end", dispatch_class);
+
+  if (meth.is_defined ())
+    ans = interpreter.feval (meth, ovl (ov, idx+1, nargs), 1).first_or_nil_ov ();
+  else
+    ans = octave_value (ov.end_index (idx, nargs));
+
+  return ans;
+}
+
+octave_value
+vm::find_fcn_for_cmd_call (std::string *name)
+{
+  interpreter& interp = __get_interpreter__();
+
+  symbol_table& symtab = interp.get_symbol_table ();
+
+  return symtab.find_function (*name);
+}
+
+vm::error_data
+vm::handle_error (error_type error_type)
+{
+  error_data ret;
+
+  error_system& es = m_tw->get_interpreter().get_error_system ();
+
+  std::stringstream ss;
+  // ip points to the "next" instruction, so search for the
+  // code location for ip - 1
+  loc_entry loc = find_loc (m_ip - 1, m_unwind_data->m_loc_entry);
+
+  switch (error_type)
+    {
+    case error_type::BAD_ALLOC:
+      {
+        execution_exception e {"error", "Octave:bad-alloc", "out of memory or dimension too large for Octave's index type"};
+        es.save_exception (e);
+
+        break;
+      }
+    case error_type::ID_UNDEFINED:
+      {
+        std::string *sp = m_sp [-1].ps;
+        m_sp--;
+        std::string id_name = *sp;
+        delete sp;
+
+        ss << "'" << id_name << "'" <<
+          " undefined near line " << loc.m_line <<
+          ", column " << loc.m_col;
+
+        execution_exception e { "error",
+          "Octave:undefined-function",
+          ss.str ()};
+
+        // Since the exception was made in the VM it has not been saved yet
+        es.save_exception (e);
+
+        break;
+      }
+    case error_type::IF_UNDEFINED:
+      {
+        // error ("%s: undefined value used in conditional expression", warn_for);
+        ss << "if's condition undefined near line " <<
+          loc.m_line << ", column " << loc.m_col;
+
+        execution_exception e {"error", "", ss.str ()};
+
+        es.save_exception (e);
+
+        break;
+      }
+    case error_type::INDEX_ERROR:
+      {
+        execution_exception *e = m_sp [-1].pee;
+
+        CHECK (e);
+        es.save_exception (*e);
+
+        delete e;
+
+        m_sp--;
+
+        break;
+      }
+    case error_type::EXECUTION_EXC:
+      {
+        execution_exception *e = m_sp [-1].pee;
+
+        CHECK (e);
+        es.save_exception (*e);
+
+        delete e;
+
+        m_sp--;
+
+        break;
+      }
+    case error_type::INTERRUPT_EXC:
+      break; // Do nothing
+    case error_type::EXIT_EXCEPTION:
+      ret.m_safe_to_return = (--m_sp)->i;
+      ret.m_exit_status = (--m_sp)->i;
+      break;
+    case error_type::INVALID_N_EL_RHS_IN_ASSIGNMENT:
+    {
+      execution_exception e {"error", "", "invalid number of elements on RHS of assignment"};
+
+      es.save_exception (e);
+
+      break;
+    }
+    case error_type::RHS_UNDEF_IN_ASSIGNMENT:
+    {
+      execution_exception e {"error", "", "value on right hand side of assignment is undefined"};
+
+      es.save_exception (e);
+
+      break;
+    }
+    default:
+      TODO ("Unhandeled error type");
+    }
+
+  return ret;
+}
+
+vm::~vm ()
+{
+  delete [] m_stack0;
+
+  CHECK (m_output_ignore_data == nullptr);
+}
+
+vm::vm (tree_evaluator *tw, bytecode &initial_bytecode)
+{
+  m_ti = &__get_type_info__();
+  m_stack0 = new stack_element[stack_size + stack_pad * 2];
+
+  for (unsigned i = 0; i < stack_pad; i++)
+    {
+      m_stack0[i].u = stack_magic_int;
+      m_stack0[i + stack_size].u = stack_magic_int;
+    }
+
+  m_sp = m_stack = m_stack0 + stack_pad;
+  m_tw = tw;
+  m_symtab = &__get_symbol_table__();
+
+  m_data = initial_bytecode.m_data.data ();
+  m_code = initial_bytecode.m_code.data ();
+  m_name_data = initial_bytecode.m_ids.data ();
+  m_unwind_data = &initial_bytecode.m_unwind_data;
+
+  // Check that the typeids are what the VM anticipates. If the id change, just change
+  // the constexpr.
+  CHECK (octave_scalar::static_type_id () == m_scalar_typeid);
+  CHECK (octave_bool::static_type_id () == m_bool_typeid);
+  CHECK (octave_matrix::static_type_id () == m_matrix_typeid);
+
+  // Function pointer used for specialized op-codes
+  m_fn_dbl_mul = m_ti->lookup_binary_op (octave_value::binary_op::op_mul, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_div = m_ti->lookup_binary_op (octave_value::binary_op::op_div, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_add = m_ti->lookup_binary_op (octave_value::binary_op::op_add, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_sub = m_ti->lookup_binary_op (octave_value::binary_op::op_sub, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_pow = m_ti->lookup_binary_op (octave_value::binary_op::op_pow, m_scalar_typeid, m_scalar_typeid);
+
+  m_fn_dbl_le = m_ti->lookup_binary_op (octave_value::binary_op::op_lt, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_le_eq = m_ti->lookup_binary_op (octave_value::binary_op::op_le, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_gr = m_ti->lookup_binary_op (octave_value::binary_op::op_gt, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_gr_eq = m_ti->lookup_binary_op (octave_value::binary_op::op_ge, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_eq = m_ti->lookup_binary_op (octave_value::binary_op::op_eq, m_scalar_typeid, m_scalar_typeid);
+  m_fn_dbl_neq = m_ti->lookup_binary_op (octave_value::binary_op::op_ne, m_scalar_typeid, m_scalar_typeid);
+
+  m_fn_dbl_usub = m_ti->lookup_unary_op (octave_value::unary_op::op_uminus, m_scalar_typeid);
+  m_fn_dbl_not = m_ti->lookup_unary_op (octave_value::unary_op::op_not, m_scalar_typeid);
+  m_fn_bool_not = m_ti->lookup_unary_op (octave_value::unary_op::op_not, m_bool_typeid);
+
+  m_pi_builtin_fn = m_symtab->find_built_in_function ("pi").function_value ();
+  // If the platform has no M_PI we need to initialize ov_pi
+#if !defined (M_PI)
+  ov_pi = 4.0 * atan (1.0);
+#endif
+}
+
+// If there are too many return values we can't just move them since the stacks will overlap so we
+// need to copy the args first with this proc
+static void copy_many_args_to_caller (octave::stack_element *sp,
+                                      octave::stack_element *caller_stack_end,
+                                      int n_args_to_move, int n_args_caller_expects)
+{
+  // Move args to an ovl
+  octave_value_list ovl;
+  for (int i = 0; i < n_args_to_move; i++)
+    {
+      octave_value &arg = caller_stack_end[i].ov;
+      ovl.append (std::move (arg));
+    }
+
+  for (int i = 0; i < n_args_to_move; i++)
+    {
+      PUSH_OV (ovl(n_args_to_move - 1 - i)); // backwards
+    }
+
+  // Push missing args
+  for (int i = n_args_to_move; i < n_args_caller_expects; i++)
+    PUSH_OV ();
+}
+
+static octave_value xeval_for_numel (octave_value &ov, const std::string& type, const std::list<octave_value_list>& idx);
+
+// This function reimplements octave_lvalue::numel()
+// TODO: octave_lvalue::numel() could be broken out or made static and used instead. But don't mess with that code
+//       to keep the VM somewhat independent of other code.
+static int lhs_assign_numel (octave_value &ov, const std::string& type, const std::list<octave_value_list>& idx)
+{
+  // Return 1 if there is no index because without an index there
+  // should be no way to have a cs-list here.  Cs-lists may be passed
+  // around internally but they are not supposed to be stored as
+  // single symbols in a stack frame.
+
+  std::size_t num_indices = idx.size ();
+
+  if (num_indices == 0)
+    return 1;
+
+  switch (type[num_indices-1])
+    {
+    case '(':
+      return 1;
+
+    case '{':
+      {
+        // FIXME: Duplicate code in '.' case below...
+
+        // Evaluate, skipping the last index.
+
+        std::string tmp_type = type;
+        std::list<octave_value_list> tmp_idx = idx;
+
+        tmp_type.pop_back ();
+        tmp_idx.pop_back ();
+
+        octave_value tmp = xeval_for_numel (ov, tmp_type, tmp_idx);
+
+        octave_value_list tidx = idx.back ();
+
+        if (tmp.is_undefined ())
+          {
+            if (tidx.has_magic_colon ())
+              err_invalid_inquiry_subscript ();
+
+            tmp = Cell ();
+          }
+        else if (tmp.is_zero_by_zero ()
+                 && (tmp.is_matrix_type () || tmp.is_string ()))
+          {
+            tmp = Cell ();
+          }
+
+        return tmp.xnumel (tidx);
+      }
+      break;
+
+    case '.':
+      {
+        // Evaluate, skipping either the last index or the last two
+        // indices if we are looking at "(idx).field".
+
+        std::string tmp_type = type;
+        std::list<octave_value_list> tmp_idx = idx;
+
+        tmp_type.pop_back ();
+        tmp_idx.pop_back ();
+
+        bool paren_dot = num_indices > 1 && type[num_indices-2] == '(';
+
+        // Index for paren operator, if any.
+        octave_value_list pidx;
+
+        if (paren_dot)
+          {
+            pidx = tmp_idx.back ();
+
+            tmp_type.pop_back ();
+            tmp_idx.pop_back ();
+          }
+
+        octave_value tmp = xeval_for_numel (ov, tmp_type, tmp_idx);
+
+        bool autoconv = (tmp.is_zero_by_zero ()
+                         && (tmp.is_matrix_type () || tmp.is_string ()
+                             || tmp.iscell ()));
+
+        if (paren_dot)
+          {
+            // Use octave_map, not octave_scalar_map so that the
+            // dimensions are 0x0, not 1x1.
+
+            if (tmp.is_undefined ())
+              {
+                if (pidx.has_magic_colon ())
+                  err_invalid_inquiry_subscript ();
+
+                tmp = octave_map ();
+              }
+            else if (autoconv)
+              tmp = octave_map ();
+
+            return tmp.xnumel (pidx);
+          }
+        else if (tmp.is_undefined () || autoconv)
+          return 1;
+        else
+          return tmp.xnumel (octave_value_list ());
+      }
+      break;
+
+    default:
+      panic_impossible ();
+    }
+}
+
+static octave_value xeval_for_numel (octave_value &ov, const std::string& type, const std::list<octave_value_list>& idx)
+{
+  octave_value retval;
+
+  try
+    {
+      retval = ov;
+
+      if (retval.is_constant () && ! idx.empty ())
+        retval = retval.subsref (type, idx);
+    }
+  catch (const execution_exception&)
+    {
+      // Ignore an error and treat it as undefined.  The error
+      // could happen because there is an index is out of range
+      // and we will be resizing a cell array.
+
+      interpreter& interp = __get_interpreter__ ();
+
+      interp.recover_from_exception ();
+
+      retval = octave_value ();
+    }
+
+  return retval;
+}
+
+
+loc_entry vm::find_loc (int ip, std::vector<octave::loc_entry> &loc_entries)
+{
+  int best = -1;
+
+  int n = loc_entries.size ();
+
+  // TODO: Should maybe be some binary search, but only called in
+  //       exceptions so who cares?
+  for (int i = 0; i < n; i++)
+    {
+      loc_entry &e = loc_entries[i];
+
+      if (ip >= e.m_ip_start && ip < e.m_ip_end)
+        best = i;
+    }
+
+  if (best == -1)
+    return {};
+
+  return loc_entries[best];
+}
+
+void vm::set_nargin (int nargin)
+{
+  m_tw->set_nargin (nargin);
+}
+
+void vm::set_nargout (int nargout)
+{
+  m_tw->set_nargout (nargout);
+}
+
+int
+vm::find_unwind_entry_for_forloop (int current_stack_depth)
+{
+  int best_match = -1;
+
+  // Find a for loop entry that matches the current instruction pointer
+  // range and also got an anticipated stack depth less than current stack
+  // depth.
+  //
+  // I.e. if the ip is in a for loop, we want to unwind down the stack
+  // untill we reach the stack depth of the for loop to be able to remove
+  // its native int:s properly.
+  //
+  // To be able to unwind nested for loops we look for smaller and
+  // smaller stack depths given by current_stack_depth parameter.
+
+  for (unsigned i = 0; i < m_unwind_data->m_unwind_entries.size(); i++)
+    {
+      unwind_entry& entry = m_unwind_data->m_unwind_entries[i];
+      int start = entry.m_ip_start;
+      int end = entry.m_ip_end;
+      int stack_depth = entry.m_stack_depth;
+
+      // Skip not for loop entries
+      if (entry.m_unwind_entry_type != unwind_entry_type::FOR_LOOP)
+        continue;
+      // Are ip the range?
+      if (start > m_ip || end <= m_ip)
+        continue;
+      // Is the stack depth ok?
+      if (stack_depth >= current_stack_depth)
+        continue;
+
+      // Is it better than prior match?
+      if (best_match != -1)
+        {
+          if (best_match > stack_depth)
+            continue;
+        }
+
+      best_match = stack_depth;
+    }
+
+  return best_match;
+}
+
+unwind_entry*
+vm::find_unwind_entry_for_current_state (bool only_find_unwind_protect)
+{
+  int best_match = -1;
+
+  // Find the entry with the highest start instruction offset
+  for (unsigned i = 0; i < m_unwind_data->m_unwind_entries.size(); i++)
+    {
+      unwind_entry& entry = m_unwind_data->m_unwind_entries[i];
+      int start = entry.m_ip_start;
+      int end = entry.m_ip_end;
+
+      // When unwinding for e.g. interrupt exceptions we are only looking for UNWIND_PROTECT
+      if (only_find_unwind_protect && (entry.m_unwind_entry_type != unwind_entry_type::UNWIND_PROTECT))
+        continue;
+
+      // Skip for loop entries
+      if (entry.m_unwind_entry_type == unwind_entry_type::FOR_LOOP)
+        continue;
+
+      // Are ip the range?
+      if (start > m_ip || end <= m_ip) // TODO: end < m_ip ???
+        continue;
+
+      // Is it better than prior match?
+      if (best_match != -1)
+        {
+          int best_start =
+            m_unwind_data->m_unwind_entries[best_match].m_ip_start;
+          if (best_start > start)
+            continue;
+        }
+
+      best_match = i;
+    }
+
+  if (best_match == -1)
+    return nullptr;
+
+  return &m_unwind_data->m_unwind_entries[best_match];
+}
+
+static bool ov_need_stepwise_subsrefs (octave_value &ov)
+{
+  return !ov.isobject () && !ov.isjava () && !(ov.is_classdef_meta () && ! ov.is_package ());
+}
+
+int64_t
+vm_profiler::unow ()
+{
+  return octave_gettime_ns_wrapper ();
+}
+
+void
+vm_profiler::vm_profiler_fn_stats::add_t (int64_t dt)
+{
+  int ip = m_v_ip.back ();
+  maybe_resize (ip);
+
+  m_v_cum_t[ip] += dt;
+  ++m_v_n_cum[ip];
+}
+
+void
+vm_profiler::add_t (int64_t dt)
+{
+  if (!m_shadow_call_stack.size ())
+    return;
+
+  m_shadow_call_stack.back ().m_t_self_cum += dt;
+}
+
+// There is no std::format since we use C++ 11 so lets make our own.
+// The 'format' attribute gives nice compiler warnings on missuse.
+static
+std::string
+x_snprintf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+
+static
+std::string
+x_snprintf (const char *fmt, ...)
+{
+    int n = 32;
+    do {
+      char *buff = new char[n];
+
+      va_list va;
+      va_start (va, fmt);
+      int n_needed = vsnprintf (buff, n, fmt, va);
+      va_end (va);
+
+      std::string ret;
+
+      try
+        {
+          std::string tmp {buff};
+          ret = tmp;
+        }
+      catch (...) // Maybe bad_alloc could be thrown
+        {
+          delete [] buff;
+          throw;
+        }
+
+      delete [] buff;
+
+      if (n_needed < 0)
+        error ("Profiler internal error: Invalid call to x_snprintf()");
+      if (n_needed < n)
+        return ret;
+
+      n = n_needed + 1;
+    } while (1);
+}
+
+void
+vm_profiler::print_to_stdout ()
+{
+  using std::string;
+  using std::vector;
+  using std::map;
+  using std::pair;
+
+  // These could probably be vectors, but we'll do with maps to keep the
+  // code easier to follow.
+  map<string, int64_t> map_fn_to_cum_t;
+  map<string, int64_t> map_fn_to_self_cum_t;
+  map<string, vector<string>> map_fn_to_sourcerows;
+  map<string, vector<pair<int, string>>> map_fn_to_opcodes_stringrows;
+  map<string, string> map_fn_to_annotated_source;
+  map<string, string> map_fn_to_annotated_bytecode;
+
+  // Calculate cumulative function time
+  for (auto kv : m_map_fn_stats)
+    {
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+
+      int64_t t_fn_cum = 0;
+      int64_t t_fn_self_cum = 0;
+      unsigned n = stats.m_v_cum_t.size ();
+
+      for (unsigned ip = 0; ip < n; ip++)
+        {
+          t_fn_cum += stats.m_v_cum_t[ip];
+          t_fn_self_cum += stats.m_v_cum_t[ip];
+        }
+      for (unsigned ip = 0; ip < stats.m_v_cum_call_t.size (); ip++)
+        t_fn_cum += stats.m_v_cum_call_t[ip];
+
+      map_fn_to_cum_t[fn_name] = t_fn_cum;
+      map_fn_to_self_cum_t[fn_name] = t_fn_self_cum;
+    }
+
+  // Try to get the source code
+  for (auto kv : m_map_fn_stats)
+    {
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+      string file = stats.m_fn_file;
+
+      auto &interp = __get_interpreter__ ();
+
+      // Call type with the quiet flag to get the source
+      // Also works for functions without source code in files.
+      octave_value_list ans;
+      string source_text;
+
+      bool got_source_text = false;
+
+      if (!got_source_text)
+        {
+          octave_value_list args;
+          args.append ("-q");
+          args.append (file);
+          try
+            {
+              if (file.size ())
+                ans = interp.feval ("type", args, 1);
+            }
+          catch (execution_exception &)
+            {
+              // Didn't work
+            }
+        }
+
+      if (ans.length () >= 1)
+        source_text = ans(0).string_value ();
+      if (source_text.size ())
+        got_source_text = true;
+
+      if (!got_source_text)
+        {
+          octave_value_list args;
+          args.append ("-q");
+          args.append (fn_name);
+          try
+            {
+              if (fn_name.size ())
+                ans = interp.feval ("type", args, 1);
+            }
+          catch (execution_exception &)
+            {
+              // Didn't work
+            }
+        }
+
+      if (ans.length () >= 1)
+        source_text = ans(0).string_value ();
+      if (source_text.size ())
+        got_source_text = true;
+
+      if (got_source_text)
+        {
+          // Split source by row
+          vector<string> v_rows;
+
+          std::stringstream ss(source_text);
+          string buff;
+
+          while(std::getline (ss, buff, '\n'))
+              v_rows.push_back (buff);
+
+          map_fn_to_sourcerows[fn_name] = v_rows;
+        }
+    }
+
+  // Get bytecode "source code" rows
+  for (auto kv : m_map_fn_stats)
+    {
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+
+      auto v_ls = opcodes_to_strings (stats.m_code, stats.m_ids);
+
+      map_fn_to_opcodes_stringrows[fn_name] = v_ls;
+    }
+
+  // Annotate bytecode
+  for (auto kv : m_map_fn_stats)
+    {
+      std::string ans;
+
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+
+      auto v_ls = map_fn_to_opcodes_stringrows[fn_name];
+      int64_t fn_cum_t = map_fn_to_cum_t[fn_name];
+
+      for (auto ls : v_ls)
+        {
+          int ip = ls.first; // Opcode offset
+          string s = ls.second; // Text representation of the opcode
+
+          // Ignore strange data
+          if (ip < 0)
+            continue;
+
+          if (static_cast<unsigned> (ip) >= stats.m_v_cum_t.size () || (stats.m_v_cum_t[ip] == 0 && stats.m_v_cum_call_t[ip] == 0))
+          {
+            ans += x_snprintf ("\t%*s %5d: %s\n", 43, "", ip, s.c_str ());
+            continue;
+          }
+
+          int64_t n_hits = stats.m_v_n_cum[ip];
+          int64_t t_op = stats.m_v_cum_t[ip] + stats.m_v_cum_call_t[ip];
+          double share_of_fn = 100. * static_cast<double> (t_op) / fn_cum_t;
+
+          // Try to make the table neat around the decimal separator
+          int wholes = floor (share_of_fn);
+          int rest = (share_of_fn - wholes) * 100;
+
+          if (share_of_fn >= 0.1)
+            ans += x_snprintf ("\t%8lld %12lld ns %5d.%-3d %% %12d: %s\n", static_cast<long long> (n_hits), static_cast<long long> (t_op), wholes, rest, ip, s.c_str ());
+          else
+            ans += x_snprintf ("\t%8lld %12lld ns  %7.3e%% %12d: %s\n", static_cast<long long> (n_hits), static_cast<long long> (t_op), share_of_fn, ip, s.c_str ());
+        }
+
+      map_fn_to_annotated_bytecode[fn_name] = ans;
+    }
+
+  // Annotate source code
+  for (auto kv : m_map_fn_stats)
+    {
+      std::string ans;
+
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+
+      // First we need to create a map between opcode offset and source line
+      auto v_ip_s = map_fn_to_opcodes_stringrows[fn_name];
+
+      map<int, int> map_op_offset_to_src_line;
+
+      for (auto ip_s : v_ip_s)
+        {
+          int ip = ip_s.first;
+          loc_entry loc = vm::find_loc (ip, stats.m_loc_entries);
+          map_op_offset_to_src_line[ip] = loc.m_line;
+        }
+
+      // Sum up the time spent on a source line
+      map<int, int64_t> map_srcline_to_tcum;
+      map<int, int64_t> map_srcline_to_nhits;
+
+      for (unsigned ip = 0; ip < stats.m_v_cum_t.size (); ip++)
+        {
+          int64_t tcum = stats.m_v_cum_t[ip] + stats.m_v_cum_call_t[ip];
+          int64_t nhits = stats.m_v_n_cum[ip];
+          int src_line = map_op_offset_to_src_line[ip];
+          map_srcline_to_tcum[src_line] += tcum;
+          map_srcline_to_nhits[src_line] += nhits;
+        }
+
+      auto v_src_rows = map_fn_to_sourcerows[fn_name];
+      // Annotate the source code
+
+      // Put all time spent in opcodes that does not correnspond to any source line,
+      // on the first row with "function.*fnname" on.
+      bool found = false;
+      for (unsigned i = 0; i < v_src_rows.size(); i++)
+        {
+          string &row = v_src_rows[i];
+          std::size_t func_idx = row.find ("function");
+          std::size_t name_idx = row.find (stats.m_fn_name);
+
+          if (func_idx == string::npos || name_idx == string::npos)
+            continue;
+
+          string def = row.substr (0, func_idx + strlen ("function"));
+
+          // Any comment making it a fake?
+          if (def.find ('#') != string::npos || def.find ('%') != string::npos)
+            continue;
+
+          int line_nr = i + 1;
+          map_srcline_to_tcum[line_nr] += map_srcline_to_tcum[-1];
+          map_srcline_to_nhits[line_nr] += map_srcline_to_nhits[-1];
+          found = true;
+          break;
+        }
+
+      if (!found)
+      {
+        map_srcline_to_tcum[1] += map_srcline_to_tcum[-1];
+        map_srcline_to_nhits[1] += map_srcline_to_nhits[-1];
+      }
+      int64_t fn_cum_t = map_fn_to_cum_t[fn_name];
+
+      for (unsigned i = 0; i < v_src_rows.size(); i++)
+        {
+          int line_nr = i + 1;
+          int64_t t_line_cum = map_srcline_to_tcum[line_nr];
+          int64_t n_hits = map_srcline_to_nhits[line_nr];
+
+          double share_of_fn = 100. * static_cast<double> (t_line_cum) / fn_cum_t;
+
+          // Try to make the table neat around the decimal separator
+          int wholes = floor (share_of_fn);
+          int rest = (share_of_fn - wholes) * 100;
+
+          string src_line = v_src_rows[i];
+
+          if (share_of_fn == 0)
+            ans += x_snprintf ("\t%*s %5d: %s\n", 43, "", line_nr, src_line.c_str ());
+          else if (share_of_fn >= 0.1)
+            ans += x_snprintf ("\t%8lld %12lld ns %5d.%-3d %% %12d: %s\n", static_cast<long long> (n_hits), static_cast<long long> (t_line_cum), wholes, rest, line_nr, src_line.c_str ());
+          else
+            ans += x_snprintf ("\t%8lld %12lld ns  %7.3e%% %12d: %s\n", static_cast<long long> (n_hits), static_cast<long long> (t_line_cum), share_of_fn, line_nr, src_line.c_str ());
+        }
+
+      map_fn_to_annotated_source[fn_name] = ans;
+    }
+
+  map<int64_t, string> map_cumt_to_fn;
+  for (auto &kv : map_fn_to_cum_t)
+    map_cumt_to_fn[kv.second] = kv.first;
+
+  int64_t t_tot = 0;
+  for (auto &kv : map_fn_to_cum_t)
+    t_tot += kv.second;
+
+  // Print stuff to the user
+
+  printf ("\n\n\nProfiled functions:\n");
+  printf ("\tRuntime order:\n");
+  for (auto it = map_cumt_to_fn.rbegin (); it != map_cumt_to_fn.rend (); it++)
+    printf ("\t\t%12lld ns %3.0f%% %s\n", static_cast<long long> (it->first), it->first * 100. / t_tot, it->second.c_str ());
+  printf ("\tFirst call order:\n");
+  for (string fn_name : m_fn_first_call_order)
+  {
+    int64_t tcum = map_fn_to_cum_t[fn_name];
+    printf ("\t\t%12lld ns %3.0f%% %s\n", static_cast<long long> (tcum), tcum * 100. / t_tot, fn_name.c_str ());
+  }
+
+  for (auto kv : m_map_fn_stats)
+    {
+      string fn_name = kv.first;
+      vm_profiler_fn_stats &stats = kv.second;
+
+      int64_t fn_cum_t = map_fn_to_cum_t[fn_name];
+      int64_t fn_self_cum_t = map_fn_to_self_cum_t[fn_name];
+      string annotated_source = map_fn_to_annotated_source[fn_name];
+      string annotated_bytecode = map_fn_to_annotated_bytecode[fn_name];
+
+      printf ("\n\n\nFunction: %s\n\n", kv.first.c_str ());
+      if (stats.m_fn_file.size ())
+        printf ("\tFile: %s\n", stats.m_fn_file.c_str ());
+      printf ("\tAmount of calls: %lld\n", static_cast<long long> (stats.m_n_calls));
+      printf ("\tCallers:         ");
+      for (string caller : stats.m_set_callers)
+        printf ("%s ", caller.c_str ());
+      printf ("\n");
+      printf ("\tCumulative time: %9.5gs %lld ns\n", fn_cum_t/1e9, static_cast<long long> (fn_cum_t));
+      printf ("\tCumulative self time: %9.5gs %lld ns\n", fn_self_cum_t/1e9, static_cast<long long> (fn_self_cum_t));
+      printf ("\n\n");
+
+      if (annotated_source.size ())
+      {
+         printf ("\tAnnotated source:\n");
+         printf ("\t     ops         time       share\n");
+         printf ("\n");
+         printf ("%s\n\n", annotated_source.c_str ());
+      }
+      if (annotated_bytecode.size ())
+      {
+        printf ("\tAnnotated bytecode:\n");
+        printf ("\t     hits         time       share\n");
+        printf ("\n");
+        printf ("%s\n\n", annotated_bytecode.c_str ());
+      }
+      printf ("\n");
+    }
+}
+
+void
+vm_profiler::enter_fn (std::string caller_name, bytecode &bc)
+{
+  unsigned char *code = bc.m_code.data ();
+  std::string *name_data = bc.m_ids.data ();
+  unwind_data *unwind_data = &bc.m_unwind_data;
+
+  std::string callee_name = bc.m_data[2].string_value (); // profiler_name () querried at compile time
+
+  enter_fn (callee_name, caller_name, unwind_data, name_data, code);
+}
+
+void
+vm_profiler::enter_fn (std::string fn_name, std::string caller, octave::unwind_data *unwind_data, std::string *name_data, unsigned char *code)
+{
+  if (!m_map_fn_stats.count (fn_name))
+    m_fn_first_call_order.push_back (fn_name);
+
+  vm_profiler_fn_stats &callee_stat = m_map_fn_stats[fn_name];
+
+  callee_stat.m_set_callers.insert (caller);
+  callee_stat.m_v_callers.push_back (caller);
+  callee_stat.m_n_calls++;
+
+  vm_profiler_call call{};
+  call.m_callee = fn_name;
+  call.m_caller = caller;
+
+  int64_t now = unow ();
+  call.m_entry_time = now;
+
+  m_shadow_call_stack.push_back (call);
+
+  callee_stat.m_v_t.push_back (now);
+  callee_stat.m_v_ip.push_back (0);
+
+  if (callee_stat.m_code.size ())
+    return;
+
+  callee_stat.m_fn_file = unwind_data->m_file;
+  callee_stat.m_fn_name = unwind_data->m_name;
+
+  // We need to copy the bytecode with id names to the stat object to be able
+  // to print it later.
+  unsigned n_code = unwind_data->m_code_size;
+  unsigned n_ids = unwind_data->m_ids_size;
+  callee_stat.m_code = std::vector<unsigned char> (n_code);
+  callee_stat.m_ids = std::vector<std::string> (n_ids);
+
+  callee_stat.m_loc_entries = unwind_data->m_loc_entry;
+
+  for (unsigned i = 0; i < n_code; i++)
+    callee_stat.m_code[i] = code[i];
+  for (unsigned i = 0; i < n_ids; i++)
+    callee_stat.m_ids[i] = name_data[i];
+}
+
+void
+vm_profiler::purge_shadow_stack ()
+{
+  warning ("Profiler shadow stack got messed up. Measurement results might be inaccurate.");
+
+  m_shadow_call_stack.clear ();
+
+  for (auto &kv : m_map_fn_stats)
+  {
+    auto &v = kv.second;
+    v.m_v_callers.clear ();
+    v.m_v_t.clear ();
+    v.m_v_ip.clear ();
+  }
+}
+
+void
+vm_profiler::exit_fn (std::string fn_name)
+{
+  {
+    int64_t t_exit = unow ();
+
+    vm_profiler_fn_stats &callee_stat = m_map_fn_stats[fn_name];
+
+    // Add the cost of the RET up till now to the callee
+    if (callee_stat.m_v_t.size () && callee_stat.m_v_t.back () != -1)
+      {
+        int64_t t0 = callee_stat.m_v_t.back ();
+        int64_t dt = t_exit - t0;
+
+        callee_stat.add_t (dt);
+        this->add_t (dt);
+      }
+
+    if (!m_shadow_call_stack.size ())
+      goto error;
+    if (!callee_stat.m_v_callers.size ())
+      goto error;
+
+    bool is_recursive = false;
+    for (auto &call : m_shadow_call_stack)
+      {
+        if (call.m_caller == fn_name)
+          {
+            is_recursive = true;
+            break;
+          }
+      }
+
+    vm_profiler_call call = m_shadow_call_stack.back ();
+    m_shadow_call_stack.pop_back ();
+
+    std::string caller = call.m_caller;
+
+    std::string caller_according_to_callee = callee_stat.m_v_callers.back ();
+
+    // Pop one level
+    callee_stat.m_v_callers.pop_back ();
+    callee_stat.m_v_t.pop_back ();
+    callee_stat.m_v_ip.pop_back ();
+
+    if (caller_according_to_callee != caller)
+      goto error;
+
+    if (caller != "") // If the caller name is "" the callee has no profiled caller
+      {
+        vm_profiler_fn_stats &caller_stat = m_map_fn_stats[caller];
+
+        if (!caller_stat.m_v_t.size ())
+          goto error;
+
+        int64_t caller_enters_call = caller_stat.m_v_t.back ();
+        int64_t caller_enters_callee = call.m_entry_time;
+        int64_t caller_call_overhead = caller_enters_callee - caller_enters_call;
+        int64_t callee_dt = call.m_t_self_cum + call.m_t_call_cum - caller_call_overhead;
+
+        // Add the call's cumulative time to the caller's "time spent in bytecode call"-vector
+        // unless the call is recursive (to prevent confusing double book keeping of the time).
+        unsigned caller_ip = caller_stat.m_v_ip.back ();
+        caller_stat.maybe_resize (caller_ip);
+
+        if (!is_recursive)
+        {
+          // Add to cumulative spent in call from this ip, in caller
+          caller_stat.m_v_cum_call_t[caller_ip] += callee_dt;
+          // Add to cumulative time spent in *the latest call* to caller
+          if (m_shadow_call_stack.size ())
+            m_shadow_call_stack.back ().m_t_call_cum += callee_dt;
+        }
+        // Change the caller's last timestamp to now and subtract the caller's call overhead.
+        caller_stat.m_v_t.back () = unow () - caller_call_overhead;
+      }
+    return;
+  }
+error:
+  purge_shadow_stack ();
+  return;
+}
+
+// Debugging functions to be called from gdb
+
+extern "C" void
+vm_debug_print_ov (void *p)
+{
+  octave_value *ov = reinterpret_cast<octave_value*> (p);
+  ov->print (std::cout);
+}
+
+extern "C" void
+vm_debug_print_ovl (void *p)
+{
+  octave_value_list *ovl = reinterpret_cast<octave_value_list*> (p);
+
+  if (! ovl) return;
+
+  for (int i = 0; i < ovl->length (); i++)
+    {
+      (*ovl) (i).print (std::cout);
+    }
+}
+
+
+extern "C" void dummy_mark_1 (void)
+{
+  static int cntr;
+  cntr++;
+  asm ("");
+}
+
+extern "C" void dummy_mark_2 (void)
+{
+  static int cntr;
+  cntr++;
+  asm ("");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode-vm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,572 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+/*
+
+  -- About the experimental VM for GNU Octave
+
+  The VM is a "monkey tracing" stack based VM, executing linear bytecode compiled
+  from the abstract syntax tree (class tree_expression etc.).
+
+  Files of interest are:
+    * pt-bytecode-walk.cc:
+        The compiler translating the AST to bytecode
+    * pt-bytecode-vm.cc:
+        The VM
+    * stack-frame.cc:
+      bytecode_fcn_stack_frame, is the dynamic stack frame
+
+  -- Stack
+    The VM has one stack where it put arguments, returns, locals and temporaries.
+    The stack elements have the type 'union stack_element', which is a union of
+    octave_value and some pointers and native long long, double etc.
+
+    I.e. octave_value:s are constructed inplace on the stack. Not all stack elements
+    are octave_value:s.
+
+    Nested calls to compiled bytecode functions use the same stack.
+
+    The stack area does not grow. If the stack space runs out, the execution aborts.
+
+    To access arguments, returns and locals their "slot number" is used. I.e. offset
+    from the base stack register.
+
+    At VM termination, the end and start of the stack is checked for magic numbers
+    that should be there, and aborts if they are changed.
+
+  -- Registers
+    The VM uses the following pseudo-register:
+      * instruction pointer ('ip')
+      * base instruction register ('code')
+      * stack register ('sp')
+      * base stack register ('bsp')
+          The start of the current stack frame
+      * constant base register ('data')
+          A pointer to an array of octave_value "literal constants", like "3"
+
+    The registers are popped and pushed in each return or call together with the
+    follwing auxilliary data:
+      * unwind data
+      * name data (names of the identifiers)
+      * nargout
+      * nargin
+
+    Note that 'argnames' is lazy in the VM. There is more kludge state stored in
+    the VM object other then the happy path state noted above.
+
+  -- Dynamic stack frame
+    The VM uses its own stack frames, but also pushes a 'stack_frame' of the subclass
+    'bytecode_fcn_stack_frame' to the 'tree_evaluator', to be able to cooperate
+    with C++-compiled functions and the 'tree_evaluator'.
+
+    'bytecode_fcn_stack_frame' is quite lazy and lets e.g. a compiled function
+    or user code executed with the 'tree_evaluator' create, read and write variables
+    on the VM stack.
+
+  -- Monkey tracing
+    During execution of some op-codes the VM checks the type of the operands
+    and might modify the bytecode to execute a specialized op-code.
+
+    E.g. the "index identifier"-opcode becomes the "index matrix with one scalar"-opcode
+    if the index is one double and the object to index is a matrix.
+
+    If later the preconditions are not true, the specialized opcode replaces itself
+    with the general opcode.
+
+    "Monkey tracing" is a made up term for this concept.
+
+  -- Function caching
+    Function lookups are cached in the corrensponding slot of an identifier on
+    the VM stack. If any function is added to the symbol table, the current
+    directory is changed or 'clear' is called, all function caches are invalidated.
+
+    The function cache is dependent on the argument types. If the argument types
+    change, the cache is invalidated.
+
+    Binary and unary operators for doubles are looked up on VM start and cached in
+    the VM. They are not invalidated aslong the VM is running.
+
+  -- Compilation
+    At runtime when user code is about to be executed, it is compiled, if VM
+    evaluation is turned on.
+
+    It is also possible to compile ahead of time.
+
+    Compiled code is reused the next invocation of the user function. If the
+    user function is changed, the compiled code is cleared.
+
+    Compilation is done be the 'bytecode_walker' class in 'pt-bytecode-walk.cc'.
+
+  -- Opcodes
+
+  The op-codes are byte aligned and some are variable length.
+
+  The first byte always identifies the op-code and is also the offset used in the
+  dispatch table 'instr'.
+
+  'octave_value' is abbreviated 'ov' in this table.
+  "<-" means, state of stack before operation. The right most element is the toppiest of the stack.
+  "->" means, state of stack after operation.
+
+    ** Binary math operations
+      Pop two 'ov:s' of the stack and do the appropiate operation, then push the
+      resulting 'ov'. The top of the stack is the right hand side.
+
+      For all:
+      <- (ov lhs) (ov rhs)
+      -> (ov ans)
+
+      -- MUL DIV ADD SUB POW LDIV EL_MUL EL_DIV EL_POW EL_LDIV
+          *   /   +   -   ^   \     .*     ./     .^     .\
+
+      The following specializations for double arguments exist:
+        MUL_DBL, ADD_DBL, SUB_DBL, DIV_DBL, POW_DBL
+
+    ** Compound math operations
+      Pop two 'ov:s' off the stack and do the appropiate operation, then push the
+      resulting 'ov'. The top of the stack is the right hand side.
+
+      The opcodes are combinations of an unary math operation and a binary.
+
+      <- (ov lhs) (ov rhs)
+      -> (ov ans)
+
+      -- TRANS_MUL  MUL_TRANS  HERM_MUL  MUL_HERM  TRANS_LDIV HERM_LDIV
+          a.'*b      a*b.'      a'*b      a*b'      a.'\b      a'\b
+
+    ** Unary math operations
+      Pop one 'ov' and do the appropiate operation, then push the
+      resulting 'ov'.
+
+      <- (ov arg)
+      -> (ov ans)
+
+      -- UADD
+        Unary addition. Note that unary plus is not a nop in GNU Octave. It
+        can be overloaded to do whatever.
+      -- USUB
+        Unary subtraction
+      -- TRANS
+        Transpose, ".'"
+      -- HERM
+        Hermitian, "'"
+
+    ** Logical unary operations
+      Pop one 'ov' and do the appropiate operation, then push the
+      resulting 'ov'.
+
+      <- (ov arg)
+      -> (ov ans)
+
+      -- NOT
+        "!", "~"
+
+      -- UNARY_TRUE
+        Converts an ov on the stack to either ov false or ov true.
+        The op-code is used to construct control flow for e.g. shortcircuits.
+        User values' truthness are checked by JMP_IF and JMP_IFN which errors
+        on undefined values.
+
+    ** Logical binary operations
+      Pop two 'ov:s' of the stack and do the appropiate operation, then push the
+      resulting 'ov'. The top of the stack is the right hand side.
+
+      For all:
+      <- (ov lhs) (ov rhs)
+      -> (ov ans)
+
+      -- LE  GR  EQ  NEQ  GR_EQ  LE_EQ EL_AND EL_OR
+         <   >   ==  !=   >=     <=     &      |
+
+      Note that EL_AND and EL_OR does not emulate braindamaged if-conditions. That
+      is done by the bytecode compiler with the help of the opcodes
+      BRAINDEAD_PRECONDITION and BRAINDEAD_WARNING together with some convoluted
+      bytecode.
+
+      The following specializations exist:
+        LE_DBL, LE_EQ_DBL, GR_DBL, GR_EQ_DBL, EQ_DBL, NEQ_DBL
+
+    ** Stack control
+      -- POP
+      <- (ov)
+      ->
+        Pop one 'ov' element of the stack.
+
+      -- DUP
+      <- (ov1)
+      -> (ov1) (ov1)
+
+        Duplicate the 'ov' on top of the stack and push it to the stack.
+
+      -- ROT
+      <- (ov1) (ov2)
+      -> (ov2) (ov1)
+        Rotate the top two 'ov:s' on the stack.
+
+      -- DUPN (uint8 offset) (uint8 n)
+      <- (ov -offset - n) ... (ov -offset) ... (offset amount of stack elements)
+      -> The range "(ov -offset - n) ... (ov -offset)" copied to the top of the stack in the same order.
+        Pushes 'n' ov:s from the stack at depth 'offset' to the top of the
+        stack. The copies have the same order on the stack as the originals.
+        An 'offset' of 0 means the top element of the stack.
+
+      -- PUSH_SLOT_NARGOUT0 (uint8 slot)
+      -- PUSH_SLOT_NARGOUT1 (uint8 slot)
+      -- PUSH_SLOT_NARGOUTN (uint8 slot) (uint8 nargout)
+      <-
+      -> (ov 1) (ov 2)? ... (ov n)?
+        If the local 'ov' at 'bsp[slot]' is an ordinary variable, push it
+        to the stack.
+
+        If the local is undefined, assume it is a command call function,
+        look the function name up, and call it with the nargout 0, 1 or n.
+
+        If the local is a function object, call it with the nargout 0, 1 or n.
+
+        PUSH_SLOT_NARGOUT1_SPECIAL is like PUSH_SLOT_NARGOUT1 but pushes 'classdef_metas'
+        instead of trying to execute them. PUSH_SLOT_DISP keeps track of whether the
+        slot variable was executed or not for a correct display call.
+
+      -- PUSH_SLOT_INDEXED (uint8 slot)
+      <-
+      -> (ov)
+        Push the local 'ov' at 'bsp[slot]' to the stack. This opcode is used for
+        e.g. pushing 'x' in "x(2)".
+
+      -- PUSH_PI (uint8 slot)
+      <-
+      -> (ov 1) (ov 2)? ... (ov n)?
+        Like PUSH_SLOT_NARGOUT1, but if the slot variable resolves to a call to
+        the builtin function 'pi', just push pi to the stack as a double ov.
+
+      -- PUSH_OV_U64
+      <-
+      -> (ov1)
+        Push an ov of the type uint64 with the value 0, to the stack.
+
+      -- PUSH_CELL
+      <- (ov i) (ov j) ... [a mess of ov:s]
+      -> (ov ans)
+        Create a cell ov on the stack with up to i*j ov objects in it. Note that the last row can
+        shorter than the other rows and that any row can be empty and ignored.
+
+        Each row is initially pushed as following:
+          1. element by element, if any
+          2. an integer ov with the row length
+
+      -- PUSH_NIL
+      <-
+      -> (ov nil)
+        Push a default constructed 'octave_value' to the stack.
+
+      -- POP_N_INTS (uint8 n)
+      <- (int i1) ... (int in)
+      ->
+        Pops 'n' native values of the stack. It could be pointers or doubles, not just int:s.
+
+    ** Data control
+      -- LOAD_CST (uint8 offset)
+      <-
+      -> (ov)
+        Load the 'ov' at 'data[offset]' and push it to the stack.
+        LOAD_CST_ALTx are duplicates of the opcode existing for branch prediction reasons.
+
+      -- LOAD_FAR_CST (int32 offset)
+      <-
+      -> (ov)
+        Load the 'ov' at 'data[offset]' and push it to the stack.
+
+      -- INIT_GLOBAL (uint8 type) (uint8 slot) (uint8 unused) (bool has_init_code) (uint16 target)?
+        Initializes a persistent or global variable depending on 'type'.
+        If 'has_init_code' is true, jumps to 'target' if the variable does not exist yet
+        in the global namespace. If 'has_init_code' is false, it is the end of the instruction.
+
+    ** Flow control
+      -- JMP (uint16 target)
+        Set the intstruction register to the instruction base register plus target.
+
+      -- JMP_IF (uint16 target)
+      -- JMP_IFN (uint16 target)
+      <- (ov)
+      ->
+        Set the intstruction register to the instruction base register plus target
+        if the argument is true/untrue.
+
+      -- RET
+      <- [saved caller frame] (int nargout) (ov ret1) ... (ov retn) (ov arg1) ... (ov argn) (ov local1) ... (ov localn)
+      -> (ov retn) ... (ov ret1)
+        Return from a bytecode frame to another.
+
+        There is always atleast one ov on the stack after RET is executed. It might be the nil ov.
+
+      -- FOR_SETUP FOR_COND (uint16 after_target) (uint8 slot)
+      <- (ov range1)
+      -> (ov range1) (int64 n) (int64 i)
+        Executes a for-loop setup. Then falls through to the FOR_COND op-code which checks
+        if a loop body is to be executed.
+
+        FOR_SETUP is always followed by a FOR_COND opcode.
+
+        The 'slot' is the slot for the iteration variable.
+
+        The 'after_target' is the instruction offset to after the loop body.
+
+        The end of the loop body jumps to the FOR_COND op-code.
+
+        After the loop body, and at each escape point in the body,
+        the two native integers and the ov range are popped.
+
+        FOR_COMPLEX_SETUP and FOR_COMPLEX_COND is similar for "struct key-value for-loops"
+        but needs two slots.
+
+      -- THROW_IFERROBJ
+      <- (ov)
+      ->
+        Unwinds the stack until any exception handler if ov is an error object.
+
+
+      ... there are more op-codes.
+*/
+
+
+
+
+#if ! defined (octave_pt_bytecode_vm_h)
+#define octave_pt_bytecode_vm_h 1
+
+#include "octave-config.h"
+
+#include <cstddef>
+#include <vector>
+#include <memory>
+
+#include "oct-lvalue.h"
+#include "ovl.h"
+
+#include "interpreter-private.h"
+#include "symtab.h"
+
+#include "pt-bytecode.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+class tree_evaluator;
+
+struct vm_profiler
+{
+  struct vm_profiler_call
+  {
+    std::string m_caller;
+    std::string m_callee;
+    int64_t m_entry_time;
+    int64_t m_t_self_cum; // Time spent in callee it-self
+    int64_t m_t_call_cum; // Time spent in bytecode calls, called from callee
+  };
+
+  struct vm_profiler_fn_stats
+  {
+    // Cumulative ns time at op-code at offset
+    std::vector<int64_t> m_v_cum_t;
+    // Cumulative hits at op-code at offset
+    std::vector<int64_t> m_v_n_cum;
+    // Cumulative time spent in nested calls to a bytecode function at op-code at offset
+    std::vector<int64_t> m_v_cum_call_t;
+
+    void maybe_resize (unsigned ip)
+    {
+      if (ip >= m_v_cum_t.size ())
+        m_v_cum_t.resize (ip + 1);
+      if (ip >= m_v_n_cum.size ())
+        m_v_n_cum.resize (ip + 1);
+      if (ip >= m_v_cum_call_t.size ())
+        m_v_cum_call_t.resize (ip + 1);
+    }
+
+    // The last bytecode timestamp, i.e. the start of the currently running opcode. One level per call
+    std::vector<int64_t> m_v_t;
+    // The last ip, i.e. the ip being executed. One level per call
+    std::vector<int> m_v_ip;
+    // Set of callers. One entry for each caller
+    std::set<std::string> m_set_callers;
+    // Amount of calls to this function
+    int64_t m_n_calls;
+
+    // Data structures to keep track of calls. One level per call
+    std::vector<std::string> m_v_callers; // Used in callee to change the last timestamp of caller
+
+    std::string m_fn_name;
+    std::string m_fn_file;
+    std::vector<unsigned char> m_code; // Copy of the actual opcodes executed
+    std::vector<std::string> m_ids; // Copy of the name data
+    std::vector<loc_entry> m_loc_entries; // Copy of source code location data
+
+    void add_t (int64_t dt);
+  };
+
+  void add_t (int64_t dt);
+
+  std::vector<vm_profiler_call> m_shadow_call_stack;
+
+  std::map<std::string, vm_profiler_fn_stats> m_map_fn_stats;
+
+  std::vector<std::string> m_fn_first_call_order;
+
+  static int64_t unow ();
+  void print_to_stdout ();
+  void enter_fn (std::string callee_name, std::string caller_name, octave::unwind_data *unwind_data, std::string *name_data, unsigned char *code);
+  void enter_fn (std::string caller_name, bytecode &bc);
+  void exit_fn (std::string fn);
+  void purge_shadow_stack ();
+};
+
+class vm
+{
+ public:
+
+  static constexpr size_t stack_size = 2048 * 8;
+  static constexpr size_t stack_pad = 32;
+  static constexpr size_t stack_magic_int = 0xBABEBEEFCAFE5000;
+  static constexpr size_t stack_min_for_new_call = 1024;
+
+  vm (tree_evaluator *tw, bytecode &initial_bytecode);
+
+  ~vm ();
+
+  bool m_dbg_proper_return = false;
+  bool m_could_not_push_frame = false;
+  bool m_unwinding_interrupt = false;
+  stack_element *m_stack0 = nullptr;
+
+  std::vector<std::shared_ptr<stack_frame>> m_frame_ptr_cache;
+
+  tree_evaluator *m_tw;
+  type_info *m_ti;
+  symbol_table *m_symtab;
+  stack_element *m_stack = nullptr;
+  stack_element *m_sp = 0;
+  stack_element *m_bsp = 0;
+  stack_element *m_rsp = 0;
+
+  type_info::binary_op_fcn m_fn_dbl_mul = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_add = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_sub = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_div = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_pow = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_le = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_le_eq = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_gr = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_gr_eq = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_eq = nullptr;
+  type_info::binary_op_fcn m_fn_dbl_neq = nullptr;
+
+  type_info::unary_op_fcn m_fn_dbl_usub = nullptr;
+  type_info::unary_op_fcn m_fn_dbl_not = nullptr;
+  type_info::unary_op_fcn m_fn_bool_not = nullptr;
+
+  octave_function * m_pi_builtin_fn = nullptr;
+
+  static int constexpr m_scalar_typeid = 2;
+  static int constexpr m_matrix_typeid = 4;
+  static int constexpr m_bool_typeid = 10;
+
+  struct output_ignore_data {
+    std::vector<Matrix*> m_v_matrixes;
+    std::vector<const std::list<octave::octave_lvalue>*> m_v_lvalue_list;
+
+    bool is_pending () {return m_v_matrixes.size () && m_v_matrixes.back () != nullptr; }
+
+    Matrix get_ignore_matrix ()
+    {
+      Matrix m = *m_v_matrixes.back ();
+      delete m_v_matrixes.back ();
+      m_v_matrixes.back () = nullptr;
+
+      return m;
+    }
+
+    const std::list<octave::octave_lvalue>* pop_lvalue_list ()
+    {
+      auto *p = m_v_lvalue_list.back ();
+      m_v_lvalue_list.pop_back ();
+      return p;
+    }
+  };
+
+  output_ignore_data *m_output_ignore_data = nullptr;
+  const std::list<octave::octave_lvalue> *m_original_lvalue_list = nullptr;
+
+  unsigned char *m_code;
+  octave_value *m_data;
+  std::string *m_name_data;
+  unwind_data *m_unwind_data;
+
+  int m_ip;
+
+  // Generic data container to recreate exceptions
+  struct error_data
+  {
+    // Execution exception
+    int m_exit_status;
+    bool m_safe_to_return;
+  };
+
+  error_data
+  handle_error (error_type et);
+
+  static
+  loc_entry find_loc (int ip, std::vector<octave::loc_entry> &loc_entries);
+
+  octave_value_list execute_code (const octave_value_list &args, int root_nargout)
+    __attribute__ ((optimize("no-gcse","no-crossjumping")));
+
+  octave_value find_fcn_for_cmd_call (std::string *name);
+  octave_value handle_object_end (octave_value ov, int idx, int nargs);
+
+  void set_nargin (int nargin);
+
+  void set_nargout (int nargout);
+
+  unwind_entry* find_unwind_entry_for_current_state (bool only_find_unwind_protect);
+  int find_unwind_entry_for_forloop (int current_stack_depth);
+
+  static std::shared_ptr<vm_profiler> m_vm_profiler;
+  static bool m_profiler_enabled;
+  static bool m_trace_enabled;
+};
+
+OCTINTERP_API
+void print_bytecode (bytecode &bc);
+
+OCTINTERP_API
+std::vector<std::pair<int, std::string>>
+opcodes_to_strings (bytecode &bc);
+
+OCTINTERP_API
+std::vector<std::pair<int, std::string>>
+opcodes_to_strings (std::vector<unsigned char> &code, std::vector<std::string> &names);
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode-walk.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,4955 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "pt-all.h"
+#include "pt-bytecode-walk.h"
+#include "symrec.h"
+#include "pt-walk.h"
+#include "ov-scalar.h"
+
+//#pragma GCC optimize("Og")
+
+using namespace octave;
+
+void octave::compile_user_function (octave_user_function &ufn, bool do_print)
+{
+  try
+    {
+      if (ufn.is_classdef_constructor ())
+        error ("Classdef constructors are not supported by the VM yet"); // Needs special handling
+      if (ufn.is_inline_function () || ufn.is_nested_function ())
+        error ("Inlined or scoped functions are not supported by the VM yet");
+
+      // Begin with clearing the old bytecode, if any
+      ufn.clear_bytecode ();
+
+      bytecode_walker bw;
+
+      ufn.accept (bw);
+
+      if (do_print)
+        print_bytecode (bw.m_code);
+
+      ufn.set_bytecode (bw.m_code);
+
+      // Compile the subfunctions
+      auto subs = ufn.subfunctions ();
+      for (auto kv : subs)
+        {
+          octave_user_function *sub = kv.second.user_function_value ();
+          compile_user_function (*sub, do_print);
+          sub->get_bytecode ().m_unwind_data.m_file = ufn.fcn_file_name ();
+        }
+    }
+  catch(...)
+  {
+    ufn.clear_bytecode ();
+    throw;
+  }
+}
+
+// Class to walk the tree and see if a index expression has
+// an end in it.
+//
+// Does not walk nested index expressions.
+class find_end_walker : tree_walker
+{
+public:
+  static bool has_end (tree &e)
+  {
+    find_end_walker walker;
+    e.accept (walker);
+
+    return walker.m_has_end;
+  }
+
+  bool m_has_end = false;
+
+  void visit_identifier (tree_identifier &id)
+  {
+    std::string name = id.name ();
+    if (name == "end")
+      m_has_end = true;
+  }
+};
+
+class is_foldable_walker : tree_walker
+{
+public:
+  static bool is_foldable (tree_binary_expression &e)
+  {
+    return is_foldable_internal (e);
+  }
+
+  static bool is_foldable (tree_prefix_expression &e)
+  {
+    return is_foldable_internal (e);
+  }
+
+  static bool is_foldable (tree_postfix_expression &e)
+  {
+    return is_foldable_internal (e);
+  }
+
+private:
+  static bool is_foldable_internal (tree &e)
+  {
+    is_foldable_walker walker;
+
+    e.accept (walker);
+
+    return walker.m_is_foldable;
+  }
+
+  bool is_foldable_expr (tree_expression *e)
+  {
+    return e->is_binary_expression () || e->is_unary_expression () || e->is_constant ();
+  }
+
+  void visit_postfix_expression (tree_postfix_expression& e)
+  {
+    if (!m_is_foldable)
+      return;
+
+    tree_expression *op = e.operand ();
+
+    if (!is_foldable_expr (op))
+      {
+        m_is_foldable = false;
+        return;
+      }
+
+    op->accept (*this);
+  }
+
+  void visit_prefix_expression (tree_prefix_expression& e)
+  {
+    if (!m_is_foldable)
+      return;
+
+    tree_expression *op = e.operand ();
+
+    if (!is_foldable_expr (op))
+      {
+        m_is_foldable = false;
+        return;
+      }
+
+    op->accept (*this);
+  }
+
+  void visit_binary_expression (tree_binary_expression &e)
+  {
+    if (!m_is_foldable)
+      return;
+
+    tree_expression *rhs = e.rhs ();
+    tree_expression *lhs = e.lhs ();
+    if (!is_foldable_expr (rhs) || !is_foldable_expr (lhs))
+      {
+        m_is_foldable = false;
+        return;
+      }
+
+    lhs->accept (*this);
+    if (m_is_foldable)
+      rhs->accept (*this);
+  }
+
+  bool m_is_foldable = true;
+};
+
+class collect_idnames_walker : tree_walker
+{
+public:
+  static std::vector<std::pair<std::string, int>> collect_id_names (tree_statement_list &l)
+  {
+    collect_idnames_walker walker;
+
+    for (auto it = l.begin (); it != l.end (); it++)
+      {
+        if (*it)
+          (*it)->accept (walker);
+      }
+
+    return walker.m_id_names_and_offset;
+  }
+
+  static std::vector<std::pair<std::string, int>> collect_id_names (tree_expression &e)
+  {
+    collect_idnames_walker walker;
+    e.accept (walker);
+
+    return walker.m_id_names_and_offset;
+  }
+
+  std::vector<std::pair<std::string, int>> m_id_names_and_offset;
+
+  void visit_identifier (tree_identifier &id)
+  {
+    std::string name = id.name ();
+    if (name == "~") // We dont want this magic id
+      return;
+
+    m_id_names_and_offset.push_back ({name, id.symbol ().data_offset ()});
+  }
+
+  void visit_anon_fcn_handle (tree_anon_fcn_handle &)
+  {
+    // We dont collect any id:s in the handle, since the original scope
+    // don't.
+  }
+};
+
+template <class T>
+typename T::value_type vector_pop (T &v)
+{
+  typename T::value_type tmp = v.back ();
+  v.pop_back ();
+  return tmp;
+}
+
+#define ERR(msg) error("VM error %d: " msg, __LINE__)
+
+#define TODO(msg) error("VM error, Not done yet %d: " msg, __LINE__)
+
+#define CHECK(cond)                                                            \
+  do {                                                                         \
+    if (!(cond))                                                               \
+      ERR("Internal VM compiler consistency check failed, " #cond);             \
+  } while ((0))
+
+#define PUSH_CODE(code_) do {\
+    int code_check_s_ = static_cast<int> (code_); \
+    unsigned char code_s_ = static_cast<unsigned char> (code_check_s_);     \
+    CHECK (code_check_s_ < 256 && code_check_s_ >= -128); \
+    m_code.m_code.push_back(code_s_);        \
+  } while ((0))
+
+#define PUSH_CODE_LOAD_CST(offset) do {\
+  unsigned offset_ = offset; \
+  if (offset_ < 65536)\
+    {\
+      if (offset_ >= 256) \
+        PUSH_CODE (INSTR::WIDE); \
+      emit_alt (m_cnt_alts_cst, {INSTR::LOAD_CST, INSTR::LOAD_CST_ALT2, \
+        INSTR::LOAD_CST_ALT3, INSTR::LOAD_CST_ALT4});\
+      if (offset_ >= 256) \
+        PUSH_CODE_SHORT (offset_);\
+      else\
+        PUSH_CODE (offset_);\
+    }\
+  else\
+    {\
+      PUSH_CODE (INSTR::LOAD_FAR_CST);\
+      PUSH_CODE_INT (offset_);\
+    }\
+} while (0)
+
+#define PUSH_SSLOT(sslot) PUSH_CODE(sslot)
+#define PUSH_WSLOT(wslot) PUSH_CODE_SHORT(wslot)
+#define NEED_WIDE_SLOTS() (m_map_locals_to_slot.size () >= 256)
+
+#define MAYBE_PUSH_WIDE_OPEXT(slot) \
+do {\
+  if (slot >= 256)\
+    PUSH_CODE (INSTR::WIDE);\
+} while ((0))
+
+#define PUSH_SLOT(slot) \
+do {\
+  if (slot >= 256)\
+    PUSH_WSLOT (slot);\
+  else\
+    PUSH_SSLOT (slot);\
+} while ((0))
+
+#define CODE_SIZE() m_code.m_code.size()
+#define CODE(x) m_code.m_code[x]
+#define PUSH_CODE_SHORT(code_) do {   \
+  unsigned u = code_;                 \
+  unsigned char b0 = u & 0xFF;        \
+  unsigned char b1 = (u >> 8) & 0xFF; \
+  int code_check_ss_ = static_cast<int> (u);                  \
+  CHECK (code_check_ss_ < 65536 && code_check_ss_ >= -32768); \
+  PUSH_CODE (b0);                     \
+  PUSH_CODE (b1);                     \
+  } while ((0))
+#define PUSH_CODE_INT(code_) do {   \
+  unsigned u = code_;                 \
+  unsigned char b0 = u & 0xFF;        \
+  unsigned char b1 = (u >> 8) & 0xFF; \
+  unsigned char b2 = (u >> 16) & 0xFF;\
+  unsigned char b3 = (u >> 24) & 0xFF;\
+  PUSH_CODE (b0);                     \
+  PUSH_CODE (b1);                     \
+  PUSH_CODE (b2);                     \
+  PUSH_CODE (b3);                     \
+  } while ((0))
+
+#define SET_CODE_SHORT(offset, value) do {  \
+  int tmp = offset;                         \
+  unsigned u = value;                       \
+  unsigned char b0 = u & 0xFF;              \
+  unsigned char b1 = (u >> 8) & 0xFF;       \
+  int code_check_s_ = static_cast<int> (u); \
+  CHECK (code_check_s_ < 65536 && code_check_s_ >= -32768); \
+  CODE (tmp) = b0;                          \
+  CODE (tmp + 1) = b1;                      \
+  } while ((0))
+
+#define PUSH_DATA(cst) m_code.m_data.push_back(cst)
+#define DATA_SIZE() m_code.m_data.size()
+
+// TODO: This optimization is nice and we should get it working again.
+#define PUSH_ALL_PATHS_TERMINATED() m_all_paths_terminated.push_back (false)
+#define POP_ALL_PATHS_TERMINATED() vector_pop (m_all_paths_terminated)
+#define PEEK_ALL_PATHS_TERMINATED() m_all_paths_terminated.back ()
+#define SET_ALL_PATHS_TERMINATED() m_all_paths_terminated.back () = true
+
+#define PUSH_BREAKS() m_need_break_target.push_back ({})
+#define POP_BREAKS() vector_pop (m_need_break_target)
+#define PUSH_NEED_BREAK(offset) m_need_break_target.back ().push_back (offset)
+#define N_BREAKS() m_need_break_target.size ()
+
+#define PUSH_CONTINUE_TARGET(target) m_continue_target.push_back ({})
+#define POP_CONTINUE_TARGET() vector_pop (m_continue_target)
+#define PUSH_NEED_CONTINUE_TARGET(offset) \
+  m_continue_target.back ().push_back (offset)
+
+#define SLOT(name) get_slot (name)
+
+#define CHECK_NONNULL(ptr) if (!ptr) error ("Unexpected null %d", __LINE__)
+
+#define PUSH_ID_BEGIN_INDEXED(slot, idx, narg, is_obj) \
+  m_indexed_id.push_back ({slot, idx, narg, is_obj})
+#define POP_ID_BEING_INDEXED() m_indexed_id.pop_back ()
+#define ID_IS_BEING_INDEXED() (m_indexed_id.size () != 0)
+#define N_IDS_BEING_INDEXED() (m_indexed_id.size ())
+#define PEEK_ID_BEING_INDEXED() m_indexed_id.back ()
+#define IDS_BEING_INDEXED(idx) m_indexed_id[idx]
+
+#define PUSH_NESTING_STATEMENT(type) m_nesting_statement.push_back (type)
+#define POP_NESTING_STATEMENT() m_nesting_statement.pop_back ()
+#define NESTING_STATEMENTS() m_nesting_statement
+
+// Track how many expression deep we are in the walk.
+// I.e. identifiers need to know if they are:
+//   foo; %depth 1
+// or
+//   foo * 2; %depth 2 for id foo
+//
+// so that nargout for a command call at root is zero.
+// E.g.:
+//   tic;
+#define INC_DEPTH() ++m_depth
+#define DEC_DEPTH() --m_depth
+#define DEPTH() m_depth
+
+// We need to track the expected amount of output variables
+// for each expression. E.g.:
+// foo(); %0
+// a = foo (); %1
+// [a b] = foo (); %2
+// [a b] = foo (foo () + foo ()); %2 for outer, 1 for inner foo
+
+#define NARGOUT() m_nargout.back ()
+#define PUSH_NARGOUT(nargout) m_nargout.push_back (nargout)
+#define POP_NARGOUT() vector_pop (m_nargout)
+
+#define PUSH_ARGNAMES_ENTRY(arg_nm_e) m_code.m_unwind_data.m_argname_entries.push_back (arg_nm_e)
+
+#define PUSH_UNWIND_RETURN_TARGETS() m_need_unwind_target.push_back ({})
+#define POP_UNWIND_RETURN_TARGET() vector_pop (m_need_unwind_target)
+#define N_UNWIND_RETURN_TARGETS() m_need_unwind_target.size ()
+#define PUSH_A_UNWIND_RETURN_TARGET(offset) \
+  m_need_unwind_target.back ().push_back (offset)
+
+#define PUSH_LOC() m_code.m_unwind_data.m_loc_entry.push_back ({})
+#define LOC(i) m_code.m_unwind_data.m_loc_entry[i]
+#define N_LOC() m_code.m_unwind_data.m_loc_entry.size ()
+
+#define PUSH_UNWIND() m_code.m_unwind_data.m_unwind_entries.push_back ({})
+#define UNWIND(i) m_code.m_unwind_data.m_unwind_entries[i]
+#define N_UNWIND() m_code.m_unwind_data.m_unwind_entries.size ()
+
+#define PUSH_GLOBAL(name) do {m_map_id_is_global[name] = 1;} while ((0))
+#define IS_GLOBAL(name) (m_map_id_is_global.find (name) !=\
+                                                  m_map_id_is_global.end ())
+
+#define PUSH_PERSISTENT(name) do {m_map_id_is_persistent[name] = 1;} while ((0))
+#define IS_PERSISTENT(name) (m_map_id_is_persistent.find (name) !=\
+                             m_map_id_is_persistent.end ())
+
+// Note that the placement of PUSH_TREE_FOR_DBG() need to mirror the walk in pt-bp.cc
+#define PUSH_TREE_FOR_DBG(ptree) do { m_code.m_unwind_data.m_ip_to_tree[CODE_SIZE ()] = ptree; } while(0)
+#define PUSH_TREE_FOR_EVAL(ptree) do { m_code.m_unwind_data.m_ip_to_tree[-CODE_SIZE ()] = ptree; } while(0)
+
+void
+bytecode_walker::
+visit_statement_list (tree_statement_list& lst)
+{
+  for (tree_statement *elt : lst)
+    {
+      CHECK_NONNULL (elt);
+
+      PUSH_NARGOUT (0);
+
+      elt->accept (*this);
+      POP_NARGOUT ();
+    }
+}
+
+void
+bytecode_walker::
+visit_statement (tree_statement& stmt)
+{
+  if (stmt.is_expression ())
+    {
+      int loc_id = N_LOC ();
+      PUSH_LOC ();
+      LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+      tree_expression *expr = stmt.expression ();
+      PUSH_TREE_FOR_DBG(expr);
+      CHECK_NONNULL (expr);
+      expr->accept (*this);
+
+      LOC (loc_id).m_ip_end = CODE_SIZE ();
+      LOC (loc_id).m_col = stmt.column ();
+      LOC (loc_id).m_line = stmt.line ();
+    }
+  else if (stmt.is_command ())
+    {
+      tree_command *cmd = stmt.command ();
+      CHECK_NONNULL (cmd);
+      cmd->accept (*this);
+    }
+  else
+    TODO ();
+}
+
+void
+bytecode_walker::emit_alt (int &cntr, std::vector<INSTR> alts)
+{
+  unsigned n = alts.size ();
+  unsigned offset = cntr++ % n;
+  PUSH_CODE (alts [offset]);
+}
+
+bytecode_walker::emit_unwind_protect_data
+bytecode_walker::emit_unwind_protect_code_start ()
+{
+  emit_unwind_protect_data D; // Keeps track of state for emit_unwind_protect_code_before_cleanup() and emit_unwind_protect_code_end()
+
+    // Unwind protect has a body and cleanup part that always
+  // is executed.
+  //
+  // If the VM is unwinding it enters the cleanup code with an
+  // error object on the stack. The body puts a nil object on the
+  // stack.
+  //
+  // If there is an error object on the stack at the end of the cleanup
+  // code it rethrows it.
+  //
+  // Returns in the body jumps to the cleanup code before actually returning.
+  // If a return is reached in the body, a true object is pushed to the stack,
+  // which is checked in the cleanup code to know if we are falling through or
+  // are supposed to return.
+  //
+  // The same applies to breaks, so the code underneath gets abit messy.
+  //
+  // The body_expr, cleanup_expr and cleanup_instructions parameters are for
+  // when we need to emit some internal cleanup code that has no corrensponding
+  // unwind_protect in the user code.
+
+  int unwind_idx = N_UNWIND ();
+  PUSH_UNWIND();
+
+  UNWIND (unwind_idx).m_ip_start = CODE_SIZE ();
+
+  UNWIND (unwind_idx).m_unwind_entry_type =
+    unwind_entry_type::UNWIND_PROTECT;
+
+  UNWIND (unwind_idx).m_stack_depth = n_on_stack_due_to_stmt();
+
+  // Returns need to execute the unwind cleanup code before
+  // returning, so we need to keep track of offsets that need
+  // to jump to the cleanup code.
+  PUSH_UNWIND_RETURN_TARGETS ();
+
+  // We need to store away the pending "need breaks" since any break in the
+  // unwind protect body need to jump to the cleanup code.
+  std::vector<int> v_need_breaks_initial;
+  bool break_stack_populated = N_BREAKS ();
+  if (break_stack_populated)
+    {
+      v_need_breaks_initial = POP_BREAKS ();
+      PUSH_BREAKS ();
+    }
+
+  D.m_break_stack_populated = break_stack_populated;
+  D.m_idx_unwind = unwind_idx;
+  D.m_v_need_breaks_initial = v_need_breaks_initial;
+
+  return D;
+}
+
+void
+bytecode_walker::emit_unwind_protect_code_before_cleanup (emit_unwind_protect_data &D)
+{
+  // If the vm is unwinding it will push an error object to
+  // the stack. If we are just done executing the body we
+  // push a nil ov to the stack.
+  //
+  // At the end of the cleanup code we check the ov on the stack
+  // and continue to unwind if it is an error object, otherwise
+  // just execute the next instruction.
+  PUSH_CODE (INSTR::PUSH_NIL);
+  // For unwinding we need to keep track of the ov we pushed.
+  PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+  auto v_need_cleanup = POP_UNWIND_RETURN_TARGET ();
+  int n_need_cleanup = v_need_cleanup.size ();
+
+  std::vector<int> v_need_break;
+  if (D.m_break_stack_populated)
+    v_need_break = POP_BREAKS();
+
+  int n_need_break = v_need_break.size ();
+
+  // If there is a return statement inside the unwind body it need
+  // to jump to the cleanup code before the actual return. The return
+  // statement pushed a true ov to the stack, which is checked at the end of the
+  // cleanup code, since we use the same code for just falling throught too.
+  //
+  // The same applies to breaks, and also the combination of a possibility of
+  // breaks and returns.
+  int n_falses = 0;
+  if (n_need_break && n_need_cleanup)
+    {
+      n_falses = 2;
+      // These nils ov is the break and return  marker if we are falling
+      // through to the cleanup code from the body.
+      // We have an error object on the stack.
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ovs we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the break jumps that need to go to here
+      for (int need : v_need_break)
+        SET_CODE_SHORT (need, CODE_SIZE ());
+
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::PUSH_TRUE);// break marker
+      PUSH_CODE (INSTR::JMP);
+      int also_need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // Set the offset for all the return jumps that need to go to here
+      for (int need_cleanup : v_need_cleanup)
+        SET_CODE_SHORT (need_cleanup, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// return marker
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+
+      // If we were falling throught the body to the cleanup we jump to here
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+      SET_CODE_SHORT(also_need_after, CODE_SIZE ());
+    }
+  else if (n_need_break)
+    {
+      n_falses = 1;
+      // This nil ov is the break marker if we are falling through to the
+      // cleanup code from the body. We have an error object on the stack.
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ov we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the break jumps that need to go to here
+      for (int need : v_need_break)
+        SET_CODE_SHORT (need, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// break marker
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+  else if (n_need_cleanup)
+    {
+      n_falses = 1;
+      // This nil ov is the return marker if we are falling through to the
+      // cleanup code from the body
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::JMP); // We need to skip the pushes for the returns
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ov we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the jumps that need to go to here
+      for (int need_cleanup : v_need_cleanup)
+        SET_CODE_SHORT (need_cleanup, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// return marker
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+
+  // This is the end of protected code
+  UNWIND (D.m_idx_unwind).m_ip_end = CODE_SIZE ();
+
+  if (n_falses)
+    {
+      // Fallthrough code do not need false pushes
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      // An unwind will jump to here and needs some
+      // falses pushed to mark return or breaks
+      UNWIND (D.m_idx_unwind).m_ip_target = CODE_SIZE ();
+      for (int i = 0; i < n_falses; i++)
+        PUSH_CODE (INSTR::PUSH_FALSE);
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+  else
+    UNWIND (D.m_idx_unwind).m_ip_target = CODE_SIZE ();
+
+  // The body will just fall through into the unwind clean up code
+
+  // There might be breaks in the cleanup code too
+  if (D.m_break_stack_populated)
+    PUSH_BREAKS();
+
+  D.m_n_need_break = n_need_break;
+  D.m_n_need_cleanup = n_need_cleanup;
+}
+
+void
+bytecode_walker::emit_unwind_protect_code_end (emit_unwind_protect_data &D)
+{
+  std::vector<int> v_need_break_cleanup;
+  if (D.m_break_stack_populated)
+    v_need_break_cleanup = POP_BREAKS ();
+
+  if (v_need_break_cleanup.size ())
+    TODO ("break in cleanup code");
+
+  if (D.m_break_stack_populated)
+    {
+      // Restore the initial "need breaks"
+      PUSH_BREAKS ();
+      for (int offset : D.m_v_need_breaks_initial)
+        PUSH_NEED_BREAK (offset);
+    }
+
+  if (D.m_n_need_break && D.m_n_need_cleanup)
+    TODO ("Return and break nested");
+  if (D.m_n_need_break)
+    {
+      // The break ov marker is on the stack.
+      // If it is not true, we skip the break jump
+      PUSH_CODE (INSTR::JMP_IFN);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      POP_NESTING_STATEMENT (); // The jump ate the break marker
+
+      PUSH_CODE (INSTR::POP); // Pop the error object
+
+      // So, we break jump from here.
+      // The visitor for the loop will write to proper target
+      PUSH_CODE (INSTR::JMP);
+      int need_break = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      PUSH_NEED_BREAK (need_break); // Nesting loop need to know
+
+      // If we are not breaking we jump to here
+      SET_CODE_SHORT (need_after, CODE_SIZE ());
+    }
+  // Check if we are doing a return unwind
+  else if (D.m_n_need_cleanup)
+    {
+      // If we are in another unwind protect we need to jump to its cleanup
+      // code if the return ov marker is true
+      if (N_UNWIND_RETURN_TARGETS())
+        {
+          // The return ov marker is on the stack.
+          // If it is not true, we skip the "jump bridge"
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_after = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          POP_NESTING_STATEMENT (); // The jump ate the return marker
+
+          PUSH_CODE (INSTR::POP); // Pop the error object
+
+          PUSH_CODE (INSTR::JMP); // Jump to the nesting unwind protect
+          int need_unwind = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+          PUSH_A_UNWIND_RETURN_TARGET (need_unwind);
+
+          // If we are not returning we jump to here
+          SET_CODE_SHORT (need_after, CODE_SIZE ());
+        }
+      // Return if the return marker on the stack is true
+      else
+        {
+          // The return ov marker is on the stack.
+          // If it is not true, we skip the return
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_after = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          POP_NESTING_STATEMENT (); // The jump ate the return marker
+
+          // Generate code for a return
+          emit_return ();
+
+          // If we are not returning we jump to here
+          SET_CODE_SHORT (need_after, CODE_SIZE ());
+        }
+    }
+  // If there is an error object on top of the stack we
+  // need to continue unwinding.
+  PUSH_CODE (INSTR::THROW_IFERROBJ);
+
+  POP_NESTING_STATEMENT ();
+}
+
+void
+bytecode_walker::
+emit_unwind_protect_code (tree_statement_list *body,
+                          tree_statement_list *cleanup_code,
+                          tree_expression *body_expr,
+                          tree_expression *cleanup_expr,
+                          std::vector<int> cleanup_instructions)
+{
+  // Unwind protect has a body and cleanup part that always
+  // is executed.
+  //
+  // If the VM is unwinding it enters the cleanup code with an
+  // error object on the stack. The body puts a nil object on the
+  // stack.
+  //
+  // If there is an error object on the stack at the end of the cleanup
+  // code it rethrows it.
+  //
+  // Returns in the body jumps to the cleanup code before actually returning.
+  // If a return is reached in the body, a true object is pushed to the stack,
+  // which is checked in the cleanup code to know if we are falling through or
+  // are supposed to return.
+  //
+  // The same applies to breaks, so the code underneath gets abit messy.
+  //
+  // The body_expr, cleanup_expr and cleanup_instructions parameters are for
+  // when we need to emit some internal cleanup code that has no corrensponding
+  // unwind_protect in the user code.
+
+  int unwind_idx = N_UNWIND ();
+  PUSH_UNWIND();
+
+  UNWIND (unwind_idx).m_ip_start = CODE_SIZE ();
+
+  UNWIND (unwind_idx).m_unwind_entry_type =
+    unwind_entry_type::UNWIND_PROTECT;
+
+  UNWIND (unwind_idx).m_stack_depth = n_on_stack_due_to_stmt();
+
+  // Returns need to execute the unwind cleanup code before
+  // returning, so we need to keep track of offsets that need
+  // to jump to the cleanup code.
+  PUSH_UNWIND_RETURN_TARGETS ();
+
+  // We need to store away the pending "need breaks" since any break in the
+  // unwind protect body need to jump to the cleanup code.
+  std::vector<int> v_need_breaks_initial;
+  bool break_stack_populated = N_BREAKS ();
+  if (break_stack_populated)
+    {
+      v_need_breaks_initial = POP_BREAKS ();
+      PUSH_BREAKS ();
+    }
+
+  // Walk the body
+  if (body)
+    body->accept (*this);
+  if (body_expr)
+    body_expr->accept (*this);
+
+  // If the vm is unwinding it will push an error object to
+  // the stack. If we are just done executing the body we
+  // push a nil ov to the stack.
+  //
+  // At the end of the cleanup code we check the ov on the stack
+  // and continue to unwind if it is an error object, otherwise
+  // just execute the next instruction.
+  PUSH_CODE (INSTR::PUSH_NIL);
+  // For unwinding we need to keep track of the ov we pushed.
+  PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+  auto v_need_cleanup = POP_UNWIND_RETURN_TARGET ();
+  int n_need_cleanup = v_need_cleanup.size ();
+
+  std::vector<int> v_need_break;
+  if (break_stack_populated)
+    v_need_break = POP_BREAKS();
+
+  int n_need_break = v_need_break.size ();
+
+  // If there is a return statement inside the unwind body it need
+  // to jump to the cleanup code before the actual return. The return
+  // statement pushed a true ov to the stack, which is checked at the end of the
+  // cleanup code, since we use the same code for just falling throught too.
+  //
+  // The same applies to breaks, and also the combination of a possibility of
+  // breaks and returns.
+  int n_falses = 0;
+  if (n_need_break && n_need_cleanup)
+    {
+      n_falses = 2;
+      // These nils ov is the break and return  marker if we are falling
+      // through to the cleanup code from the body.
+      // We have an error object on the stack.
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ovs we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the break jumps that need to go to here
+      for (int need : v_need_break)
+        SET_CODE_SHORT (need, CODE_SIZE ());
+
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::PUSH_TRUE);// break marker
+      PUSH_CODE (INSTR::JMP);
+      int also_need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // Set the offset for all the return jumps that need to go to here
+      for (int need_cleanup : v_need_cleanup)
+        SET_CODE_SHORT (need_cleanup, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// return marker
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+
+      // If we were falling throught the body to the cleanup we jump to here
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+      SET_CODE_SHORT(also_need_after, CODE_SIZE ());
+    }
+  else if (n_need_break)
+    {
+      n_falses = 1;
+      // This nil ov is the break marker if we are falling through to the
+      // cleanup code from the body. We have an error object on the stack.
+      PUSH_CODE (INSTR::PUSH_FALSE); // break marker
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ov we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the break jumps that need to go to here
+      for (int need : v_need_break)
+        SET_CODE_SHORT (need, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// break marker
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+  else if (n_need_cleanup)
+    {
+      n_falses = 1;
+      // This nil ov is the return marker if we are falling through to the
+      // cleanup code from the body
+      PUSH_CODE (INSTR::PUSH_FALSE); // return marker
+      PUSH_CODE (INSTR::JMP); // We need to skip the pushes for the returns
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // For unwinding we need to keep track of the ov we pushed.
+      PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+      // Set the offset for all the jumps that need to go to here
+      for (int need_cleanup : v_need_cleanup)
+        SET_CODE_SHORT (need_cleanup, CODE_SIZE ());
+
+      PUSH_CODE (INSTR::PUSH_NIL); // error object
+      PUSH_CODE (INSTR::PUSH_TRUE);// return marker
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+
+  // This is the end of protected code
+  UNWIND (unwind_idx).m_ip_end = CODE_SIZE ();
+
+  if (n_falses)
+    {
+      // Fallthrough code do not need false pushes
+      PUSH_CODE (INSTR::JMP);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      // An unwind will jump to here and needs some
+      // falses pushed to mark return or breaks
+      UNWIND (unwind_idx).m_ip_target = CODE_SIZE ();
+      for (int i = 0; i < n_falses; i++)
+        PUSH_CODE (INSTR::PUSH_FALSE);
+
+      SET_CODE_SHORT(need_after, CODE_SIZE ());
+    }
+  else
+    UNWIND (unwind_idx).m_ip_target = CODE_SIZE ();
+
+  // The body will just fall through into the unwind clean up code
+
+  // There might be breaks in the cleanup code too
+  if (break_stack_populated)
+    PUSH_BREAKS();
+
+  // Walk the clean up code
+  if (cleanup_code)
+    cleanup_code->accept (*this);
+  if (cleanup_expr)
+    cleanup_expr->accept (*this);
+
+  // Used to e.g. always call op CLEAR_IGNORE_OUTPUTS
+  for (auto instr : cleanup_instructions)
+    PUSH_CODE (instr);
+
+  std::vector<int> v_need_break_cleanup;
+  if (break_stack_populated)
+    v_need_break_cleanup = POP_BREAKS ();
+
+  if (v_need_break_cleanup.size ())
+    TODO ("break in cleanup code");
+
+  if (break_stack_populated)
+    {
+      // Restore the initial "need breaks"
+      PUSH_BREAKS ();
+      for (int offset : v_need_breaks_initial)
+        PUSH_NEED_BREAK (offset);
+    }
+
+  if (n_need_break && n_need_cleanup)
+    TODO ("Return and break nested");
+  if (n_need_break)
+    {
+      // The break ov marker is on the stack.
+      // If it is not true, we skip the break jump
+      PUSH_CODE (INSTR::JMP_IFN);
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      POP_NESTING_STATEMENT (); // The jump ate the break marker
+
+      PUSH_CODE (INSTR::POP); // Pop the error object
+
+      // So, we break jump from here.
+      // The visitor for the loop will write to proper target
+      PUSH_CODE (INSTR::JMP);
+      int need_break = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      PUSH_NEED_BREAK (need_break); // Nesting loop need to know
+
+      // If we are not breaking we jump to here
+      SET_CODE_SHORT (need_after, CODE_SIZE ());
+    }
+  // Check if we are doing a return unwind
+  else if (n_need_cleanup)
+    {
+      // If we are in another unwind protect we need to jump to its cleanup
+      // code if the return ov marker is true
+      if (N_UNWIND_RETURN_TARGETS())
+        {
+          // The return ov marker is on the stack.
+          // If it is not true, we skip the "jump bridge"
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_after = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          POP_NESTING_STATEMENT (); // The jump ate the return marker
+
+          PUSH_CODE (INSTR::POP); // Pop the error object
+
+          PUSH_CODE (INSTR::JMP); // Jump to the nesting unwind protect
+          int need_unwind = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+          PUSH_A_UNWIND_RETURN_TARGET (need_unwind);
+
+          // If we are not returning we jump to here
+          SET_CODE_SHORT (need_after, CODE_SIZE ());
+        }
+      // Return if the return marker on the stack is true
+      else
+        {
+          // The return ov marker is on the stack.
+          // If it is not true, we skip the return
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_after = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          POP_NESTING_STATEMENT (); // The jump ate the return marker
+
+          // Generate code for a return
+          emit_return ();
+
+          // If we are not returning we jump to here
+          SET_CODE_SHORT (need_after, CODE_SIZE ());
+        }
+    }
+  // If there is an error object on top of the stack we
+  // need to continue unwinding.
+  PUSH_CODE (INSTR::THROW_IFERROBJ);
+
+  POP_NESTING_STATEMENT ();
+}
+
+void
+bytecode_walker::
+visit_unwind_protect_command (tree_unwind_protect_command& cmd)
+{
+  emit_unwind_protect_code (cmd.body (), cmd.cleanup ());
+}
+
+void
+bytecode_walker::
+visit_try_catch_command (tree_try_catch_command& cmd)
+{
+  // So we are in a try catch.
+  //
+  int unwind_idx = N_UNWIND ();
+  PUSH_UNWIND();
+
+  UNWIND (unwind_idx).m_ip_start = CODE_SIZE ();
+
+  UNWIND (unwind_idx).m_unwind_entry_type =
+    unwind_entry_type::TRY_CATCH;
+
+  tree_statement_list *try_code = cmd.body ();
+
+  // Walk the body for the code
+  if (try_code)
+    try_code->accept (*this);
+  // We need to jump past the catch code that will come after
+  PUSH_CODE (INSTR::JMP);
+  int need_after = CODE_SIZE ();
+  PUSH_CODE_SHORT (-1);
+
+  // Mark an end to the "try zone"
+  UNWIND (unwind_idx).m_ip_end = CODE_SIZE ();
+
+  // We put the catch code right after the try body
+  UNWIND (unwind_idx).m_ip_target = CODE_SIZE ();
+
+  // For loops add two native ints and one ov to the stack,
+  // and switches add one ov to the stack, so we need to
+  // record how many things we have added to the stack,
+  // from for loops and switches.
+  UNWIND (unwind_idx).m_stack_depth = n_on_stack_due_to_stmt ();
+
+  // The optional identifier "catch id"
+  tree_identifier *expr_id = cmd.identifier ();
+
+  // The unwind code in the vm will push an error object ...
+  if (expr_id)
+    {
+      // ... so assign it to the identifiers in its slot.
+      std::string name = expr_id->name ();
+      int slot = add_id_to_table (name);
+      MAYBE_PUSH_WIDE_OPEXT (slot);
+      PUSH_CODE (INSTR::ASSIGN);
+      PUSH_SLOT (slot);
+    }
+  else
+    {
+      // ... just pop the error object unceremoniously.
+      PUSH_CODE (INSTR::POP);
+    }
+
+  // Walk the catch code
+  tree_statement_list *catch_code = cmd.cleanup ();
+  if (catch_code)
+    catch_code->accept (*this);
+
+  // The body jumps to here
+  SET_CODE_SHORT (need_after, CODE_SIZE ());
+
+  return;
+}
+
+// For loops add two native ints and one ov to the stack,
+// and switches etc add one ov to the stack, so we need to
+// how how many things we have added to the stack
+int
+bytecode_walker::
+n_on_stack_due_to_stmt ()
+{
+  auto v = NESTING_STATEMENTS();
+  int n_things_on_stack = 0;
+  for (auto it = v.rbegin () ;it !=  v.rend (); it++)
+    {
+      nesting_statement t = *it;
+      switch (t)
+        {
+        case nesting_statement::FOR_LOOP:
+          n_things_on_stack += 3;
+          break;
+        case nesting_statement::ONE_OV_ON_STACK:
+          n_things_on_stack += 1;
+          break;
+        default:
+          ERR("Invalid state");
+        }
+    }
+
+  return n_things_on_stack;
+}
+
+void
+bytecode_walker::
+visit_decl_command (tree_decl_command& cmd)
+{
+  tree_decl_init_list *lst = cmd.initializer_list ();
+
+  CHECK_NONNULL (lst);
+
+  // A decl list might containt multiple declarations.
+  // E.g. "global a b = 3 c"
+  for (auto it = lst->begin (); it != lst->end (); it++)
+    {
+      tree_decl_elt *el = *it;
+      CHECK_NONNULL (el);
+
+      std::string name = el->name ();
+
+      int slot = add_id_to_table (name);
+
+      if (el->is_global () || el->is_persistent())
+        {
+          if (el->is_global ())
+            PUSH_GLOBAL (name);
+          if (el->is_persistent())
+            PUSH_PERSISTENT (name);
+
+          // Slot for variable to keep track off if the variable is actually
+          // a global. Prepended with "#" to not collide. "+" for persistent.
+          //
+          // We need this since the same identifier in a function can be both
+          // a local or a global depending on whether the global declare
+          // statement is reached or not.
+          //
+          // Since the name of the identifier that is declared global might
+          // allready be used as a local, we also need to store the slot number
+          // of the #-marker in the code too. If this feature is removed, we
+          // can save some space in the OP-codes making the slot number implicit
+          // +1.
+          std::string prefix;
+          if (el->is_global ())
+            prefix = "#";
+          else
+            prefix = "+";
+
+          int prefix_slot = add_id_to_table (prefix + name);
+
+          PUSH_CODE (INSTR::GLOBAL_INIT);
+          if (el->is_global ())
+            PUSH_CODE (global_type::GLOBAL);
+          else if (el->is_persistent ())
+            {
+              PUSH_CODE (global_type::PERSISTENT);
+              // We need a "offset" for the persistent variable that
+              // matches the exact offset the treewalker would use
+              tree_identifier *id = el->ident ();
+              CHECK_NONNULL (id);
+              int offset = id->symbol ().data_offset ();
+
+              CHECK (offset < 256); // TODO: Support more slots
+
+              // The VM need to know the special persistent variable offset
+              // so we store it in the unwind data
+              m_code.m_unwind_data.
+                m_slot_to_persistent_slot[slot] = offset;
+            }
+          PUSH_WSLOT (slot);
+          PUSH_WSLOT (prefix_slot);
+
+          tree_expression *expr = el->expression ();
+          bool has_init = expr;
+
+          PUSH_CODE (has_init); // has initialization code
+
+          // The global has an initialization expression
+          if (has_init)
+            {
+              // Placeholder for address to after init code.
+              // GLOBAL_INIT jumps to there if the global is
+              // already initialized.
+              int need_after = CODE_SIZE ();
+              PUSH_CODE_SHORT (-1);
+
+              // We want the value of the initialization on
+              // the operand stack.
+
+              INC_DEPTH();
+              PUSH_NARGOUT(1);
+
+              // Walk for the initialization code
+              expr->accept (*this);
+              // The value of rhs is on the operand stack now.
+              // So we need to write it to its local slot and then
+              // write that to its global value.
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::ASSIGN); // Write operand stack top ...
+              PUSH_SLOT (slot);   // to the local slot of the global
+
+              // I think only this makes sense
+              CHECK (DEPTH () == 1);
+
+              POP_NARGOUT ();
+              DEC_DEPTH ();
+
+              // Write the instruction address to the placeholder
+              SET_CODE_SHORT (need_after, CODE_SIZE ());
+            }
+        }
+      else
+        ERR ("Strange state");
+    }
+}
+
+void
+bytecode_walker::
+visit_postfix_expression (tree_postfix_expression& expr)
+{
+  INC_DEPTH();
+
+  tree_expression *e = expr.operand ();
+  CHECK_NONNULL (e);
+
+  octave_value::unary_op op = expr.op_type ();
+
+  int folded_need_after = -1;
+  int fold_slot = -1;
+  // Check if we should to a constant fold. It only makes sense in loops since the expression is folded at runtime.
+  // Essentially there is a PUSH_FOLDED_CST opcode that is tied to a cache. If the cache is valid, push it and jump
+  // past the initialization code, otherwise run the initialization code and set the cache with SET_FOLDED_CST
+  if (m_n_nested_loops && !m_is_folding && is_foldable_walker::is_foldable (expr))
+    {
+      m_is_folding = true;
+
+      std::string fold_name = "#cst_fold_" + std::to_string (m_n_folds++);
+      fold_slot = add_id_to_table (fold_name);
+
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::PUSH_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+      folded_need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+    }
+
+  int slot = -1;
+  // For ++ and -- we don't want a local pushed to the stack, but operate
+  // directly in the slot, and then pushing the slot.
+  if (e->is_identifier() && (op == octave_value::unary_op::op_decr ||
+                             op == octave_value::unary_op::op_incr))
+    {
+      // Just add the symbol to the table
+      // TODO: Could there be command function calls messing this up?
+      //       I.e. foo++ could be a foo()++?
+      slot = add_id_to_table (e->name ());
+    }
+  // We handle e.g. m("qwe")++ with eval
+  else if (op != octave_value::unary_op::op_incr && op != octave_value::unary_op::op_decr)
+    {
+      PUSH_NARGOUT (1);
+      e->accept (*this);
+      POP_NARGOUT ();
+    }
+
+  switch (op)
+    {
+    case octave_value::unary_op::op_not:
+      PUSH_CODE (INSTR::NOT);
+      break;
+    case octave_value::unary_op::op_uplus:
+      PUSH_CODE (INSTR::UADD);
+      break;
+    case octave_value::unary_op::op_uminus:
+      PUSH_CODE (INSTR::USUB);
+      break;
+    case octave_value::unary_op::op_transpose:
+      PUSH_CODE (INSTR::TRANS);
+      break;
+    case octave_value::unary_op::op_hermitian:
+      PUSH_CODE (INSTR::HERM);
+      break;
+    case octave_value::unary_op::op_incr:
+      {
+        if (! e->is_identifier ())
+          {
+            // TODO: Cheating with eval
+            PUSH_TREE_FOR_EVAL (&expr);
+            int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+            PUSH_CODE (INSTR::EVAL);
+            PUSH_CODE (NARGOUT ());
+            PUSH_CODE_INT (tree_idx);
+          }
+        else
+          {
+            MAYBE_PUSH_WIDE_OPEXT (slot);
+            PUSH_CODE (INSTR::INCR_ID_POSTFIX);
+            PUSH_SLOT (slot);
+          }
+      }
+      break;
+    case octave_value::unary_op::op_decr:
+      {
+        if (! e->is_identifier ())
+          {
+            // TODO: Cheating with eval
+            PUSH_TREE_FOR_EVAL (&expr);
+            int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+            PUSH_CODE (INSTR::EVAL);
+            PUSH_CODE (NARGOUT ());
+            PUSH_CODE_INT (tree_idx);
+          }
+        else
+          {
+            MAYBE_PUSH_WIDE_OPEXT (slot);
+            PUSH_CODE (INSTR::DECR_ID_POSTFIX);
+            PUSH_SLOT (slot);
+          }
+      }
+      break;
+    default:
+      TODO ("not covered");
+    }
+
+  if (fold_slot != -1)
+    {
+      m_is_folding = false;
+
+      PUSH_CODE (INSTR::DUP);
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::SET_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+
+      SET_CODE_SHORT (folded_need_after, CODE_SIZE ());
+    }
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_prefix_expression (tree_prefix_expression& expr)
+{
+  INC_DEPTH();
+
+  tree_expression *e = expr.operand ();
+  CHECK_NONNULL (e);
+
+  octave_value::unary_op op = expr.op_type ();
+
+  int folded_need_after = -1;
+  int fold_slot = -1;
+  // Check if we should to a constant fold. It only makes sense in loops since the expression is folded at runtime.
+  // Essentially there is a PUSH_FOLDED_CST opcode that is tied to a cache. If the cache is valid, push it and jump
+  // past the initialization code, otherwise run the initialization code and set the cache with SET_FOLDED_CST
+  if (m_n_nested_loops && !m_is_folding && is_foldable_walker::is_foldable (expr))
+    {
+      m_is_folding = true;
+
+      std::string fold_name = "#cst_fold_" + std::to_string (m_n_folds++);
+      fold_slot = add_id_to_table (fold_name);
+
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::PUSH_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+      folded_need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+    }
+
+  int slot = -1;
+  // For ++ and -- we don't want a local pushed to the stack, but operate
+  // directly in the slot, and then pushing the slot.
+  if (e->is_identifier() && (op == octave_value::unary_op::op_decr ||
+                             op == octave_value::unary_op::op_incr))
+    {
+      // Just add the symbol to the table
+      // TODO: Could there be command function calls messing this up?
+      //       I.e. foo++ could be a foo()++?
+      slot = add_id_to_table (e->name ());
+    }
+  // We handle e.g. m("qwe")++ with eval
+  else if (op != octave_value::unary_op::op_incr && op != octave_value::unary_op::op_decr)
+    {
+      PUSH_NARGOUT (1);
+      e->accept (*this);
+      POP_NARGOUT ();
+    }
+
+  switch (op)
+    {
+    case octave_value::unary_op::op_not:
+      PUSH_CODE (INSTR::NOT);
+      break;
+    case octave_value::unary_op::op_uplus:
+      PUSH_CODE (INSTR::UADD);
+      break;
+    case octave_value::unary_op::op_uminus:
+      PUSH_CODE (INSTR::USUB);
+      break;
+    case octave_value::unary_op::op_transpose:
+      PUSH_CODE (INSTR::TRANS);
+      break;
+    case octave_value::unary_op::op_hermitian:
+      PUSH_CODE (INSTR::HERM);
+      break;
+    case octave_value::unary_op::op_incr:
+      {
+        if (! e->is_identifier ())
+          {
+            // TODO: Cheating with eval
+            PUSH_TREE_FOR_EVAL (&expr);
+            int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+            PUSH_CODE (INSTR::EVAL);
+            PUSH_CODE (NARGOUT ());
+            PUSH_CODE_INT (tree_idx);
+          }
+        else
+          {
+            MAYBE_PUSH_WIDE_OPEXT (slot);
+            PUSH_CODE (INSTR::INCR_ID_PREFIX);
+            PUSH_SLOT (slot);
+          }
+      }
+      break;
+    case octave_value::unary_op::op_decr:
+      {
+        if (! e->is_identifier ())
+          {
+            // TODO: Cheating with eval
+            PUSH_TREE_FOR_EVAL (&expr);
+            int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+            PUSH_CODE (INSTR::EVAL);
+            PUSH_CODE (NARGOUT ());
+            PUSH_CODE_INT (tree_idx);
+          }
+        else
+          {
+            MAYBE_PUSH_WIDE_OPEXT (slot);
+            PUSH_CODE (INSTR::DECR_ID_PREFIX);
+            PUSH_SLOT (slot);
+          }
+      }
+      break;
+    default:
+      TODO ("not covered");
+    }
+
+  if (fold_slot != -1)
+    {
+      m_is_folding = false;
+
+      PUSH_CODE (INSTR::DUP);
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::SET_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+
+      SET_CODE_SHORT (folded_need_after, CODE_SIZE ());
+    }
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_boolean_expression(tree_boolean_expression& expr)
+{
+  INC_DEPTH ();
+  PUSH_NARGOUT (1);
+
+  // Since the || and && has short circuit behavoir
+  // we need to built up the expression from multiple opcodes.
+  //
+  // Note that UNARY_TRUE accepts operands that are not
+  // "is_defined ()" where as IF or IF_N would error on those,
+  // so we need UNARY_TRUE before the IFs.
+  if (expr.op_type() == tree_boolean_expression::bool_and)
+    {
+      // We want lhs on the operand stack
+      tree_expression *op1 = expr.lhs ();
+      CHECK_NONNULL (op1);
+      op1->accept (*this);
+
+      // If false, jump to push false
+      PUSH_CODE (INSTR::UNARY_TRUE);
+      PUSH_CODE (INSTR::JMP_IFN);
+      int need_false0 = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // If lhs was true, we want rhs on the
+      // operand stack too.
+      tree_expression *op2 = expr.rhs ();
+      CHECK_NONNULL (op2);
+      op2->accept (*this);
+
+      // If false, jump to push false
+      PUSH_CODE (INSTR::UNARY_TRUE);
+      PUSH_CODE (INSTR::JMP_IFN);
+      int need_false1 = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // If both lhs and rhs was true,
+      // we fallthrough to push true
+      PUSH_CODE (INSTR::PUSH_TRUE);
+      PUSH_CODE (INSTR::JMP); // Jump past PUSH_FALSE
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // The 2 JMP_IFN goes here, to PUSH_FALSE
+      int offset_false = CODE_SIZE ();
+      PUSH_CODE (INSTR::PUSH_FALSE);
+      // The JMP after PUSH_TRUE goes here
+
+      // Set the addresses for the false jumps
+      SET_CODE_SHORT (need_false0, offset_false);
+      SET_CODE_SHORT (need_false1, offset_false);
+      // The true push jumps to after
+      SET_CODE_SHORT (need_after, CODE_SIZE ());
+    }
+  else
+    {
+      // We want lhs on the operand stack
+      tree_expression *op1 = expr.lhs ();
+      CHECK_NONNULL (op1);
+      op1->accept (*this);
+
+      // If true, jump to push true
+      PUSH_CODE (INSTR::UNARY_TRUE);
+      PUSH_CODE (INSTR::JMP_IF);
+      int need_true0 = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // If lhs was false, we want rhs on the
+      // operand stack too.
+      tree_expression *op2 = expr.rhs ();
+      CHECK_NONNULL (op2);
+      op2->accept (*this);
+
+      // If true, jump to push true
+      PUSH_CODE (INSTR::UNARY_TRUE);
+      PUSH_CODE (INSTR::JMP_IF);
+      int need_true1 = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // If both lhs and rhs were false,
+      // we fallthrough to here, push false
+      PUSH_CODE (INSTR::PUSH_FALSE);
+      PUSH_CODE (INSTR::JMP); // Jump past PUSH_TRUE
+      int need_after = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+
+      // The 2 JMP_IF goes here, to PUSH_TRUE
+      int offset_true = CODE_SIZE ();
+      PUSH_CODE (INSTR::PUSH_TRUE);
+      // The JMP after PUSH_FALSE goes here
+
+      // Set the addresses for the true jumps
+      SET_CODE_SHORT (need_true0, offset_true);
+      SET_CODE_SHORT (need_true1, offset_true);
+      // The false push jumps to after
+      SET_CODE_SHORT (need_after, CODE_SIZE ());
+    }
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  DEC_DEPTH ();
+  POP_NARGOUT ();
+}
+
+void
+bytecode_walker::
+visit_compound_binary_expression (tree_compound_binary_expression &expr)
+{
+  // Compound expression are expression that are more effeicient to
+  // do fused for a matrix, like M'*A etc.
+  INC_DEPTH();
+  PUSH_NARGOUT (1);
+
+  tree_expression *op1 = expr.clhs ();
+
+  CHECK_NONNULL (op1);
+  op1->accept (*this);
+
+  tree_expression *op2 = expr.crhs ();
+
+  CHECK_NONNULL (op2);
+  op2->accept (*this);
+
+  switch (expr.cop_type ())
+    {
+    case octave_value::compound_binary_op::op_trans_mul:
+      PUSH_CODE (INSTR::TRANS_MUL);
+      break;
+    case octave_value::compound_binary_op::op_mul_trans:
+      PUSH_CODE (INSTR::MUL_TRANS);
+      break;
+    case octave_value::compound_binary_op::op_herm_mul:
+      PUSH_CODE (INSTR::HERM_MUL);
+      break;
+    case octave_value::compound_binary_op::op_mul_herm:
+      PUSH_CODE (INSTR::MUL_HERM);
+      break;
+    case octave_value::compound_binary_op::op_trans_ldiv:
+      PUSH_CODE (INSTR::TRANS_LDIV);
+      break;
+    case octave_value::compound_binary_op::op_herm_ldiv:
+      PUSH_CODE (INSTR::HERM_LDIV);
+      break;
+    default:
+      TODO ("not covered");
+    }
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  POP_NARGOUT ();
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_binary_expression (tree_binary_expression& expr)
+{
+  INC_DEPTH ();
+  PUSH_NARGOUT (1);
+
+  std::vector<int> need_after;
+  int fold_slot = -1;
+
+  // "&" and "|" have a braindead short circuit behavoiur when
+  // in if or while conditions, so we need special handling of those.
+  if (expr.is_braindead ())
+    {
+      if (expr.op_type() == octave_value::binary_op::op_el_and)
+        {
+          // We use a slot to store whether a warning has been issued
+          // or not
+          std::string id_warning = "%braindead_warning_" +
+            std::to_string(CODE_SIZE ());
+          int slot = add_id_to_table(id_warning);
+
+          // The left most expression is always evaled
+          tree_expression *op1 = expr.lhs ();
+
+          CHECK_NONNULL (op1);
+          op1->accept (*this);
+
+          // We need to check if lhs value is scalar
+          PUSH_CODE (INSTR::DUP);
+          PUSH_CODE (INSTR::BRAINDEAD_PRECONDITION);
+
+          // If the precondition is not true, we do a
+          // normal binop. Note that lhs is evaled twice
+          // since that is what the treewalker does.
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_target_not_braindead = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          // Now we do the braindead short circuit
+
+          // If the lhs expression is true we check the rhs
+          PUSH_CODE (INSTR::UNARY_TRUE);
+          PUSH_CODE (INSTR::JMP_IF);
+          int need_target_true = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          // The lhs was false which means we need to issue a warning
+          // and push a false
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::BRAINDEAD_WARNING);
+          PUSH_SLOT (slot);
+          PUSH_CODE ('&'); // The operand type to print in the warning
+          PUSH_CODE (INSTR::PUSH_FALSE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // If lhs was true we jump to here
+          SET_CODE_SHORT (need_target_true, CODE_SIZE ());
+          // Walk rhs
+          tree_expression *op2 = expr.rhs ();
+
+          CHECK_NONNULL (op2);
+          op2->accept (*this);
+
+          // With rhs on the stack, check if it is true and jump to
+          // a true push, otherwise push false and jump to after
+          PUSH_CODE (INSTR::UNARY_TRUE);
+          PUSH_CODE (INSTR::JMP_IF);
+          need_target_true = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          // Push false jump to after
+          PUSH_CODE (INSTR::PUSH_FALSE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // Push true jump to after
+          SET_CODE_SHORT (need_target_true, CODE_SIZE ());
+          PUSH_CODE (INSTR::PUSH_TRUE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // If the precondition was false we need to do the ordinary binary op
+          SET_CODE_SHORT (need_target_not_braindead, CODE_SIZE ());
+          PUSH_CODE (INSTR::POP); // Pop the evaled lhs value
+        }
+      else if (expr.op_type() == octave_value::binary_op::op_el_or)
+        {
+          // We use a slot to store whether a warning has been issued
+          // or not
+          std::string id_warning = "%braindead_warning_" +
+            std::to_string(CODE_SIZE ());
+          int slot = add_id_to_table(id_warning);
+
+          // The left most expression is always evaled
+          tree_expression *op1 = expr.lhs ();
+
+          CHECK_NONNULL (op1);
+          op1->accept (*this);
+
+          // We need to check if lhs value is scalar
+          PUSH_CODE (INSTR::DUP);
+          PUSH_CODE (INSTR::BRAINDEAD_PRECONDITION);
+
+          // If the precondition is not true, we do a
+          // normal binop. Note that lhs is evaled twice
+          // since that is what the treewalker does.
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_target_not_braindead = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          // Now we do the braindead short circuit for "or"
+
+          // If the lhs expression is true we issue a
+          // warning, push a true and jump to after.
+          // If lhs is false we instead need to check rhs too.
+          PUSH_CODE (INSTR::UNARY_TRUE);
+          PUSH_CODE (INSTR::JMP_IFN);
+          int need_target_check_rhs = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::BRAINDEAD_WARNING);
+          PUSH_SLOT (slot);
+          PUSH_CODE ('|'); // The operand type to print in the warning
+          PUSH_CODE (INSTR::PUSH_TRUE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // If lhs was false we jump to here
+          SET_CODE_SHORT (need_target_check_rhs, CODE_SIZE ());
+          // Walk rhs
+          tree_expression *op2 = expr.rhs ();
+
+          CHECK_NONNULL (op2);
+          op2->accept (*this);
+
+          // With rhs on the stack, check if it is true and jump to
+          // a true push, otherwise push false and jump to after
+          PUSH_CODE (INSTR::UNARY_TRUE);
+          PUSH_CODE (INSTR::JMP_IF);
+          int need_target_true = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1);
+
+          // Push false jump to after
+          PUSH_CODE (INSTR::PUSH_FALSE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // Push true jump to after
+          SET_CODE_SHORT (need_target_true, CODE_SIZE ());
+          PUSH_CODE (INSTR::PUSH_TRUE);
+          PUSH_CODE (INSTR::JMP);
+          need_after.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1);
+
+          // If the precondition was false we need to do the ordinary binary op
+          SET_CODE_SHORT (need_target_not_braindead, CODE_SIZE ());
+          PUSH_CODE (INSTR::POP); // Pop the evaled lhs value
+        }
+      else
+        panic_impossible ();
+    }
+  // Check if we should to a constant fold. It only makes sense in loops since the expression is folded at runtime.
+  // Essentially there is a PUSH_FOLDED_CST opcode that is tied to a cache. If the cache is valid, push it and jump
+  // past the initialization code, otherwise run the initialization code and set the cache with SET_FOLDED_CST
+  else if (m_n_nested_loops && !m_is_folding && is_foldable_walker::is_foldable (expr))
+    {
+      m_is_folding = true;
+
+      std::string fold_name = "#cst_fold_" + std::to_string (m_n_folds++);
+      fold_slot = add_id_to_table (fold_name);
+
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::PUSH_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+      need_after.push_back (CODE_SIZE ());
+      PUSH_CODE_SHORT (-1);
+    }
+
+  tree_expression *op1 = expr.lhs ();
+  tree_expression *op2 = expr.rhs ();
+  CHECK_NONNULL (op1);
+  CHECK_NONNULL (op2);
+
+  if (op1->is_constant () && op2->is_constant () && DATA_SIZE () < 255)
+    {
+      // If both rhs and lhs are constants we want to emit a super op-code
+      // aslong as the WIDE op is not going to be used (<255)
+      emit_load_2_cst (op1, op2);
+    }
+  else
+    {
+      op1->accept (*this);
+      op2->accept (*this);
+    }
+
+  switch (expr.op_type ())
+    {
+    case octave_value::binary_op::op_mul:
+      PUSH_CODE (INSTR::MUL);
+      break;
+    case octave_value::binary_op::op_div:
+      PUSH_CODE (INSTR::DIV);
+      break;
+    case octave_value::binary_op::op_add:
+      PUSH_CODE (INSTR::ADD);
+      break;
+    case octave_value::binary_op::op_sub:
+      PUSH_CODE (INSTR::SUB);
+      break;
+    case octave_value::binary_op::op_lt:
+      PUSH_CODE (INSTR::LE);
+      break;
+    case octave_value::binary_op::op_le:
+      PUSH_CODE (INSTR::LE_EQ);
+      break;
+    case octave_value::binary_op::op_gt:
+      PUSH_CODE (INSTR::GR);
+      break;
+    case octave_value::binary_op::op_ge:
+      PUSH_CODE (INSTR::GR_EQ);
+      break;
+    case octave_value::binary_op::op_eq:
+      PUSH_CODE (INSTR::EQ);
+      break;
+    case octave_value::binary_op::op_ne:
+      PUSH_CODE (INSTR::NEQ);
+      break;
+    case octave_value::binary_op::op_pow:
+      PUSH_CODE (INSTR::POW);
+      break;
+    case octave_value::binary_op::op_ldiv:
+      PUSH_CODE (INSTR::LDIV);
+      break;
+    case octave_value::binary_op::op_el_mul:
+      PUSH_CODE (INSTR::EL_MUL);
+      break;
+    case octave_value::binary_op::op_el_div:
+      PUSH_CODE (INSTR::EL_DIV);
+      break;
+    case octave_value::binary_op::op_el_pow:
+      PUSH_CODE (INSTR::EL_POW);
+      break;
+    case octave_value::binary_op::op_el_and:
+      PUSH_CODE (INSTR::EL_AND);
+      break;
+    case octave_value::binary_op::op_el_or:
+      PUSH_CODE (INSTR::EL_OR);
+      break;
+    case octave_value::binary_op::op_el_ldiv:
+      PUSH_CODE (INSTR::EL_LDIV);
+      break;
+
+    default:
+      TODO ("not covered");
+    }
+
+  if (fold_slot != -1)
+    {
+      m_is_folding = false;
+
+      PUSH_CODE (INSTR::DUP);
+      MAYBE_PUSH_WIDE_OPEXT (fold_slot);
+      PUSH_CODE (INSTR::SET_FOLDED_CST);
+      PUSH_SLOT (fold_slot);
+    }
+
+  for (int offset : need_after)
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  POP_NARGOUT ();
+
+  DEC_DEPTH ();
+}
+
+void
+
+bytecode_walker::
+emit_load_2_cst (tree_expression *lhs, tree_expression *rhs)
+{
+  INC_DEPTH();
+
+  CHECK (DEPTH () > 1);
+
+  CHECK (lhs); CHECK (rhs);
+  CHECK (lhs->is_constant ());
+  CHECK (rhs->is_constant ());
+
+  tree_constant *lhs_cst = static_cast<tree_constant *> (lhs);
+  tree_constant *rhs_cst = static_cast<tree_constant *> (rhs);
+
+  octave_value ov_lhs = lhs_cst->value ();
+  octave_value ov_rhs = rhs_cst->value ();
+
+  PUSH_DATA (ov_lhs);
+  PUSH_DATA (ov_rhs);
+
+  unsigned cst_offset = DATA_SIZE () - 1;
+  CHECK (cst_offset < 256);
+
+  PUSH_CODE (INSTR::LOAD_2_CST);
+  PUSH_CODE (cst_offset - 1); // Offset of lhs
+
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_constant (tree_constant& cst)
+{
+  INC_DEPTH();
+
+  octave_value ov_cst = cst.value ();
+
+  bool specialized = false;
+  if (ov_cst.type_id () == octave_scalar::static_type_id ())
+    {
+      double val = ov_cst.double_value ();
+      if (val == 0)
+      {
+          specialized = true;
+          PUSH_CODE (INSTR::PUSH_DBL_0);
+      }
+      else if (val == 1)
+      {
+          specialized = true;
+          PUSH_CODE (INSTR::PUSH_DBL_1);
+      }
+      else if (val == 2)
+      {
+          specialized = true;
+          PUSH_CODE (INSTR::PUSH_DBL_2);
+      }
+    }
+
+  if (!specialized)
+    {
+      PUSH_DATA (ov_cst);
+      PUSH_CODE_LOAD_CST (DATA_SIZE () - 1); // Offset of the constant
+    }
+
+  maybe_emit_bind_ans_and_disp (cst);
+
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_octave_user_function (octave_user_function& fcn)
+{
+  m_code.m_unwind_data.m_name = fcn.name ();
+  m_code.m_unwind_data.m_file = fcn.fcn_file_name ();
+  PUSH_DATA (fcn.name ());
+  PUSH_DATA (std::string {"user-function"});
+  PUSH_DATA (fcn.profiler_name ());
+
+  tree_statement_list *cmd_list = fcn.body ();
+  tree_parameter_list *returns = fcn.return_list();
+  tree_parameter_list *paras = fcn.parameter_list ();
+
+  std::vector<std::string> v_paras;
+  if (paras) // paras is 0 if function args are missing, e.g. "function foo\nend"
+    {
+      for (auto it = paras->begin (); it != paras->end (); it++)
+        {
+          CHECK_NONNULL (*it);
+          CHECK ((*it)->ident ());
+          v_paras.push_back ((*it)->name ());
+        }
+    }
+
+  // Does the function output varargout?
+  m_varargout = returns->takes_varargs ();
+  // "varargout" is not in the 'returns' list (if in the proper last position)
+  // so add one to size if 'm_varargout' is true
+  int n_returns = returns ? returns->size () + m_varargout: 0;
+
+  // The first instruction is the amount of return variables. Negative for varargout.
+  // +1 for native '%nargout' on the stack
+  PUSH_CODE (m_varargout ? -(n_returns + 1) : (n_returns + 1));
+
+  // Check if the last parameter is "varargin"
+  // If that is the case, we need to mess with the stacks
+  // in the vm, so mark the function as having negative
+  // amount of parameters.
+  bool is_varargin = paras ? paras->takes_varargs () : false;
+
+  // varargin is not among the parameter_lists elements, so
+  // add it to the vector of parameter names
+  if (is_varargin)
+    v_paras.push_back("varargin");
+
+  // The second instruction is the amount of arguments
+  int n_paras = v_paras.size ();
+  PUSH_CODE (is_varargin ? -n_paras : n_paras);
+
+  // The third is the amount of locals, which need to be set
+  // after compiling the function. So we need to store the offset
+  // to it for later
+  m_offset_n_locals = CODE_SIZE ();
+  PUSH_CODE (-1); // Placeholder
+  PUSH_CODE (-1);
+
+  // The first slot is a native int represenation nargout
+  // so we add a dummy slot object for it
+  add_id_to_table("%nargout");
+
+  // Then the return values
+  for (auto it = returns->begin (); it != returns->end (); it++)
+    {
+      std::string name = (*it)->name();
+      tree_identifier *id = (*it)->ident ();
+      CHECK_NONNULL (id);
+      add_id_to_table (id->name ());
+    }
+  if (m_varargout)
+    add_id_to_table ("varargout"); // Not in the returns list. Need to be last
+
+  // The function itself is put after the arg outs
+  /* add_id_to_table (fcn.name ()); */
+
+  // Then the arguments
+  for (std::string name : v_paras)
+    {
+      if (m_map_locals_to_slot.find (name) !=
+          m_map_locals_to_slot.end ())
+        {
+          // So the parameter is also a return value
+          // so we need to push it and assign
+          // it to the return value, since the caller
+          // will write the argument to the argument slot.
+          //
+          // We give the parameter a dummy name so it
+          // still occupies a slot, and assigns a dummy
+          // object to it after we copied it to the return
+          // slot.
+
+          std::string dummy_name = "!" + name;
+          int slot_dummy = add_id_to_table (dummy_name);
+
+          // PUSH_SLOT_INDEXED just pushes and does not check
+          // for doing a cmd function call.
+          MAYBE_PUSH_WIDE_OPEXT (slot_dummy);
+          PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+          PUSH_SLOT (slot_dummy);
+          int slot = SLOT (name);
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::FORCE_ASSIGN); // Accepts undefined rhs
+          PUSH_SLOT (slot);
+          PUSH_CODE (INSTR::PUSH_FALSE); // False will do
+          MAYBE_PUSH_WIDE_OPEXT (slot_dummy);
+          PUSH_CODE (INSTR::ASSIGN);
+          PUSH_SLOT (slot_dummy);
+
+          continue;
+        }
+
+      add_id_to_table (name);
+    }
+
+  // We always need the magic id "ans"
+  add_id_to_table ("ans");
+
+  // We add all identifiers in the body to the id-table. We also
+  // make a map mapping the interpreters frame offset of a id
+  // to the frame offset in the bytecode VM frame.
+  if (cmd_list)
+    {
+      auto v_names_offsets = collect_idnames_walker::collect_id_names (*cmd_list);
+
+      for (auto name_offset : v_names_offsets)
+        {
+          std::string name = name_offset.first;
+          int frame_offset = name_offset.second;
+          add_id_to_table (name_offset.first);
+          int slot = SLOT (name);
+
+          m_code.m_unwind_data.m_external_frame_offset_to_internal[frame_offset] = slot;
+        }
+    }
+  // We need the arguments and return id:s in the map too.
+  if (paras)
+    {
+      for (auto it = paras->begin (); it != paras->end (); it++)
+        {
+          CHECK_NONNULL (*it);
+          tree_identifier *id = (*it)->ident ();
+          int frame_offset = id->symbol ().data_offset ();
+          int slot = SLOT (id->name ());
+          m_code.m_unwind_data.m_external_frame_offset_to_internal[frame_offset] = slot;
+
+          // If the parameter has an init expression e.g.
+          // "function foo (a = sin (pi))"
+          // , we need to search it for id:s too.
+          tree_expression *init_expr = (*it)->expression ();
+          if (init_expr)
+            {
+              auto v_names_offsets = collect_idnames_walker::collect_id_names (*init_expr);
+              for (auto name_offset : v_names_offsets)
+                {
+                  std::string name = name_offset.first;
+                  int frame_offset_i = name_offset.second;
+                  add_id_to_table (name_offset.first);
+                  int slot_i = SLOT (name);
+
+                  m_code.m_unwind_data.m_external_frame_offset_to_internal[frame_offset_i] = slot_i;
+                }
+            }
+        }
+    }
+  for (auto it = returns->begin (); it != returns->end (); it++)
+    {
+      std::string name = (*it)->name();
+      tree_identifier *id = (*it)->ident ();
+      int frame_offset = id->symbol ().data_offset ();
+      int slot = SLOT (name);
+      m_code.m_unwind_data.m_external_frame_offset_to_internal[frame_offset] = slot;
+    }
+
+  // The function name should be in the frame as an id too aswell
+  // as 'varargin', 'varargout' and 'ans'.
+  //
+  // 'ans' is allready added to the id table and 'varargin' and 'varargout' too
+  // if they are used, but we don't have their external offset.
+  //
+  // The function name is not added to the id table yet.
+  //
+  // Note that there might be symbols added to the original scope by
+  // eg. eval ("foo = 3"). We just ignore those.
+  std::string function_name = fcn.name ();
+  auto dot_idx = function_name.find_last_of ('.'); // Names might be e.g. "get.Count" but we only want "Count"
+  if (dot_idx != std::string::npos)
+    function_name = function_name.substr (dot_idx + 1);
+
+  // We need to keep track of which id is the function name so that
+  // we can add the id to the id-table and get it's external offset.
+  //
+  // Note that the file 'bar.m' can have one function with the id name 'foo'
+  // which will be added to the scope by the parser, but the function name
+  // and thus call-name is 'bar'.
+  std::size_t idx_fn_name = n_returns + 1; // "+1" since 'ans' is always added first
+
+  for (auto p : fcn.scope ().symbols ())
+    {
+      std::string name = p.first;
+      symbol_record sym = p.second;
+      std::size_t offset = sym.data_offset ();
+
+      bool is_fn_id = offset == idx_fn_name; // Are we at the function name id?
+
+      auto it = m_map_locals_to_slot.find (name);
+      if (it == m_map_locals_to_slot.end ())
+        {
+          if (is_fn_id)
+            {
+              // Add the function name id to the table and add the correct external offset.
+              // (The name might not be the call-name of the function.)
+              int slot = add_id_to_table (name);
+              m_code.m_unwind_data.m_external_frame_offset_to_internal[offset] = slot;
+            }
+          else
+            continue;
+        }
+
+      if (name == "varargin")
+        m_code.m_unwind_data.m_external_frame_offset_to_internal[offset] = SLOT ("varargin");
+      else if (name == "varargout")
+        m_code.m_unwind_data.m_external_frame_offset_to_internal[offset] = SLOT ("varargout");
+      else if (name == "ans")
+        m_code.m_unwind_data.m_external_frame_offset_to_internal[offset] = SLOT ("ans");
+    }
+
+  // Add code to handle default arguments. If an argument is undefined or
+  // "magic colon" it is to get its default value.
+  if (paras)
+    {
+      for (auto it = paras->begin (); it != paras->end (); it++)
+        {
+          tree_expression *init_expr = (*it)->expression ();
+          // TODO: Default init for varargin?
+
+          if (init_expr)
+            {
+              // There is a default arg.
+
+              std::string name = (*it)->name ();
+              int slot = SLOT (name);
+
+              // Push the arg to the operand stack from its slot
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+              PUSH_SLOT (slot);
+              // If it is undefined or "Magic colon", execute the init code
+              // otherwise jump past it.
+              PUSH_CODE (INSTR::JMP_IFDEF);
+              int need_after = CODE_SIZE ();
+              PUSH_CODE_SHORT (-1); // Placeholder
+
+              INC_DEPTH();
+              PUSH_NARGOUT(1); // nargout is 1 for simple assignments
+
+              // Walk for the rhs code
+              init_expr->accept (*this);
+
+              // The value of rhs is now on the operand stack. Assign it
+              // to the arg.
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::ASSIGN);
+              PUSH_SLOT (slot);
+
+              POP_NARGOUT ();
+              DEC_DEPTH();
+
+              // The jump need to go here, if the argument is defined, so
+              // set the placeholder from above.
+              SET_CODE_SHORT (need_after, CODE_SIZE ());
+            }
+        }
+    }
+
+  CHECK_NONNULL (cmd_list);
+  cmd_list->accept (*this);
+
+  // Set the amount of locals that has a placeholder since earlier
+  SET_CODE_SHORT (m_offset_n_locals, m_n_locals);
+
+  // We want to add the locals to the scope in slot order
+  // so we push all the locals' names to a vector by their slot
+  // number
+  unsigned n_slots = m_map_locals_to_slot.size ();
+  CHECK (n_slots == static_cast<unsigned> (m_n_locals));
+  std::vector<std::string> names (n_slots);
+
+  auto iter = m_map_locals_to_slot.begin ();
+  for (unsigned i = 0; i < n_slots; i++)
+    {
+      auto kv = *iter++;
+
+      const std::string& name = kv.first;
+      int slot = kv.second;
+
+      CHECK (slot >= 0 && slot < static_cast<int> (n_slots));
+      CHECK (names[slot] == ""); // Check not duplicate slot number used
+
+      names[slot] = name;
+    }
+
+  // Check that the mapping between external offsets and internal slots has no holes in it
+  int i = 0;
+  for (auto it : m_code.m_unwind_data.m_external_frame_offset_to_internal)
+    {
+      int external_offset = it.first;
+      CHECK (external_offset == i);
+      i++;
+    }
+
+  // The profiler needs to know these sizes when copying from pointers.
+  m_code.m_unwind_data.m_code_size = m_code.m_code.size ();
+  m_code.m_unwind_data.m_ids_size = m_code.m_ids.size ();
+}
+
+void
+bytecode_walker::
+visit_multi_assignment (tree_multi_assignment& expr)
+{
+  INC_DEPTH();
+  int outer_nargout = NARGOUT ();
+
+  tree_argument_list *lhs = expr.left_hand_side ();
+
+  // Lists are annoying, move lhs elements to a vector
+  std::vector<tree_expression *> v_lhs;
+  for (auto it = lhs->begin (); it != lhs->end (); it++)
+    {
+      CHECK_NONNULL(*it);
+      v_lhs.push_back (*it);
+    }
+
+  CHECK_NONNULL (lhs);
+  // Set nargout
+  size_t n_args = v_lhs.size ();
+  PUSH_NARGOUT (n_args);
+
+  std::vector<std::string> v_arg_names;
+  std::vector<bool> v_is_blackhole;
+
+  // Can't nest ignored outputs as the code here is written. Is it even possible to nest those?
+  CHECK (m_pending_ignore_outputs == false);
+
+  // TODO:
+  //       Something smarter is needed to split of cs-lists among different lhs values
+  //       This does not work for e.g. [C{1:2}, D] = {1,2,3}{:}
+  //       Probably need some opcode ASSIGNNX or something.
+  //       See tree_multi_assignment::evaluate_n and octave_lvalue::eval_for_numel
+  //
+  //       There probably has to be another tree_walker figuring out how many elements
+  //       a lvalue will "ask for". In [C{1:2}] = deal (1,2) deal will have to have nargout 2
+  //       which is annoying since we will have to be able to set nargout dynamically.
+  //       With a slot maybe?
+  //
+  //       Maybe make a octave_lvalue and call numel() for simplicity?
+  //
+  //       Meanwhile, just call eval on it ...
+
+  bool any_lhs_not_id = false;
+  for (tree_expression *e : v_lhs)
+    if (! e->is_identifier ())
+      any_lhs_not_id = true;
+
+  if (any_lhs_not_id)
+    {
+      // The VM need to access the tree expr.
+      // Abuse the dbg info.
+      PUSH_TREE_FOR_EVAL (&expr);
+      int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+      PUSH_CODE (INSTR::EVAL);
+      PUSH_CODE (outer_nargout);
+      PUSH_CODE_INT (tree_idx);
+
+      if (DEPTH () == 1)
+        PUSH_CODE (INSTR::POP);
+
+      POP_NARGOUT ();
+      DEC_DEPTH ();
+      return;
+    }
+
+  int n_blackholes = 0;
+  int i = 0;
+  for (tree_expression *e : v_lhs)
+    {
+      if (!e->is_identifier ())
+        {
+          v_arg_names.push_back ("");
+          v_is_blackhole.push_back (false);
+          continue;
+        }
+
+      std::string name = e->name ();
+      if (name == "~") // We need to handle the special "ignore id" '~' as in [~, a] = foo ()
+        {
+          m_v_ignored.push_back (i + 1); // Output parameters are one-indexed
+          name = "%~" + std::to_string (n_blackholes++); // We rename it to "%~X"
+          v_is_blackhole.push_back (true);
+        }
+      else
+        v_is_blackhole.push_back (false);
+
+      v_arg_names.push_back (name);
+
+      add_id_to_table (name);
+
+      i++;
+    }
+
+  CHECK (v_arg_names.size () == n_args);
+
+  /* Handle ignored outputs. Since the called function can ask with isargout()
+   * whether an output is ignored or not we need to set a state for this. */
+  if (m_v_ignored.size ())
+    {
+      m_pending_ignore_outputs = 1;
+      m_ignored_of_total = n_args;
+    }
+
+  tree_expression *rhs = expr.right_hand_side ();
+  CHECK_NONNULL(rhs);
+
+  // We want push NARGOUT elements to the operand stack
+
+  emit_unwind_protect_data D;
+  if (m_pending_ignore_outputs)
+    D = emit_unwind_protect_code_start ();
+
+  rhs->accept (*this); // Walks rhs for NARGOUT elements
+
+  if (DEPTH () != 1)
+    TODO ("Only root multi assignment supported now");
+
+  PUSH_CODE (INSTR::ASSIGNN);
+  // Push the amount of slots
+  PUSH_CODE (v_lhs.size ());
+
+  // Push the slots
+  for (std::string &name : v_arg_names)
+    PUSH_WSLOT (SLOT (name));
+
+  // Emit code to disp if no ;
+  for (std::string &name : v_arg_names)
+    maybe_emit_push_and_disp_id (expr, name);
+
+  if (m_pending_ignore_outputs)
+    {
+      emit_unwind_protect_code_before_cleanup (D);
+
+      // As we are ignoring outputs we need to unwind protect to clear the VM state with opcode CLEAR_IGNORE_OUTPUTS
+      // We need to supply each black hole slot
+
+      PUSH_CODE (INSTR::CLEAR_IGNORE_OUTPUTS);
+      PUSH_CODE (n_blackholes);
+
+      for (unsigned j = 0; j < n_args; j++)
+        {
+          if (v_is_blackhole.at (j))
+            PUSH_WSLOT (SLOT (v_arg_names.at (j)));
+        }
+
+      emit_unwind_protect_code_end (D);
+    }
+
+  if (m_pending_ignore_outputs)
+    {
+      m_pending_ignore_outputs = 0;
+      m_v_ignored.clear ();
+    }
+
+  POP_NARGOUT ();
+  DEC_DEPTH ();
+}
+
+std::map<std::string, octave_base_value::unary_mapper_t> bytecode_walker::m_name_to_unary_func =
+{
+{"abs",       octave_base_value::umap_abs},
+{"acos",      octave_base_value::umap_acos},
+{"acosh",     octave_base_value::umap_acosh},
+{"angle",     octave_base_value::umap_angle},
+{"arg",       octave_base_value::umap_arg},
+{"asin",      octave_base_value::umap_asin},
+{"asinh",     octave_base_value::umap_asinh},
+{"atan",      octave_base_value::umap_atan},
+{"atanh",     octave_base_value::umap_atanh},
+{"cbrt",      octave_base_value::umap_cbrt},
+{"ceil",      octave_base_value::umap_ceil},
+{"conj",      octave_base_value::umap_conj},
+{"cos",       octave_base_value::umap_cos},
+{"cosh",      octave_base_value::umap_cosh},
+{"erf",       octave_base_value::umap_erf},
+{"erfinv",    octave_base_value::umap_erfinv},
+{"erfcinv",   octave_base_value::umap_erfcinv},
+{"erfc",      octave_base_value::umap_erfc},
+{"erfcx",     octave_base_value::umap_erfcx},
+{"erfi",      octave_base_value::umap_erfi},
+{"dawson",    octave_base_value::umap_dawson},
+{"exp",       octave_base_value::umap_exp},
+{"expm1",     octave_base_value::umap_expm1},
+{"isfinite",  octave_base_value::umap_isfinite},
+{"fix",       octave_base_value::umap_fix},
+{"floor",     octave_base_value::umap_floor},
+{"gamma",     octave_base_value::umap_gamma},
+{"imag",      octave_base_value::umap_imag},
+{"isinf",     octave_base_value::umap_isinf},
+{"isna",      octave_base_value::umap_isna},
+{"isnan",     octave_base_value::umap_isnan},
+{"lgamma",    octave_base_value::umap_lgamma},
+{"log",       octave_base_value::umap_log},
+{"log2",      octave_base_value::umap_log2},
+{"log10",     octave_base_value::umap_log10},
+{"log1p",     octave_base_value::umap_log1p},
+{"real",      octave_base_value::umap_real},
+{"round",     octave_base_value::umap_round},
+{"roundb",    octave_base_value::umap_roundb},
+{"signum",    octave_base_value::umap_signum},
+{"sin",       octave_base_value::umap_sin},
+{"sinh",      octave_base_value::umap_sinh},
+{"sqrt",      octave_base_value::umap_sqrt},
+{"tan",       octave_base_value::umap_tan},
+{"tanh",      octave_base_value::umap_tanh},
+{"isalnum",   octave_base_value::umap_xisalnum},
+{"isalpha",   octave_base_value::umap_xisalpha},
+{"isascii",   octave_base_value::umap_xisascii},
+{"iscntrl",   octave_base_value::umap_xiscntrl},
+{"isdigit",   octave_base_value::umap_xisdigit},
+{"isgraph",   octave_base_value::umap_xisgraph},
+{"islower",   octave_base_value::umap_xislower},
+{"isprint",   octave_base_value::umap_xisprint},
+{"ispunct",   octave_base_value::umap_xispunct},
+{"isspace",   octave_base_value::umap_xisspace},
+{"isupper",   octave_base_value::umap_xisupper},
+{"isxdigit",  octave_base_value::umap_xisxdigit},
+{"signbit",   octave_base_value::umap_xsignbit},
+{"tolower",   octave_base_value::umap_xtolower},
+{"toupper",   octave_base_value::umap_xtoupper},
+};
+
+void
+bytecode_walker::
+emit_disp_obj (tree_expression &expr)
+{
+  CHECK (expr.print_result ());
+  CHECK (DEPTH () == 1);
+  PUSH_CODE (INSTR::DISP);
+  // Magic slot number 0 (%nargout that is a native int) that
+  // will never be printed corrensponds to "" name tag stashing of
+  // the ovl before calling display.
+  PUSH_SLOT (0);
+  PUSH_WSLOT (0); // never a command function call
+}
+
+void
+bytecode_walker::
+maybe_emit_push_and_disp_id (tree_expression &expr, const std::string &name, const std::string maybe_cmd_name)
+{
+  if (!expr.print_result ())
+    return;
+
+  if (name.size () && name[0] == '%') // Don't print internal variables like black holes
+    return;
+
+  CHECK (DEPTH () == 1);
+  int slot = SLOT (name);
+  MAYBE_PUSH_WIDE_OPEXT (slot);
+  PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+  PUSH_SLOT (slot);
+  maybe_emit_disp_id (expr, name, maybe_cmd_name); // Always, not maybe
+}
+
+void
+bytecode_walker::
+maybe_emit_disp_id (tree_expression &expr, const std::string &name, const std::string maybe_cmd_name)
+{
+  if (!expr.print_result ())
+    return;
+
+  if (name.size () && name[0] == '%') // Don't print internal variables like black holes
+    return;
+
+  // The Octave function inputname (i) needs to be able to know the name
+  // of the argument to a function, so we need to make an entry of
+  // the id printed if the user overloads display()
+  arg_name_entry arg_name_entry;
+  arg_name_entry.m_arg_names = string_vector {name};
+
+  arg_name_entry.m_ip_start = CODE_SIZE ();
+
+  CHECK (DEPTH () == 1);
+  int slot = SLOT (name);
+  MAYBE_PUSH_WIDE_OPEXT (slot);
+  PUSH_CODE (INSTR::DISP);
+  PUSH_SLOT (slot);
+  // E.g. "x" might either be a command call x() that should print
+  // "ans = ..." or a variable that should print "x = ..." so we
+  // store the information on whether a certain symbol
+  // was a variable or command call in a slot.
+  // Some expressions like "1+1" are never command calls
+  // ans have maybe_cmd_name as ""
+  if (maybe_cmd_name != "")
+    PUSH_WSLOT (SLOT (maybe_cmd_name));
+  else
+    PUSH_WSLOT (0);
+
+  arg_name_entry.m_ip_end = CODE_SIZE ();
+  PUSH_ARGNAMES_ENTRY (arg_name_entry);
+}
+
+void
+bytecode_walker::
+maybe_emit_bind_ans_and_disp (tree_expression &expr, const std::string maybe_cmd_name)
+{
+  bool print_result = expr.print_result ();
+
+  // If this is an root expression we need to write the return value
+  // to ans.
+  if (DEPTH () == 1)
+    {
+      if (print_result)
+        PUSH_CODE (INSTR::DUP);
+      int slot = SLOT ("ans");
+      MAYBE_PUSH_WIDE_OPEXT (slot);
+      PUSH_CODE (INSTR::BIND_ANS);
+      PUSH_SLOT (slot);
+    }
+
+  if (expr.is_identifier ())
+    maybe_emit_disp_id (expr, expr.name (), maybe_cmd_name);
+  else
+    maybe_emit_disp_id (expr, "ans", maybe_cmd_name);
+}
+
+void
+bytecode_walker::
+emit_return ()
+{
+  // For loops, unwind protect and switches etc have stuff on the stack
+  // inside them, so we need to pop those before executing the RET opcode.
+  auto v = NESTING_STATEMENTS();
+  // Reverse it backwards (top to bottom)
+  for (auto it = v.rbegin () ;it !=  v.rend (); it++)
+    {
+      nesting_statement t = *it;
+      switch (t)
+        {
+        case nesting_statement::FOR_LOOP:
+          // We need to pop the counter and n
+          PUSH_CODE (INSTR::POP_N_INTS);
+          PUSH_CODE (2);
+          // Pop the rhs ov (the range)
+          PUSH_CODE (INSTR::POP);
+          break;
+        case nesting_statement::ONE_OV_ON_STACK:
+          PUSH_CODE (INSTR::POP);
+          break;
+        default:
+          ERR("Invalid state");
+        }
+    }
+
+  PUSH_CODE (INSTR::RET);
+}
+
+void
+bytecode_walker::
+visit_return_command (tree_return_command &cmd)
+{
+  int loc_id = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+  // If we are in a unwind protect and returning we need to
+  // run the cleanup code before returning.
+  if (N_UNWIND_RETURN_TARGETS())
+    {
+      PUSH_CODE (INSTR::JMP);
+      int need_unwind = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1); // Placeholder
+      PUSH_A_UNWIND_RETURN_TARGET (need_unwind);
+    }
+  else
+    emit_return ();
+
+  LOC (loc_id).m_ip_end = CODE_SIZE ();
+  LOC (loc_id).m_col = cmd.column ();
+  LOC (loc_id).m_line = cmd.line ();
+}
+
+void
+bytecode_walker::
+visit_simple_assignment (tree_simple_assignment& expr)
+{
+  INC_DEPTH();
+  PUSH_NARGOUT(1); // nargout is 1 for simple assignments
+
+  tree_expression *lhs = expr.left_hand_side ();
+
+  CHECK_NONNULL (lhs);
+
+  if (!lhs->is_identifier() && !lhs->is_index_expression())
+    TODO ("lhs not identifier or index expression");
+
+  octave_value::assign_op op = expr.op_type ();
+
+  // There is a general op-code SUBASSIGN_CHAINED for "complex" index assignments
+  // and some specialized for "simple" ones
+  bool complex_index_assignment = false;
+  bool idx_has_ends = false;
+
+  if (lhs->is_index_expression ())
+    {
+      tree_index_expression *idx = dynamic_cast<tree_index_expression*> (lhs);
+      complex_index_assignment = idx->type_tags ().size () != 1;
+
+      // We want to know if there is any magic end index in the arguments
+      std::list<tree_argument_list *> args_lists = idx->arg_lists ();
+      for (auto it = args_lists.begin (); it != args_lists.end (); it++)
+        {
+          if (!*it)
+            continue;
+          tree_argument_list *args = *it;
+          for (auto it_args = args->begin (); it_args != args->end (); it_args++)
+            {
+              if (!*it_args)
+                continue;
+              if (find_end_walker::has_end (**it_args))
+                idx_has_ends = true;
+            }
+        }
+
+      if (op != octave_value::assign_op::op_asn_eq)
+        complex_index_assignment = true;
+    }
+
+  if (complex_index_assignment)
+    {
+      if (idx_has_ends)
+        {
+          // TODO: Need lvalue walk to figure out how big subexpression are for end.
+          //       Eval as workaround.
+
+          // The VM need to access the tree expr.
+          // Abuse the dbg info.
+          PUSH_TREE_FOR_EVAL (&expr);
+          int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+          PUSH_CODE (INSTR::EVAL);
+          PUSH_CODE (0); // nargout
+          PUSH_CODE_INT (tree_idx);
+
+          if (DEPTH () == 1)
+            PUSH_CODE (INSTR::POP);
+
+          POP_NARGOUT ();
+          DEC_DEPTH ();
+          return;
+        }
+
+      tree_index_expression *idx = dynamic_cast<tree_index_expression*> (lhs);
+
+      tree_expression *e = idx->expression ();
+      std::list<tree_argument_list *> args_lists = idx->arg_lists ();
+      std::list<tree_expression *> dyns_fields = idx->dyn_fields ();
+      std::list<string_vector> fields_names = idx->arg_names();
+      std::string type_tags = idx->type_tags ();
+
+      size_t n_chained = type_tags.size ();
+
+      // Begin with rhs
+      tree_expression *rhs = expr.right_hand_side ();
+      CHECK_NONNULL (rhs);
+      rhs->accept (*this);
+
+      // rhs is on the stack now
+
+      if (e->is_identifier ())
+        {
+          // Name of the identifier
+          std::string name = e->name ();
+
+          int slot = add_id_to_table (name);
+
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+          PUSH_SLOT (slot);
+        }
+      else
+        {
+          // Visit the lhs expression. This should put whatever
+          // we are assigning to, on the stack.
+          e->accept (*this);
+        }
+
+      // Subassigns are abit awkward on a stack VM, since we can't
+      // do this piecewise. We need to construct a list of lists of
+      // arguments to all the chained subassigns and feed them to
+      // ov.assign (). TODO: make a "ref_subsasgn()" call or what
+      // ever in ov.cc for the middle in the chain.
+      //
+      // Also, any inclusion of 'end' get quite annoying since we
+      // need to save subsrefs to each chained subexpression to be
+      // able to figure out the subexpressions sizes.
+
+      auto it_args_lists = args_lists.begin ();
+      auto it_dyns_fields = dyns_fields.begin ();
+      auto it_fields_names = fields_names.begin ();
+
+      int active_idx_slot = -1;
+      if (idx_has_ends)
+        {
+          // We need to store the active subexpression in a slot for end
+          // to be able to access it.
+          std::string name = "%active_idx_" + std::to_string (CODE_SIZE ());
+          add_id_to_table (name);
+          active_idx_slot = SLOT (name);
+          // Write the root value to the slot
+          // i.e. root(2:end)(3,end)
+          PUSH_CODE (INSTR::DUP);
+          MAYBE_PUSH_WIDE_OPEXT (active_idx_slot);
+          PUSH_CODE (INSTR::FORCE_ASSIGN);
+          PUSH_SLOT (active_idx_slot);
+        }
+
+      std::vector<int> n_args_per_part;
+
+      for (size_t i = 0; i < n_chained; i++)
+        {
+          // Amount of args in the subexpresseion
+          // E.g. foo(1,2).bar(1) = ... => 2 and 1
+          int n_args_in_part = 0;
+          char type = type_tags[i];
+
+          tree_argument_list *args = *it_args_lists++;
+          tree_expression *dyn_fields = *it_dyns_fields++;
+          string_vector field_names = *it_fields_names++;
+
+          if (type == '.' && dyn_fields)
+            {
+              INC_DEPTH ();
+              dyn_fields->accept (*this);
+              DEC_DEPTH ();
+              n_args_in_part++; // Dynamic struct fields are always one arg
+            }
+          else if (type == '.')
+            {
+              // We want to push the field name as a ovtave_string to the stack
+              std::string field_name = field_names.elem (0);
+              octave_value ov_field_name{field_name};
+              PUSH_DATA (ov_field_name); // Make a constant
+              // Load the constant
+              PUSH_CODE_LOAD_CST (DATA_SIZE () - 1); // Offset of the constant
+
+              n_args_in_part++;
+            }
+          else
+            {
+              // Push all the args to the stack
+
+              n_args_in_part = args->size ();
+              int j = 0;
+              // We want to push the args to the stack
+              // The order of eval is left to right
+              for (auto it = args->begin (); it != args->end (); it++, j++)
+                {
+                  INC_DEPTH ();
+                  // Any end will work on the active idx slot's object
+                  PUSH_ID_BEGIN_INDEXED (active_idx_slot, j, n_args_in_part, false);
+                  (*it)->accept (*this);
+                  POP_ID_BEING_INDEXED ();
+                  DEC_DEPTH ();
+                }
+            }
+
+          // If we have an end in the assignment we need to write the active subexpression
+          // to the designated slot for end to be able to access it.
+          // Unecessary for the last in the chain.
+          if (idx_has_ends && i + 1 != n_chained)
+            {
+              // Push the prior active index subexpression
+              MAYBE_PUSH_WIDE_OPEXT (active_idx_slot);
+              PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+              PUSH_SLOT (active_idx_slot);
+              // Duplicate the args
+              PUSH_CODE (INSTR::DUPN);
+              PUSH_CODE (1); // offset, under the object being indexed
+              PUSH_CODE (n_args_in_part); // amount of objects to duplicate
+              // Index the prior active index subexpression
+              PUSH_CODE (INSTR::INDEX_OBJ);
+              PUSH_CODE (1); // nargout
+              PUSH_CODE (0); // "has slot"
+              PUSH_WSLOT (0); // The w/e slot
+              PUSH_CODE (n_args_in_part);
+              PUSH_CODE (type);
+              // Write the new active subexpression back to the slot
+              MAYBE_PUSH_WIDE_OPEXT (active_idx_slot);
+              PUSH_CODE (INSTR::FORCE_ASSIGN);
+              PUSH_SLOT (active_idx_slot);
+            }
+
+          n_args_per_part.push_back (n_args_in_part);
+        }
+
+      // So we have alot of arguments to different subexpression evaluated on the
+      // stack now.
+      //
+      // We want to put them in lists and feed them to a subsassgn() call. We use
+      // a special op-code for this.
+
+      PUSH_CODE (INSTR::SUBASSIGN_CHAINED);
+      PUSH_CODE (op); // =, += etc.
+      PUSH_CODE (n_chained);
+      for (unsigned i = 0; i < n_chained; i++)
+        {
+          PUSH_CODE (n_args_per_part[i]); // Amount of args, left to right
+           // The type, i.e. '.' or '(' or '{'
+          PUSH_CODE (type_tags[i]);
+        }
+
+      // Now we got the value that is subassigned to, on the stack
+      if (e->is_identifier ())
+        {
+          if (DEPTH () != 1) // Duplicate value for chained assignments
+            PUSH_CODE (INSTR::DUP);
+
+          // Write the subassigned value back to the slot
+          int slot = SLOT (e->name ());
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::FORCE_ASSIGN);
+          PUSH_SLOT (slot);
+
+          maybe_emit_push_and_disp_id (expr, e->name ());
+        }
+      else
+        {
+          if (expr.print_result ())
+            {
+              PUSH_CODE (INSTR::DUP);
+              emit_disp_obj (expr);
+            }
+          if (DEPTH () == 1)
+            PUSH_CODE (INSTR::POP);
+        }
+    }
+  else if (lhs->is_index_expression()) // eg "foo(2) = bar" or "foo.a = bar"?
+    {
+      /* We have differen op codes for struct, cell, () index assignement
+       * of ids and another for assignments where the rhs of the index is not
+       * an id, e.g. foo.("bar") = 2 */
+
+      CHECK (op == octave_value::assign_op::op_asn_eq);
+
+      // We want the arguments to the index expression on the
+      // operand stack. They are evaluated before the rhs expression.
+      tree_index_expression *idx = dynamic_cast<tree_index_expression*> (lhs);
+
+      tree_expression *ee = idx->expression ();
+      std::list<tree_argument_list *> arg_lists = idx->arg_lists ();
+      std::list<tree_expression *> dyn_fields = idx->dyn_fields ();
+      std::list<string_vector> field_names = idx->arg_names();
+
+      std::string type_tags = idx->type_tags ();
+      CHECK (type_tags.size () == 1);
+      CHECK (dyn_fields.size () == 1);
+      CHECK (arg_lists.size () == 1);
+      CHECK (field_names.size () == 1);
+
+      char type = type_tags[0];
+
+
+      bool is_id = ee->is_identifier ();
+      CHECK_NONNULL(ee);
+
+      bool is_dynamic_field = false;
+      if (type == '.')
+        {
+          tree_expression *dyn_field = dyn_fields.front ();
+          if (dyn_field)
+            is_dynamic_field = true;
+        }
+
+      if (!is_id && type != '.')
+        {
+          tree_argument_list *arg = *arg_lists.begin ();
+
+          // TODO: The other branches evaluate rhs after the arguments.
+          //       Has to be wrong?
+          tree_expression *rhs = expr.right_hand_side ();
+
+          CHECK_NONNULL (rhs);
+          rhs->accept (*this);
+          // The value of rhs is on the stack now
+
+          // Visit the lhs expression
+          ee->accept (*this);
+          // Pushed the left most lhs expression to the stack
+
+          int nargs = 0;
+
+          if (arg)
+            {
+              // If we are indexing an object, and have a magic end index
+              // we need to save the stack depth in a slot
+              bool obj_has_end = false;
+              for (auto it = arg->begin (); it != arg->end (); it++)
+                {
+                  CHECK_NONNULL (*it);
+                  tree_expression &t = **it;
+                  obj_has_end = find_end_walker::has_end (t);
+                  if (obj_has_end)
+                    break;
+                }
+
+              int obj_stack_depth_slot = -1;
+              if (obj_has_end)
+                {
+                  std::string obj_stack_depth_name = "%objsd_" + std::to_string (CODE_SIZE ());
+                  obj_stack_depth_slot = add_id_to_table (obj_stack_depth_name);
+
+                  MAYBE_PUSH_WIDE_OPEXT (obj_stack_depth_slot);
+                  PUSH_CODE (INSTR::SET_SLOT_TO_STACK_DEPTH);
+                  PUSH_SLOT (obj_stack_depth_slot);
+                }
+
+              nargs = arg->size ();
+              int i = 0;
+              // We want to push the args to the stack
+              for (auto it = arg->begin (); it != arg->end (); it++, i++)
+                {
+                  INC_DEPTH ();
+                  PUSH_ID_BEGIN_INDEXED (obj_stack_depth_slot, i, nargs, true);
+                  (*it)->accept (*this);
+                  POP_ID_BEING_INDEXED ();
+                  DEC_DEPTH ();
+                }
+            }
+          // rhs, lhs root expression, lhs's args on the stack now
+
+          PUSH_CODE (INSTR::SUBASSIGN_OBJ);
+          PUSH_CODE (nargs);
+          PUSH_CODE (type);
+
+          if (expr.print_result ())
+            {
+              PUSH_CODE (INSTR::DUP);
+              emit_disp_obj (expr);
+            }
+
+          // SUBASSIGN_OBJ puts the lhs back on the stack
+          // but since lhs is not an id from a slot we just
+          // pop it unless it is used by a chained assign.
+          if (DEPTH () == 1)
+            PUSH_CODE (INSTR::POP);
+        }
+      else if (type == '(')
+        {
+          // Name of the identifier
+          std::string name = ee->name ();
+
+          add_id_to_table (name);
+
+          tree_argument_list *arg = *arg_lists.begin ();
+
+          int nargs = 0;
+          if (arg)
+            {
+              nargs = arg->size ();
+              int i = 0;
+              // We want to push the args to the stack
+              for (auto it = arg->begin (); it != arg->end (); it++, i++)
+                {
+                  INC_DEPTH ();
+                  PUSH_ID_BEGIN_INDEXED (SLOT (name), i, nargs, false);
+                  (*it)->accept (*this);
+                  POP_ID_BEING_INDEXED ();
+                  DEC_DEPTH ();
+                }
+            }
+
+          tree_expression *rhs = expr.right_hand_side ();
+
+          CHECK_NONNULL (rhs);
+          rhs->accept (*this);
+          // The value of rhs is on the operand stack now
+
+          // If the assignment is not at root we want to keep the
+          // value on the stack, e.g.
+          //   a = b(1) = 3;
+          //   Gives: a == 3
+          // We use a slot to store the rhs in.
+          std::string rhs_copy_nm = "%rhs_" + std::to_string (CODE_SIZE ());
+          int slot_cpy = -1;
+          if (DEPTH () != 1)
+            {
+              slot_cpy = add_id_to_table (rhs_copy_nm);
+              PUSH_CODE (INSTR::DUP);
+              MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+              PUSH_CODE (INSTR::FORCE_ASSIGN);
+              PUSH_SLOT (slot_cpy);
+            }
+
+          int slot = SLOT (name);
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::SUBASSIGN_ID);
+          PUSH_SLOT (slot);
+          PUSH_CODE (nargs);
+
+          if (DEPTH () != 1)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+              PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+              PUSH_SLOT (slot_cpy);
+            }
+
+          maybe_emit_push_and_disp_id (expr, name);
+        }
+      else if (type == '.')
+        {
+          tree_expression *e = idx->expression ();
+          CHECK_NONNULL(e);
+
+          if (is_id && !is_dynamic_field)
+            {
+              // Name of the identifier
+              std::string name = e->name ();
+
+              add_id_to_table (name);
+
+              std::list<string_vector>  l_pv_nms = idx->arg_names ();
+              CHECK (l_pv_nms.size () == 1);
+              auto pv_nms = l_pv_nms.begin ();
+              CHECK (pv_nms->numel () == 1);
+
+              std::string field_name = pv_nms->elem (0);
+
+              // We just need the field's name in the VM
+              int slot_field = add_id_to_table (field_name);
+
+              tree_expression *rhs = expr.right_hand_side ();
+
+              CHECK_NONNULL (rhs);
+              rhs->accept (*this);
+              // The value of rhs is on the operand stack now
+
+              std::string rhs_copy_nm = "%rhs_" + std::to_string (CODE_SIZE ());
+              int slot_cpy = -1;
+              if (DEPTH () != 1) // Chained assignments?
+                {
+                  slot_cpy = add_id_to_table (rhs_copy_nm);
+                  PUSH_CODE (INSTR::DUP);
+                  MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+                  PUSH_CODE (INSTR::FORCE_ASSIGN);
+                  PUSH_SLOT (slot_cpy);
+                }
+
+              int slot = SLOT (name);
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::SUBASSIGN_STRUCT);
+              PUSH_SLOT (slot);
+              PUSH_WSLOT (slot_field);
+
+              if (DEPTH () != 1)
+                {
+                  MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+                  PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+                  PUSH_SLOT (slot_cpy);
+                }
+
+              maybe_emit_push_and_disp_id (expr, name);
+            }
+          else if (is_dynamic_field && is_id)
+            {
+              // Name of the identifier
+              std::string name = e->name ();
+
+              add_id_to_table (name);
+
+              tree_expression *rhs = expr.right_hand_side ();
+              CHECK_NONNULL (rhs);
+              rhs->accept (*this);
+              // The value of rhs is on the stack now
+
+              // We want lhs on the stack
+              int slot = SLOT (name);
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+              PUSH_SLOT (slot);
+
+              // The argument, foo.(arg) = bar
+              tree_expression *dyn_expr = dyn_fields.front ();
+              CHECK_NONNULL (dyn_expr);
+
+              INC_DEPTH ();
+              PUSH_NARGOUT (1);
+              dyn_expr->accept (*this);
+              // The value of the arg on the stack, i.e. foo.(arg) = baz
+              POP_NARGOUT ();
+              DEC_DEPTH ();
+
+              PUSH_CODE (INSTR::SUBASSIGN_OBJ);
+              PUSH_CODE (1); // nargout
+              PUSH_CODE (type);
+
+              if (DEPTH () != 1) // Chained assignments?
+                PUSH_CODE (INSTR::DUP);
+
+              // Assign the assigned to value back to the slot
+              // TODO: Neccessary?
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::FORCE_ASSIGN);
+              PUSH_SLOT (slot);
+
+              maybe_emit_push_and_disp_id (expr, name);
+            }
+          else if (!is_dynamic_field && !is_id)
+            {
+              tree_expression *rhs = expr.right_hand_side ();
+              CHECK_NONNULL (rhs);
+              rhs->accept (*this);
+              // The value of rhs is on the operand stack now
+
+              // Visit the lhs expression
+              e->accept (*this);
+              // Pushed the left most lhs expression to the stack
+
+              string_vector ptr = field_names.front ();
+              CHECK (ptr.numel() == 1);
+              std::string field_name = ptr.elem (0);
+
+              /* Make a ov string with the field name in it that
+                * we store as a constant. */
+              octave_value ov_field_name{field_name};
+              PUSH_DATA (ov_field_name);
+
+              PUSH_CODE_LOAD_CST (DATA_SIZE () - 1); // Offset of the constant
+
+              PUSH_CODE (INSTR::SUBASSIGN_OBJ);
+              PUSH_CODE (1); // nargout
+              PUSH_CODE (type);
+
+              if (expr.print_result ())
+                {
+                  PUSH_CODE (INSTR::DUP);
+                  emit_disp_obj (expr);
+                }
+
+              // SUBASSIGN_OBJ puts the lhs back on the stack
+              // but since lhs is not an id from a slot we just
+              // pop it, unless there are chained assignments.
+              if (DEPTH () == 1)
+                PUSH_CODE (INSTR::POP);
+            }
+          else //(is_dynamic_field && !is_id)
+            {
+              tree_expression *rhs = expr.right_hand_side ();
+              CHECK_NONNULL (rhs);
+              rhs->accept (*this);
+              // The value of rhs is on the operand stack now
+
+              // Visit the lhs expression
+              e->accept (*this);
+              // Pushed the left most lhs expression to the stack
+
+              // The argument, foo.(arg) = bar
+              tree_expression *dyn_expr = dyn_fields.front ();
+              CHECK_NONNULL (dyn_expr);
+
+              INC_DEPTH ();
+              PUSH_NARGOUT (1);
+              dyn_expr->accept (*this);
+              // The value of the arg on the stack, i.e. foo.(arg) = baz
+              POP_NARGOUT ();
+              DEC_DEPTH ();
+
+              PUSH_CODE (INSTR::SUBASSIGN_OBJ);
+              PUSH_CODE (1); // nargout
+              PUSH_CODE (type);
+
+              if (expr.print_result ())
+                {
+                  PUSH_CODE (INSTR::DUP);
+                  emit_disp_obj (expr);
+                }
+
+              // SUBASSIGN_OBJ puts the lhs back on the stack
+              // but since lhs is not an id from a slot we just
+              // pop it, unless there are chained assignments.
+              if (DEPTH () == 1)
+                PUSH_CODE (INSTR::POP);
+            }
+        }
+      else if (type == '{')
+        {
+          tree_expression *e = idx->expression ();
+          CHECK_NONNULL(e);
+          CHECK (e->is_identifier ());
+
+          // Name of the identifier
+          std::string name = e->name ();
+
+          add_id_to_table (name);
+
+          CHECK (arg_lists.size ());
+          tree_argument_list *arg = *arg_lists.begin ();
+
+          int nargs = 0;
+          if (arg)
+            {
+              nargs = arg->size ();
+              int i = 0;
+              // We want to push the args to the stack
+              for (auto it = arg->begin (); it != arg->end (); it++, i++)
+                {
+                  INC_DEPTH ();
+                  PUSH_ID_BEGIN_INDEXED (SLOT (name), i, nargs, false);
+                  (*it)->accept (*this);
+                  POP_ID_BEING_INDEXED ();
+                  DEC_DEPTH ();
+                }
+            }
+
+          tree_expression *rhs = expr.right_hand_side ();
+
+          CHECK_NONNULL (rhs);
+          rhs->accept (*this);
+          // The value of rhs is on the operand stack now
+
+          // If the assignment is not at root we want to keep the
+          // value on the stack, e.g.
+          // a = b(1) = 3;
+          // Gives: a == 3
+          // We use a slot to store the rhs in.
+          std::string rhs_copy_nm = "%rhs_" + std::to_string (CODE_SIZE ());
+          int slot_cpy = -1;
+          if (DEPTH () != 1)
+            {
+              slot_cpy = add_id_to_table (rhs_copy_nm);
+              PUSH_CODE (INSTR::DUP);
+              MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+              PUSH_CODE (INSTR::FORCE_ASSIGN);
+              PUSH_SLOT (slot_cpy);
+            }
+
+          int slot = SLOT (name);
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::SUBASSIGN_CELL_ID);
+          PUSH_SLOT (slot);
+          PUSH_CODE (nargs);
+
+          if (DEPTH () != 1)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot_cpy);
+              PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+              PUSH_SLOT (slot_cpy);
+            }
+
+          maybe_emit_push_and_disp_id (expr, name);
+        }
+      else
+        TODO ("Type of subassignment not done yet");
+    }
+  else if (lhs->is_identifier ())
+    {
+      std::string name = lhs->name ();
+
+      int slot = add_id_to_table (name);
+
+      tree_expression *rhs = expr.right_hand_side ();
+
+      CHECK_NONNULL (rhs);
+      rhs->accept (*this);
+      // The value of rhs is on the operand stack now
+
+      if (op != octave_value::assign_op::op_asn_eq)
+        {
+          // Compound assignment have the type of operation in the code
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::ASSIGN_COMPOUND);
+          PUSH_SLOT (slot);
+          PUSH_CODE (op);
+        }
+      else
+        {
+          // Ordinary assignment has its own opcode.
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::ASSIGN);
+          PUSH_SLOT (slot);
+        }
+
+      // If the assignment is not at root we want to keep the
+      // value on the stack, e.g.
+      // a = (b = 3);
+      if (DEPTH () != 1)
+        {
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+          PUSH_SLOT (slot);
+        }
+
+      maybe_emit_push_and_disp_id (expr, name);
+    }
+
+  POP_NARGOUT ();
+  DEC_DEPTH();
+}
+
+void
+bytecode_walker::
+visit_matrix (tree_matrix &m)
+{
+  INC_DEPTH ();
+
+  bool is_rectangle = true;
+  std::vector<int> row_lengths;
+
+  /* We want to know if the matrix is rectangular. I.e.
+   * all rows are of equal length. */
+  size_t first_row_size = static_cast<size_t> (-1);
+  for (auto it = m.begin (); it != m.end (); it++)
+  {
+    // This is a row
+    tree_argument_list *row = *it;
+    size_t row_size = row->size ();
+
+    if (first_row_size == static_cast<size_t> (-1))
+      first_row_size = row_size;
+    else if (first_row_size != row_size)
+      is_rectangle = false;
+
+    row_lengths.push_back (row_size);
+  }
+
+
+  auto p = m.begin ();
+  int n_rows = 0;
+  int n_cols = 0;
+
+  // Push each row element to operand stack
+  while (p != m.end ())
+    {
+      // This is a row
+      tree_argument_list *elt = *p++;
+
+      n_cols = 0;
+      CHECK_NONNULL (elt);
+      for (auto it = elt->begin (); it != elt->end (); it++)
+        {
+          // This is an element
+          tree_expression *e = *it;
+          CHECK_NONNULL (e);
+
+          INC_DEPTH ();
+          e->accept (*this);
+          DEC_DEPTH ();
+          n_cols++;
+        }
+      n_rows++;
+    }
+
+  CHECK (n_cols > 0);
+  CHECK (n_rows > 0);
+
+  if (is_rectangle && n_cols < 256 && n_rows < 256) // Small rectangle matrix
+    {
+      PUSH_CODE (INSTR::MATRIX);
+      PUSH_CODE (n_rows);
+      PUSH_CODE (n_cols);
+    }
+  else if (is_rectangle) // Big rectangle matrix
+    {
+      PUSH_CODE (INSTR::MATRIX_UNEVEN);
+      PUSH_CODE (1); // Type 1, Big rectangle matrix
+      PUSH_CODE_INT (n_rows);
+      PUSH_CODE_INT (n_cols);
+    }
+  else // Uneven matrix
+    {
+      PUSH_CODE (INSTR::MATRIX_UNEVEN);
+      PUSH_CODE (0); // Type 0, Uneven matrix
+      PUSH_CODE_INT (n_rows);
+      for (int i : row_lengths)
+        PUSH_CODE_INT (i);
+    }
+
+  maybe_emit_bind_ans_and_disp (m);
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+visit_cell (tree_cell &m)
+{
+  INC_DEPTH ();
+
+  auto p = m.begin ();
+  int n_rows = 0;
+  int n_cols = -1;
+
+  PUSH_CODE (INSTR::PUSH_OV_U64); // number of rows
+
+  // Push each row element to operand stack
+  while (p != m.end ())
+    {
+      // This is a row
+      tree_argument_list *elt = *p++;
+
+      PUSH_CODE (INSTR::PUSH_OV_U64); //number of columns
+
+      int n_cols_old = n_cols;
+      n_cols = 0;
+      CHECK_NONNULL (elt);
+      for (auto it = elt->begin (); it != elt->end (); it++)
+        {
+          // This is an element
+          tree_expression *e = *it;
+          CHECK_NONNULL (e);
+
+          INC_DEPTH ();
+          e->accept (*this);
+          DEC_DEPTH ();
+          n_cols++;
+
+          // We now need to expand the value (if it is an cs list)
+          // and rotate the counters to the top of the stack.
+          //
+          // Expand cslist does that in one opcode.
+          PUSH_CODE (INSTR::EXPAND_CS_LIST);
+        }
+
+      if (n_cols > n_cols_old)
+        n_cols_old = n_cols;
+
+      // The amount of rows is on the second position of the stack,
+      // rotate it with the amount of columns and increment the rows.
+      PUSH_CODE (INSTR::ROT);
+      PUSH_CODE (INSTR::INCR_PREFIX);
+
+      n_rows++;
+    }
+
+  PUSH_CODE (INSTR::PUSH_CELL);
+
+  maybe_emit_bind_ans_and_disp (m);
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+visit_identifier (tree_identifier& id)
+{
+  INC_DEPTH();
+
+  std::string name = id.name ();
+  if (name == "__VM_DBG")
+  {
+    PUSH_CODE (INSTR::PUSH_FALSE); // An id need to put something on the stack
+    PUSH_CODE (INSTR::DEBUG);
+  }
+  // The magic end id need special handling
+  else if (name == "end")
+    {
+      CHECK (ID_IS_BEING_INDEXED ());
+
+      // Since in e.g. "M = [1 2 3]; M (min (10, end))" the 'end' will
+      // refer to the end of M, not the function min, we need a special
+      // op-code for nested indexings that can refer to any outer object
+      int n_ids = N_IDS_BEING_INDEXED ();
+
+      if (n_ids == 1) // Simple case
+        {
+          id_being_indexed obj = PEEK_ID_BEING_INDEXED ();
+          if (obj.type == 0)
+            {
+              /* TODO: Is this op-code with slots really needed? */
+              MAYBE_PUSH_WIDE_OPEXT (obj.slot);
+              PUSH_CODE (INSTR::END_ID);
+              PUSH_SLOT (obj.slot); // The slot variable being indexed
+              PUSH_CODE (obj.nargs); // The amount of dimensions being indexed
+              PUSH_CODE (obj.idx); // The offset of the index being indexed right now
+            }
+          else if (obj.type == 1)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (obj.slot);
+              PUSH_CODE (INSTR::END_OBJ);
+              // Slot for keeping the stack depth of the object being indexed
+              PUSH_SLOT (obj.slot);
+              PUSH_CODE (obj.nargs); // The amount of dimensions being indexed
+              PUSH_CODE (obj.idx); // The offset of the index being indexed right now
+            }
+          else
+            panic_impossible ();
+        }
+      else // Nested indexing
+        {
+          PUSH_CODE (INSTR::END_X_N);
+          PUSH_CODE (n_ids);
+
+          // Note: Pushing inner to outer.
+          // foo (bar (baz (1, end))) => 1: baz, 2: bar, 3: foo
+          for (int i = n_ids - 1; i >= 0; i--)
+            {
+              id_being_indexed obj = IDS_BEING_INDEXED (i);
+              PUSH_CODE (obj.nargs);
+              PUSH_CODE (obj.idx);
+              PUSH_CODE (obj.type);
+              PUSH_WSLOT (obj.slot);
+            }
+        }
+    }
+  else
+    {
+      int slot = add_id_to_table (name);
+
+      int loc_id = N_LOC ();
+      PUSH_LOC ();
+      LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+      if (m_pending_ignore_outputs && DEPTH () == 2)
+        {
+          PUSH_CODE (INSTR::SET_IGNORE_OUTPUTS);
+          PUSH_CODE (m_v_ignored.size ());
+          PUSH_CODE (m_ignored_of_total);
+          for (int i : m_v_ignored)
+            PUSH_CODE (i);
+        }
+
+      if (id.is_postfix_indexed ())
+        {
+          // "foo.a" and "foo{1}" might be command function calls
+          // which is checked for in PUSH_SLOT_NARGOUT1_SPECIAL
+          // Also foo might be a classdef meta object.
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          if (id.postfix_index () != '(')
+            PUSH_CODE (INSTR::PUSH_SLOT_NARGOUT1_SPECIAL);
+          else
+            PUSH_CODE (INSTR::PUSH_SLOT_INDEXED);
+          PUSH_SLOT (slot);
+        }
+      else if (DEPTH () == 1)
+        {
+          CHECK (NARGOUT () == 0);
+
+          if (id.print_result ())
+            {
+              // Need to keep track of if this is a command call
+              // or not for display since "x" will print "x = 3"
+              // for e.g. variables but "ans = 3" for command calls.
+              std::string maybe_cmd_name = "%maybe_command";
+              int slot_cmd = add_id_to_table (maybe_cmd_name);
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::PUSH_SLOT_DISP);
+              PUSH_SLOT (slot);
+              PUSH_WSLOT (slot_cmd);
+
+              maybe_emit_bind_ans_and_disp (id, maybe_cmd_name);
+            }
+          else
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::PUSH_SLOT_NARGOUT0);
+              PUSH_SLOT (slot);
+
+              // Write the return value to ans. It is either the variables
+              // value straight off, or e.g. a cmd function call return value.
+              maybe_emit_bind_ans_and_disp (id);
+            }
+        }
+      else if (NARGOUT () == 1)
+        {
+          // Push the local at its slot number to the stack
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          if (name == "pi")
+            PUSH_CODE (INSTR::PUSH_PI);
+          else
+            PUSH_CODE (INSTR::PUSH_SLOT_NARGOUT1);
+          PUSH_SLOT (slot);
+        }
+      else if (NARGOUT() > 1)
+        {
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::PUSH_SLOT_NARGOUTN);
+          PUSH_SLOT (slot);
+          PUSH_CODE (NARGOUT ());
+        }
+      else
+        {
+          // Push the local at its slot number to the stack
+          MAYBE_PUSH_WIDE_OPEXT (slot);
+          PUSH_CODE (INSTR::PUSH_SLOT_NARGOUT0);
+          PUSH_SLOT (slot);
+        }
+
+      LOC (loc_id).m_ip_end = CODE_SIZE ();
+      LOC (loc_id).m_col = id.column ();
+      LOC (loc_id).m_line = id.line ();
+    }
+  DEC_DEPTH();
+}
+
+int
+bytecode_walker::
+add_id_to_table (std::string name)
+{
+  // Is the id already added to the local table?
+  auto it = m_map_locals_to_slot.find (name);
+
+  if (it == m_map_locals_to_slot.end ())
+    {
+      // Push local
+      m_code.m_ids.push_back(name);
+      m_map_locals_to_slot[name] = m_n_locals++;
+
+      return m_n_locals - 1;
+    }
+
+  return it->second;
+}
+
+void
+bytecode_walker::
+visit_no_op_command (tree_no_op_command& cmd)
+{
+  if (cmd.is_end_of_fcn_or_script())
+    {
+      // Put a return in the end so that we don't fall of the edge
+      // of the world
+
+      int loc_id = N_LOC ();
+      PUSH_LOC ();
+      LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+      PUSH_TREE_FOR_DBG (&cmd);
+      emit_return ();
+
+      LOC (loc_id).m_ip_end = CODE_SIZE ();
+      LOC (loc_id).m_col = cmd.column ();
+      LOC (loc_id).m_line = cmd.line ();
+    }
+}
+
+void
+bytecode_walker::
+visit_do_until_command (tree_do_until_command& cmd)
+{
+  tree_expression *expr = cmd.condition ();
+  int code_start = CODE_SIZE ();
+
+  tree_statement_list *list = cmd.body ();
+
+  PUSH_CONTINUE_TARGET ();
+  PUSH_BREAKS ();
+
+  // Push an opcode that checks for signals, e.g. ctrl-c
+  PUSH_CODE (INSTR::HANDLE_SIGNALS);
+
+  // A empty body will yield a null list pointer
+  m_n_nested_loops++;
+  if (list)
+    list->accept (*this);
+  m_n_nested_loops--;
+
+  // Any continue jumps to here (before the condition)
+  for (int offset : POP_CONTINUE_TARGET())
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+
+  CHECK_NONNULL (expr);
+  INC_DEPTH (); // Since we need the value
+  PUSH_TREE_FOR_DBG (expr);
+  expr->accept (*this);
+  DEC_DEPTH ();
+
+  // The condition value is on the operand stack, do
+  // a jmp_ifn to the start of the body, on false
+  PUSH_CODE (INSTR::JMP_IFN);
+  PUSH_CODE_SHORT (code_start);
+
+  // The breaks jump to here
+  for (int offset : POP_BREAKS ())
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+}
+
+void
+bytecode_walker::
+visit_while_command (tree_while_command& cmd)
+{
+  tree_expression *expr = cmd.condition ();
+
+  // Location data for the condition
+  int loc_id = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+  int cond_offset = CODE_SIZE ();
+
+  CHECK_NONNULL (expr);
+  INC_DEPTH (); // Since we need the value
+  PUSH_TREE_FOR_DBG (expr);
+  expr->accept (*this);
+  DEC_DEPTH ();
+
+  // The condition value is on the operand stack, do
+  // a jmp_ifn to after the body, on false
+  PUSH_CODE (INSTR::JMP_IFN);
+  int offset_need_jmp_after = CODE_SIZE ();
+  PUSH_CODE_SHORT (-1); // Placeholder
+
+  LOC (loc_id).m_ip_end = CODE_SIZE ();
+  LOC (loc_id).m_col = expr->column ();
+  LOC (loc_id).m_line = expr->line ();
+
+  tree_statement_list *list = cmd.body ();
+
+  PUSH_CONTINUE_TARGET ();
+  PUSH_BREAKS ();
+
+  // Push an opcode that checks for signals, e.g. ctrl-c
+  PUSH_CODE (INSTR::HANDLE_SIGNALS);
+
+  // nullptr if body is empty
+  m_n_nested_loops++;
+  if (list)
+    list->accept (*this);
+  m_n_nested_loops--;
+
+  // The continue targets can now be set, to jump back
+  // to the condition.
+  for (int offset : POP_CONTINUE_TARGET())
+    SET_CODE_SHORT (offset, cond_offset);
+
+  // Jump back to the condition, TODO: unless all paths are terminated
+  PUSH_CODE (INSTR::JMP);
+  PUSH_CODE_SHORT (cond_offset);
+
+  // Now we can set where the condition should jump on false, i.e.
+  // to here, after the jump back to the condition
+  SET_CODE_SHORT (offset_need_jmp_after, CODE_SIZE ());
+
+  // The breaks jump to the same place
+  for (int offset : POP_BREAKS ())
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+}
+
+void
+bytecode_walker::
+visit_switch_command (tree_switch_command& cmd)
+{
+  tree_expression *expr = cmd.switch_value ();
+  CHECK_NONNULL (expr);
+
+  tree_switch_case_list *lst = cmd.case_list ();
+
+  std::vector<int> need_after_all;
+
+  // First off we need the switch value on the stack
+  INC_DEPTH ();
+  PUSH_NARGOUT(1);
+
+  expr->accept (*this);
+
+  POP_NARGOUT ();
+  DEC_DEPTH ();
+
+  // Since the switch have a value on the stack through the whole switch
+  // statement we need to track that so returns can pop it.
+  PUSH_NESTING_STATEMENT (nesting_statement::ONE_OV_ON_STACK);
+
+  // Any nested continue or break need to pop the switch value
+  PUSH_CONTINUE_TARGET ();
+  PUSH_BREAKS ();
+
+  // We now have the switch value on the operand stack,
+  // so now we need to compare it with the first label
+  // either execute its code or skip it depending on
+  // wheter the switch value and the label are "equal"
+
+  tree_switch_case *default_case = nullptr;
+
+  if (lst)
+    for (tree_switch_case *t : *lst)
+      {
+        // We want to do the default case last
+        if (t->is_default_case ())
+          {
+            default_case = t;
+            continue;
+          }
+
+        // We need to duplicate the switch value on the stack so
+        // each label will have its own
+        PUSH_CODE (INSTR::DUP);
+
+        INC_DEPTH ();
+        PUSH_NARGOUT(1);
+
+        // Walk for code for the case label expression
+        t->case_label()->accept(*this);
+
+        POP_NARGOUT ();
+        DEC_DEPTH ();
+
+        // case label value is now on the stack
+
+        PUSH_CODE (INSTR::JMP_IFNCASEMATCH);
+        int need_next = CODE_SIZE ();
+        PUSH_CODE_SHORT (-1);
+
+        // Walk for the case label body
+
+        tree_statement_list *stmt_lst = t->commands ();
+
+        if (stmt_lst)
+          stmt_lst->accept (*this);
+
+        // TODO: Unless the body is terminated we need to jump past
+        // the rest of the switch bodies
+        PUSH_CODE (INSTR::JMP);
+        need_after_all.push_back (CODE_SIZE ());
+        PUSH_CODE_SHORT (-1); // Placeholder, jump to after all
+
+        // If the label was not "true" we jump to here. Under there will be
+        // another case or the end of the switch
+        SET_CODE_SHORT (need_next, CODE_SIZE ()); // The placeholder above
+      }
+
+  // If there was a default case, generate code for it
+  if (default_case)
+    {
+      tree_statement_list *stmt_lst = default_case->commands();
+
+      if (stmt_lst)
+        stmt_lst->accept (*this);
+    }
+
+  // Any nested break or continue need to jump here to pop an ov
+  // and then jump to a outer break or continue block.
+  auto v_breaks = POP_BREAKS ();
+  auto v_continues = POP_CONTINUE_TARGET ();
+
+  if (v_breaks.size () || v_continues.size ())
+    {
+      // Fallthrough from default need to jump past break and continue bridges
+      PUSH_CODE (INSTR::JMP);
+      int offset = CODE_SIZE ();
+      need_after_all.push_back (offset);
+      PUSH_CODE_SHORT (-1);
+    }
+
+  if (v_breaks.size ())
+    {
+      for (int offset : v_breaks)
+        SET_CODE_SHORT (offset, CODE_SIZE ());
+      // We need to pop the switch value
+      PUSH_CODE (INSTR::POP);
+      // Jump to the outer break target
+      PUSH_CODE (INSTR::JMP);
+      int offset = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      PUSH_NEED_BREAK (offset);
+    }
+  if (v_continues.size ())
+    {
+      // Nested continues should jump to there
+      int target_offset = CODE_SIZE ();
+      for (int offset : v_continues)
+        SET_CODE_SHORT (offset, target_offset);
+      // We need to pop the switch value
+      PUSH_CODE (INSTR::POP);
+      // Jump to the outer continue target (i.e. start of whatever loop)
+      PUSH_CODE (INSTR::JMP);
+      int need_continue_target = CODE_SIZE ();
+      PUSH_CODE_SHORT (-1);
+      PUSH_NEED_CONTINUE_TARGET (need_continue_target);
+    }
+
+  // Some code points might need a jump to after the switch statement
+  for (int offset : need_after_all)
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+
+  // We need to pop the switch value
+  PUSH_CODE (INSTR::POP);
+
+  // We are out of the switch statement so pop it from the nesting stack
+  POP_NESTING_STATEMENT ();
+}
+
+void
+bytecode_walker::
+visit_if_command (tree_if_command& cmd)
+{
+  tree_if_command_list *list = cmd.cmd_list ();
+  CHECK_NONNULL (list);
+
+  // Offset to jump addresses that will need to jump
+  // to after all the if clauses and bodies. E.g.
+  // the end of each if body, if there are more than one if.
+  std::vector<int> need_after_all;
+
+  // Offset for the jump address of the condition test, which
+  // need to go to after the body.
+  int need_after_body = -1;
+
+  std::size_t n = list->size ();
+
+  std::size_t idx = 0;
+  for (auto p = list->begin (); p != list->end (); p++, idx++)
+    {
+      bool is_last = idx + 1 == n;
+
+      tree_if_clause *elt = *p;
+      CHECK_NONNULL (elt);
+
+      tree_statement_list *body = elt->commands ();
+
+      bool is_not_else = ! elt->is_else_clause ();
+      // Condition
+      if (is_not_else)
+        {
+          tree_expression *cond = elt->condition ();
+          CHECK_NONNULL (cond);
+
+          // Location data for the condition
+          int loc_id = N_LOC ();
+          PUSH_LOC ();
+          LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+          PUSH_TREE_FOR_DBG (elt); // We want the debug hit before the condition
+
+          PUSH_NARGOUT (1);
+          INC_DEPTH ();
+          cond->accept (*this);
+          DEC_DEPTH ();
+          POP_NARGOUT ();
+
+          // The condition is on the operand stack now
+          PUSH_CODE (INSTR::JMP_IFN);
+          need_after_body = CODE_SIZE ();
+          PUSH_CODE_SHORT (-1); // Placeholder, jump to after all
+
+          LOC (loc_id).m_ip_end = CODE_SIZE ();
+          LOC (loc_id).m_col = cond->column ();
+          LOC (loc_id).m_line = cond->line ();
+        }
+
+      // Body
+      // nullptr if body is empty
+      if (body)
+        body->accept (*this);
+
+      if (!is_last)
+        {
+          PUSH_CODE (INSTR::JMP);
+          need_after_all.push_back (CODE_SIZE ());
+          PUSH_CODE_SHORT (-1); // Placeholder, jump to after all
+        }
+
+      // Now we can set the address to which failed condition
+      // will jump
+      if (is_not_else)
+        SET_CODE_SHORT (need_after_body, CODE_SIZE ());
+    }
+
+  for (int offset : need_after_all)
+    SET_CODE_SHORT (offset, CODE_SIZE ());
+}
+
+void
+bytecode_walker::
+visit_anon_fcn_handle (tree_anon_fcn_handle &expr)
+{
+  INC_DEPTH ();
+
+  PUSH_TREE_FOR_EVAL (&expr);
+  int tree_idx = -CODE_SIZE ();
+
+  PUSH_CODE (INSTR::PUSH_ANON_FCN_HANDLE);
+  PUSH_CODE_INT (tree_idx);
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+emit_args_for_visit_index_expression (tree_argument_list *arg_list,
+                                      tree_expression *root_lhs_id)
+{
+  int nargs = arg_list->size ();
+  int idx = 0;
+  bool lhs_is_id = root_lhs_id ? root_lhs_id->is_identifier () : false;
+
+  // If we are indexing an object, and have a magic end index
+  // we need to save the stack depth in a slot
+  bool obj_has_end = false;
+  if (!lhs_is_id)
+    {
+      for (auto it = arg_list->begin (); it != arg_list->end (); it++)
+        {
+          CHECK_NONNULL (*it);
+          obj_has_end = find_end_walker::has_end (**it);
+          if (obj_has_end)
+            break;
+        }
+    }
+
+  int obj_stack_depth_slot = -1;
+  if (obj_has_end)
+    {
+      std::string obj_stack_depth_name = "%objsd_" + std::to_string (CODE_SIZE ());
+      obj_stack_depth_slot = add_id_to_table (obj_stack_depth_name);
+
+      MAYBE_PUSH_WIDE_OPEXT (obj_stack_depth_slot);
+      PUSH_CODE (INSTR::SET_SLOT_TO_STACK_DEPTH);
+      PUSH_SLOT (obj_stack_depth_slot);
+    }
+
+  // We want to push the args to the stack
+  for (auto it = arg_list->begin (); it != arg_list->end (); it++, idx++)
+    {
+      INC_DEPTH ();
+      if (lhs_is_id)
+        PUSH_ID_BEGIN_INDEXED (SLOT (root_lhs_id->name ()), idx, nargs, false);
+      else
+        PUSH_ID_BEGIN_INDEXED (obj_stack_depth_slot, idx, nargs, true);
+
+      PUSH_NARGOUT (1);
+      (*it)->accept (*this);
+      POP_NARGOUT ();
+      POP_ID_BEING_INDEXED ();
+      DEC_DEPTH ();
+    }
+}
+
+void
+bytecode_walker::
+emit_fields_for_visit_index_expression (string_vector &field_names,
+                                        tree_expression *dyn_expr,
+                                        tree_expression *lhs_root,
+                                        bool *struct_is_id_dot_id)
+{
+  if (struct_is_id_dot_id)
+    *struct_is_id_dot_id = false;
+  // For struct the "arg" is the field and not executed.
+  // Just add it as an identifier so that we can get it's
+  // name as a string in the VM.
+  CHECK (field_names.numel() == 1);
+
+  std::string field_name = field_names.elem (0);
+
+  if (lhs_root && lhs_root->is_identifier () && field_name.size ())
+    {
+      if (struct_is_id_dot_id)
+        *struct_is_id_dot_id = true;
+      add_id_to_table (field_name);
+    }
+  else if (field_name.size ())
+    {
+      octave_value ov_field_name{field_name};
+      PUSH_DATA (ov_field_name);
+
+      PUSH_CODE_LOAD_CST (DATA_SIZE () - 1); // Offset of the constant
+    }
+  else
+    {
+      CHECK_NONNULL (dyn_expr);
+
+      INC_DEPTH ();
+      PUSH_NARGOUT (1);
+      dyn_expr->accept (*this);
+      POP_NARGOUT ();
+      DEC_DEPTH ();
+    }
+}
+
+void
+bytecode_walker::
+eval_visit_index_expression (tree_index_expression& expr)
+{
+  INC_DEPTH ();
+  tree_expression *e = expr.expression ();
+  CHECK_NONNULL(e);
+
+  PUSH_TREE_FOR_EVAL (&expr);
+  int tree_idx = -CODE_SIZE (); // NB: Negative to not collide with debug data
+
+  PUSH_CODE (INSTR::EVAL);
+  PUSH_CODE (NARGOUT ());
+  PUSH_CODE_INT (tree_idx);
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  if (DEPTH () == 1 && NARGOUT () > 1)
+    TODO ("Silly state");
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+simple_visit_index_expression (tree_index_expression& expr)
+{
+  INC_DEPTH ();
+  tree_expression *e = expr.expression ();
+  CHECK_NONNULL(e);
+
+  // Word commands are on the form:
+  // foo bar baz; <=> foo('bar', 'baz');
+  bool is_wordcmd = expr.is_word_list_cmd ();
+
+  std::string type_tags = expr.type_tags ();
+
+  size_t n_chained = type_tags.size ();
+  CHECK (n_chained == 1);
+
+  // Put the object to index on the stack
+  INC_DEPTH ();
+  e->accept (*this);
+  DEC_DEPTH ();
+
+  // The Octave function inputname (i) needs to be able to know the name
+  // of th nth argument to a function, so we need to make an entry of
+  // the names.
+  arg_name_entry arg_name_entry;
+
+  std::list<octave::tree_argument_list *> arg_lists = expr.arg_lists ();
+  std::list<string_vector> arg_names = expr.arg_names ();
+  std::list<octave::tree_expression *> dyn_fields = expr.dyn_fields ();
+
+  CHECK (arg_lists.size () == n_chained);
+  CHECK (arg_names.size () == n_chained);
+  CHECK (dyn_fields.size () == n_chained);
+  CHECK (type_tags.size () == n_chained);
+
+  auto arg_names_it = arg_names.begin ();
+  auto arg_lists_it = arg_lists.begin ();
+  auto arg_lists_dyn_it = dyn_fields.begin ();
+  auto arg_type_tags_it = type_tags.begin ();
+
+  char type = *arg_type_tags_it;
+
+  int nargout = NARGOUT ();
+
+  bool struct_is_id_dot_id = false;
+  if (type == '.')
+    emit_fields_for_visit_index_expression (*arg_names_it, *arg_lists_dyn_it, e, &struct_is_id_dot_id);
+  else if (*arg_lists_it)
+    {
+      emit_args_for_visit_index_expression (*arg_lists_it, e);
+      // Push the argnames for inputname ()
+      size_t n_args = arg_names_it->numel ();
+      string_vector names(n_args);
+      for (int i = 0; i < arg_names_it->numel (); i++)
+        names.elem (i) = arg_names_it->elem (i);
+      arg_name_entry.m_arg_names = names;
+    }
+
+  if (m_pending_ignore_outputs && DEPTH () == 2)
+    {
+      PUSH_CODE (INSTR::SET_IGNORE_OUTPUTS);
+      PUSH_CODE (m_v_ignored.size ());
+      PUSH_CODE (m_ignored_of_total);
+      for (int i : m_v_ignored)
+        PUSH_CODE (i);
+    }
+
+  int loc_id = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+  arg_name_entry.m_ip_start = CODE_SIZE ();
+
+  tree_argument_list *args = *arg_lists_it;
+
+  if (is_wordcmd)
+    {
+      CHECK (e->is_identifier ());
+
+      std::string id_name = e->name ();
+      int slot = SLOT (id_name);
+      MAYBE_PUSH_WIDE_OPEXT (slot);
+      PUSH_CODE (INSTR::WORDCMD);
+      // The vm need the name of the identifier for function lookups
+      PUSH_SLOT (slot);
+      PUSH_CODE (nargout);
+      // Push nargin
+      PUSH_CODE (args ? args->size () : 0);
+    }
+  else if (e->is_identifier () && !(type == '.' && !struct_is_id_dot_id))
+    {
+      std::string id_name = e->name ();
+      int slot = SLOT (id_name);
+
+      if (type == '(')
+        {
+          if (nargout == 0)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::INDEX_ID_NARGOUT0);
+              // The vm need the name of the identifier for function lookups
+              PUSH_SLOT (slot);
+            }
+          else if (nargout == 1)
+            {
+              // If the id is "sin", "cos", "round" etc, and there is one argument,
+              // in the end map(unary_mapper_t) will be called while executing,
+              // unless the user have overriden those.
+              // We do a special opcode for those to speed them up.
+              // Don't do the special opcode if it would need wide slots, i.e. slot nr > 256.
+              auto umaped_fn_it = m_name_to_unary_func.find (id_name);
+              if (!args || args->size () != 1 || umaped_fn_it == m_name_to_unary_func.end () || slot > 256)
+                {
+                  MAYBE_PUSH_WIDE_OPEXT (slot);
+                  PUSH_CODE (INSTR::INDEX_ID_NARGOUT1);
+                }
+              else
+                {
+                  octave_base_value::unary_mapper_t idx = umaped_fn_it->second;
+                  PUSH_CODE (INSTR::INDEX_ID1_MATHY_UFUN);
+                  PUSH_CODE (static_cast<int> (idx));
+                }
+
+              PUSH_SLOT (slot);
+            }
+          else
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::INDEX_IDN);
+              PUSH_SLOT (slot);
+              PUSH_CODE (nargout);
+            }
+
+          // Push nargin
+          PUSH_CODE (args ? args->size () : 0);
+        }
+      else if (type == '{')
+        {
+          if (nargout == 0)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::INDEX_CELL_ID_NARGOUT0);
+              // The vm need the name of the identifier for function lookups
+              PUSH_SLOT (slot);
+            }
+          else if (nargout == 1)
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::INDEX_CELL_ID_NARGOUT1);
+              PUSH_SLOT (slot);
+            }
+          else
+            {
+              MAYBE_PUSH_WIDE_OPEXT (slot);
+              PUSH_CODE (INSTR::INDEX_CELL_ID_NARGOUTN);
+              PUSH_SLOT (slot);
+              PUSH_CODE (nargout);
+            }
+
+          // Push nargin
+          PUSH_CODE (args ? args->size () : 0);
+        }
+      else if (type == '.')
+        {
+          PUSH_CODE (INSTR::INDEX_STRUCT_NARGOUTN);
+          PUSH_CODE (nargout);
+
+          string_vector field_names = *arg_names_it;
+          CHECK (field_names.numel ());
+          std::string field_name = field_names.elem (0);
+
+          PUSH_WSLOT (slot);   // id to index
+          PUSH_WSLOT (SLOT (field_name)); // VM need name of the field
+        }
+      else
+        TODO ("Not implemeted typetag");
+    }
+  else
+    {
+      // We are not indexing an id, but e.g.:
+      // (foo).()
+      // I.e. a temporary object.
+      PUSH_CODE (INSTR::INDEX_OBJ);
+      PUSH_CODE (nargout);
+      PUSH_CODE (0); // "has slot"
+      PUSH_WSLOT (0); // The w/e slot TODO: Remove?
+      // Push nargin
+      if (type == '.')
+        PUSH_CODE (1); // Nargin always one for struct indexing
+      else
+        PUSH_CODE (args ? args->size () : 0);
+      PUSH_CODE (type);
+    }
+
+  arg_name_entry.m_ip_end = CODE_SIZE ();
+  PUSH_ARGNAMES_ENTRY (arg_name_entry);
+
+  LOC (loc_id).m_ip_end = CODE_SIZE ();
+  LOC (loc_id).m_col = expr.column ();
+  LOC (loc_id).m_line = expr.line ();
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  if (DEPTH () == 1 && NARGOUT () > 1)
+    TODO ("Silly state");
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+visit_index_expression (tree_index_expression& expr)
+{
+
+  tree_expression *e = expr.expression ();
+  CHECK_NONNULL(e);
+
+  std::list<octave::tree_argument_list *> arg_lists = expr.arg_lists ();
+  std::list<string_vector> arg_names = expr.arg_names ();
+  std::list<octave::tree_expression *> dyn_fields = expr.dyn_fields ();
+  std::string type_tags = expr.type_tags ();
+
+  size_t n_chained = type_tags.size ();
+  CHECK (n_chained);
+
+  // For un-chained index expressions we use specialized
+  // op-codes that has e.g. nargout and type '(','{' and '.'
+  // encoded in the op-code it self to speed things up.
+  if (n_chained == 1)
+    {
+      simple_visit_index_expression (expr);
+      return;
+    }
+
+  // If there is any struct in the chain and an end, we cheat and use
+  // eval. We can't use the existing end op-codes since they need a value
+  // to check the size of, but e.g. "foo.bar(end)" might be a
+  // class cmd form method call "foo.bar" and we can't know the size before
+  // that has been checked.
+  //
+  // TODO: Solve this. Maybe with some special if?
+  bool has_end = false;
+  for (auto outer_it = arg_lists.begin (); outer_it != arg_lists.end (); outer_it++)
+    {
+      auto arg_list = *outer_it;
+      if (!arg_list)
+        continue;
+      for (auto it = arg_list->begin (); it != arg_list->end (); it++)
+        {
+          CHECK_NONNULL (*it);
+          has_end = find_end_walker::has_end (**it);
+          if (has_end)
+            break;
+        }
+    }
+  if (has_end)
+    {
+      eval_visit_index_expression (expr);
+      return;
+    }
+
+  INC_DEPTH ();
+
+  // A chained index expression might be: foo.bar(2).baz{1} => n_chained == 4
+
+  int loc_id = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+  // The Octave function inputname (i) needs to be able to know the name
+  // of th nth argument to a function, so we need to make an entry of
+  // the names.
+  arg_name_entry arg_name_entry;
+
+  // We push the first object to index to the stack.
+  // Subsequent indexings will have the prior index result on the
+  // stack.
+  INC_DEPTH ();
+  e->accept (*this);
+  DEC_DEPTH ();
+
+  CHECK (arg_lists.size () == n_chained);
+  CHECK (arg_names.size () == n_chained);
+  CHECK (dyn_fields.size () == n_chained);
+  CHECK (type_tags.size () == n_chained);
+
+  auto arg_names_it = arg_names.begin ();
+  auto arg_lists_it = arg_lists.begin ();
+  auto arg_lists_dyn_it = dyn_fields.begin ();
+  auto arg_type_tags_it = type_tags.begin ();
+
+  tree_expression *first_expression = e;
+  // Iterate over the chained subexpressions
+  std::vector<int> v_n_args {}; // We pushed one field above
+  std::vector<int> v_types {};// The type is .
+  while (arg_lists_it != arg_lists.end ())
+    {
+      tree_argument_list *arg_list = *arg_lists_it++;
+      string_vector field_names = *arg_names_it++;
+      tree_expression *dyn_expr = *arg_lists_dyn_it++;
+      char type = *arg_type_tags_it++;
+
+      v_types.push_back (type);
+
+      if (type == '.')
+        {
+          emit_fields_for_visit_index_expression (field_names, dyn_expr, nullptr, nullptr);
+          v_n_args.push_back (1);
+        }
+      else if (arg_list)
+        {
+          emit_args_for_visit_index_expression (arg_list, nullptr);
+          v_n_args.push_back (arg_list->size ());
+          // Push the argnames for inputname ()
+          int n_args = field_names.numel ();
+          string_vector names(n_args);
+          for (int i = 0; i < n_args; i++)
+            names.elem (i) = field_names.elem (i);
+          arg_name_entry.m_arg_names = names;
+        }
+      else
+        v_n_args.push_back (0); // e.g. the call to "bar" in "foo.bar ()"
+    }
+
+  if (m_pending_ignore_outputs && DEPTH () == 2)
+    {
+      PUSH_CODE (INSTR::SET_IGNORE_OUTPUTS);
+      PUSH_CODE (m_v_ignored.size ());
+      PUSH_CODE (m_ignored_of_total);
+      for (int i : m_v_ignored)
+        PUSH_CODE (i);
+    }
+
+  int nargout = NARGOUT ();
+
+  arg_name_entry.m_ip_start = CODE_SIZE ();
+
+  if (first_expression && first_expression->is_identifier ())
+    {
+      int slot = SLOT (first_expression->name ());
+      MAYBE_PUSH_WIDE_OPEXT (slot);
+      PUSH_CODE (INSTR::INDEX_STRUCT_CALL);
+      PUSH_SLOT (slot); // the slot
+      PUSH_CODE (1); // has slot
+      PUSH_CODE (nargout);
+    }
+  else
+    {
+      PUSH_CODE (INSTR::INDEX_STRUCT_CALL);
+      PUSH_SLOT (0); // slot
+      PUSH_CODE (0); // has slot
+      PUSH_CODE (nargout);
+    }
+
+  PUSH_CODE (v_n_args.size ());
+  for (unsigned i = 0; i < v_n_args.size (); i++)
+    {
+      PUSH_CODE (v_n_args[i]);
+      PUSH_CODE (v_types[i]);
+    }
+
+  arg_name_entry.m_ip_end = CODE_SIZE ();
+  PUSH_ARGNAMES_ENTRY (arg_name_entry);
+  arg_name_entry = {}; // TODO: Remove?
+
+  LOC (loc_id).m_ip_end = CODE_SIZE ();
+  LOC (loc_id).m_col = expr.column ();
+  LOC (loc_id).m_line = expr.line ();
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  if (DEPTH () == 1 && NARGOUT () > 1)
+    TODO ("Silly state");
+
+  DEC_DEPTH ();
+}
+
+// For loops are setup like this:
+//
+// Setup block:
+//   * The range variable is on the top of the stack
+//   * Push the amount of iterations to the stack, octave_idx_type
+//   * Push a counter to the stack initialized to ~0, octave_idx_type,
+//     so that it wraps to zero after incrementing.
+//   * Fall through to condition block
+// Condition block:
+//   * Increase counter
+//   * If there are no iterations left, go to after.
+//   * Write the iteration's value to the local
+//   * Fall through to body
+// Body block:
+//   * Execute the body code
+//   * Jump to condition block
+// After block:
+//   * Pop the type, counter and limit variables
+//
+// FOR_SETUP = opcode
+// FOR_COND  = opcode, after address, local slot
+
+void
+bytecode_walker::
+visit_simple_for_command (tree_simple_for_command& cmd)
+{
+  tree_expression *lhs = cmd.left_hand_side ();
+
+  int loc_id = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id).m_ip_start = CODE_SIZE ();
+
+  CHECK_NONNULL (lhs);
+  if (! lhs->is_identifier ())
+    TODO ("For loop with lhs not id ???");
+
+  std::string id_name = lhs->name ();
+  // We don't want the id pushed to the stack so we
+  // don't walk it.
+  int slot = add_id_to_table (id_name);
+
+  tree_expression *expr = cmd.control_expr ();
+  CHECK_NONNULL (expr);
+
+  PUSH_TREE_FOR_DBG (&cmd); // Debug hit before rhs
+
+  // We want the rhs expression on the stack
+  INC_DEPTH ();
+  PUSH_NARGOUT (1);
+  expr->accept (*this);
+  POP_NARGOUT ();
+  DEC_DEPTH ();
+
+  // For loops need a special unwind entry to destroy the
+  // native ints on the stack properly.
+  int unwind_idx = N_UNWIND ();
+  PUSH_UNWIND();
+  UNWIND (unwind_idx).m_ip_start = CODE_SIZE ();
+
+  UNWIND (unwind_idx).m_unwind_entry_type =
+    unwind_entry_type::FOR_LOOP;
+
+  // For loops add two native ints and one ov to the stack,
+  // and switches add one ov to the stack, so we need to
+  // record how many things we have added to the stack,
+  // not counting this for loop. From for loops and
+  // switches.
+  int n_things_on_stack = n_on_stack_due_to_stmt();
+
+  // Store added things on stack (due to for loops and switches)
+  // in the unwind table.
+  UNWIND (unwind_idx).m_stack_depth = n_things_on_stack;
+
+  PUSH_CODE (INSTR::FOR_SETUP);
+  // FOR_COND need to come after FOR_SETUP
+  // FOR_SETUP uses FOR_COND's operands the first loop iteration
+  PUSH_TREE_FOR_DBG (&cmd); // Debug hit at condition
+  int cond_offset = CODE_SIZE ();
+  MAYBE_PUSH_WIDE_OPEXT (slot);
+  PUSH_CODE (INSTR::FOR_COND);
+  PUSH_SLOT (slot); // The for loop variable
+  int need_after = CODE_SIZE ();
+  PUSH_CODE_SHORT (-1); // Placeholder for after address
+
+  LOC (loc_id).m_ip_end = CODE_SIZE ();
+  LOC (loc_id).m_col = cmd.column ();
+  LOC (loc_id).m_line = cmd.line ();
+
+  // Walk body
+  tree_statement_list *list = cmd.body ();
+
+  // The body can be empty
+  if (list)
+    {
+      m_n_nested_loops++;
+      PUSH_NESTING_STATEMENT (nesting_statement::FOR_LOOP);
+      PUSH_BREAKS ();
+      PUSH_CONTINUE_TARGET ();
+      list->accept (*this);
+      for (int offset : POP_CONTINUE_TARGET())
+        SET_CODE_SHORT (offset, cond_offset);
+      POP_NESTING_STATEMENT ();
+      m_n_nested_loops--;
+    }
+
+  // A new loc for the for loop suffix code, so that any time
+  // spent there end up by the "for"-row in the profiler
+
+  int loc_id2 = N_LOC ();
+  PUSH_LOC ();
+  LOC (loc_id2).m_ip_start = CODE_SIZE ();
+
+  // Jump to condition block, TODO: unless all paths terminated
+  PUSH_CODE (INSTR::JMP);
+  PUSH_CODE_SHORT (cond_offset);
+
+  // Now we can set the after jump in cond
+  SET_CODE_SHORT (need_after, CODE_SIZE ());
+
+  if (list)
+    {
+      // Also all breaks jump to here
+      for (int need_break : POP_BREAKS ())
+        {
+          SET_CODE_SHORT (need_break, CODE_SIZE ());
+        }
+    }
+
+  // Mark an end to the special for loop unwind entry
+  UNWIND (unwind_idx).m_ip_end = CODE_SIZE ();
+
+  // We need to pop the counter, n and range
+  PUSH_CODE (INSTR::POP_N_INTS);
+  PUSH_CODE (2);
+  // Pop the rhs ov (the range)
+  PUSH_CODE (INSTR::POP);
+
+  LOC (loc_id2).m_ip_end = CODE_SIZE ();
+  LOC (loc_id2).m_col = cmd.column ();
+  LOC (loc_id2).m_line = cmd.line ();
+}
+
+void
+bytecode_walker::
+visit_complex_for_command (tree_complex_for_command& cmd)
+{
+  tree_argument_list *lhs = cmd.left_hand_side ();
+
+  CHECK (lhs);
+  CHECK (lhs->size () == 2);
+
+  auto p = lhs->begin ();
+  tree_expression *val = *p++;
+  tree_expression *key = *p++;
+
+  CHECK (val); CHECK (key);
+
+  CHECK (val->is_identifier ());
+  CHECK (key->is_identifier ());
+
+  std::string val_name = val->name ();
+  std::string key_name = key->name ();
+
+  add_id_to_table (val_name);
+  add_id_to_table (key_name);
+
+  tree_expression *expr = cmd.control_expr ();
+  CHECK_NONNULL (expr);
+
+  // We want the rhs expression on the stack
+  INC_DEPTH ();
+  PUSH_NARGOUT (1);
+  expr->accept (*this);
+  POP_NARGOUT ();
+  DEC_DEPTH ();
+
+  // For loops need a special unwind entry to destroy the
+  // native ints on the stack properly.
+  int unwind_idx = N_UNWIND ();
+  PUSH_UNWIND();
+  UNWIND (unwind_idx).m_ip_start = CODE_SIZE ();
+
+  UNWIND (unwind_idx).m_unwind_entry_type =
+    unwind_entry_type::FOR_LOOP;
+
+  // For loops add two native ints and one ov to the stack,
+  // and switches add one ov to the stack, so we need to
+  // record how many things we have added to the stack,
+  // not counting this for loop. From for loops and
+  // switches.
+  int n_things_on_stack = n_on_stack_due_to_stmt();
+
+  // Store added things on stack (due to for loops and switches)
+  // in the unwind table.
+  UNWIND (unwind_idx).m_stack_depth = n_things_on_stack;
+
+  PUSH_CODE (INSTR::FOR_COMPLEX_SETUP);
+  int need_after0 = CODE_SIZE ();
+  PUSH_CODE_SHORT (-1); // Placeholder for after address for a jump if rhs is undefined
+
+  int cond_offset = CODE_SIZE ();
+  PUSH_CODE (INSTR::FOR_COMPLEX_COND);
+  int need_after1 = CODE_SIZE ();
+  PUSH_CODE_SHORT (-1); // Placeholder for after address
+  PUSH_WSLOT (SLOT (key_name));
+  PUSH_WSLOT (SLOT (val_name));
+
+  // Walk body
+  tree_statement_list *list = cmd.body ();
+    // The body can be empty
+  if (list)
+    {
+      m_n_nested_loops++;
+      PUSH_NESTING_STATEMENT (nesting_statement::FOR_LOOP);
+      PUSH_BREAKS ();
+      PUSH_CONTINUE_TARGET ();
+      list->accept (*this);
+      for (int offset : POP_CONTINUE_TARGET())
+        SET_CODE_SHORT (offset, cond_offset);
+      POP_NESTING_STATEMENT ();
+      m_n_nested_loops--;
+    }
+
+  // Jump to condition block, TODO: unless all paths terminated
+  PUSH_CODE (INSTR::JMP);
+  PUSH_CODE_SHORT (cond_offset);
+
+  // Now we can set the after jump in cond and setup
+  SET_CODE_SHORT (need_after0, CODE_SIZE ());
+  SET_CODE_SHORT (need_after1, CODE_SIZE ());
+
+  if (list)
+    {
+      // Also all breaks jump to here
+      for (int need_break : POP_BREAKS ())
+        {
+          SET_CODE_SHORT (need_break, CODE_SIZE ());
+        }
+    }
+
+  // Mark an end to the special for loop unwind entry
+  UNWIND (unwind_idx).m_ip_end = CODE_SIZE ();
+
+  // We need to pop the counter, n and rhs struct
+  PUSH_CODE (INSTR::POP_N_INTS);
+  PUSH_CODE (2);
+  // Pop the rhs ov (the struct)
+  PUSH_CODE (INSTR::POP);
+}
+
+void
+bytecode_walker::
+visit_fcn_handle (tree_fcn_handle &handle)
+{
+  INC_DEPTH ();
+  std::string name = handle.name ();
+  // We prepend the handles with @ to not risk collisions with
+  // other identifiers in the id table
+  std::string aname = "@" + name;
+
+  if (name.find ('.') != std::string::npos)
+    TODO ("No support for method fcn handles yet");
+
+  // slot for the handle function cache
+  int slot = add_id_to_table(aname);
+
+  MAYBE_PUSH_WIDE_OPEXT (slot);
+  PUSH_CODE (INSTR::PUSH_FCN_HANDLE);
+  PUSH_SLOT (slot);
+
+  maybe_emit_bind_ans_and_disp (handle);
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+visit_colon_expression (tree_colon_expression& expr)
+{
+  INC_DEPTH ();
+
+  tree_expression *op1 = expr.base ();
+
+  CHECK_NONNULL (op1);
+  op1->accept (*this);
+
+  tree_expression *op2 = expr.increment ();
+
+  if (op2)
+    op2->accept (*this);
+
+  tree_expression *op3 = expr.limit ();
+
+  CHECK_NONNULL (op3);
+  op3->accept (*this);
+
+  // Colon expressions have some different semantics
+  // in command expressions.
+  if (expr.is_for_cmd_expr ())
+    {
+      if (op2)
+        PUSH_CODE (INSTR::COLON3_CMD);
+      else
+        PUSH_CODE (INSTR::COLON2_CMD);
+    }
+  else
+    {
+      if (op2)
+        PUSH_CODE (INSTR::COLON3);
+      else
+        PUSH_CODE (INSTR::COLON2);
+    }
+
+  maybe_emit_bind_ans_and_disp (expr);
+
+  DEC_DEPTH ();
+}
+
+void
+bytecode_walker::
+visit_break_command (tree_break_command&)
+{
+  PUSH_CODE (INSTR::JMP);
+  // Need to set where to jump to after we know where the loop ends
+  PUSH_NEED_BREAK (CODE_SIZE ());
+  PUSH_CODE_SHORT (-1); // Placeholder
+}
+
+
+
+void
+bytecode_walker::
+visit_continue_command (tree_continue_command&)
+{
+  PUSH_CODE (INSTR::JMP);
+  // The address to jump to need to be set by the loop
+  // visitor (do until jumps forward), så push the code
+  // address that need a target address.
+  PUSH_NEED_CONTINUE_TARGET (CODE_SIZE ());
+  PUSH_CODE_SHORT (-1); // Placeholder
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode-walk.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,418 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_pt_bytecode_walk_h)
+#define octave_pt_bytecode_walk_h 1
+
+#include <map>
+
+#include "octave-config.h"
+#include "pt-walk.h"
+#include "error.h"
+
+#include "pt-bytecode-vm.h"
+
+class octave_user_script;
+class octave_user_function;
+
+#define ERROR_NOT_IMPLEMENTED \
+{ error("Not implemented %s:%d", __FILE__, __LINE__); }
+
+namespace octave
+{
+  void compile_user_function (octave_user_function &fn, bool print);
+
+  // No separate visitor needed
+  // Base classes only, so no need to include them.
+  //
+  //  class tree_array_list
+  //  class tree_unary_expression
+  //  class tree_black_hole
+
+  class tree_anon_fcn_handle;
+  class tree_arg_size_spec;
+  class tree_arg_validation;
+  class tree_arg_validation_fcns;
+  class tree_args_block_attribute_list;
+  class tree_args_block_validation_list;
+  class tree_argument_list;
+  class tree_arguments_block;
+  class tree_binary_expression;
+  class tree_boolean_expression;
+  class tree_compound_binary_expression;
+  class tree_break_command;
+  class tree_colon_expression;
+  class tree_continue_command;
+  class tree_decl_command;
+  class tree_decl_init_list;
+  class tree_decl_elt;
+  class tree_simple_for_command;
+  class tree_complex_for_command;
+  class tree_spmd_command;
+  class tree_function_def;
+  class tree_identifier;
+  class tree_if_clause;
+  class tree_if_command;
+  class tree_if_command_list;
+  class tree_switch_case;
+  class tree_switch_case_list;
+  class tree_switch_command;
+  class tree_index_expression;
+  class tree_matrix;
+  class tree_cell;
+  class tree_multi_assignment;
+  class tree_no_op_command;
+  class tree_constant;
+  class tree_fcn_handle;
+  class tree_parameter_list;
+  class tree_postfix_expression;
+  class tree_prefix_expression;
+  class tree_return_command;
+  class tree_simple_assignment;
+  //class tree_simple_index_expression;
+  class tree_statement;
+  //class tree_statement_cmd;
+  //class tree_statement_expression;
+  //class tree_statement_null;
+  class tree_statement_list;
+  class tree_try_catch_command;
+  class tree_unwind_protect_command;
+  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;
+  class tree_classdef_superclass_list;
+  class tree_classdef_property;
+  class tree_classdef_property_list;
+  class tree_classdef_properties_block;
+  class tree_classdef_methods_list;
+  class tree_classdef_methods_block;
+  class tree_classdef_event;
+  class tree_classdef_events_list;
+  class tree_classdef_events_block;
+  class tree_classdef_enum;
+  class tree_classdef_enum_list;
+  class tree_classdef_enum_block;
+  class tree_classdef_body;
+  class tree_classdef;
+
+  struct id_being_indexed
+  {
+    int slot;
+    int idx;
+    int nargs;
+    int type;
+  };
+
+  class bytecode_walker : public tree_walker
+  {
+  public:
+
+    enum class nesting_statement
+      {
+        INVALID,
+        FOR_LOOP,
+        ONE_OV_ON_STACK,
+      };
+
+    bytecode_walker (void) { }
+
+    virtual ~bytecode_walker (void) = default;
+
+    // The bytecode will be put in this container
+    bytecode m_code;
+    // The bytecode need its own scope object that will
+    // be written back to the octave_user_function object
+    symbol_scope m_scope;
+
+    bool m_varargout = false;
+
+    std::vector<std::vector<int>> m_continue_target;
+    std::vector<std::vector<int>> m_need_break_target;
+    std::vector<int> m_loop_target;
+    std::vector<bool> m_all_paths_terminated;
+    std::vector<int> m_nargout;
+    std::vector<std::vector<int>> m_need_unwind_target;
+
+    std::vector<nesting_statement> m_nesting_statement;
+
+    // For "end" in indexing expression we need to know what variable is
+    // being indexed.
+    std::vector<id_being_indexed> m_indexed_id;
+
+    int m_depth = 0;
+    int m_offset_n_locals = -1;
+    int m_n_locals = 0;
+    int m_n_nested_loops = 0;
+
+    // Counter to choose different alternative op-codes in a try to help branch prediction
+    int m_cnt_alts_cst = 0;
+    int m_cnt_alts_mul = 0;
+    int m_cnt_alts_add = 0;
+    int m_cnt_alts_div = 0;
+
+    // Simple way to keep down amount of temporary slots made to store results
+    int m_n_multi_assign = 0;
+
+    // Need to keep track of ignored outputs with the '~'
+    bool m_pending_ignore_outputs = false;
+    int m_ignored_of_total = 0;
+    std::vector<int> m_v_ignored;
+
+    //
+    bool m_is_folding = false;
+    std::vector<tree*> m_v_trees_to_fold;
+    std::vector<int> m_v_offset_of_folds;
+    int m_n_folds = 0;
+
+    std::map<std::string, int> m_map_locals_to_slot;
+
+    std::map<std::string, bool> m_map_id_is_global;
+    std::map<std::string, bool> m_map_id_is_persistent;
+
+    static std::map<std::string, octave_base_value::unary_mapper_t> m_name_to_unary_func;
+
+    int add_id_to_table (std::string name);
+
+    int n_on_stack_due_to_stmt ();
+
+    void emit_return ();
+
+    void emit_alt (int &cntr, std::vector<INSTR> alts);
+
+    void emit_load_2_cst (tree_expression *lhs, tree_expression *rhs);
+
+    void maybe_emit_bind_ans_and_disp (tree_expression &expr, const std::string maybe_cmd_name = "");
+    void maybe_emit_disp_id (tree_expression &expr, const std::string &name, const std::string maybe_cmd_name = "" );
+    void maybe_emit_push_and_disp_id (tree_expression &expr, const std::string &name, const std::string maybe_cmd_name = "");
+    void emit_disp_obj (tree_expression &expr);
+
+    int get_slot (std::string name)
+    {
+      auto it = m_map_locals_to_slot.find (name);
+      if (it == m_map_locals_to_slot.end ())
+        error ("VM internal error: Slot %s does not exist", name.c_str ());
+      return it->second;
+    }
+
+    void ctor_unary_map ();
+
+    // No copying!
+
+    bytecode_walker (const bytecode_walker&) = delete;
+
+    bytecode_walker& operator = (const bytecode_walker&) = delete;
+
+    void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+
+    void visit_argument_list (tree_argument_list&) ERROR_NOT_IMPLEMENTED
+
+    void visit_arguments_block (tree_arguments_block&) ERROR_NOT_IMPLEMENTED
+
+    void visit_args_block_attribute_list (tree_args_block_attribute_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_args_block_validation_list (tree_args_block_validation_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_arg_validation (tree_arg_validation&) ERROR_NOT_IMPLEMENTED
+
+    void visit_arg_size_spec (tree_arg_size_spec&) ERROR_NOT_IMPLEMENTED
+
+    void visit_arg_validation_fcns (tree_arg_validation_fcns&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_binary_expression (tree_binary_expression&);
+
+    void visit_boolean_expression (tree_boolean_expression&);
+
+    void visit_compound_binary_expression (tree_compound_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_elt (tree_decl_elt&) ERROR_NOT_IMPLEMENTED
+
+    void visit_decl_init_list (tree_decl_init_list&) ERROR_NOT_IMPLEMENTED
+
+    void visit_simple_for_command (tree_simple_for_command&);
+
+    void visit_complex_for_command (tree_complex_for_command&);
+
+    void visit_spmd_command (tree_spmd_command&) ERROR_NOT_IMPLEMENTED
+
+    void visit_octave_user_script (octave_user_script&) ERROR_NOT_IMPLEMENTED
+
+    void visit_octave_user_function (octave_user_function&);
+
+    void visit_function_def (tree_function_def&) ERROR_NOT_IMPLEMENTED
+
+    void visit_identifier (tree_identifier&);
+
+    void visit_if_clause (tree_if_clause&) ERROR_NOT_IMPLEMENTED
+
+    void visit_if_command (tree_if_command&);
+
+    void visit_if_command_list (tree_if_command_list&) ERROR_NOT_IMPLEMENTED
+
+    void visit_switch_case (tree_switch_case&) ERROR_NOT_IMPLEMENTED
+
+    void visit_switch_case_list (tree_switch_case_list&) ERROR_NOT_IMPLEMENTED
+
+    void visit_switch_command (tree_switch_command&);
+
+    // Helper functions
+    void
+    emit_args_for_visit_index_expression (tree_argument_list *arg_list,
+                                          tree_expression *lhs_root);
+
+    void
+    emit_fields_for_visit_index_expression (string_vector &field_names,
+                                            tree_expression *dyn_expr,
+                                            tree_expression *lhs_root,
+                                            bool *struct_is_id_dot_id);
+
+    void simple_visit_index_expression (tree_index_expression&);
+    void eval_visit_index_expression (tree_index_expression&);
+
+    void visit_index_expression (tree_index_expression&);
+
+    //void visit_simple_index_expression (tree_simple_index_expression&);
+
+    void visit_matrix (tree_matrix&);
+
+    void visit_cell (tree_cell&);
+
+    void visit_multi_assignment (tree_multi_assignment&);
+
+    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&) ERROR_NOT_IMPLEMENTED
+
+    void visit_postfix_expression (tree_postfix_expression&);
+
+    void visit_prefix_expression (tree_prefix_expression&);
+
+    void visit_return_command (tree_return_command&);
+
+    void visit_simple_assignment (tree_simple_assignment&);
+
+    void visit_statement (tree_statement&);
+
+    void visit_statement_list (tree_statement_list&);
+
+    void visit_try_catch_command (tree_try_catch_command&);
+
+    void emit_unwind_protect_code (tree_statement_list *body,
+                                   tree_statement_list *cleanup_code,
+                                   tree_expression *body_expr = nullptr,
+                                   tree_expression *cleanup_expr = nullptr,
+                                   std::vector<int> cleanup_instructions = {});
+
+    struct emit_unwind_protect_data
+    {
+      int m_idx_unwind;
+      bool m_break_stack_populated;
+      std::vector<int> m_v_need_breaks_initial;
+      int m_n_need_break;
+      int m_n_need_cleanup;
+    };
+
+    emit_unwind_protect_data emit_unwind_protect_code_start ();
+    void emit_unwind_protect_code_before_cleanup (emit_unwind_protect_data &data);
+    void emit_unwind_protect_code_end (emit_unwind_protect_data &data);
+
+    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&) ERROR_NOT_IMPLEMENTED
+
+    void visit_metaclass_query (tree_metaclass_query&) ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_attribute (tree_classdef_attribute&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_attribute_list (tree_classdef_attribute_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_superclass (tree_classdef_superclass&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_superclass_list (tree_classdef_superclass_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_property (tree_classdef_property&) ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_property_list (tree_classdef_property_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_properties_block (tree_classdef_properties_block&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_methods_list (tree_classdef_methods_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_methods_block (tree_classdef_methods_block&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_event (tree_classdef_event&) ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_events_list (tree_classdef_events_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_events_block (tree_classdef_events_block&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_enum (tree_classdef_enum&) ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_enum_list (tree_classdef_enum_list&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_enum_block (tree_classdef_enum_block&)
+      ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef_body (tree_classdef_body&) ERROR_NOT_IMPLEMENTED
+
+    void visit_classdef (tree_classdef&) ERROR_NOT_IMPLEMENTED
+  };
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-bytecode.h	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,293 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2023 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// 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_pt_bytecode_h)
+#define octave_pt_bytecode_h 1
+
+#include <vector>
+#include <map>
+
+#include "octave-config.h"
+#include "Cell.h"
+#include "ov-vm.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+class tree;
+
+enum class INSTR
+{
+  POP,
+  DUP,
+  LOAD_CST,
+  MUL,
+  DIV,
+  ADD,
+  SUB,
+  RET,
+  ASSIGN,
+  JMP_IF,
+  JMP,
+  JMP_IFN,
+  PUSH_SLOT_NARGOUT0,
+  LE,
+  LE_EQ,
+  GR,
+  GR_EQ,
+  EQ,
+  NEQ,
+  INDEX_ID_NARGOUT0,
+  PUSH_SLOT_INDEXED,
+  POW,
+  LDIV,
+  EL_MUL,
+  EL_DIV,
+  EL_POW,
+  EL_AND,
+  EL_OR,
+  EL_LDIV,
+  NOT,
+  UADD,
+  USUB,
+  TRANS,
+  HERM,
+  // TODO: These should have an inplace optimization (no push)
+  INCR_ID_PREFIX,
+  DECR_ID_PREFIX,
+  INCR_ID_POSTFIX,
+  DECR_ID_POSTFIX,
+  FOR_SETUP,
+  FOR_COND,
+  POP_N_INTS,
+  PUSH_SLOT_NARGOUT1,
+  INDEX_ID_NARGOUT1,
+  PUSH_FCN_HANDLE,
+  COLON3,
+  COLON2,
+  COLON3_CMD,
+  COLON2_CMD,
+  PUSH_TRUE,
+  PUSH_FALSE,
+  UNARY_TRUE,
+  INDEX_IDN,
+  ASSIGNN,
+  PUSH_SLOT_NARGOUTN,
+  SUBASSIGN_ID,
+  END_ID,
+  MATRIX,
+  TRANS_MUL,
+  MUL_TRANS,
+  HERM_MUL,
+  MUL_HERM,
+  TRANS_LDIV,
+  HERM_LDIV,
+  WORDCMD,
+  HANDLE_SIGNALS,
+  PUSH_CELL,
+  PUSH_OV_U64,
+  EXPAND_CS_LIST,
+  INDEX_CELL_ID_NARGOUT0,
+  INDEX_CELL_ID_NARGOUT1,
+  INDEX_CELL_ID_NARGOUTN,
+  INCR_PREFIX,
+  ROT,
+  GLOBAL_INIT,
+  ASSIGN_COMPOUND,
+  JMP_IFDEF,
+  JMP_IFNCASEMATCH,
+  BRAINDEAD_PRECONDITION,
+  BRAINDEAD_WARNING,
+  FORCE_ASSIGN, // Accepts undefined rhs
+  PUSH_NIL,
+  THROW_IFERROBJ,
+  INDEX_STRUCT_NARGOUTN,
+  SUBASSIGN_STRUCT,
+  SUBASSIGN_CELL_ID,
+  INDEX_OBJ,
+  SUBASSIGN_OBJ,
+  MATRIX_UNEVEN,
+  LOAD_FAR_CST,
+  END_OBJ,
+  SET_IGNORE_OUTPUTS,
+  CLEAR_IGNORE_OUTPUTS,
+  SUBASSIGN_CHAINED,
+  SET_SLOT_TO_STACK_DEPTH,
+  DUPN,
+  DEBUG,
+  INDEX_STRUCT_CALL,
+  END_X_N,
+  EVAL,
+  BIND_ANS,
+  PUSH_ANON_FCN_HANDLE,
+  FOR_COMPLEX_SETUP, // opcode
+  FOR_COMPLEX_COND,
+  PUSH_SLOT_NARGOUT1_SPECIAL,
+  DISP,
+  PUSH_SLOT_DISP,
+  LOAD_CST_ALT2,
+  LOAD_CST_ALT3,
+  LOAD_CST_ALT4,
+  LOAD_2_CST,
+  MUL_DBL,
+  ADD_DBL,
+  SUB_DBL,
+  DIV_DBL,
+  POW_DBL,
+  LE_DBL,
+  LE_EQ_DBL,
+  GR_DBL,
+  GR_EQ_DBL,
+  EQ_DBL,
+  NEQ_DBL,
+  INDEX_ID1_MAT_1D,
+  INDEX_ID1_MAT_2D,
+  PUSH_PI,
+  INDEX_ID1_MATHY_UFUN,
+  SUBASSIGN_ID_MAT_1D,
+  INCR_ID_PREFIX_DBL,
+  DECR_ID_PREFIX_DBL,
+  INCR_ID_POSTFIX_DBL,
+  DECR_ID_POSTFIX_DBL,
+  PUSH_DBL_0,
+  PUSH_DBL_1,
+  PUSH_DBL_2,
+  JMP_IF_BOOL,
+  JMP_IFN_BOOL,
+  USUB_DBL,
+  NOT_DBL,
+  NOT_BOOL,
+  PUSH_FOLDED_CST,
+  SET_FOLDED_CST,
+  WIDE,
+};
+
+enum class unwind_entry_type
+{
+  INVALID,
+  FOR_LOOP,
+  TRY_CATCH,
+  UNWIND_PROTECT,
+};
+
+struct unwind_entry
+{
+  int m_ip_start;
+  int m_ip_end;
+  int m_ip_target;
+  int m_stack_depth;
+  unwind_entry_type m_unwind_entry_type;
+};
+
+struct loc_entry
+{
+  int m_ip_start = -1;
+  int m_ip_end = -1;
+  int m_col = -1;
+  int m_line = -1;
+};
+
+struct arg_name_entry
+{
+  int m_ip_start;
+  int m_ip_end;
+  Cell m_arg_names;
+  std::string m_obj_name;
+};
+
+struct unwind_data
+{
+  std::vector<unwind_entry> m_unwind_entries;
+  std::vector<loc_entry> m_loc_entry;
+  std::map<int, int> m_slot_to_persistent_slot;
+  std::map<int, tree*> m_ip_to_tree;
+  std::vector<arg_name_entry> m_argname_entries;
+  std::map<int,int> m_external_frame_offset_to_internal;
+
+  std::string m_name;
+  std::string m_file;
+
+  unsigned m_code_size;
+  unsigned m_ids_size;
+};
+
+struct bytecode
+{
+  std::vector<unsigned char> m_code;
+  std::vector<octave_value> m_data;
+  std::vector<std::string> m_ids;
+  unwind_data m_unwind_data;
+};
+
+union stack_element
+{
+  octave_value ov;
+  octave_value_vm ov_vm;
+  octave_base_value *ovb;
+  uint64_t u;
+  int64_t i;
+  double d;
+
+  void *pv;
+  const char *pcc;
+  unsigned char *puc;
+  stack_element *pse;
+  octave_value *pov;
+  std::string *ps;
+  unwind_data *pud;
+  execution_exception *pee;
+
+  stack_element(){}
+  ~stack_element(){}
+};
+
+// Enums to describe what error message to build
+enum class error_type
+{
+  INVALID,
+  ID_UNDEFINED,
+  ID_UNDEFINEDN,
+  IF_UNDEFINED,
+  INDEX_ERROR,
+  EXECUTION_EXC,
+  INTERRUPT_EXC,
+  INVALID_N_EL_RHS_IN_ASSIGNMENT,
+  RHS_UNDEF_IN_ASSIGNMENT,
+  BAD_ALLOC,
+  EXIT_EXCEPTION,
+};
+
+enum class global_type
+{
+  GLOBAL,
+  PERSISTENT,
+  GLOBAL_OR_PERSISTENT,
+};
+
+// If TRUE, use VM evaluator rather than tree walker.
+extern bool V__enable_vm_eval__;
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- a/libinterp/parse-tree/pt-cbinop.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-cbinop.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -89,32 +89,6 @@
     return octave_value::unknown_unary_op;
 }
 
-#if 0
-// Restore this code if short-circuit behavior can be preserved when needed.
-// See bug #54465.
-
-static octave_value::unary_op
-strip_not (tree_expression_ptr_t& exp)
-{
-  if (exp->is_unary_expression ())
-    {
-      tree_unary_expression *uexp
-        = dynamic_cast<tree_unary_expression *> (exp);
-
-      octave_value::unary_op op = uexp->op_type ();
-
-      if (op == octave_value::op_not)
-        exp = uexp->operand ();
-      else
-        op = octave_value::unknown_unary_op;
-
-      return op;
-    }
-  else
-    return octave_value::unknown_unary_op;
-}
-#endif
-
 // Possibly convert multiplication to trans_mul, mul_trans, herm_mul,
 // or mul_herm.
 
@@ -163,42 +137,6 @@
 
 // Possibly contract and/or with negation.
 
-#if 0
-// Restore this code if short-circuit behavior can be preserved when needed.
-// See bug #54465.
-static octave_value::compound_binary_op
-simplify_and_or_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b,
-                    octave_value::binary_op op)
-{
-  octave_value::compound_binary_op retop
-    = octave_value::unknown_compound_binary_op;
-
-  octave_value::unary_op opa = strip_not (a);
-
-  if (opa == octave_value::op_not)
-    {
-      if (op == octave_value::op_el_and)
-        retop = octave_value::op_el_not_and;
-      else if (op == octave_value::op_el_or)
-        retop = octave_value::op_el_not_or;
-    }
-  else
-    {
-      octave_value::unary_op opb = strip_not (b);
-
-      if (opb == octave_value::op_not)
-        {
-          if (op == octave_value::op_el_and)
-            retop = octave_value::op_el_and_not;
-          else if (op == octave_value::op_el_or)
-            retop = octave_value::op_el_or_not;
-        }
-    }
-
-  return retop;
-}
-#endif
-
 tree_binary_expression *
 maybe_compound_binary_expression (tree_expression *a, tree_expression *b,
                                   int l, int c, octave_value::binary_op t)
@@ -217,15 +155,6 @@
       ct = simplify_ldiv_op (ca, cb);
       break;
 
-#if 0
-    // Restore this case if short-circuit behavior can be preserved
-    // when needed.  See bug #54465.
-    case octave_value::op_el_and:
-    case octave_value::op_el_or:
-      ct = simplify_and_or_op (ca, cb, t);
-      break;
-#endif
-
     default:
       ct = octave_value::unknown_compound_binary_op;
       break;
--- a/libinterp/parse-tree/pt-cbinop.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-cbinop.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,12 +54,17 @@
       m_etype (ct)
   { }
 
-  octave_value::compound_binary_op cop_type (void) const { return m_etype; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_compound_binary_expression)
+
+  // FIXME: who is responsibile for deleting M_LHS and M_RHS?
+  ~tree_compound_binary_expression () = default;
 
-  bool rvalue_ok (void) const { return true; }
+  octave_value::compound_binary_op cop_type () const { return m_etype; }
 
-  tree_expression * clhs (void) { return m_lhs; }
-  tree_expression * crhs (void) { return m_rhs; }
+  bool rvalue_ok () const { return true; }
+
+  tree_expression * clhs () { return m_lhs; }
+  tree_expression * crhs () { return m_rhs; }
 
   octave_value evaluate (tree_evaluator&, int nargout = 1);
 
@@ -79,13 +84,6 @@
   tree_expression *m_rhs;
 
   octave_value::compound_binary_op m_etype;
-
-  // No copying!
-
-  tree_compound_binary_expression (const tree_compound_binary_expression&) = delete;
-
-  tree_compound_binary_expression&
-  operator = (const tree_compound_binary_expression&) = delete;
 };
 
 // a "virtual constructor"
--- a/libinterp/parse-tree/pt-cell.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-cell.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,17 +51,13 @@
     : tree_array_list (row, l, c)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_cell)
 
-  tree_cell (const tree_cell&) = delete;
-
-  tree_cell& operator = (const tree_cell&) = delete;
+  ~tree_cell () = default;
 
-  ~tree_cell (void) = default;
+  bool iscell () const { return true; }
 
-  bool iscell (void) const { return true; }
-
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
--- a/libinterp/parse-tree/pt-check.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-check.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,16 +42,12 @@
 {
 public:
 
-  tree_checker (void)
+  tree_checker ()
     : m_do_lvalue_check (false), m_file_name () { }
 
-  // No copying!
-
-  tree_checker (const tree_checker&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_checker)
 
-  tree_checker& operator = (const tree_checker&) = delete;
-
-  ~tree_checker (void) = default;
+  ~tree_checker () = default;
 
   void visit_argument_list (tree_argument_list&);
 
--- a/libinterp/parse-tree/pt-classdef.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-classdef.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -95,7 +95,7 @@
 
 // Classdef attribute_list
 
-tree_classdef_attribute_list::~tree_classdef_attribute_list (void)
+tree_classdef_attribute_list::~tree_classdef_attribute_list ()
 {
   while (! empty ())
     {
@@ -109,7 +109,7 @@
 
 // Classdef superclass_list
 
-tree_classdef_superclass_list::~tree_classdef_superclass_list (void)
+tree_classdef_superclass_list::~tree_classdef_superclass_list ()
 {
   while (! empty ())
     {
@@ -143,26 +143,26 @@
     m_doc_string (check_for_doc_string (m_comments))
 { }
 
-tree_classdef_property::~tree_classdef_property (void)
+tree_classdef_property::~tree_classdef_property ()
 {
   delete m_av;
 }
 
-tree_identifier *tree_classdef_property::ident (void)
+tree_identifier *tree_classdef_property::ident ()
 {
   tree_expression *id_expr = m_av->identifier_expression ();
 
   return dynamic_cast<tree_identifier *> (id_expr);
 }
 
-tree_expression *tree_classdef_property::expression (void)
+tree_expression *tree_classdef_property::expression ()
 {
   return m_av->initializer_expression ();
 }
 
 // Classdef property_list
 
-tree_classdef_property_list::~tree_classdef_property_list (void)
+tree_classdef_property_list::~tree_classdef_property_list ()
 {
   while (! empty ())
     {
@@ -188,7 +188,7 @@
 
 // Classdef events_list
 
-tree_classdef_events_list::~tree_classdef_events_list (void)
+tree_classdef_events_list::~tree_classdef_events_list ()
 {
   while (! empty ())
     {
@@ -211,7 +211,7 @@
 
 // Classdef enum_list
 
-tree_classdef_enum_list::~tree_classdef_enum_list (void)
+tree_classdef_enum_list::~tree_classdef_enum_list ()
 {
   while (! empty ())
     {
@@ -225,7 +225,7 @@
 
 // Classdef body
 
-tree_classdef_body::tree_classdef_body (void)
+tree_classdef_body::tree_classdef_body ()
   : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst ()
 { }
 
@@ -257,7 +257,7 @@
   append (enb);
 }
 
-tree_classdef_body::~tree_classdef_body (void)
+tree_classdef_body::~tree_classdef_body ()
 {
   while (! m_properties_lst.empty ())
     {
--- a/libinterp/parse-tree/pt-classdef.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-classdef.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,25 +50,21 @@
 {
 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;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_superclass_ref)
 
-  tree_superclass_ref& operator = (const tree_superclass_ref&) = delete;
+  ~tree_superclass_ref () = default;
 
-  std::string method_name (void) const
+  std::string method_name () const
   {
     return m_method_name;
   }
 
-  std::string class_name (void) const { return m_class_name; }
+  std::string class_name () const { return m_class_name; }
 
   tree_superclass_ref * dup (symbol_scope& scope) const;
 
@@ -101,19 +97,15 @@
 {
 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;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_metaclass_query)
 
-  tree_metaclass_query& operator = (const tree_metaclass_query&) = delete;
+  ~tree_metaclass_query () = default;
 
-  std::string class_name (void) const { return m_class_name; }
+  std::string class_name () const { return m_class_name; }
 
   tree_metaclass_query * dup (symbol_scope& scope) const;
 
@@ -147,23 +139,19 @@
     : m_id (i), m_expr (nullptr), m_neg (b)
   { }
 
-  // No copying!
-
-  tree_classdef_attribute (const tree_classdef_attribute&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute)
 
-  tree_classdef_attribute& operator = (const tree_classdef_attribute&) = delete;
-
-  ~tree_classdef_attribute (void)
+  ~tree_classdef_attribute ()
   {
     delete m_id;
     delete m_expr;
   }
 
-  tree_identifier * ident (void) { return m_id; }
+  tree_identifier * ident () { return m_id; }
 
-  tree_expression * expression (void) { return m_expr; }
+  tree_expression * expression () { return m_expr; }
 
-  bool negate (void) { return m_neg; }
+  bool negate () { return m_neg; }
 
   void accept (tree_walker& tw)
   {
@@ -181,7 +169,7 @@
 {
 public:
 
-  tree_classdef_attribute_list (void) { }
+  tree_classdef_attribute_list () { }
 
   tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); }
 
@@ -189,14 +177,9 @@
     : base_list<tree_classdef_attribute *> (a)
   { }
 
-  // No copying!
-
-  tree_classdef_attribute_list (const tree_classdef_attribute_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute_list)
 
-  tree_classdef_attribute_list&
-  operator = (const tree_classdef_attribute_list&) = delete;
-
-  ~tree_classdef_attribute_list (void);
+  ~tree_classdef_attribute_list ();
 
   void accept (tree_walker& tw)
   {
@@ -212,16 +195,11 @@
     : m_cls_name (cname)
   { }
 
-  // No copying!
-
-  tree_classdef_superclass (const tree_classdef_superclass&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_superclass)
 
-  tree_classdef_superclass&
-  operator = (const tree_classdef_superclass&) = delete;
+  ~tree_classdef_superclass () = default;
 
-  ~tree_classdef_superclass (void) = default;
-
-  std::string class_name (void) { return m_cls_name; }
+  std::string class_name () { return m_cls_name; }
 
   void accept (tree_walker& tw)
   {
@@ -238,7 +216,7 @@
 {
 public:
 
-  tree_classdef_superclass_list (void) { }
+  tree_classdef_superclass_list () { }
 
   tree_classdef_superclass_list (tree_classdef_superclass *sc)
   {
@@ -249,14 +227,9 @@
     : base_list<tree_classdef_superclass *> (a)
   { }
 
-  // No copying!
-
-  tree_classdef_superclass_list (const tree_classdef_superclass_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_superclass_list)
 
-  tree_classdef_superclass_list&
-  operator = (const tree_classdef_superclass_list&) = delete;
-
-  ~tree_classdef_superclass_list (void);
+  ~tree_classdef_superclass_list ();
 
   void accept (tree_walker& tw)
   {
@@ -276,13 +249,9 @@
       m_lead_comm (lc), m_trail_comm (tc)
   { }
 
-  // No copying!
-
-  tree_classdef_element (const tree_classdef_element&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_element)
 
-  tree_classdef_element& operator = (const tree_classdef_element&) = delete;
-
-  ~tree_classdef_element (void)
+  ~tree_classdef_element ()
   {
     delete m_attr_list;
     delete m_elt_list;
@@ -290,13 +259,13 @@
     delete m_trail_comm;
   }
 
-  tree_classdef_attribute_list * attribute_list (void) { return m_attr_list; }
+  tree_classdef_attribute_list * attribute_list () { return m_attr_list; }
 
-  T * element_list (void) { return m_elt_list; }
+  T * element_list () { return m_elt_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker&) { }
 
@@ -322,25 +291,21 @@
   tree_classdef_property (tree_arg_validation *av,
                           comment_list *comments = nullptr);
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_property)
 
-  tree_classdef_property (const tree_classdef_property&) = delete;
-
-  tree_classdef_property& operator = (const tree_classdef_property&) = delete;
+  ~tree_classdef_property ();
 
-  ~tree_classdef_property (void);
-
-  tree_identifier * ident (void);
+  tree_identifier * ident ();
 
-  tree_expression * expression (void);
+  tree_expression * expression ();
 
-  comment_list * comments (void) const { return m_comments; }
+  comment_list * comments () const { return m_comments; }
 
   void doc_string (const std::string& txt) { m_doc_string = txt; }
 
-  std::string doc_string (void) const { return m_doc_string; }
+  std::string doc_string () const { return m_doc_string; }
 
-  bool have_doc_string (void) const { return ! m_doc_string.empty (); }
+  bool have_doc_string () const { return ! m_doc_string.empty (); }
 
   void accept (tree_walker& tw)
   {
@@ -358,21 +323,16 @@
 {
 public:
 
-  tree_classdef_property_list (void) { }
+  tree_classdef_property_list () { }
 
   tree_classdef_property_list (tree_classdef_property *p) { append (p); }
 
   tree_classdef_property_list (const base_list<tree_classdef_property *>& a)
     : base_list<tree_classdef_property *> (a) { }
 
-  // No copying!
-
-  tree_classdef_property_list (const tree_classdef_property_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_property_list)
 
-  tree_classdef_property_list&
-  operator = (const tree_classdef_property_list&) = delete;
-
-  ~tree_classdef_property_list (void);
+  ~tree_classdef_property_list ();
 
   void accept (tree_walker& tw)
   {
@@ -392,14 +352,9 @@
     : tree_classdef_element<tree_classdef_property_list> (a, plist, lc, tc, l, c)
   { }
 
-  // No copying!
-
-  tree_classdef_properties_block (const tree_classdef_properties_block&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_properties_block)
 
-  tree_classdef_properties_block&
-  operator = (const tree_classdef_properties_block&) = delete;
-
-  ~tree_classdef_properties_block (void) = default;
+  ~tree_classdef_properties_block () = default;
 
   void accept (tree_walker& tw)
   {
@@ -411,21 +366,16 @@
 {
 public:
 
-  tree_classdef_methods_list (void) { }
+  tree_classdef_methods_list () { }
 
   tree_classdef_methods_list (const octave_value& f) { append (f); }
 
   tree_classdef_methods_list (const base_list<octave_value>& a)
     : base_list<octave_value> (a) { }
 
-  // No copying!
-
-  tree_classdef_methods_list (const tree_classdef_methods_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_methods_list)
 
-  tree_classdef_methods_list&
-  operator = (const tree_classdef_methods_list&) = delete;
-
-  ~tree_classdef_methods_list (void) = default;
+  ~tree_classdef_methods_list () = default;
 
   void accept (tree_walker& tw)
   {
@@ -445,14 +395,9 @@
     : tree_classdef_element<tree_classdef_methods_list> (a, mlist, lc, tc, l, c)
   { }
 
-  // No copying!
-
-  tree_classdef_methods_block (const tree_classdef_methods_block&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_methods_block)
 
-  tree_classdef_methods_block&
-  operator = (const tree_classdef_methods_block&) = delete;
-
-  ~tree_classdef_methods_block (void) = default;
+  ~tree_classdef_methods_block () = default;
 
   void accept (tree_walker& tw)
   {
@@ -467,26 +412,22 @@
   tree_classdef_event (tree_identifier *i = nullptr,
                        comment_list *comments = nullptr);
 
-  // No copying!
-
-  tree_classdef_event (const tree_classdef_event&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_event)
 
-  tree_classdef_event& operator = (const tree_classdef_event&) = delete;
-
-  ~tree_classdef_event (void)
+  ~tree_classdef_event ()
   {
     delete m_id;
   }
 
-  tree_identifier * ident (void) { return m_id; }
+  tree_identifier * ident () { return m_id; }
 
-  comment_list * comments (void) const { return m_comments; }
+  comment_list * comments () const { return m_comments; }
 
   void doc_string (const std::string& txt) { m_doc_string = txt; }
 
-  std::string doc_string (void) const { return m_doc_string; }
+  std::string doc_string () const { return m_doc_string; }
 
-  bool have_doc_string (void) const { return ! m_doc_string.empty (); }
+  bool have_doc_string () const { return ! m_doc_string.empty (); }
 
   void accept (tree_walker& tw)
   {
@@ -504,7 +445,7 @@
 {
 public:
 
-  tree_classdef_events_list (void) { }
+  tree_classdef_events_list () { }
 
   tree_classdef_events_list (tree_classdef_event *e) { append (e); }
 
@@ -512,14 +453,9 @@
     : base_list<tree_classdef_event *> (a)
   { }
 
-  // No copying!
-
-  tree_classdef_events_list (const tree_classdef_events_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_events_list)
 
-  tree_classdef_events_list&
-  operator = (const tree_classdef_events_list&) = delete;
-
-  ~tree_classdef_events_list (void);
+  ~tree_classdef_events_list ();
 
   void accept (tree_walker& tw)
   {
@@ -539,14 +475,9 @@
     : tree_classdef_element<tree_classdef_events_list> (a, elist, lc, tc, l, c)
   { }
 
-  // No copying!
-
-  tree_classdef_events_block (const tree_classdef_events_block&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_events_block)
 
-  tree_classdef_events_block&
-  operator = (const tree_classdef_events_block&) = delete;
-
-  ~tree_classdef_events_block (void) = default;
+  ~tree_classdef_events_block () = default;
 
   void accept (tree_walker& tw)
   {
@@ -561,29 +492,25 @@
   tree_classdef_enum (tree_identifier *i, tree_expression *e,
                       comment_list *comments);
 
-  // No copying!
-
-  tree_classdef_enum (const tree_classdef_enum&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum)
 
-  tree_classdef_enum& operator = (const tree_classdef_enum&) = delete;
-
-  ~tree_classdef_enum (void)
+  ~tree_classdef_enum ()
   {
     delete m_id;
     delete m_expr;
   }
 
-  tree_identifier * ident (void) { return m_id; }
+  tree_identifier * ident () { return m_id; }
 
-  tree_expression * expression (void) { return m_expr; }
+  tree_expression * expression () { return m_expr; }
 
-  comment_list * comments (void) const { return m_comments; }
+  comment_list * comments () const { return m_comments; }
 
   void doc_string (const std::string& txt) { m_doc_string = txt; }
 
-  std::string doc_string (void) const { return m_doc_string; }
+  std::string doc_string () const { return m_doc_string; }
 
-  bool have_doc_string (void) const { return ! m_doc_string.empty (); }
+  bool have_doc_string () const { return ! m_doc_string.empty (); }
 
   void accept (tree_walker& tw)
   {
@@ -602,7 +529,7 @@
 {
 public:
 
-  tree_classdef_enum_list (void) { }
+  tree_classdef_enum_list () { }
 
   tree_classdef_enum_list (tree_classdef_enum *e) { append (e); }
 
@@ -610,13 +537,9 @@
     : base_list<tree_classdef_enum *> (a)
   { }
 
-  // No copying!
-
-  tree_classdef_enum_list (const tree_classdef_enum_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_enum_list)
 
-  tree_classdef_enum_list& operator = (const tree_classdef_enum_list&) = delete;
-
-  ~tree_classdef_enum_list (void);
+  ~tree_classdef_enum_list ();
 
   void accept (tree_walker& tw)
   {
@@ -636,14 +559,9 @@
     : tree_classdef_element<tree_classdef_enum_list> (a, elist, lc, tc, l, c)
   { }
 
-  // No copying!
-
-  tree_classdef_enum_block (const tree_classdef_enum_block&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum_block)
 
-  tree_classdef_enum_block&
-  operator = (const tree_classdef_enum_block&) = delete;
-
-  ~tree_classdef_enum_block (void) = default;
+  ~tree_classdef_enum_block () = default;
 
   void accept (tree_walker& tw)
   {
@@ -673,7 +591,7 @@
   typedef std::list<tree_classdef_enum_block *>::const_iterator
     enum_list_const_iterator;
 
-  tree_classdef_body (void);
+  tree_classdef_body ();
 
   tree_classdef_body (tree_classdef_properties_block *pb);
 
@@ -683,13 +601,9 @@
 
   tree_classdef_body (tree_classdef_enum_block *enb);
 
-  // No copying!
-
-  tree_classdef_body (const tree_classdef_body&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_body)
 
-  tree_classdef_body& operator = (const tree_classdef_body&) = delete;
-
-  ~tree_classdef_body (void);
+  ~tree_classdef_body ();
 
   void append (tree_classdef_properties_block *pb)
   {
@@ -711,31 +625,31 @@
     m_enum_lst.push_back (enb);
   }
 
-  std::list<tree_classdef_properties_block *> properties_list (void)
+  std::list<tree_classdef_properties_block *> properties_list ()
   {
     return m_properties_lst;
   }
 
-  std::list<tree_classdef_methods_block *> methods_list (void)
+  std::list<tree_classdef_methods_block *> methods_list ()
   {
     return m_methods_lst;
   }
 
-  std::list<tree_classdef_events_block *> events_list (void)
+  std::list<tree_classdef_events_block *> events_list ()
   {
     return m_events_lst;
   }
 
-  std::list<tree_classdef_enum_block *> enum_list (void)
+  std::list<tree_classdef_enum_block *> enum_list ()
   {
     return m_enum_lst;
   }
 
   void doc_string (const std::string& txt) { m_doc_string = txt; }
 
-  std::string doc_string (void) const { return m_doc_string; }
+  std::string doc_string () const { return m_doc_string; }
 
-  bool have_doc_string (void) const { return ! m_doc_string.empty (); }
+  bool have_doc_string () const { return ! m_doc_string.empty (); }
 
   void accept (tree_walker& tw)
   {
@@ -774,13 +688,9 @@
       m_trail_comm (tc), m_pack_name (pn), m_file_name (fn)
   { }
 
-  // No copying!
-
-  tree_classdef (const tree_classdef&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef)
 
-  tree_classdef& operator = (const tree_classdef&) = delete;
-
-  ~tree_classdef (void)
+  ~tree_classdef ()
   {
     delete m_attr_list;
     delete m_id;
@@ -790,29 +700,29 @@
     delete m_trail_comm;
   }
 
-  symbol_scope scope (void) { return m_scope; }
+  symbol_scope scope () { return m_scope; }
 
   tree_classdef_attribute_list *
-  attribute_list (void) { return m_attr_list; }
+  attribute_list () { return m_attr_list; }
 
-  tree_identifier * ident (void) { return m_id; }
+  tree_identifier * ident () { return m_id; }
 
   tree_classdef_superclass_list *
-  superclass_list (void) { return m_supclass_list; }
+  superclass_list () { return m_supclass_list; }
 
-  tree_classdef_body * body (void) { return m_element_list; }
+  tree_classdef_body * body () { return m_element_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
-  std::string package_name (void) const { return m_pack_name; }
+  std::string package_name () const { return m_pack_name; }
 
-  std::string file_name (void) const { return m_file_name; }
+  std::string file_name () const { return m_file_name; }
 
   octave_value make_meta_class (interpreter& interp,
                                 bool is_at_folder = false);
 
-  std::string doc_string (void) const
+  std::string doc_string () const
   {
     return m_element_list ? m_element_list->doc_string () : "";
   }
--- a/libinterp/parse-tree/pt-cmd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-cmd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,13 +46,9 @@
   tree_command (int l = -1, int c = -1)
     : tree (l, c) { }
 
-  // No copying!
-
-  tree_command (const tree_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_command)
 
-  tree_command& operator = (const tree_command&) = delete;
-
-  virtual ~tree_command (void) = default;
+  virtual ~tree_command () = default;
 };
 
 // No-op.
@@ -65,27 +61,23 @@
                       int l = -1, int c = -1)
     : tree_command (l, c), m_eof (e), m_orig_cmd (cmd) { }
 
-  // No copying!
-
-  tree_no_op_command (const tree_no_op_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_no_op_command)
 
-  tree_no_op_command& operator = (const tree_no_op_command&) = delete;
-
-  ~tree_no_op_command (void) = default;
+  ~tree_no_op_command () = default;
 
   void accept (tree_walker& tw)
   {
     tw.visit_no_op_command (*this);
   }
 
-  bool is_end_of_fcn_or_script (void) const
+  bool is_end_of_fcn_or_script () const
   {
     return (m_orig_cmd == "endfunction" || m_orig_cmd == "endscript");
   }
 
-  bool is_end_of_file (void) const { return m_eof; }
+  bool is_end_of_file () const { return m_eof; }
 
-  std::string original_command (void) { return m_orig_cmd; }
+  std::string original_command () { return m_orig_cmd; }
 
 private:
 
@@ -103,20 +95,16 @@
   tree_function_def (octave_function *f, int l = -1, int c = -1)
     : tree_command (l, c), m_fcn (f) { }
 
-  // No copying!
-
-  tree_function_def (const tree_function_def&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_function_def)
 
-  tree_function_def& operator = (const tree_function_def&) = delete;
-
-  ~tree_function_def (void) = default;
+  ~tree_function_def () = default;
 
   void accept (tree_walker& tw)
   {
     tw.visit_function_def (*this);
   }
 
-  octave_value function (void) { return m_fcn; }
+  octave_value function () { return m_fcn; }
 
 private:
 
--- a/libinterp/parse-tree/pt-colon.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-colon.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,13 +60,9 @@
     : tree_expression (l, c), m_base (bas), m_limit (lim),
       m_increment (inc), m_save_base (false) { }
 
-  // No copying!
-
-  tree_colon_expression (const tree_colon_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_colon_expression)
 
-  tree_colon_expression& operator = (const tree_colon_expression&) = delete;
-
-  ~tree_colon_expression (void)
+  ~tree_colon_expression ()
   {
     if (! m_save_base)
       delete m_base;
@@ -75,21 +71,21 @@
     delete m_increment;
   }
 
-  void preserve_base (void) { m_save_base = true; }
+  void preserve_base () { m_save_base = true; }
 
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   void eval_error (const std::string& s) const;
 
-  tree_expression * base (void) { return m_base; }
+  tree_expression * base () { return m_base; }
 
-  tree_expression * limit (void) { return m_limit; }
+  tree_expression * limit () { return m_limit; }
 
-  tree_expression * increment (void) { return m_increment; }
+  tree_expression * increment () { return m_increment; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
-  bool is_colon_expression (void) const { return true; }
+  bool is_colon_expression () const { return true; }
 
   octave_value evaluate (tree_evaluator&, int nargout = 1);
 
--- a/libinterp/parse-tree/pt-const.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-const.h	Fri Jun 23 20:51:51 2023 +0200
@@ -61,19 +61,15 @@
     : tree_expression (l, c), m_value (v), m_orig_text (ot)
   { }
 
-  // No copying!
-
-  tree_constant (const tree_constant&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_constant)
 
-  tree_constant& operator = (const tree_constant&) = delete;
-
-  ~tree_constant (void) = default;
+  ~tree_constant () = default;
 
   // Type.  It would be nice to eliminate the need for this.
 
-  bool is_constant (void) const { return true; }
+  bool is_constant () const { return true; }
 
-  void maybe_mutate (void) { m_value.maybe_mutate (); }
+  void maybe_mutate () { m_value.maybe_mutate (); }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false,
               bool pr_orig_txt = true);
@@ -81,9 +77,9 @@
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
                   bool pr_orig_txt = true);
 
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
-  octave_value value (void) { return m_value; }
+  octave_value value () { return m_value; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -97,7 +93,7 @@
 
   void stash_original_text (const std::string& s) { m_orig_text = s; }
 
-  std::string original_text (void) const { return m_orig_text; }
+  std::string original_text () const { return m_orig_text; }
 
   octave_value evaluate (tree_evaluator&, int nargout = 1)
   {
--- a/libinterp/parse-tree/pt-decl.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-decl.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -45,13 +45,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)
+  : m_type (unknown), m_id (i), m_expr (e)
 {
   if (! m_id)
     error ("tree_decl_elt: invalid ID");
 }
 
-tree_decl_elt::~tree_decl_elt (void)
+tree_decl_elt::~tree_decl_elt ()
 {
   delete m_id;
   delete m_expr;
@@ -84,7 +84,7 @@
     }
 }
 
-tree_decl_command::~tree_decl_command (void)
+tree_decl_command::~tree_decl_command ()
 {
   delete m_init_list;
 }
--- a/libinterp/parse-tree/pt-decl.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-decl.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,37 +59,33 @@
 
   tree_decl_elt (tree_identifier *i, tree_expression *e = nullptr);
 
-  // No copying!
-
-  tree_decl_elt (const tree_decl_elt&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_decl_elt)
 
-  tree_decl_elt& operator = (const tree_decl_elt&) = delete;
+  ~tree_decl_elt ();
 
-  ~tree_decl_elt (void);
-
-  void mark_as_formal_parameter (void)
+  void mark_as_formal_parameter ()
   {
     m_id->mark_as_formal_parameter ();
   }
 
-  bool lvalue_ok (void) { return m_id->lvalue_ok (); }
+  bool lvalue_ok () { return m_id->lvalue_ok (); }
 
   octave_lvalue lvalue (tree_evaluator& tw)
   {
     return m_id->lvalue (tw);
   }
 
-  void mark_global (void) { type = global; }
-  bool is_global (void) const { return type == global; }
+  void mark_global () { m_type = global; }
+  bool is_global () const { return m_type == global; }
 
-  void mark_persistent (void) { type = persistent; }
-  bool is_persistent (void) const { return type == persistent; }
+  void mark_persistent () { m_type = persistent; }
+  bool is_persistent () const { return m_type == persistent; }
 
-  tree_identifier * ident (void) { return m_id; }
+  tree_identifier * ident () { return m_id; }
 
-  std::string name (void) const { return m_id->name (); }
+  std::string name () const { return m_id->name (); }
 
-  tree_expression * expression (void) { return m_expr; }
+  tree_expression * expression () { return m_expr; }
 
   tree_decl_elt * dup (symbol_scope& scope) const;
 
@@ -100,7 +96,7 @@
 
 private:
 
-  decl_type type;
+  decl_type m_type;
 
   // An identifier to tag with the declared property.
   tree_identifier *m_id;
@@ -113,17 +109,13 @@
 {
 public:
 
-  tree_decl_init_list (void) { }
+  tree_decl_init_list () { }
 
   tree_decl_init_list (tree_decl_elt *t) { append (t); }
 
-  // No copying!
-
-  tree_decl_init_list (const tree_decl_init_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_decl_init_list)
 
-  tree_decl_init_list& operator = (const tree_decl_init_list&) = delete;
-
-  ~tree_decl_init_list (void)
+  ~tree_decl_init_list ()
   {
     while (! empty ())
       {
@@ -133,19 +125,19 @@
       }
   }
 
-  void mark_global (void)
+  void mark_global ()
   {
     for (tree_decl_elt *elt : *this)
       elt->mark_global ();
   }
 
-  void mark_persistent (void)
+  void mark_persistent ()
   {
     for (tree_decl_elt *elt : *this)
       elt->mark_persistent ();
   }
 
-  std::list<std::string> variable_names (void) const
+  std::list<std::string> variable_names () const
   {
     std::list<std::string> retval;
 
@@ -178,29 +170,25 @@
   tree_decl_command (const std::string& n, tree_decl_init_list *t,
                      int l = -1, int c = -1);
 
-  // No copying!
-
-  tree_decl_command (const tree_decl_command&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_decl_command)
 
-  tree_decl_command& operator = (const tree_decl_command&) = delete;
+  ~tree_decl_command ();
 
-  ~tree_decl_command (void);
-
-  void mark_global (void)
+  void mark_global ()
   {
     if (m_init_list)
       m_init_list->mark_global ();
   }
 
-  void mark_persistent (void)
+  void mark_persistent ()
   {
     if (m_init_list)
       m_init_list->mark_persistent ();
   }
 
-  tree_decl_init_list * initializer_list (void) { return m_init_list; }
+  tree_decl_init_list * initializer_list () { return m_init_list; }
 
-  std::string name (void) const { return m_cmd_name; }
+  std::string name () const { return m_cmd_name; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-eval.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -72,6 +72,7 @@
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
+#include "pt-bytecode-vm.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -87,9 +88,9 @@
 
   quit_debug_exception& operator = (const quit_debug_exception&) = default;
 
-  ~quit_debug_exception (void) = default;
-
-  bool all (void) const { return m_all; }
+  ~quit_debug_exception () = default;
+
+  bool all () const { return m_all; }
 
 private:
 
@@ -101,25 +102,25 @@
 public:
 
   enum execution_mode
-  {
-    EX_NORMAL = 0,
-    EX_CONTINUE = 1,
-    EX_QUIT = 2,
-    EX_QUIT_ALL = 3
-  };
+    {
+      EX_NORMAL = 0,
+      EX_CONTINUE = 1,
+      EX_QUIT = 2,
+      EX_QUIT_ALL = 3
+    };
 
   debugger (interpreter& interp, std::size_t level)
     : m_interpreter (interp), m_level (level),
       m_execution_mode (EX_NORMAL), m_in_debug_repl (false)
   { }
 
-  int server_loop (void);
+  int server_loop ();
 
   void repl (const std::string& prompt = "debug> ");
 
-  bool in_debug_repl (void) const { return m_in_debug_repl; }
-
-  void dbcont (void) { m_execution_mode = EX_CONTINUE; }
+  bool in_debug_repl () const { return m_in_debug_repl; }
+
+  void dbcont () { m_execution_mode = EX_CONTINUE; }
 
   void dbquit (bool all = false)
   {
@@ -129,7 +130,7 @@
       m_execution_mode = EX_QUIT;
   }
 
-  bool quitting_debugger (void) const;
+  bool quitting_debugger () const;
 
 private:
 
@@ -144,7 +145,7 @@
 // with the corresponding tree_evaluator functions or do they need to
 // remain separate?  They perform nearly the same functions.
 
-int debugger::server_loop (void)
+int debugger::server_loop ()
 {
   // Process events from the event queue.
 
@@ -350,7 +351,7 @@
       frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ());
 
       std::shared_ptr<push_parser>
-      debug_parser (new push_parser (m_interpreter));
+        debug_parser (new push_parser (m_interpreter));
 
       tw.set_parser (debug_parser);
 
@@ -365,8 +366,8 @@
       if (m_level > 0)
         tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg;
 
-      frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ());
-      input_sys.PS1 (tmp_prompt);
+      frame.add (&interpreter::set_PS1, &m_interpreter, m_interpreter.PS1 ());
+      m_interpreter.PS1 (tmp_prompt);
 
       if (! m_interpreter.interactive ())
         {
@@ -439,7 +440,7 @@
 
                   retval = debug_parser.run (input_line, false);
 
-                  prompt = command_editor::decode_prompt_string (input_sys.PS2 ());
+                  prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());
                 }
               while (retval < 0);
 
@@ -503,7 +504,7 @@
     }
 }
 
-bool debugger::quitting_debugger (void) const
+bool debugger::quitting_debugger () const
 {
   if (m_execution_mode == EX_QUIT)
     {
@@ -531,7 +532,7 @@
   return false;
 }
 
-bool tree_evaluator::at_top_level (void) const
+bool tree_evaluator::at_top_level () const
 {
   return m_call_stack.at_top_level ();
 }
@@ -608,7 +609,7 @@
   if (m_exit_status == 0)
     {
       std::shared_ptr<tree_statement_list>
-      stmt_list = m_parser->statement_list ();
+        stmt_list = m_parser->statement_list ();
 
       if (stmt_list)
         {
@@ -636,7 +637,7 @@
   evmgr.pre_input_event ();
 }
 
-void tree_evaluator::get_line_and_eval (void)
+void tree_evaluator::get_line_and_eval ()
 {
   std::mutex mtx;
   std::unique_lock<std::mutex> lock (mtx);
@@ -645,7 +646,6 @@
   bool evaluation_pending = false;
   bool exiting = false;
 
-  input_system& input_sys = m_interpreter.get_input_system ();
   event_manager& evmgr = m_interpreter.get_event_manager ();
 
   while (true)
@@ -654,7 +654,8 @@
       // so, then we need to disable idle event loop hook function
       // execution.
 
-      std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 ();
+      std::string ps
+        = incomplete_parse ? m_interpreter.PS2 () : m_interpreter.PS1 ();
 
       std::cout << command_editor::decode_prompt_string (ps);
 
@@ -669,54 +670,54 @@
       exiting = false;
 
       evmgr.post_event
-      ([&] (interpreter& interp)
-      {
-        // INTERPRETER THREAD
-
-        std::lock_guard<std::mutex> local_lock (mtx);
-
-        try
-          {
-            interp.parse_and_execute (input, incomplete_parse);
-          }
-        catch (const exit_exception&)
-          {
-            evaluation_pending = false;
-            exiting = true;
-            cv.notify_all ();
-            throw;
-          }
-        catch (const execution_exception& ee)
-          {
-            error_system& es = m_interpreter.get_error_system ();
-
-            es.save_exception (ee);
-            es.display_exception (ee);
-
-            if (m_interpreter.interactive ())
-              {
-                m_interpreter.recover_from_exception ();
-                m_parser->reset ();
-                evaluation_pending = false;
-                cv.notify_all ();
-              }
-            else
-              {
-                evaluation_pending = false;
-                cv.notify_all ();
-                throw exit_exception (1);
-              }
-          }
-        catch (...)
-          {
-            evaluation_pending = false;
-            cv.notify_all ();
-            throw;
-          }
-
-        evaluation_pending = false;
-        cv.notify_all ();
-      });
+        ([&] (interpreter& interp)
+         {
+           // INTERPRETER THREAD
+
+           std::lock_guard<std::mutex> local_lock (mtx);
+
+           try
+             {
+               interp.parse_and_execute (input, incomplete_parse);
+             }
+           catch (const exit_exception&)
+             {
+               evaluation_pending = false;
+               exiting = true;
+               cv.notify_all ();
+               throw;
+             }
+           catch (const execution_exception& ee)
+             {
+               error_system& es = m_interpreter.get_error_system ();
+
+               es.save_exception (ee);
+               es.display_exception (ee);
+
+               if (m_interpreter.interactive ())
+                 {
+                   m_interpreter.recover_from_exception ();
+                   m_parser->reset ();
+                   evaluation_pending = false;
+                   cv.notify_all ();
+                 }
+               else
+                 {
+                   evaluation_pending = false;
+                   cv.notify_all ();
+                   throw exit_exception (1);
+                 }
+             }
+           catch (...)
+             {
+               evaluation_pending = false;
+               cv.notify_all ();
+               throw;
+             }
+
+           evaluation_pending = false;
+           cv.notify_all ();
+         });
 
       // Wait until evaluation is finished before prompting for input
       // again.
@@ -728,7 +729,7 @@
     }
 }
 
-int tree_evaluator::repl (void)
+int tree_evaluator::repl ()
 {
   // The big loop.  Read, Eval, Print, Loop.  Normally user
   // interaction at the command line in a terminal session, but we may
@@ -795,7 +796,7 @@
           if (exit_status == 0)
             {
               std::shared_ptr<tree_statement_list>
-              stmt_list = repl_parser->statement_list ();
+                stmt_list = repl_parser->statement_list ();
 
               if (stmt_list)
                 {
@@ -869,7 +870,7 @@
   return exit_status;
 }
 
-int tree_evaluator::server_loop (void)
+int tree_evaluator::server_loop ()
 {
   // Process events from the event queue.
 
@@ -1083,7 +1084,7 @@
 }
 
 octave_value tree_evaluator::eval_string (const std::string& eval_str,
-    bool silent, int& parse_status)
+                                          bool silent, int& parse_status)
 {
   octave_value retval;
 
@@ -1096,8 +1097,8 @@
 }
 
 octave_value_list tree_evaluator::eval_string (const octave_value& arg,
-    bool silent, int& parse_status,
-    int nargout)
+                                               bool silent, int& parse_status,
+                                               int nargout)
 {
   std::string s = arg.xstring_value ("eval: expecting string argument");
 
@@ -1160,13 +1161,13 @@
 }
 
 octave_value_list tree_evaluator::evalin (const std::string& context,
-    const std::string& try_code,
-    int nargout)
+                                          const std::string& try_code,
+                                          int nargout)
 {
   unwind_action act ([=] (std::size_t frm)
-  {
-    m_call_stack.restore_frame (frm);
-  }, m_call_stack.current_frame ());
+                     {
+                       m_call_stack.restore_frame (frm);
+                     }, m_call_stack.current_frame ());
 
   if (context == "caller")
     m_call_stack.goto_caller_frame ();
@@ -1181,16 +1182,16 @@
 }
 
 octave_value_list tree_evaluator::evalin (const std::string& context,
-    const std::string& try_code,
-    const std::string& catch_code,
-    int nargout)
+                                          const std::string& try_code,
+                                          const std::string& catch_code,
+                                          int nargout)
 {
   octave_value_list retval;
 
   unwind_action act1 ([=] (std::size_t frm)
-  {
-    m_call_stack.restore_frame (frm);
-  }, m_call_stack.current_frame ());
+                      {
+                        m_call_stack.restore_frame (frm);
+                      }, m_call_stack.current_frame ());
 
   if (context == "caller")
     m_call_stack.goto_caller_frame ();
@@ -1353,14 +1354,14 @@
 }
 
 bool
-tree_evaluator::statement_printing_enabled (void)
+tree_evaluator::statement_printing_enabled ()
 {
   return ! (m_silent_functions && (m_statement_context == SC_FUNCTION
                                    || m_statement_context == SC_SCRIPT));
 }
 
 void
-tree_evaluator::reset_debug_state (void)
+tree_evaluator::reset_debug_state ()
 {
   m_debug_mode = (m_bp_table.have_breakpoints ()
                   || m_dbstep_flag != 0
@@ -1414,12 +1415,12 @@
 
   m_debugger_stack.push (dbgr);
 
-  frame.add ([=] (void)
-  {
-    delete m_debugger_stack.top ();
-    m_debugger_stack.pop ();
-    reset_debug_state ();
-  });
+  frame.add ([=] ()
+             {
+               delete m_debugger_stack.top ();
+               m_debugger_stack.pop ();
+               reset_debug_state ();
+             });
 
   dbgr->repl (prompt);
 }
@@ -1437,7 +1438,7 @@
 }
 
 Matrix
-tree_evaluator::ignored_fcn_outputs (void) const
+tree_evaluator::ignored_fcn_outputs () const
 {
   Matrix retval;
 
@@ -1483,15 +1484,9 @@
   // the corresponding function name.  At least try to do it without N
   // string compares.
 
-  // FIXME: .+, .-, **, and .** are deprecated but still need to be
-  // handled here until they are removed.
-
   std::size_t len = name.length ();
 
-  if (len == 3 && name == ".**")
-    // deprecated
-    return "power";
-  else if (len == 2)
+  if (len == 2)
     {
       if (name[0] == '.')
         {
@@ -1500,14 +1495,6 @@
             case '\'':
               return "transpose";
 
-            case '+':
-              // deprecated
-              return "plus";
-
-            case '-':
-              // deprecated
-              return "minus";
-
             case '*':
               return "times";
 
@@ -1545,9 +1532,6 @@
               break;
             }
         }
-      else if (name == "**")
-        // deprecated
-        return "mpower";
     }
   else if (len == 1)
     {
@@ -1820,10 +1804,7 @@
 
 /*
 %!test
-%! x = {".**", "power";
-%!      ".'", "transpose";
-%!      ".+", "plus";
-%!      ".-", "minus";
+%! x = {".'", "transpose";
 %!      ".*", "times";
 %!      "./", "rdivide";
 %!      ".^", "power";
@@ -1833,7 +1814,6 @@
 %!      ">=", "ge";
 %!      "!=", "ne";
 %!      "~=", "ne";
-%!      "**", "mpower";
 %!      "~", "not";
 %!      "!", "not";
 %!      "\'", "ctranspose";
@@ -2015,9 +1995,9 @@
   // calling assign on that?
 
   unwind_action act ([=] (std::size_t frm)
-  {
-    m_call_stack.restore_frame (frm);
-  }, m_call_stack.current_frame ());
+                     {
+                       m_call_stack.restore_frame (frm);
+                     }, m_call_stack.current_frame ());
 
   if (context == "caller")
     m_call_stack.goto_caller_frame ();
@@ -2201,6 +2181,18 @@
   m_call_stack.set_auto_fcn_var (avt, val);
 }
 
+void
+tree_evaluator::set_nargin (int nargin)
+{
+  m_call_stack.set_nargin (nargin);
+}
+
+void
+tree_evaluator::set_nargout (int nargout)
+{
+  m_call_stack.set_nargout (nargout);
+}
+
 octave_value
 tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const
 {
@@ -2208,8 +2200,14 @@
 }
 
 void
+tree_evaluator::set_active_bytecode_ip (int ip)
+{
+  m_call_stack.set_active_bytecode_ip (ip);
+}
+
+void
 tree_evaluator::define_parameter_list_from_arg_vector
-(tree_parameter_list *param_list, const octave_value_list& args)
+  (tree_parameter_list *param_list, const octave_value_list& args)
 {
   if (! param_list || param_list->varargs_only ())
     return;
@@ -2250,7 +2248,7 @@
 
 // END is documented in op-kw-docs.
 DEFMETHOD (end, interp, args, ,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn {} {} end
 Last element of an array or the end of any @code{for}, @code{parfor},
 @code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
@@ -2265,19 +2263,19 @@
 @group
 @var{x} = [ 1 2 3; 4 5 6 ];
 @var{x}(1,end)
-   @result{} 3
+ @result{} 3
 @var{x}(end,1)
-   @result{} 4
+ @result{} 4
 @var{x}(end,end)
-   @result{} 6
+ @result{} 6
 @end group
 @end example
 @seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.evaluate_end_expression (args);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.evaluate_end_expression (args);
 }
 
 /*
@@ -2322,8 +2320,8 @@
 
 octave_value_list
 tree_evaluator::convert_return_list_to_const_vector
-(tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs,
- const Cell& varargout)
+  (tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs,
+   const Cell& varargout)
 {
   octave_idx_type vlen = varargout.numel ();
   int len = ret_list->length ();
@@ -2411,7 +2409,7 @@
 
 bool
 tree_evaluator::switch_case_label_matches (tree_switch_case *expr,
-    const octave_value& val)
+                                           const octave_value& val)
 {
   tree_expression *label = expr->case_label ();
 
@@ -2427,7 +2425,7 @@
             {
               for (octave_idx_type j = 0; j < cell.columns (); j++)
                 {
-                  bool match = val.is_equal (cell(i, j));
+                  bool match = val.is_equal (cell(i,j));
 
                   if (match)
                     return true;
@@ -2469,27 +2467,38 @@
   m_call_stack.push (fcn);
 }
 
-void tree_evaluator::pop_stack_frame (void)
+void tree_evaluator::push_stack_frame (vm &vm, octave_user_function *fcn, int nargout, int nargin)
+{
+  m_call_stack.push (vm, fcn, nargout, nargin);
+}
+
+void tree_evaluator::pop_stack_frame ()
 {
   m_call_stack.pop ();
 }
 
-int tree_evaluator::current_line (void) const
+std::shared_ptr<stack_frame>
+tree_evaluator::pop_return_stack_frame ()
+{
+  return m_call_stack.pop_return ();
+}
+
+int tree_evaluator::current_line () const
 {
   return m_call_stack.current_line ();
 }
 
-int tree_evaluator::current_column (void) const
+int tree_evaluator::current_column () const
 {
   return m_call_stack.current_column ();
 }
 
-int tree_evaluator::debug_user_code_line (void) const
+int tree_evaluator::debug_user_code_line () const
 {
   return m_call_stack.debug_user_code_line ();
 }
 
-int tree_evaluator::debug_user_code_column (void) const
+int tree_evaluator::debug_user_code_column () const
 {
   return m_call_stack.debug_user_code_column ();
 }
@@ -2501,27 +2510,27 @@
   frm->display_stopped_in_message (os);
 }
 
-octave_user_code *tree_evaluator::current_user_code (void) const
+octave_user_code * tree_evaluator::current_user_code () const
 {
   return m_call_stack.current_user_code ();
 }
 
-unwind_protect *tree_evaluator::curr_fcn_unwind_protect_frame (void)
+unwind_protect * tree_evaluator::curr_fcn_unwind_protect_frame ()
 {
   return m_call_stack.curr_fcn_unwind_protect_frame ();
 }
 
-octave_user_code *tree_evaluator::debug_user_code (void) const
+octave_user_code * tree_evaluator::debug_user_code () const
 {
   return m_call_stack.debug_user_code ();
 }
 
-octave_function *tree_evaluator::current_function (bool skip_first) const
+octave_function * tree_evaluator::current_function (bool skip_first) const
 {
   return m_call_stack.current_function (skip_first);
 }
 
-octave_function *tree_evaluator::caller_function (void) const
+octave_function * tree_evaluator::caller_function () const
 {
   return m_call_stack.current_function (true);
 }
@@ -2531,12 +2540,12 @@
   return m_call_stack.goto_frame (n, verbose);
 }
 
-void tree_evaluator::goto_caller_frame (void)
+void tree_evaluator::goto_caller_frame ()
 {
   m_call_stack.goto_caller_frame ();
 }
 
-void tree_evaluator::goto_base_frame (void)
+void tree_evaluator::goto_base_frame ()
 {
   m_call_stack.goto_base_frame ();
 }
@@ -2546,7 +2555,7 @@
   return m_call_stack.restore_frame (n);
 }
 
-std::string tree_evaluator::get_dispatch_class (void) const
+std::string tree_evaluator::get_dispatch_class () const
 {
   return m_call_stack.get_dispatch_class ();
 }
@@ -2569,13 +2578,13 @@
 }
 
 std::list<std::shared_ptr<stack_frame>>
-                                     tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const
+tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const
 {
   return m_call_stack.backtrace_frames (curr_user_frame);
 }
 
 std::list<std::shared_ptr<stack_frame>>
-                                     tree_evaluator::backtrace_frames (void) const
+tree_evaluator::backtrace_frames () const
 {
   return m_call_stack.backtrace_frames ();
 }
@@ -2587,7 +2596,7 @@
   return m_call_stack.backtrace_info (curr_user_frame, print_subfn);
 }
 
-std::list<frame_info> tree_evaluator::backtrace_info (void) const
+std::list<frame_info> tree_evaluator::backtrace_info () const
 {
   return m_call_stack.backtrace_info ();
 }
@@ -2599,17 +2608,17 @@
   return m_call_stack.backtrace (curr_user_frame, print_subfn);
 }
 
-octave_map tree_evaluator::backtrace (void) const
+octave_map tree_evaluator::backtrace () const
 {
   return m_call_stack.backtrace ();
 }
 
-octave_map tree_evaluator::empty_backtrace (void) const
+octave_map tree_evaluator::empty_backtrace () const
 {
   return m_call_stack.empty_backtrace ();
 }
 
-std::string tree_evaluator::backtrace_message (void) const
+std::string tree_evaluator::backtrace_message () const
 {
   std::list<frame_info> frames = backtrace_info ();
 
@@ -2644,17 +2653,17 @@
   m_call_stack.push (dummy_scope);
 }
 
-void tree_evaluator::pop_scope (void)
+void tree_evaluator::pop_scope ()
 {
   m_call_stack.pop ();
 }
 
-symbol_scope tree_evaluator::get_top_scope (void) const
+symbol_scope tree_evaluator::get_top_scope () const
 {
   return m_call_stack.top_scope ();
 }
 
-symbol_scope tree_evaluator::get_current_scope (void) const
+symbol_scope tree_evaluator::get_current_scope () const
 {
   return m_call_stack.current_scope ();
 }
@@ -2707,7 +2716,7 @@
   return m_call_stack.max_stack_depth (args, nargout);
 }
 
-void tree_evaluator::display_call_stack (void) const
+void tree_evaluator::display_call_stack () const
 {
   m_call_stack.display ();
 }
@@ -2736,7 +2745,7 @@
   return symtab.fcn_table_find (name, ovl ());
 }
 
-void tree_evaluator::clear_objects (void)
+void tree_evaluator::clear_objects ()
 {
   std::shared_ptr<stack_frame> frame
     = m_call_stack.get_current_stack_frame ();
@@ -2768,7 +2777,7 @@
   frame->clear_variable_regexp (pattern);
 }
 
-void tree_evaluator::clear_variables (void)
+void tree_evaluator::clear_variables ()
 {
   std::shared_ptr<stack_frame> frame
     = m_call_stack.get_current_stack_frame ();
@@ -2792,7 +2801,7 @@
   m_call_stack.clear_global_variable_regexp (pattern);
 }
 
-void tree_evaluator::clear_global_variables (void)
+void tree_evaluator::clear_global_variables ()
 {
   m_call_stack.clear_global_variables ();
 }
@@ -2842,17 +2851,17 @@
   symtab.clear_function_regexp (pattern);
 }
 
-std::list<std::string> tree_evaluator::global_variable_names (void) const
+std::list<std::string> tree_evaluator::global_variable_names () const
 {
   return m_call_stack.global_variable_names ();
 }
 
-std::list<std::string> tree_evaluator::top_level_variable_names (void) const
+std::list<std::string> tree_evaluator::top_level_variable_names () const
 {
   return m_call_stack.top_level_variable_names ();
 }
 
-std::list<std::string> tree_evaluator::variable_names (void) const
+std::list<std::string> tree_evaluator::variable_names () const
 {
   return m_call_stack.variable_names ();
 }
@@ -2962,7 +2971,7 @@
 }
 
 bool
-tree_evaluator::in_user_code (void) const
+tree_evaluator::in_user_code () const
 {
   return m_call_stack.current_user_code () != nullptr;
 }
@@ -3031,7 +3040,7 @@
 {
   octave_idx_type steps = rng.numel ();
 
-  if (math::isinf (rng.limit ()))
+  if (math::isinf (rng.limit ()) || math::isinf (rng.base ()))
     warning_with_id ("Octave:infinite-loop",
                      "FOR loop limit is infinite, will stop after %"
                      OCTAVE_IDX_TYPE_FORMAT " steps", steps);
@@ -3097,63 +3106,7 @@
           return;
         }
 
-      // For now, disable all but range<double>.
-
-#if 0
-      if (rhs.is_int64_type ())
-        {
-          execute_range_loop (rhs.int64_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_uint64_type ())
-        {
-          execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_int32_type ())
-        {
-          execute_range_loop (rhs.int32_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_uint32_type ())
-        {
-          execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_int16_type ())
-        {
-          execute_range_loop (rhs.int16_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_uint16_type ())
-        {
-          execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_int8_type ())
-        {
-          execute_range_loop (rhs.int8_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_uint8_type ())
-        {
-          execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body);
-          return;
-        }
-
-      if (rhs.is_single_type ())
-        {
-          execute_range_loop (rhs.float_range_value (), line, ult, loop_body);
-          return;
-        }
-#endif
+      // For now, enable only range<double>.
     }
 
   if (rhs.is_scalar_type ())
@@ -3423,8 +3376,8 @@
 
 octave_value_list
 tree_evaluator::execute_builtin_function (octave_builtin& builtin_function,
-    int nargout,
-    const octave_value_list& args)
+                                          int nargout,
+                                          const octave_value_list& args)
 {
   octave_value_list retval;
 
@@ -3544,6 +3497,48 @@
   // argument, which must be the partially constructed object instance.
 
   octave_value_list args (xargs);
+
+  // FIXME: this probably shouldn't be a double-precision matrix.
+  Matrix ignored_outputs = ignored_fcn_outputs ();
+
+  // Check if it has been compiled and execute the bytecode if so
+  if (user_function.is_compiled ())
+    {
+      bytecode &bc = user_function.get_bytecode ();
+
+      vm vm (this, bc);
+
+      bool caller_is_bytecode = get_current_stack_frame ()->is_bytecode_fcn_frame ();
+
+      // Pushes a bytecode stackframe. nargin is set inside the VM.
+      push_stack_frame (vm, &user_function, nargout, 0);
+
+      // The arg names of root stackframe in VM need to be set here, unless the caller is bytecode.
+      // The caller can be bytecode if evalin("caller", ...) is used in some uncompiled function.
+      if (!caller_is_bytecode)
+        set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (xargs.name_tags ()));
+      set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
+
+      octave_value_list ret;
+
+      try {
+        ret = vm.execute_code (args, nargout);
+      } catch (std::exception &e) {
+        if (vm.m_dbg_proper_return == false)
+          {
+            std::cout << e.what () << std::endl;
+            // TODO: Replace with panic when the VM almost works
+
+            // Some test code eats errors messages, so we print to stderr too.
+            fprintf (stderr, "VM error %d: " "Exception in function %s escaped the VM\n", __LINE__, user_function.name ().c_str());
+            error("VM error %d: " "Exception in function %s escaped the VM\n", __LINE__, user_function.name ().c_str());
+          }
+        throw;
+      }
+
+      return ret;
+    }
+
   octave_value_list ret_args;
 
   int nargin = args.length ();
@@ -3560,9 +3555,6 @@
         panic_impossible ();
     }
 
-  // FIXME: this probably shouldn't be a double-precision matrix.
-  Matrix ignored_outputs = ignored_fcn_outputs ();
-
   tree_parameter_list *param_list = user_function.parameter_list ();
 
   bool takes_varargs = false;
@@ -3626,10 +3618,9 @@
   if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))
     error ("max_recursion_depth exceeded");
 
-  unwind_action act2 ([&user_function] ()
-  {
-    user_function.restore_warning_states ();
-  });
+  unwind_action act2 ([&user_function] () {
+                        user_function.restore_warning_states ();
+                      });
 
   // Evaluate the commands that make up the function.
 
@@ -3640,7 +3631,7 @@
   if (cmd_list)
     {
       profiler::enter<octave_user_function>
-      block (m_profiler, user_function);
+        block (m_profiler, user_function);
 
       if (echo ())
         push_echo_state (tree_evaluator::ECHO_FUNCTIONS,
@@ -3686,8 +3677,8 @@
         }
 
       retval = convert_return_list_to_const_vector (ret_list, nargout,
-               ignored_outputs,
-               varargout);
+                                                    ignored_outputs,
+                                                    varargout);
     }
 
   return retval;
@@ -3911,7 +3902,7 @@
           if (cmd)
             {
               unwind_protect_var<const std::list<octave_lvalue> *>
-              upv (m_lvalue_list, nullptr);
+                upv (m_lvalue_list, nullptr);
 
               cmd->accept (*this);
             }
@@ -4442,7 +4433,7 @@
 
               octave_value_list args = ovl (varval (ans));
               args.stash_name_tags (string_vector (ans));
-              feval ("display", args);
+              m_interpreter.feval ("display", args);
             }
         }
     }
@@ -4568,18 +4559,18 @@
 }
 
 symbol_info_list
-tree_evaluator::get_symbol_info (void)
+tree_evaluator::get_symbol_info ()
 {
   return m_call_stack.get_symbol_info ();
 }
 
 symbol_info_list
-tree_evaluator::top_scope_symbol_info (void) const
+tree_evaluator::top_scope_symbol_info () const
 {
   return m_call_stack.top_scope_symbol_info ();
 }
 
-octave_map tree_evaluator::get_autoload_map (void) const
+octave_map tree_evaluator::get_autoload_map () const
 {
   Cell fcn_names (dim_vector (m_autoload_map.size (), 1));
   Cell file_names (dim_vector (m_autoload_map.size (), 1));
@@ -4617,7 +4608,7 @@
   return retval;
 }
 
-std::list<std::string> tree_evaluator::autoloaded_functions (void) const
+std::list<std::string> tree_evaluator::autoloaded_functions () const
 {
   std::list<std::string> names;
 
@@ -4644,6 +4635,9 @@
 {
   std::string file_name = check_autoload_file (nm);
 
+  // Signal to load path that the function cache is invalid
+  octave::load_path::signal_clear_fcn_cache ();
+
   m_autoload_map[fcn] = file_name;
 }
 
@@ -4652,6 +4646,9 @@
 {
   check_autoload_file (nm);
 
+  // Signal to load path that the function cache is invalid
+  octave::load_path::signal_clear_fcn_cache ();
+
   // Remove function from symbol table and autoload map.
   symbol_table& symtab = m_interpreter.get_symbol_table ();
 
@@ -4731,7 +4728,7 @@
   if (args)
     {
       unwind_protect_var<const std::list<octave_lvalue> *>
-      upv (m_lvalue_list, nullptr);
+        upv (m_lvalue_list, nullptr);
 
       int len = args->length ();
 
@@ -4821,7 +4818,7 @@
 }
 
 void
-tree_evaluator::maybe_set_echo_state (void)
+tree_evaluator::maybe_set_echo_state ()
 {
   octave_function *caller = caller_function ();
 
@@ -4853,7 +4850,7 @@
              m_echo_state, m_echo_file_name, m_echo_file_pos);
 }
 
-bool tree_evaluator::maybe_push_echo_state_cleanup (void)
+bool tree_evaluator::maybe_push_echo_state_cleanup ()
 {
   // This function is expected to be called from ECHO, which would be
   // the top of the call stack.  If the caller of ECHO is a
@@ -5000,13 +4997,13 @@
   return octave_value ();
 }
 
-bool tree_evaluator::in_debug_repl (void) const
+bool tree_evaluator::in_debug_repl () const
 {
   return (m_debugger_stack.empty ()
           ? false : m_debugger_stack.top()->in_debug_repl ());
 }
 
-void tree_evaluator::dbcont (void)
+void tree_evaluator::dbcont ()
 {
   if (! m_debugger_stack.empty ())
     m_debugger_stack.top()->dbcont ();
@@ -5018,35 +5015,6 @@
     m_debugger_stack.top()->dbquit (all);
 }
 
-static octave_value end_value (const octave_value& value,
-                               octave_idx_type index_position,
-                               octave_idx_type num_indices)
-{
-  dim_vector dv = value.dims ();
-  int ndims = dv.ndims ();
-
-  if (num_indices < ndims)
-    {
-      for (int i = num_indices; i < ndims; i++)
-        dv(num_indices-1) *= dv(i);
-
-      if (num_indices == 1)
-        {
-          ndims = 2;
-          dv.resize (ndims);
-          dv(1) = 1;
-        }
-      else
-        {
-          ndims = num_indices;
-          dv.resize (ndims);
-        }
-    }
-
-  return (index_position < ndims
-          ? octave_value (dv(index_position)) : octave_value (1.0));
-}
-
 octave_value_list
 tree_evaluator::evaluate_end_expression (const octave_value_list& args)
 {
@@ -5069,7 +5037,7 @@
       if (num_indices < 1)
         error ("end: N must be greater than zero");
 
-      return end_value (args(0), index_position-1, num_indices);
+      return octave_value (args(0).end_index (index_position-1, num_indices));
     }
 
   // If m_indexed_object is undefined, then this use of 'end' is
@@ -5097,9 +5065,9 @@
           // token applies to in the calling stack frame.
 
           unwind_action act ([=] (std::size_t frm)
-          {
-            m_call_stack.restore_frame (frm);
-          }, m_call_stack.current_frame ());
+                             {
+                               m_call_stack.restore_frame (frm);
+                             }, m_call_stack.current_frame ());
 
           std::size_t n = m_call_stack.find_current_user_frame ();
           m_call_stack.goto_frame (n);
@@ -5138,10 +5106,10 @@
 
       if (meth.is_defined ())
         return m_interpreter.feval
-               (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1);
+          (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1);
     }
 
-  return end_value (expr_result, m_index_position, m_num_indices);
+  return octave_value (expr_result.end_index (m_index_position, m_num_indices));
 }
 
 octave_value
@@ -5204,7 +5172,7 @@
 }
 
 // Decide if it's time to quit a for or while loop.
-bool tree_evaluator::quit_loop_now (void)
+bool tree_evaluator::quit_loop_now ()
 {
   octave_quit ();
 
@@ -5222,10 +5190,10 @@
 }
 
 void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,
-    const Matrix& ignored_outputs,
-    int nargin, int nargout,
-    bool takes_varargs,
-    const octave_value_list& va_args)
+                                         const Matrix& ignored_outputs,
+                                         int nargin, int nargout,
+                                         bool takes_varargs,
+                                         const octave_value_list& va_args)
 {
   set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names));
   set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
@@ -5277,7 +5245,7 @@
 }
 
 DEFMETHOD (max_recursion_depth, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} max_recursion_depth ()
 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val})
 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val}, "local")
@@ -5294,9 +5262,9 @@
 @seealso{max_stack_depth}
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.max_recursion_depth (args, nargout);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.max_recursion_depth (args, nargout);
 }
 
 /*
@@ -5312,7 +5280,7 @@
 */
 
 DEFMETHOD (whos_line_format, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} whos_line_format ()
 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val})
 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val}, "local")
@@ -5387,13 +5355,13 @@
 @seealso{whos}
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.whos_line_format (args, nargout);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.whos_line_format (args, nargout);
 }
 
 DEFMETHOD (silent_functions, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} silent_functions ()
 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val})
 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val}, "local")
@@ -5409,9 +5377,9 @@
 The original variable value is restored when exiting the function.
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.silent_functions (args, nargout);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.silent_functions (args, nargout);
 }
 
 /*
@@ -5427,7 +5395,7 @@
 */
 
 DEFMETHOD (string_fill_char, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} string_fill_char ()
 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val})
 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val}, "local")
@@ -5441,9 +5409,9 @@
 @group
 string_fill_char ("X");
 [ "these"; "are"; "strings" ]
-      @result{}  "theseXX"
-          "areXXXX"
-          "strings"
+    @result{}  "theseXX"
+        "areXXXX"
+        "strings"
 @end group
 @end example
 
@@ -5452,9 +5420,9 @@
 The original variable value is restored when exiting the function.
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.string_fill_char (args, nargout);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.string_fill_char (args, nargout);
 }
 
 /*
@@ -5476,7 +5444,7 @@
 */
 
 DEFMETHOD (PS4, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} PS4 ()
 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val})
 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val}, "local")
@@ -5492,13 +5460,11 @@
 @seealso{echo, PS1, PS2}
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.PS4 (args, nargout);
+return interp.PS4 (args, nargout);
 }
 
 DEFMETHOD (echo, interp, args, nargout,
-           doc: /* -*- texinfo -*-
+         doc: /* -*- texinfo -*-
 @deftypefn  {} {} echo
 @deftypefnx {} {} echo on
 @deftypefnx {} {} echo off
@@ -5538,9 +5504,9 @@
 @seealso{PS4}
 @end deftypefn */)
 {
-  tree_evaluator& tw = interp.get_evaluator ();
-
-  return tw.echo (args, nargout);
+tree_evaluator& tw = interp.get_evaluator ();
+
+return tw.echo (args, nargout);
 }
 
 /*
--- a/libinterp/parse-tree/pt-eval.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-eval.h	Fri Jun 23 20:51:51 2023 +0200
@@ -61,6 +61,7 @@
 class interpreter;
 class push_parser;
 class unwind_protect;
+class vm;
 
 // How to evaluate the code that the parse trees represent.
 
@@ -68,6 +69,8 @@
 {
 public:
 
+  friend class vm;
+
   enum echo_state
   {
     ECHO_OFF = 0,
@@ -81,44 +84,38 @@
   {
   public:
 
-    value_stack (void) = default;
-
-    value_stack (const value_stack&) = default;
-
-    value_stack& operator = (const value_stack&) = default;
-
-    ~value_stack (void) = default;
+    OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (value_stack)
 
     void push (const T& val) { m_stack.push (val); }
 
-    void pop (void)
+    void pop ()
     {
       m_stack.pop ();
     }
 
-    T val_pop (void)
+    T val_pop ()
     {
       T retval = m_stack.top ();
       m_stack.pop ();
       return retval;
     }
 
-    T top (void) const
+    T top () const
     {
       return m_stack.top ();
     }
 
-    std::size_t size (void) const
+    std::size_t size () const
     {
       return m_stack.size ();
     }
 
-    bool empty (void) const
+    bool empty () const
     {
       return m_stack.empty ();
     }
 
-    void clear (void)
+    void clear ()
     {
       while (! m_stack.empty ())
         m_stack.pop ();
@@ -148,15 +145,11 @@
       m_index_position (0), m_num_indices (0)
   { }
 
-  // No copying!
-
-  tree_evaluator (const tree_evaluator&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_evaluator)
 
-  tree_evaluator& operator = (const tree_evaluator&) = delete;
+  ~tree_evaluator () = default;
 
-  ~tree_evaluator (void) = default;
-
-  std::shared_ptr<push_parser> get_parser (void)
+  std::shared_ptr<push_parser> get_parser ()
   {
     return m_parser;
   }
@@ -166,7 +159,7 @@
     m_parser = parser;
   }
 
-  bool at_top_level (void) const;
+  bool at_top_level () const;
 
   std::string mfilename (const std::string& opt = "") const;
 
@@ -176,15 +169,15 @@
 
   void parse_and_execute (const std::string& input, bool& incomplete_parse);
 
-  void get_line_and_eval (void);
+  void get_line_and_eval ();
 
-  int repl (void);
+  int repl ();
 
-  bool in_top_level_repl (void) const { return m_in_top_level_repl; }
+  bool in_top_level_repl () const { return m_in_top_level_repl; }
 
-  int server_loop (void);
+  int server_loop ();
 
-  bool server_mode (void) const { return m_server_mode; }
+  bool server_mode () const { return m_server_mode; }
 
   void server_mode (bool arg) { m_server_mode = arg; }
 
@@ -333,9 +326,9 @@
 
   void bind_ans (const octave_value& val, bool print);
 
-  bool statement_printing_enabled (void);
+  bool statement_printing_enabled ();
 
-  void reset_debug_state (void);
+  void reset_debug_state ();
 
   void reset_debug_state (bool mode);
 
@@ -353,7 +346,7 @@
     SC_OTHER      // command-line input or eval string
   };
 
-  Matrix ignored_fcn_outputs (void) const;
+  Matrix ignored_fcn_outputs () const;
 
   octave_value make_fcn_handle (const std::string& nm);
 
@@ -405,8 +398,13 @@
   void set_auto_fcn_var (stack_frame::auto_var_type avt,
                          const octave_value& val = octave_value ());
 
+  void set_nargin (int nargin);
+  void set_nargout (int nargout);
+
   octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const;
 
+  void set_active_bytecode_ip (int ip);
+
   void define_parameter_list_from_arg_vector
   (tree_parameter_list *param_list, const octave_value_list& args);
 
@@ -424,11 +422,11 @@
   bool switch_case_label_matches (tree_switch_case *expr,
                                   const octave_value& val);
 
-  interpreter& get_interpreter (void) { return m_interpreter; }
+  interpreter& get_interpreter () { return m_interpreter; }
 
-  bp_table& get_bp_table (void) { return m_bp_table; }
+  bp_table& get_bp_table () { return m_bp_table; }
 
-  profiler& get_profiler (void) { return m_profiler; }
+  profiler& get_profiler () { return m_profiler; }
 
   void push_stack_frame (const symbol_scope& scope);
 
@@ -443,52 +441,56 @@
 
   void push_stack_frame (octave_function *fcn);
 
-  void pop_stack_frame (void);
+  void push_stack_frame (vm &vm, octave_user_function *fcn, int nargout, int nargin);
+
+  void pop_stack_frame ();
 
-  std::shared_ptr<stack_frame> get_current_stack_frame (void) const
+  std::shared_ptr<stack_frame> pop_return_stack_frame ();
+
+  std::shared_ptr<stack_frame> get_current_stack_frame () const
   {
     return m_call_stack.get_current_stack_frame ();
   }
 
-  std::shared_ptr<stack_frame> current_user_frame (void) const
+  std::shared_ptr<stack_frame> current_user_frame () const
   {
     return m_call_stack.current_user_frame ();
   }
 
   // Current line in current function.
-  int current_line (void) const;
+  int current_line () const;
 
   // Current column in current function.
-  int current_column (void) const;
+  int current_column () const;
 
   // Line number in current function that we are debugging.
-  int debug_user_code_line (void) const;
+  int debug_user_code_line () const;
 
   // Column number in current function that we are debugging.
-  int debug_user_code_column (void) const;
+  int debug_user_code_column () const;
 
   void debug_where (std::ostream& os) const;
 
-  octave_user_code * current_user_code (void) const;
+  octave_user_code * current_user_code () const;
 
-  unwind_protect * curr_fcn_unwind_protect_frame (void);
+  unwind_protect * curr_fcn_unwind_protect_frame ();
 
   // Current function that we are debugging.
-  octave_user_code * debug_user_code (void) const;
+  octave_user_code * debug_user_code () const;
 
   octave_function * current_function (bool skip_first = false) const;
 
-  octave_function * caller_function (void) const;
+  octave_function * caller_function () const;
 
   bool goto_frame (std::size_t n = 0, bool verbose = false);
 
-  void goto_caller_frame (void);
+  void goto_caller_frame ();
 
-  void goto_base_frame (void);
+  void goto_base_frame ();
 
   void restore_frame (std::size_t n);
 
-  std::string get_dispatch_class (void) const;
+  std::string get_dispatch_class () const;
 
   void set_dispatch_class (const std::string& class_name);
 
@@ -504,22 +506,22 @@
   std::list<frame_info> backtrace_info (octave_idx_type& curr_user_frame,
                                         bool print_subfn = true) const;
 
-  std::list<frame_info> backtrace_info (void) const;
+  std::list<frame_info> backtrace_info () const;
 
   octave_map backtrace (octave_idx_type& curr_user_frame,
                         bool print_subfn = true) const;
 
-  octave_map backtrace (void) const;
+  octave_map backtrace () const;
 
-  octave_map empty_backtrace (void) const;
+  octave_map empty_backtrace () const;
 
-  std::string backtrace_message (void) const;
+  std::string backtrace_message () const;
 
   void push_dummy_scope (const std::string& name);
-  void pop_scope (void);
+  void pop_scope ();
 
-  symbol_scope get_top_scope (void) const;
-  symbol_scope get_current_scope (void) const;
+  symbol_scope get_top_scope () const;
+  symbol_scope get_current_scope () const;
 
   void mlock (bool skip_first = false) const;
 
@@ -530,11 +532,11 @@
   octave_value max_stack_depth (const octave_value_list& args, int nargout);
 
   // Useful for debugging
-  void display_call_stack (void) const;
+  void display_call_stack () const;
 
   octave_value find (const std::string& name);
 
-  void clear_objects (void);
+  void clear_objects ();
 
   void clear_variable (const std::string& name);
 
@@ -542,7 +544,7 @@
 
   void clear_variable_regexp (const std::string& pattern);
 
-  void clear_variables (void);
+  void clear_variables ();
 
   void clear_global_variable (const std::string& name);
 
@@ -550,7 +552,7 @@
 
   void clear_global_variable_regexp (const std::string& pattern);
 
-  void clear_global_variables (void);
+  void clear_global_variables ();
 
   void clear_all (bool force = false);
 
@@ -560,32 +562,32 @@
 
   void clear_symbol_regexp (const std::string& pattern);
 
-  std::list<std::string> global_variable_names (void) const;
+  std::list<std::string> global_variable_names () const;
 
-  std::list<std::string> top_level_variable_names (void) const;
+  std::list<std::string> top_level_variable_names () const;
 
-  std::list<std::string> variable_names (void) const;
+  std::list<std::string> variable_names () const;
 
   octave_user_code * get_user_code (const std::string& fname = "",
                                    const std::string& class_name = "");
 
   std::string current_function_name (bool skip_first = false) const;
 
-  bool in_user_code (void) const;
+  bool in_user_code () const;
 
   symbol_info_list glob_symbol_info (const std::string& pattern) const;
 
   symbol_info_list regexp_symbol_info (const std::string& pattern) const;
 
-  symbol_info_list get_symbol_info (void);
+  symbol_info_list get_symbol_info ();
 
-  symbol_info_list top_scope_symbol_info (void) const;
+  symbol_info_list top_scope_symbol_info () const;
 
-  octave_map get_autoload_map (void) const;
+  octave_map get_autoload_map () const;
 
   std::string lookup_autoload (const std::string& nm) const;
 
-  std::list<std::string> autoloaded_functions (void) const;
+  std::list<std::string> autoloaded_functions () const;
 
   std::list<std::string> reverse_lookup_autoload (const std::string& nm) const;
 
@@ -593,7 +595,7 @@
 
   void remove_autoload (const std::string& fcn, const std::string& nm);
 
-  int max_recursion_depth (void) const { return m_max_recursion_depth; }
+  int max_recursion_depth () const { return m_max_recursion_depth; }
 
   int max_recursion_depth (int n)
   {
@@ -605,7 +607,7 @@
   octave_value
   max_recursion_depth (const octave_value_list& args, int nargout);
 
-  bool silent_functions (void) const { return m_silent_functions; }
+  bool silent_functions () const { return m_silent_functions; }
 
   bool silent_functions (bool b)
   {
@@ -616,7 +618,7 @@
 
   octave_value whos_line_format (const octave_value_list& args, int nargout);
 
-  std::string whos_line_format (void) const { return m_whos_line_format; }
+  std::string whos_line_format () const { return m_whos_line_format; }
 
   std::string whos_line_format (const std::string& s)
   {
@@ -628,7 +630,7 @@
   octave_value
   silent_functions (const octave_value_list& args, int nargout);
 
-  std::size_t debug_frame (void) const { return m_debug_frame; }
+  std::size_t debug_frame () const { return m_debug_frame; }
 
   std::size_t debug_frame (std::size_t n)
   {
@@ -637,12 +639,12 @@
     return val;
   }
 
-  std::size_t current_call_stack_frame_number (void) const
+  std::size_t current_call_stack_frame_number () const
   {
     return m_call_stack.current_frame ();
   }
 
-  bool quiet_breakpoint_flag (void) const { return m_quiet_breakpoint_flag; }
+  bool quiet_breakpoint_flag () const { return m_quiet_breakpoint_flag; }
 
   bool quiet_breakpoint_flag (bool flag)
   {
@@ -651,7 +653,7 @@
     return val;
   }
 
-  char string_fill_char (void) const { return m_string_fill_char; }
+  char string_fill_char () const { return m_string_fill_char; }
 
   char string_fill_char (char c)
   {
@@ -664,9 +666,9 @@
   // call the corresponding functions in the debugger class for the
   // current debugger (if any).
 
-  bool in_debug_repl (void) const;
+  bool in_debug_repl () const;
 
-  void dbcont (void);
+  void dbcont ();
 
   // Return true if we are in the debug repl and m_execution_mode is
   // set to exit the debugger.  Otherwise, do nothing.
@@ -689,21 +691,21 @@
 
   // Clear the set of expressions that may be evaluated when the
   // debugger stops at a breakpoint.
-  void clear_debug_watch_expressions (void)
+  void clear_debug_watch_expressions ()
   {
     m_debug_watch_expressions.clear ();
   }
 
   // Return the set of expressions that may be evaluated when the
   // debugger stops at a breakpoint.
-  std::set<std::string> debug_watch_expressions (void) const
+  std::set<std::string> debug_watch_expressions () const
   {
     return m_debug_watch_expressions;
   }
 
   octave_value PS4 (const octave_value_list& args, int nargout);
 
-  std::string PS4 (void) const { return m_PS4; }
+  std::string PS4 () const { return m_PS4; }
 
   std::string PS4 (const std::string& s)
   {
@@ -712,7 +714,9 @@
     return val;
   }
 
-  octave_value indexed_object (void) const
+  void set_PS4 (const std::string& s) { m_PS4 = s; }
+
+  octave_value indexed_object () const
   {
     return m_indexed_object;
   }
@@ -722,7 +726,7 @@
     m_indexed_object = obj;
   }
 
-  const std::list<octave_value_list>& index_list (void) const
+  const std::list<octave_value_list>& index_list () const
   {
     return m_index_list;
   }
@@ -734,7 +738,7 @@
     m_index_list = index_list;
   }
 
-  void clear_index_list (void)
+  void clear_index_list ()
   {
     m_index_type = "";
     m_index_list.clear ();
@@ -746,18 +750,18 @@
     m_index_list.push_back (idx);
   }
 
-  const std::string& index_type (void) const
+  const std::string& index_type () const
   {
     return m_index_type;
   }
 
-  int index_position (void) const { return m_index_position; }
+  int index_position () const { return m_index_position; }
 
-  int num_indices (void) const { return m_num_indices; }
+  int num_indices () const { return m_num_indices; }
 
   octave_value_list evaluate_end_expression (const octave_value_list& args);
 
-  const std::list<octave_lvalue> * lvalue_list (void) const
+  const std::list<octave_lvalue> * lvalue_list () const
   {
     return m_lvalue_list;
   }
@@ -767,7 +771,7 @@
     m_lvalue_list = lst;
   }
 
-  int breaking (void) const { return m_breaking; }
+  int breaking () const { return m_breaking; }
 
   int breaking (int n)
   {
@@ -776,7 +780,7 @@
     return val;
   }
 
-  int continuing (void) const { return m_continuing; }
+  int continuing () const { return m_continuing; }
 
   int continuing (int n)
   {
@@ -785,7 +789,7 @@
     return val;
   }
 
-  int returning (void) const { return m_returning; }
+  int returning () const { return m_returning; }
 
   int returning (int n)
   {
@@ -794,7 +798,7 @@
     return val;
   }
 
-  int dbstep_flag (void) const { return m_dbstep_flag; }
+  int dbstep_flag () const { return m_dbstep_flag; }
 
   int dbstep_flag (int val)
   {
@@ -805,7 +809,7 @@
 
   void set_dbstep_flag (int step) { m_dbstep_flag = step; }
 
-  bool break_on_next_statement (void) const
+  bool break_on_next_statement () const
   {
     return m_break_on_next_stmt;
   }
@@ -824,7 +828,7 @@
 
   octave_value echo (const octave_value_list& args, int nargout);
 
-  int echo (void) const { return m_echo; }
+  int echo () const { return m_echo; }
 
   int echo (int val)
   {
@@ -848,6 +852,8 @@
 
   void push_echo_state (int type, const std::string& file_name, int pos = 1);
 
+  bool debug_mode () const { return m_debug_mode; }
+
 private:
 
   template <typename T>
@@ -857,11 +863,11 @@
 
   void set_echo_state (int type, const std::string& file_name, int pos);
 
-  void maybe_set_echo_state (void);
+  void maybe_set_echo_state ();
 
   void push_echo_state_cleanup (unwind_protect& frame);
 
-  bool maybe_push_echo_state_cleanup (void);
+  bool maybe_push_echo_state_cleanup ();
 
   void do_breakpoint (tree_statement& stmt);
 
@@ -877,7 +883,7 @@
 
   void echo_code (int line);
 
-  bool quit_loop_now (void);
+  bool quit_loop_now ();
 
   void bind_auto_fcn_vars (const string_vector& arg_names,
                            const Matrix& ignored_outputs, int nargin,
@@ -951,8 +957,8 @@
 
   // Echo commands as they are executed?
   //
-  //   1  ==>  echo commands read from script files
-  //   2  ==>  echo commands from functions
+  //   1 => echo commands read from script files
+  //   2 => echo commands from functions
   //
   // more than one state can be active at once.
   int m_echo;
--- a/libinterp/parse-tree/pt-except.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-except.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 
 // Simple exception handling.
 
-tree_try_catch_command::~tree_try_catch_command (void)
+tree_try_catch_command::~tree_try_catch_command ()
 {
   delete m_expr_id;
   delete m_try_code;
@@ -59,7 +59,7 @@
 
 // Simple exception handling.
 
-tree_unwind_protect_command::~tree_unwind_protect_command (void)
+tree_unwind_protect_command::~tree_unwind_protect_command ()
 {
   delete m_unwind_protect_code;
   delete m_cleanup_code;
--- a/libinterp/parse-tree/pt-except.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-except.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,25 +59,21 @@
       m_expr_id (id), m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_try_catch_command)
 
-  tree_try_catch_command (const tree_try_catch_command&) = delete;
+  ~tree_try_catch_command ();
 
-  tree_try_catch_command& operator = (const tree_try_catch_command&) = delete;
+  tree_identifier * identifier () { return m_expr_id; }
 
-  ~tree_try_catch_command (void);
-
-  tree_identifier * identifier (void) { return m_expr_id; }
+  tree_statement_list * body () { return m_try_code; }
 
-  tree_statement_list * body (void) { return m_try_code; }
+  tree_statement_list * cleanup () { return m_catch_code; }
 
-  tree_statement_list * cleanup (void) { return m_catch_code; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * middle_comment () { return m_mid_comm; }
 
-  comment_list * middle_comment (void) { return m_mid_comm; }
-
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -127,24 +123,19 @@
       m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct)
   { }
 
-  // No copying!
-
-  tree_unwind_protect_command (const tree_unwind_protect_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_unwind_protect_command)
 
-  tree_unwind_protect_command&
-  operator = (const tree_unwind_protect_command&) = delete;
+  ~tree_unwind_protect_command ();
 
-  ~tree_unwind_protect_command (void);
+  tree_statement_list * body () { return m_unwind_protect_code; }
 
-  tree_statement_list * body (void) { return m_unwind_protect_code; }
+  tree_statement_list * cleanup () { return m_cleanup_code; }
 
-  tree_statement_list * cleanup (void) { return m_cleanup_code; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * middle_comment () { return m_mid_comm; }
 
-  comment_list * middle_comment (void) { return m_mid_comm; }
-
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-exp.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-exp.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 }
 
 std::string
-tree_expression::original_text (void) const
+tree_expression::original_text () const
 {
   return "";
 }
--- a/libinterp/parse-tree/pt-exp.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-exp.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,67 +51,63 @@
     : tree (l, c), m_num_parens (0), m_postfix_index_type ('\0'),
       m_for_cmd_expr (false), m_print_flag (false) { }
 
-  // No copying!
-
-  tree_expression (const tree_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_expression)
 
-  tree_expression& operator = (const tree_expression&) = delete;
-
-  virtual ~tree_expression (void) = default;
+  virtual ~tree_expression () = default;
 
   virtual tree_expression * dup (symbol_scope& scope) const = 0;
 
-  virtual bool is_constant (void) const { return false; }
+  virtual bool is_constant () const { return false; }
 
-  virtual bool is_matrix (void) const { return false; }
+  virtual bool is_matrix () const { return false; }
 
-  virtual bool iscell (void) const { return false; }
+  virtual bool iscell () const { return false; }
 
-  virtual bool is_identifier (void) const { return false; }
+  virtual bool is_identifier () const { return false; }
 
-  virtual bool is_index_expression (void) const { return false; }
+  virtual bool is_index_expression () const { return false; }
 
-  virtual bool is_assignment_expression (void) const { return false; }
+  virtual bool is_assignment_expression () const { return false; }
 
-  virtual bool is_prefix_expression (void) const { return false; }
+  virtual bool is_prefix_expression () const { return false; }
 
-  virtual bool is_unary_expression (void) const { return false; }
+  virtual bool is_unary_expression () const { return false; }
 
-  virtual bool is_binary_expression (void) const { return false; }
+  virtual bool is_binary_expression () const { return false; }
 
-  virtual bool is_boolean_expression (void) const { return false; }
+  virtual bool is_boolean_expression () const { return false; }
 
-  virtual bool is_colon_expression (void) const { return false; }
+  virtual bool is_colon_expression () const { return false; }
 
-  virtual bool lvalue_ok (void) const { return false; }
+  virtual bool lvalue_ok () const { return false; }
 
-  virtual bool rvalue_ok (void) const { return false; }
+  virtual bool rvalue_ok () const { return false; }
 
   virtual octave_lvalue lvalue (tree_evaluator&);
 
-  int paren_count (void) const { return m_num_parens; }
+  int paren_count () const { return m_num_parens; }
 
-  bool is_postfix_indexed (void) const
+  bool is_postfix_indexed () const
   { return (m_postfix_index_type != '\0'); }
 
-  char postfix_index (void) const { return m_postfix_index_type; }
+  char postfix_index () const { return m_postfix_index_type; }
 
   // Check if the result of the expression should be printed.
   // Should normally be used in conjunction with
   // tree_evaluator::statement_printing_enabled.
-  bool print_result (void) const { return m_print_flag; }
+  bool print_result () const { return m_print_flag; }
 
-  virtual std::string oper (void) const { return "<unknown>"; }
+  virtual std::string oper () const { return "<unknown>"; }
 
-  virtual std::string name (void) const { return "<unknown>"; }
+  virtual std::string name () const { return "<unknown>"; }
 
-  virtual std::string original_text (void) const;
+  virtual std::string original_text () const;
 
-  void mark_as_for_cmd_expr (void) { m_for_cmd_expr = true; }
+  void mark_as_for_cmd_expr () { m_for_cmd_expr = true; }
 
-  bool is_for_cmd_expr (void) const { return m_for_cmd_expr; }
+  bool is_for_cmd_expr () const { return m_for_cmd_expr; }
 
-  tree_expression * mark_in_parens (void)
+  tree_expression * mark_in_parens ()
   {
     m_num_parens++;
     return this;
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -66,7 +66,7 @@
   return tw.make_fcn_handle (m_name);
 }
 
-tree_anon_fcn_handle::~tree_anon_fcn_handle (void)
+tree_anon_fcn_handle::~tree_anon_fcn_handle ()
 {
   delete m_parameter_list;
   delete m_expression;
--- a/libinterp/parse-tree/pt-fcn-handle.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Fri Jun 23 20:51:51 2023 +0200
@@ -55,13 +55,9 @@
   tree_fcn_handle (const std::string& n, int l = -1, int c = -1)
     : tree_expression (l, c), m_name (n) { }
 
-  // No copying!
-
-  tree_fcn_handle (const tree_fcn_handle&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_fcn_handle)
 
-  tree_fcn_handle& operator = (const tree_fcn_handle&) = delete;
-
-  ~tree_fcn_handle (void) = default;
+  ~tree_fcn_handle () = default;
 
   void print (std::ostream& os, bool pr_as_read_syntax = false,
               bool pr_orig_txt = true);
@@ -69,9 +65,9 @@
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
                   bool pr_orig_txt = true);
 
-  std::string name (void) const { return m_name; }
+  std::string name () const { return m_name; }
 
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -111,28 +107,24 @@
       m_scope (scope), m_parent_scope (parent_scope), m_file_name ()
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_anon_fcn_handle)
 
-  tree_anon_fcn_handle (const tree_anon_fcn_handle&) = delete;
-
-  tree_anon_fcn_handle& operator = (const tree_anon_fcn_handle&) = delete;
+  ~tree_anon_fcn_handle ();
 
-  ~tree_anon_fcn_handle (void);
+  bool rvalue_ok () const { return true; }
 
-  bool rvalue_ok (void) const { return true; }
-
-  tree_parameter_list * parameter_list (void) const
+  tree_parameter_list * parameter_list () const
   {
     return m_parameter_list;
   }
 
-  tree_expression * expression (void) const { return m_expression; }
+  tree_expression * expression () const { return m_expression; }
 
-  symbol_scope scope (void) const { return m_scope; }
+  symbol_scope scope () const { return m_scope; }
 
-  symbol_scope parent_scope (void) const { return m_parent_scope; }
+  symbol_scope parent_scope () const { return m_parent_scope; }
 
-  bool has_parent_scope (void) const { return m_parent_scope.is_valid (); }
+  bool has_parent_scope () const { return m_parent_scope.is_valid (); }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -147,7 +139,7 @@
 
   void stash_file_name (const std::string& file) { m_file_name = file; }
 
-  std::string file_name (void) const { return m_file_name; }
+  std::string file_name () const { return m_file_name; }
 
 private:
 
--- a/libinterp/parse-tree/pt-id.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-id.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 #include "error.h"
 #include "interpreter-private.h"
 #include "oct-lvalue.h"
-#include "parse.h"
 #include "pt-const.h"
 #include "pt-id.h"
 #include "symscope.h"
@@ -42,7 +41,7 @@
 // Symbols from the symbol table.
 
 void
-tree_identifier::eval_undefined_error (void)
+tree_identifier::eval_undefined_error ()
 {
   int l = line ();
   int c = column ();
@@ -136,7 +135,10 @@
             {
               octave_value_list args = ovl (val);
               args.stash_name_tags (string_vector (name ()));
-              feval ("display", args);
+
+              interpreter& interp = tw.get_interpreter ();
+
+              interp.feval ("display", args);
             }
 
           retval = ovl (val);
--- a/libinterp/parse-tree/pt-id.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-id.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,32 +60,28 @@
                    int l = -1, int c = -1)
     : tree_expression (l, c), m_sym (s) { }
 
-  // No copying!
-
-  tree_identifier (const tree_identifier&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_identifier)
 
-  tree_identifier& operator = (const tree_identifier&) = delete;
+  ~tree_identifier () = default;
 
-  ~tree_identifier (void) = default;
+  bool is_identifier () const { return true; }
 
-  bool is_identifier (void) const { return true; }
-
-  std::string name (void) const { return m_sym.name (); }
+  std::string name () const { return m_sym.name (); }
 
-  virtual bool is_black_hole (void) const { return false; }
+  virtual bool is_black_hole () const { return false; }
 
-  void mark_as_formal_parameter (void) { m_sym.mark_formal (); }
+  void mark_as_formal_parameter () { m_sym.mark_formal (); }
 
   // 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; }
+  bool lvalue_ok () const { return true; }
 
   octave_lvalue lvalue (tree_evaluator& tw);
 
-  void eval_undefined_error (void);
+  void eval_undefined_error ();
 
-  void static_workspace_error (void)
+  void static_workspace_error ()
   {
     error (R"(can not add variable "%s" to a static workspace)",
            name ().c_str ());
@@ -107,7 +103,7 @@
     tw.visit_identifier (*this);
   }
 
-  symbol_record symbol (void) const { return m_sym; }
+  symbol_record symbol () const { return m_sym; }
 
 protected:
 
@@ -122,9 +118,13 @@
   tree_black_hole (int l = -1, int c = -1)
     : tree_identifier (l, c) { }
 
-  std::string name (void) const { return "~"; }
+  OCTAVE_DISABLE_COPY_MOVE (tree_black_hole)
+
+  ~tree_black_hole () = default;
 
-  bool is_black_hole (void) const { return true; }
+  std::string name () const { return "~"; }
+
+  bool is_black_hole () const { return true; }
 
   tree_black_hole * dup (symbol_scope&) const
   {
--- a/libinterp/parse-tree/pt-idx.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -113,7 +113,7 @@
   return this;
 }
 
-tree_index_expression::~tree_index_expression (void)
+tree_index_expression::~tree_index_expression ()
 {
   delete m_expr;
 
@@ -136,7 +136,7 @@
 // assignment.
 
 std::string
-tree_index_expression::name (void) const
+tree_index_expression::name () const
 {
   return m_expr->name ();
 }
--- a/libinterp/parse-tree/pt-idx.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-idx.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,13 +62,9 @@
   tree_index_expression (tree_expression *e, tree_expression *df,
                          int l = -1, int c = -1);
 
-  // No copying!
-
-  tree_index_expression (const tree_index_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_index_expression)
 
-  tree_index_expression& operator = (const tree_index_expression&) = delete;
-
-  ~tree_index_expression (void);
+  ~tree_index_expression ();
 
   tree_index_expression *
   append (tree_argument_list *lst = nullptr, char t = '(');
@@ -77,27 +73,27 @@
 
   tree_index_expression * append (tree_expression *df);
 
-  bool is_index_expression (void) const { return true; }
+  bool is_index_expression () const { return true; }
 
-  std::string name (void) const;
+  std::string name () const;
 
-  tree_expression * expression (void) { return m_expr; }
+  tree_expression * expression () { return m_expr; }
 
-  std::list<tree_argument_list *> arg_lists (void) { return m_args; }
+  std::list<tree_argument_list *> arg_lists () { return m_args; }
 
-  std::string type_tags (void) { return m_type; }
+  std::string type_tags () { return m_type; }
 
-  std::list<string_vector> arg_names (void) { return m_arg_nm; }
+  std::list<string_vector> arg_names () { return m_arg_nm; }
 
-  std::list<tree_expression *> dyn_fields (void) { return m_dyn_field; }
+  std::list<tree_expression *> dyn_fields () { return m_dyn_field; }
 
-  void mark_word_list_cmd (void) { m_word_list_cmd = true; }
+  void mark_word_list_cmd () { m_word_list_cmd = true; }
 
-  bool is_word_list_cmd (void) const { return m_word_list_cmd; }
+  bool is_word_list_cmd () const { return m_word_list_cmd; }
 
-  bool lvalue_ok (void) const { return m_expr->lvalue_ok (); }
+  bool lvalue_ok () const { return m_expr->lvalue_ok (); }
 
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   octave_lvalue lvalue (tree_evaluator& tw);
 
@@ -145,7 +141,7 @@
 
   tree_index_expression (int l, int c);
 
-  octave_map make_arg_struct (void) const;
+  octave_map make_arg_struct () const;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-jump.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-jump.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,13 +42,9 @@
   tree_break_command (int l = -1, int c = -1)
     : tree_command (l, c) { }
 
-  // No copying!
-
-  tree_break_command (const tree_break_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_break_command)
 
-  tree_break_command& operator = (const tree_break_command&) = delete;
-
-  ~tree_break_command (void) = default;
+  ~tree_break_command () = default;
 
   void accept (tree_walker& tw)
   {
@@ -65,13 +61,9 @@
   tree_continue_command (int l = -1, int c = -1)
     : tree_command (l, c) { }
 
-  // No copying!
-
-  tree_continue_command (const tree_continue_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_continue_command)
 
-  tree_continue_command& operator = (const tree_continue_command&) = delete;
-
-  ~tree_continue_command (void) = default;
+  ~tree_continue_command () = default;
 
   void accept (tree_walker& tw)
   {
@@ -88,13 +80,9 @@
   tree_return_command (int l = -1, int c = -1)
     : tree_command (l, c) { }
 
-  // No copying!
-
-  tree_return_command (const tree_return_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_return_command)
 
-  tree_return_command& operator = (const tree_return_command&) = delete;
-
-  ~tree_return_command (void) = default;
+  ~tree_return_command () = default;
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-loop.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-loop.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 
 // While.
 
-tree_while_command::~tree_while_command (void)
+tree_while_command::~tree_while_command ()
 {
   delete m_expr;
   delete m_list;
@@ -46,7 +46,7 @@
 
 // For.
 
-tree_simple_for_command::~tree_simple_for_command (void)
+tree_simple_for_command::~tree_simple_for_command ()
 {
   delete m_lhs;
   delete m_expr;
@@ -56,7 +56,7 @@
   delete m_trail_comm;
 }
 
-tree_complex_for_command::~tree_complex_for_command (void)
+tree_complex_for_command::~tree_complex_for_command ()
 {
   delete m_lhs;
   delete m_expr;
--- a/libinterp/parse-tree/pt-loop.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-loop.h	Fri Jun 23 20:51:51 2023 +0200
@@ -66,21 +66,17 @@
       m_trail_comm (tc)
   { }
 
-  // No copying!
-
-  tree_while_command (const tree_while_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_while_command)
 
-  tree_while_command& operator = (const tree_while_command&) = delete;
+  ~tree_while_command ();
 
-  ~tree_while_command (void);
+  tree_expression * condition () { return m_expr; }
 
-  tree_expression * condition (void) { return m_expr; }
-
-  tree_statement_list * body (void) { return m_list; }
+  tree_statement_list * body () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -126,13 +122,9 @@
     : tree_while_command (e, lst, lc, tc, l, c)
   { }
 
-  // No copying!
-
-  tree_do_until_command (const tree_do_until_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_do_until_command)
 
-  tree_do_until_command& operator = (const tree_do_until_command&) = delete;
-
-  ~tree_do_until_command (void) = default;
+  ~tree_do_until_command () = default;
 
   void accept (tree_walker& tw)
   {
@@ -164,27 +156,23 @@
       m_lead_comm (lc), m_trail_comm (tc)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_simple_for_command)
 
-  tree_simple_for_command (const tree_simple_for_command&) = delete;
+  ~tree_simple_for_command ();
 
-  tree_simple_for_command& operator = (const tree_simple_for_command&) = delete;
+  bool in_parallel () { return m_parallel; }
 
-  ~tree_simple_for_command (void);
-
-  bool in_parallel (void) { return m_parallel; }
+  tree_expression * left_hand_side () { return m_lhs; }
 
-  tree_expression * left_hand_side (void) { return m_lhs; }
+  tree_expression * control_expr () { return m_expr; }
 
-  tree_expression * control_expr (void) { return m_expr; }
-
-  tree_expression * maxproc_expr (void) { return m_maxproc; }
+  tree_expression * maxproc_expr () { return m_maxproc; }
 
-  tree_statement_list * body (void) { return m_list; }
+  tree_statement_list * body () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -234,23 +222,19 @@
       m_lead_comm (lc), m_trail_comm (tc)
   { }
 
-  // No copying!
-
-  tree_complex_for_command (const tree_complex_for_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_complex_for_command)
 
-  tree_complex_for_command& operator = (const tree_complex_for_command&) = delete;
+  ~tree_complex_for_command ();
 
-  ~tree_complex_for_command (void);
+  tree_argument_list * left_hand_side () { return m_lhs; }
 
-  tree_argument_list * left_hand_side (void) { return m_lhs; }
+  tree_expression * control_expr () { return m_expr; }
 
-  tree_expression * control_expr (void) { return m_expr; }
+  tree_statement_list * body () { return m_list; }
 
-  tree_statement_list * body (void) { return m_list; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
-
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-mat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-mat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,17 +54,13 @@
     : tree_array_list (row, l, c)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_matrix)
 
-  tree_matrix (const tree_matrix&) = delete;
-
-  tree_matrix& operator = (const tree_matrix&) = delete;
+  ~tree_matrix () = default;
 
-  ~tree_matrix (void) = default;
+  bool is_matrix () const { return true; }
 
-  bool is_matrix (void) const { return true; }
-
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
--- a/libinterp/parse-tree/pt-misc.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-misc.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 
 // Parameter lists.
 
-tree_parameter_list::~tree_parameter_list (void)
+tree_parameter_list::~tree_parameter_list ()
 {
   while (! empty ())
     {
@@ -45,14 +45,14 @@
 }
 
 void
-tree_parameter_list::mark_as_formal_parameters (void)
+tree_parameter_list::mark_as_formal_parameters ()
 {
   for (tree_decl_elt *elt : *this)
     elt->mark_as_formal_parameter ();
 }
 
 std::list<std::string>
-tree_parameter_list::variable_names (void) const
+tree_parameter_list::variable_names () const
 {
   std::list<std::string> retval;
 
--- a/libinterp/parse-tree/pt-misc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-misc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -68,31 +68,27 @@
     append (new tree_decl_elt (id));
   }
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_parameter_list)
 
-  tree_parameter_list (const tree_parameter_list&) = delete;
-
-  tree_parameter_list& operator = (const tree_parameter_list&) = delete;
+  ~tree_parameter_list ();
 
-  ~tree_parameter_list (void);
+  void mark_as_formal_parameters ();
 
-  void mark_as_formal_parameters (void);
+  void mark_varargs () { m_marked_for_varargs = 1; }
 
-  void mark_varargs (void) { m_marked_for_varargs = 1; }
+  void mark_varargs_only () { m_marked_for_varargs = -1; }
 
-  void mark_varargs_only (void) { m_marked_for_varargs = -1; }
+  bool takes_varargs () const { return m_marked_for_varargs != 0; }
 
-  bool takes_varargs (void) const { return m_marked_for_varargs != 0; }
+  bool varargs_only () { return (m_marked_for_varargs < 0); }
 
-  bool varargs_only (void) { return (m_marked_for_varargs < 0); }
+  bool is_input_list () const { return m_in_or_out == in; }
 
-  bool is_input_list (void) const { return m_in_or_out == in; }
-
-  bool is_output_list (void) const { return m_in_or_out == out; }
+  bool is_output_list () const { return m_in_or_out == out; }
 
-  std::list<std::string> variable_names (void) const;
+  std::list<std::string> variable_names () const;
 
-  std::string varargs_symbol_name (void) const
+  std::string varargs_symbol_name () const
   {
     return m_in_or_out == in ? "varargin" : "varargout";
   }
--- a/libinterp/parse-tree/pt-pr-code.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-pr-code.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -1201,7 +1201,7 @@
 // Each print_code() function should call this before printing anything.
 
 void
-tree_print_code::indent (void)
+tree_print_code::indent ()
 {
   panic_unless (m_curr_print_indent_level >= 0);
 
@@ -1236,7 +1236,7 @@
 // For resetting print_code state.
 
 void
-tree_print_code::reset (void)
+tree_print_code::reset ()
 {
   m_beginning_of_line = true;
   m_curr_print_indent_level = 0;
--- a/libinterp/parse-tree/pt-pr-code.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-pr-code.h	Fri Jun 23 20:51:51 2023 +0200
@@ -58,13 +58,9 @@
     m_nesting.push ('n');
   }
 
-  // No copying!
-
-  tree_print_code (const tree_print_code&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_print_code)
 
-  tree_print_code& operator = (const tree_print_code&) = delete;
-
-  ~tree_print_code (void) = default;
+  ~tree_print_code () = default;
 
   void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
@@ -185,17 +181,17 @@
   // Nonzero means we are not printing newlines and indenting.
   int m_suppress_newlines;
 
-  void reset_indent_level (void) { m_curr_print_indent_level = 0; }
+  void reset_indent_level () { m_curr_print_indent_level = 0; }
 
-  void increment_indent_level (void) { m_curr_print_indent_level += 2; }
+  void increment_indent_level () { m_curr_print_indent_level += 2; }
 
-  void decrement_indent_level (void) { m_curr_print_indent_level -= 2; }
+  void decrement_indent_level () { m_curr_print_indent_level -= 2; }
 
   void newline (const char *alt_txt = ", ");
 
-  void indent (void);
+  void indent ();
 
-  void reset (void);
+  void reset ();
 
   void print_parens (const tree_expression& expr, const char *txt);
 
@@ -207,7 +203,7 @@
 
   // Must create with an output stream!
 
-  tree_print_code (void);
+  tree_print_code ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-select.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-select.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,7 @@
 
 // If clauses.
 
-tree_if_clause::~tree_if_clause (void)
+tree_if_clause::~tree_if_clause ()
 {
   delete m_expr;
   delete m_list;
@@ -44,7 +44,7 @@
 
 // If.
 
-tree_if_command::~tree_if_command (void)
+tree_if_command::~tree_if_command ()
 {
   delete m_list;
   delete m_lead_comm;
@@ -53,7 +53,7 @@
 
 // Switch cases.
 
-tree_switch_case::~tree_switch_case (void)
+tree_switch_case::~tree_switch_case ()
 {
   delete m_label;
   delete m_list;
@@ -62,7 +62,7 @@
 
 // Switch.
 
-tree_switch_command::~tree_switch_command (void)
+tree_switch_command::~tree_switch_command ()
 {
   delete m_expr;
   delete m_list;
--- a/libinterp/parse-tree/pt-select.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-select.h	Fri Jun 23 20:51:51 2023 +0200
@@ -57,21 +57,17 @@
                   int l = -1, int c = -1)
     : tree (l, c), m_expr (e), m_list (sl), m_lead_comm (lc) { }
 
-  // No copying!
-
-  tree_if_clause (const tree_if_clause&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_if_clause)
 
-  tree_if_clause& operator = (const tree_if_clause&) = delete;
+  ~tree_if_clause ();
 
-  ~tree_if_clause (void);
+  bool is_else_clause () { return ! m_expr; }
 
-  bool is_else_clause (void) { return ! m_expr; }
-
-  tree_expression * condition (void) { return m_expr; }
+  tree_expression * condition () { return m_expr; }
 
-  tree_statement_list * commands (void) { return m_list; }
+  tree_statement_list * commands () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -94,17 +90,13 @@
 {
 public:
 
-  tree_if_command_list (void) { }
+  tree_if_command_list () { }
 
   tree_if_command_list (tree_if_clause *t) { append (t); }
 
-  // No copying!
-
-  tree_if_command_list (const tree_if_command_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_if_command_list)
 
-  tree_if_command_list& operator = (const tree_if_command_list&) = delete;
-
-  ~tree_if_command_list (void)
+  ~tree_if_command_list ()
   {
     while (! empty ())
       {
@@ -134,19 +126,15 @@
     : tree_command (l, c), m_list (lst), m_lead_comm (lc), m_trail_comm (tc)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree_if_command)
 
-  tree_if_command (const tree_if_command&) = delete;
-
-  tree_if_command& operator = (const tree_if_command&) = delete;
+  ~tree_if_command ();
 
-  ~tree_if_command (void);
-
-  tree_if_command_list * cmd_list (void) { return m_list; }
+  tree_if_command_list * cmd_list () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -184,21 +172,17 @@
                     int l = -1, int c = -1)
     : tree (l, c), m_label (e), m_list (sl), m_lead_comm (lc) { }
 
-  // No copying!
-
-  tree_switch_case (const tree_switch_case&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_switch_case)
 
-  tree_switch_case& operator = (const tree_switch_case&) = delete;
+  ~tree_switch_case ();
 
-  ~tree_switch_case (void);
+  bool is_default_case () { return ! m_label; }
 
-  bool is_default_case (void) { return ! m_label; }
-
-  tree_expression * case_label (void) { return m_label; }
+  tree_expression * case_label () { return m_label; }
 
-  tree_statement_list * commands (void) { return m_list; }
+  tree_statement_list * commands () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
   void accept (tree_walker& tw)
   {
@@ -221,17 +205,13 @@
 {
 public:
 
-  tree_switch_case_list (void) { }
+  tree_switch_case_list () { }
 
   tree_switch_case_list (tree_switch_case *t) { append (t); }
 
-  // No copying!
-
-  tree_switch_case_list (const tree_switch_case_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_switch_case_list)
 
-  tree_switch_case_list& operator = (const tree_switch_case_list&) = delete;
-
-  ~tree_switch_case_list (void)
+  ~tree_switch_case_list ()
   {
     while (! empty ())
       {
@@ -261,21 +241,17 @@
     : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc),
       m_trail_comm (tc) { }
 
-  // No copying!
-
-  tree_switch_command (const tree_switch_command&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_switch_command)
 
-  tree_switch_command& operator = (const tree_switch_command&) = delete;
+  ~tree_switch_command ();
 
-  ~tree_switch_command (void);
+  tree_expression * switch_value () { return m_expr; }
 
-  tree_expression * switch_value (void) { return m_expr; }
-
-  tree_switch_case_list * case_list (void) { return m_list; }
+  tree_switch_case_list * case_list () { return m_list; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-spmd.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-spmd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-tree_spmd_command::~tree_spmd_command (void)
+tree_spmd_command::~tree_spmd_command ()
 {
   delete m_body;
   delete m_lead_comm;
--- a/libinterp/parse-tree/pt-spmd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-spmd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,19 +48,15 @@
     : tree_command (l, c), m_body (body), m_lead_comm (lc), m_trail_comm (tc)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_spmd_command)
 
-  tree_spmd_command (const tree_spmd_command&) = delete;
-
-  tree_spmd_command& operator = (const tree_spmd_command&) = delete;
+  ~tree_spmd_command ();
 
-  ~tree_spmd_command (void);
-
-  tree_statement_list * body (void) { return m_body; }
+  tree_statement_list * body () { return m_body; }
 
-  comment_list * leading_comment (void) { return m_lead_comm; }
+  comment_list * leading_comment () { return m_lead_comm; }
 
-  comment_list * trailing_comment (void) { return m_trail_comm; }
+  comment_list * trailing_comment () { return m_trail_comm; }
 
   void accept (tree_walker& tw)
   {
--- a/libinterp/parse-tree/pt-stmt.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-stmt.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 
 // A list of commands to be executed.
 
-tree_statement::~tree_statement (void)
+tree_statement::~tree_statement ()
 {
   delete m_command;
   delete m_expression;
@@ -68,7 +68,7 @@
 }
 
 bool
-tree_statement::print_result (void)
+tree_statement::print_result ()
 {
   return m_expression && m_expression->print_result ();
 }
@@ -83,7 +83,7 @@
 }
 
 void
-tree_statement::delete_breakpoint (void)
+tree_statement::delete_breakpoint ()
 {
   if (m_command)
     m_command->delete_breakpoint ();
@@ -92,7 +92,7 @@
 }
 
 bool
-tree_statement::is_breakpoint (void) const
+tree_statement::is_breakpoint () const
 {
   return m_command ? m_command->is_breakpoint ()
          : (m_expression ? m_expression->is_breakpoint ()
@@ -116,7 +116,7 @@
 }
 
 int
-tree_statement::line (void) const
+tree_statement::line () const
 {
   return (m_command
           ? m_command->line ()
@@ -124,7 +124,7 @@
 }
 
 int
-tree_statement::column (void) const
+tree_statement::column () const
 {
   return (m_command
           ? m_command->column ()
@@ -149,7 +149,7 @@
 }
 
 bool
-tree_statement::is_end_of_fcn_or_script (void) const
+tree_statement::is_end_of_fcn_or_script () const
 {
   bool retval = false;
 
@@ -166,7 +166,7 @@
 }
 
 bool
-tree_statement::is_end_of_file (void) const
+tree_statement::is_end_of_file () const
 {
   bool retval = false;
 
@@ -218,7 +218,7 @@
 }
 
 octave_value_list
-tree_statement_list::list_breakpoints (void)
+tree_statement_list::list_breakpoints ()
 {
   tree_breakpoint tbp (0, tree_breakpoint::list);
   accept (tbp);
@@ -228,7 +228,7 @@
 
 // Get list of pairs (breakpoint line, breakpoint condition)
 std::list<bp_type>
-tree_statement_list::breakpoints_and_conds (void)
+tree_statement_list::breakpoints_and_conds ()
 {
   tree_breakpoint tbp (0, tree_breakpoint::list);
   accept (tbp);
--- a/libinterp/parse-tree/pt-stmt.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-stmt.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 {
 public:
 
-  tree_statement (void)
+  tree_statement ()
     : m_command (nullptr), m_expression (nullptr),
       m_comment_list (nullptr) { }
 
@@ -63,53 +63,49 @@
   tree_statement (tree_expression *e, comment_list *cl)
     : m_command (nullptr), m_expression (e), m_comment_list (cl) { }
 
-  // No copying!
-
-  tree_statement (const tree_statement&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_statement)
 
-  tree_statement& operator = (const tree_statement&) = delete;
-
-  ~tree_statement (void);
+  ~tree_statement ();
 
   void set_print_flag (bool print_flag);
 
-  bool print_result (void);
+  bool print_result ();
 
-  bool is_command (void) const { return m_command != nullptr; }
+  bool is_command () const { return m_command != nullptr; }
 
-  bool is_expression (void) const { return m_expression != nullptr; }
+  bool is_expression () const { return m_expression != nullptr; }
 
   void set_breakpoint (const std::string& condition);
 
-  void delete_breakpoint (void);
+  void delete_breakpoint ();
 
-  bool is_breakpoint (void) const;
+  bool is_breakpoint () const;
 
   bool is_active_breakpoint (tree_evaluator& tw) const;
 
   std::string bp_cond () const;
 
-  int line (void) const;
-  int column (void) const;
+  int line () const;
+  int column () const;
 
   void set_location (int l, int c);
 
   void echo_code (const std::string& prefix);
 
-  tree_command * command (void) { return m_command; }
+  tree_command * command () { return m_command; }
 
-  tree_expression * expression (void) { return m_expression; }
+  tree_expression * expression () { return m_expression; }
 
-  comment_list * comment_text (void) { return m_comment_list; }
+  comment_list * comment_text () { return m_comment_list; }
 
-  bool is_null_statement (void) const
+  bool is_null_statement () const
   {
     return ! (m_command || m_expression || m_comment_list);
   }
 
-  bool is_end_of_fcn_or_script (void) const;
+  bool is_end_of_fcn_or_script () const;
 
-  bool is_end_of_file (void) const;
+  bool is_end_of_file () const;
 
   // Allow modification of this statement.  Note that there is no
   // checking.  If you use these, are you sure you know what you are
@@ -144,7 +140,7 @@
 {
 public:
 
-  tree_statement_list (void)
+  tree_statement_list ()
     : m_function_body (false), m_anon_function_body (false),
       m_script_body (false) { }
 
@@ -152,13 +148,9 @@
     : m_function_body (false), m_anon_function_body (false),
       m_script_body (false) { append (s); }
 
-  // No copying!
-
-  tree_statement_list (const tree_statement_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_statement_list)
 
-  tree_statement_list& operator = (const tree_statement_list&) = delete;
-
-  ~tree_statement_list (void)
+  ~tree_statement_list ()
   {
     while (! empty ())
       {
@@ -168,25 +160,25 @@
       }
   }
 
-  void mark_as_function_body (void) { m_function_body = true; }
+  void mark_as_function_body () { m_function_body = true; }
 
-  void mark_as_anon_function_body (void) { m_anon_function_body = true; }
+  void mark_as_anon_function_body () { m_anon_function_body = true; }
 
-  void mark_as_script_body (void) { m_script_body = true; }
+  void mark_as_script_body () { m_script_body = true; }
 
-  bool is_function_body (void) const { return m_function_body; }
+  bool is_function_body () const { return m_function_body; }
 
-  bool is_anon_function_body (void) const { return m_anon_function_body; }
+  bool is_anon_function_body () const { return m_anon_function_body; }
 
-  bool is_script_body (void) const { return m_script_body; }
+  bool is_script_body () const { return m_script_body; }
 
   int set_breakpoint (int line, const std::string& condition);
 
   void delete_breakpoint (int line);
 
-  octave_value_list list_breakpoints (void);
+  octave_value_list list_breakpoints ();
 
-  std::list<bp_type> breakpoints_and_conds (void);
+  std::list<bp_type> breakpoints_and_conds ();
 
   bp_table::bp_lines add_breakpoint (event_manager& evmgr,
                                      const std::string& file,
--- a/libinterp/parse-tree/pt-tm-const.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-tm-const.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -60,7 +60,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-void tm_row_const::cellify (void)
+void tm_row_const::cellify ()
 {
   bool elt_changed = false;
 
@@ -160,6 +160,13 @@
   m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;
 }
 
+// FIXME: This function is mostly a duplicate of
+//
+//   void tm_row_const::init (const octave_value *, const octave_value *)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
 void tm_row_const::init (const tree_argument_list& row, tree_evaluator& tw)
 {
   bool first_elem = true;
@@ -214,6 +221,68 @@
     }
 }
 
+// FIXME: This function is mostly a duplicate of
+//
+//   void tm_row_const::init (const tree_argument_list&, tree_evaluator&)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+void tm_row_const::init (const octave_value *beg, const octave_value *end)
+{
+  bool first_elem = true;
+
+  for (; beg != end; beg++)
+    {
+      octave_quit ();
+
+      octave_value tmp = *beg;
+
+      if (tmp.is_undefined ())
+        error ("undefined element in matrix list");
+
+      if (tmp.is_cs_list ())
+        {
+          octave_value_list tlst = tmp.list_value ();
+
+          for (octave_idx_type i = 0; i < tlst.length (); i++)
+            {
+              octave_quit ();
+
+              init_element (tlst(i), first_elem);
+            }
+        }
+      else
+        init_element (tmp, first_elem);
+    }
+
+  if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct)
+    cellify ();
+
+  first_elem = true;
+
+  for (const auto& val : m_values)
+    {
+      octave_quit ();
+
+      dim_vector this_elt_dv = val.dims ();
+
+      if (! this_elt_dv.zero_by_zero ())
+        {
+          m_all_empty = false;
+
+          if (first_elem)
+            {
+              first_elem = false;
+              m_dv = this_elt_dv;
+            }
+          else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1)))
+            eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
+        }
+    }
+}
+
+
 octave_value tm_const::concat (char string_fill_char) const
 {
   if (m_tm_rows.empty ())
@@ -295,6 +364,16 @@
     return generic_concat ();
 }
 
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        const std::vector<int>&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        octave_idx_type)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
 void tm_const::init (const tree_matrix& tm)
 {
   bool first_elem = true;
@@ -410,6 +489,261 @@
     }
 }
 
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const tree_matrix&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        octave_idx_type)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+// For variable length rows
+void tm_const::init (const octave_value *beg, const octave_value *end,
+                     const std::vector<int>& row_lengths)
+{
+  bool first_elem = true;
+  bool first_elem_is_struct = false;
+
+  // Just eval and figure out if what we have is complex or all strings.
+  // We can't check columns until we know that this is a numeric matrix --
+  // collections of strings can have elements of different lengths.
+
+  for (int i = 0; beg != end; beg += row_lengths[i++])
+    {
+      octave_quit ();
+
+      if (beg + row_lengths[i] > end)
+        error ("invalid call to tm_const::init");
+
+      tm_row_const row (beg, beg + row_lengths[i]);
+
+      if (first_elem)
+        {
+          first_elem_is_struct = row.first_elem_struct_p ();
+
+          first_elem = false;
+        }
+
+      if (row.empty ())
+        continue;
+
+      if (m_all_strings && ! row.all_strings_p ())
+        m_all_strings = false;
+
+      if (m_all_sq_strings && ! row.all_sq_strings_p ())
+        m_all_sq_strings = false;
+
+      if (m_all_dq_strings && ! row.all_dq_strings_p ())
+        m_all_dq_strings = false;
+
+      if (! m_some_strings && row.some_strings_p ())
+        m_some_strings = true;
+
+      if (m_all_real && ! row.all_real_p ())
+        m_all_real = false;
+
+      if (m_all_complex && ! row.all_complex_p ())
+        m_all_complex = false;
+
+      if (m_all_empty && ! row.all_empty_p ())
+        m_all_empty = false;
+
+      if (! m_any_cell && row.any_cell_p ())
+        m_any_cell = true;
+
+      if (! m_any_sparse && row.any_sparse_p ())
+        m_any_sparse = true;
+
+      if (! m_any_class && row.any_class_p ())
+        m_any_class = true;
+
+      m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
+
+      m_tm_rows.push_back (row);
+    }
+
+  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
+    {
+      for (auto& elt : m_tm_rows)
+        {
+          octave_quit ();
+
+          elt.cellify ();
+        }
+    }
+
+  first_elem = true;
+
+  for (const auto& elt : m_tm_rows)
+    {
+      octave_quit ();
+
+      octave_idx_type this_elt_nr = elt.rows ();
+      octave_idx_type this_elt_nc = elt.cols ();
+
+      std::string this_elt_class_name = elt.class_name ();
+      m_class_name = get_concat_class (m_class_name, this_elt_class_name);
+
+      dim_vector this_elt_dv = elt.dims ();
+
+      m_all_empty = false;
+
+      if (first_elem)
+        {
+          first_elem = false;
+
+          m_dv = this_elt_dv;
+        }
+      else if (m_all_strings && m_dv.ndims () == 2
+               && this_elt_dv.ndims () == 2)
+        {
+          // This is Octave's specialty.
+          // Character matrices support rows of unequal length.
+          if (m_dv.any_zero ())
+            {
+              // Empty existing element (bug #52542).
+              // Replace empty element with non-empty one.
+              m_dv = this_elt_dv;
+            }
+          else
+            {
+              if (this_elt_nc > cols ())
+                m_dv(1) = this_elt_nc;
+              m_dv(0) += this_elt_nr;
+            }
+        }
+      else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
+        eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
+    }
+}
+
+// FIXME: This function is mostly a duplicate of both of the functions
+//
+//   void tm_const::init (const tree_matrix&)
+//   void tm_const::init (const octave_value *, const octave_value *,
+//                        const std::vector<int>&)
+//
+// The common parts should be factored out into a single function that
+// is used by the others.
+
+// Fixed row size
+void tm_const::init (const octave_value *beg, const octave_value *end,
+                     octave_idx_type row_length)
+{
+  bool first_elem = true;
+  bool first_elem_is_struct = false;
+
+  // Just eval and figure out if what we have is complex or all strings.
+  // We can't check columns until we know that this is a numeric matrix --
+  // collections of strings can have elements of different lengths.
+
+  for (;beg != end; beg += row_length)
+    {
+      octave_quit ();
+
+      tm_row_const row (beg, beg + row_length);
+
+      if (first_elem)
+        {
+          first_elem_is_struct = row.first_elem_struct_p ();
+
+          first_elem = false;
+        }
+
+      if (row.empty ())
+        continue;
+
+      if (m_all_strings && ! row.all_strings_p ())
+        m_all_strings = false;
+
+      if (m_all_sq_strings && ! row.all_sq_strings_p ())
+        m_all_sq_strings = false;
+
+      if (m_all_dq_strings && ! row.all_dq_strings_p ())
+        m_all_dq_strings = false;
+
+      if (! m_some_strings && row.some_strings_p ())
+        m_some_strings = true;
+
+      if (m_all_real && ! row.all_real_p ())
+        m_all_real = false;
+
+      if (m_all_complex && ! row.all_complex_p ())
+        m_all_complex = false;
+
+      if (m_all_empty && ! row.all_empty_p ())
+        m_all_empty = false;
+
+      if (! m_any_cell && row.any_cell_p ())
+        m_any_cell = true;
+
+      if (! m_any_sparse && row.any_sparse_p ())
+        m_any_sparse = true;
+
+      if (! m_any_class && row.any_class_p ())
+        m_any_class = true;
+
+      m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
+
+      m_tm_rows.push_back (row);
+    }
+
+  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
+    {
+      for (auto& elt : m_tm_rows)
+        {
+          octave_quit ();
+
+          elt.cellify ();
+        }
+    }
+
+  first_elem = true;
+
+  for (const auto& elt : m_tm_rows)
+    {
+      octave_quit ();
+
+      octave_idx_type this_elt_nr = elt.rows ();
+      octave_idx_type this_elt_nc = elt.cols ();
+
+      std::string this_elt_class_name = elt.class_name ();
+      m_class_name = get_concat_class (m_class_name, this_elt_class_name);
+
+      dim_vector this_elt_dv = elt.dims ();
+
+      m_all_empty = false;
+
+      if (first_elem)
+        {
+          first_elem = false;
+
+          m_dv = this_elt_dv;
+        }
+      else if (m_all_strings && m_dv.ndims () == 2
+               && this_elt_dv.ndims () == 2)
+        {
+          // This is Octave's specialty.
+          // Character matrices support rows of unequal length.
+          if (m_dv.any_zero ())
+            {
+              // Empty existing element (bug #52542).
+              // Replace empty element with non-empty one.
+              m_dv = this_elt_dv;
+            }
+          else
+            {
+              if (this_elt_nc > cols ())
+                m_dv(1) = this_elt_nc;
+              m_dv(0) += this_elt_nr;
+            }
+        }
+      else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
+        eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
+    }
+}
+
 octave_value tm_const::char_array_concat (char string_fill_char) const
 {
   char type = (m_all_dq_strings ? '"' : '\'');
@@ -421,7 +755,7 @@
   return octave_value (result, type);
 }
 
-octave_value tm_const::class_concat (void) const
+octave_value tm_const::class_concat () const
 {
   octave_value retval;
 
@@ -454,7 +788,7 @@
   return retval;
 }
 
-octave_value tm_const::generic_concat (void) const
+octave_value tm_const::generic_concat () const
 {
   // The line below might seem crazy, since we take a copy of the
   // first argument, resize it to be empty and then resize it to be
@@ -590,7 +924,7 @@
 }
 
 template <typename TYPE>
-TYPE tm_const::array_concat (void) const
+TYPE tm_const::array_concat () const
 {
   typedef typename TYPE::element_type ELT_T;
 
@@ -639,7 +973,7 @@
 }
 
 template <typename TYPE>
-TYPE tm_const::sparse_array_concat (void) const
+TYPE tm_const::sparse_array_concat () const
 {
   if (m_dv.any_zero ())
     return TYPE (m_dv);
@@ -673,7 +1007,7 @@
 }
 
 template <typename MAP>
-octave_map tm_const::map_concat (void) const
+octave_map tm_const::map_concat () const
 {
   if (m_dv.any_zero ())
     return octave_map (m_dv);
--- a/libinterp/parse-tree/pt-tm-const.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-tm-const.h	Fri Jun 23 20:51:51 2023 +0200
@@ -77,25 +77,25 @@
       m_first_elem_is_struct (false), m_class_name ()
   { }
 
-  dim_vector dims (void) const { return m_dv; }
+  dim_vector dims () const { return m_dv; }
 
-  octave_idx_type rows (void) const { return m_dv(0); }
-  octave_idx_type cols (void) const { return m_dv(1); }
+  octave_idx_type rows () const { return m_dv(0); }
+  octave_idx_type cols () const { return m_dv(1); }
 
-  bool all_strings_p (void) const { return m_all_strings; }
-  bool all_sq_strings_p (void) const { return m_all_sq_strings; }
-  bool all_dq_strings_p (void) const { return m_all_dq_strings; }
-  bool some_strings_p (void) const { return m_some_strings; }
-  bool all_real_p (void) const { return m_all_real; }
-  bool all_complex_p (void) const { return m_all_complex; }
-  bool all_empty_p (void) const { return m_all_empty; }
-  bool any_cell_p (void) const { return m_any_cell; }
-  bool any_sparse_p (void) const { return m_any_sparse; }
-  bool any_class_p (void) const { return m_any_class; }
-  bool all_1x1_p (void) const { return m_all_1x1; }
-  bool first_elem_struct_p (void) const { return m_first_elem_is_struct; }
+  bool all_strings_p () const { return m_all_strings; }
+  bool all_sq_strings_p () const { return m_all_sq_strings; }
+  bool all_dq_strings_p () const { return m_all_dq_strings; }
+  bool some_strings_p () const { return m_some_strings; }
+  bool all_real_p () const { return m_all_real; }
+  bool all_complex_p () const { return m_all_complex; }
+  bool all_empty_p () const { return m_all_empty; }
+  bool any_cell_p () const { return m_any_cell; }
+  bool any_sparse_p () const { return m_any_sparse; }
+  bool any_class_p () const { return m_any_class; }
+  bool all_1x1_p () const { return m_all_1x1; }
+  bool first_elem_struct_p () const { return m_first_elem_is_struct; }
 
-  std::string class_name (void) const { return m_class_name; }
+  std::string class_name () const { return m_class_name; }
 
 protected:
 
@@ -149,7 +149,7 @@
   typedef std::list<octave_value>::iterator iterator;
   typedef std::list<octave_value>::const_iterator const_iterator;
 
-  tm_row_const (void) = delete;
+  tm_row_const () = delete;
 
   tm_row_const (const tree_argument_list& row, tree_evaluator& tw)
     : tm_info (row.empty ()), m_values ()
@@ -157,23 +157,29 @@
     init (row, tw);
   }
 
+  tm_row_const (const octave_value *beg, const octave_value *end)
+    : tm_info (beg == end), m_values ()
+  {
+    init (beg, end);
+  }
+
   tm_row_const (const tm_row_const&) = default;
 
   tm_row_const& operator = (const tm_row_const&) = delete;
 
-  ~tm_row_const (void) = default;
+  ~tm_row_const () = default;
 
-  iterator begin (void) { return m_values.begin (); }
-  const_iterator begin (void) const { return m_values.begin (); }
+  iterator begin () { return m_values.begin (); }
+  const_iterator begin () const { return m_values.begin (); }
 
-  iterator end (void) { return m_values.end (); }
-  const_iterator end (void) const { return m_values.end (); }
+  iterator end () { return m_values.end (); }
+  const_iterator end () const { return m_values.end (); }
 
-  bool empty (void) const { return m_values.empty (); }
+  bool empty () const { return m_values.empty (); }
 
-  std::size_t length (void) const { return m_values.size (); }
+  std::size_t length () const { return m_values.size (); }
 
-  void cellify (void);
+  void cellify ();
 
 private:
 
@@ -182,6 +188,7 @@
   void init_element (const octave_value&, bool&);
 
   void init (const tree_argument_list&, tree_evaluator& tw);
+  void init (const octave_value *beg, const octave_value *end);
 };
 
 class tm_const : public tm_info
@@ -191,7 +198,7 @@
   typedef std::list<tm_row_const>::iterator iterator;
   typedef std::list<tm_row_const>::const_iterator const_iterator;
 
-  tm_const (void) = delete;
+  tm_const () = delete;
 
   tm_const (const tree_matrix& tm, tree_evaluator& tw)
     : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows ()
@@ -199,13 +206,23 @@
     init (tm);
   }
 
-  // No copying!
-
-  tm_const (const tm_const&) = delete;
+  tm_const (const octave_value *beg, const octave_value *end,
+            octave_idx_type n_rows, tree_evaluator& tw)
+    : tm_info (beg == end), m_evaluator (tw), m_tm_rows ()
+  {
+     init (beg, end, n_rows);
+  }
 
-  tm_const& operator = (const tm_const&) = delete;
+  tm_const (const octave_value *beg, const octave_value *end,
+            const std::vector<int>& row_lengths, tree_evaluator& tw)
+    : tm_info (beg == end), m_evaluator (tw), m_tm_rows ()
+  {
+     init (beg, end, row_lengths);
+  }
 
-  ~tm_const (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (tm_const)
+
+  ~tm_const () = default;
 
   octave_value concat (char string_fill_char) const;
 
@@ -221,23 +238,29 @@
 
   void init (const tree_matrix& tm);
 
+  void init (const octave_value *beg, const octave_value *end,
+             octave_idx_type row_length);
+
+  void init (const octave_value *beg, const octave_value *end,
+             const std::vector<int>& row_lengths);
+
   octave_value char_array_concat (char string_fill_char) const;
 
-  octave_value class_concat (void) const;
+  octave_value class_concat () const;
 
-  octave_value generic_concat (void) const;
+  octave_value generic_concat () const;
 
   template <typename TYPE>
   void array_concat_internal (TYPE& result) const;
 
   template <typename TYPE>
-  TYPE array_concat (void) const;
+  TYPE array_concat () const;
 
   template <typename TYPE>
-  TYPE sparse_array_concat (void) const;
+  TYPE sparse_array_concat () const;
 
   template <typename MAP>
-  octave_map map_concat (void) const;
+  octave_map map_concat () const;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-unop.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-unop.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 // Unary expressions.
 
 std::string
-tree_unary_expression::oper (void) const
+tree_unary_expression::oper () const
 {
   return octave_value::unary_op_as_string (m_etype);
 }
--- a/libinterp/parse-tree/pt-unop.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-unop.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,21 +59,17 @@
 
 public:
 
-  // No copying!
-
-  tree_unary_expression (const tree_unary_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_unary_expression)
 
-  tree_unary_expression& operator = (const tree_unary_expression&) = delete;
+  ~tree_unary_expression () { delete m_op; }
 
-  ~tree_unary_expression (void) { delete m_op; }
+  bool is_unary_expression () const { return true; }
 
-  bool is_unary_expression (void) const { return true; }
-
-  tree_expression * operand (void) { return m_op; }
+  tree_expression * operand () { return m_op; }
 
-  std::string oper (void) const;
+  std::string oper () const;
 
-  octave_value::unary_op op_type (void) const { return m_etype; }
+  octave_value::unary_op op_type () const { return m_etype; }
 
 protected:
 
@@ -98,15 +94,11 @@
                           = octave_value::unknown_unary_op)
     : tree_unary_expression (e, l, c, t) { }
 
-  // No copying!
-
-  tree_prefix_expression (const tree_prefix_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_prefix_expression)
 
-  tree_prefix_expression& operator = (const tree_prefix_expression&) = delete;
+  ~tree_prefix_expression () = default;
 
-  ~tree_prefix_expression (void) = default;
-
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -122,7 +114,7 @@
     tw.visit_prefix_expression (*this);
   }
 
-  std::string profiler_name (void) const { return "prefix " + oper (); }
+  std::string profiler_name () const { return "prefix " + oper (); }
 };
 
 // Postfix expressions.
@@ -139,15 +131,11 @@
                            = octave_value::unknown_unary_op)
     : tree_unary_expression (e, l, c, t) { }
 
-  // No copying!
-
-  tree_postfix_expression (const tree_postfix_expression&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_postfix_expression)
 
-  tree_postfix_expression& operator = (const tree_postfix_expression&) = delete;
+  ~tree_postfix_expression () = default;
 
-  ~tree_postfix_expression (void) = default;
-
-  bool rvalue_ok (void) const { return true; }
+  bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
 
@@ -163,7 +151,7 @@
     tw.visit_postfix_expression (*this);
   }
 
-  std::string profiler_name (void) const { return "postfix " + oper (); }
+  std::string profiler_name () const { return "postfix " + oper (); }
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-vm-eval.cc	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2022-2023 The Octave Project Developers
-//
-// See the file COPYRIGHT.md in the top-level directory of this
-// distribution or <https://octave.org/copyright/>.
-//
-// This file is part of Octave.
-//
-// Octave is free software: you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Octave is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Octave; see the file COPYING.  If not, see
-// <https://www.gnu.org/licenses/>.
-//
-////////////////////////////////////////////////////////////////////////
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "defun.h"
-#include "variables.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-// If TRUE, use VM evaluator rather than tree walker.
-
-static bool V__enable_vm_eval__ = false;
-
-DEFUN (__enable_vm_eval__, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{val} =} __enable_vm_eval__ ()
-@deftypefnx {} {@var{old_val} =} __enable_vm_eval__ (@var{new_val})
-@deftypefnx {} {@var{old_val} =} __enable_vm_eval__ (@var{new_val}, "local")
-Query or set whether Octave uses a virtual machine (VM) for evaluation of
-parsed statements.
-
-The default value is false.  When false, Octave uses a traditional tree walker
-to evaluate statements parsed from m-code.  When true, Octave translates parsed
-statements to an intermediate representation that is then evaluated by a
-virtual machine.
-
-When called from inside a function with the @qcode{"local"} option, the setting
-is changed locally for the function and any subroutines it calls.  The original
-setting is restored when exiting the function.
-@end deftypefn */)
-{
-#if defined (OCTAVE_ENABLE_VM_EVALUATOR)
-
-  return set_internal_variable (V__enable_vm_eval__, args, nargout,
-                                "__enable_vm_eval__");
-
-#else
-
-  octave_unused_parameter (args);
-
-  err_disabled_feature ("vm-evaluator",
-                        "using a Virtual Machine for statement evaluation");
-
-#endif
-}
-
-OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-walk.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt-walk.h	Fri Jun 23 20:51:51 2023 +0200
@@ -111,17 +111,13 @@
 {
 protected:
 
-  tree_walker (void) { }
+  tree_walker () { }
 
-  virtual ~tree_walker (void) = default;
+  virtual ~tree_walker () = default;
 
 public:
 
-  // No copying!
-
-  tree_walker (const tree_walker&) = delete;
-
-  tree_walker& operator = (const tree_walker&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (tree_walker)
 
   virtual void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
--- a/libinterp/parse-tree/pt.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 // create a memory leak.
 
 std::string
-tree::str_print_code (void)
+tree::str_print_code ()
 {
   std::ostringstream buf;
 
--- a/libinterp/parse-tree/pt.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/pt.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,17 +49,13 @@
     : m_line_num (l), m_column_num (c), m_bp_cond (nullptr)
   { }
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (tree)
 
-  tree (const tree&) = delete;
-
-  tree& operator = (const tree&) = delete;
+  virtual ~tree () = default;
 
-  virtual ~tree (void) = default;
+  virtual int line () const { return m_line_num; }
 
-  virtual int line (void) const { return m_line_num; }
-
-  virtual int column (void) const { return m_column_num; }
+  virtual int column () const { return m_column_num; }
 
   void line (int l) { m_line_num = l; }
 
@@ -79,7 +75,7 @@
       m_bp_cond = new std::string (condition);
   }
 
-  virtual void delete_breakpoint (void)
+  virtual void delete_breakpoint ()
   {
     if (m_bp_cond)
       {
@@ -91,7 +87,7 @@
 
   bool meets_bp_condition (tree_evaluator& tw) const;
 
-  bool is_breakpoint (void) const
+  bool is_breakpoint () const
   {
     return m_bp_cond;
   }
@@ -103,12 +99,12 @@
 
   // breakpoint condition, or "0" (i.e., "false") if no breakpoint.
   // To distinguish "0" from a disabled breakpoint, test "is_breakpoint" too.
-  const std::string bp_cond (void) const
+  const std::string bp_cond () const
   {
     return m_bp_cond ? *m_bp_cond : "0";
   }
 
-  std::string str_print_code (void);
+  std::string str_print_code ();
 
   virtual void accept (tree_walker& tw) = 0;
 
--- a/libinterp/parse-tree/token.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/token.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -83,7 +83,7 @@
     m_tok_info (meth, cls), m_orig_text ()
 { }
 
-token::~token (void)
+token::~token ()
 {
   if (m_type_tag == string_token)
     delete m_tok_info.m_str;
@@ -94,48 +94,48 @@
 }
 
 std::string
-token::text (void) const
+token::text () const
 {
   panic_if (m_type_tag != string_token);
   return *m_tok_info.m_str;
 }
 
 octave_value
-token::number (void) const
+token::number () const
 {
   panic_if (m_type_tag != numeric_token);
   return *m_tok_info.m_num;
 }
 
 token::token_type
-token::ttype (void) const
+token::ttype () const
 {
   return m_type_tag;
 }
 
 token::end_tok_type
-token::ettype (void) const
+token::ettype () const
 {
   panic_if (m_type_tag != ettype_token);
   return m_tok_info.m_et;
 }
 
 std::string
-token::superclass_method_name (void) const
+token::superclass_method_name () const
 {
   panic_if (m_type_tag != scls_name_token);
   return m_tok_info.m_superclass_info->m_method_name;
 }
 
 std::string
-token::superclass_class_name (void) const
+token::superclass_class_name () const
 {
   panic_if (m_type_tag != scls_name_token);
   return m_tok_info.m_superclass_info->m_class_name;
 }
 
 std::string
-token::text_rep (void) const
+token::text_rep () const
 {
   return m_orig_text;
 }
--- a/libinterp/parse-tree/token.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/parse-tree/token.h	Fri Jun 23 20:51:51 2023 +0200
@@ -89,49 +89,45 @@
   token (int tv, const std::string& mth, const std::string& cls,
          const filepos& beg_pos, const filepos& end_pos);
 
-  // No copying!
-
-  token (const token&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (token)
 
-  token& operator = (const token&) = delete;
-
-  ~token (void);
+  ~token ();
 
-  void mark_may_be_command (void) { m_maybe_cmd = true; }
-  bool may_be_command (void) const { return m_maybe_cmd; }
+  void mark_may_be_command () { m_maybe_cmd = true; }
+  bool may_be_command () const { return m_maybe_cmd; }
 
-  void mark_trailing_space (void) { m_tspc = true; }
-  bool space_follows_token (void) const { return m_tspc; }
+  void mark_trailing_space () { m_tspc = true; }
+  bool space_follows_token () const { return m_tspc; }
 
-  int token_value (void) const { return m_tok_val; }
+  int token_value () const { return m_tok_val; }
   bool token_value_is (int tv) const { return tv == m_tok_val; }
 
-  filepos beg_pos (void) const { return m_beg_pos; }
-  filepos end_pos (void) const { return m_end_pos; }
+  filepos beg_pos () const { return m_beg_pos; }
+  filepos end_pos () const { return m_end_pos; }
 
   void beg_pos (const filepos& pos) { m_beg_pos = pos; }
   void end_pos (const filepos& pos) { m_end_pos = pos; }
 
   // These will probably be removed.
-  int line (void) const { return m_beg_pos.line (); }
-  int column (void) const { return m_beg_pos.column (); }
+  int line () const { return m_beg_pos.line (); }
+  int column () const { return m_beg_pos.column (); }
 
-  bool iskeyword (void) const
+  bool iskeyword () const
   {
     return m_type_tag == keyword_token || m_type_tag == ettype_token;
   }
 
-  bool isstring (void) const { return m_type_tag == string_token; }
+  bool isstring () const { return m_type_tag == string_token; }
 
-  std::string text (void) const;
-  octave_value number (void) const;
-  token_type ttype (void) const;
-  end_tok_type ettype (void) const;
+  std::string text () const;
+  octave_value number () const;
+  token_type ttype () const;
+  end_tok_type ettype () const;
 
-  std::string superclass_method_name (void) const;
-  std::string superclass_class_name (void) const;
+  std::string superclass_method_name () const;
+  std::string superclass_class_name () const;
 
-  std::string text_rep (void) const;
+  std::string text_rep () const;
 
 private:
 
@@ -148,7 +144,7 @@
 
   union tok_info
   {
-    tok_info (void) { }
+    tok_info () { }
 
     tok_info (const char *s) : m_str (new std::string (s)) { }
 
@@ -162,11 +158,9 @@
       : m_superclass_info (new superclass_info (meth, cls))
     { }
 
-    tok_info (const tok_info&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (tok_info)
 
-    tok_info& operator = (const tok_info&) = delete;
-
-    ~tok_info (void) { }
+    ~tok_info () { }
 
     std::string *m_str;
 
@@ -181,13 +175,11 @@
         : m_method_name (meth), m_class_name (cls)
       { }
 
-      superclass_info (void) = delete;
-
-      superclass_info (const superclass_info&) = delete;
+      superclass_info () = delete;
 
-      superclass_info& operator = (const superclass_info&) = delete;
+      OCTAVE_DISABLE_COPY_MOVE (superclass_info)
 
-      ~superclass_info (void) = default;
+      ~superclass_info () = default;
 
       //--------
 
--- a/libinterp/usage.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/libinterp/usage.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 // Usage message with extra help.
 
 static void
-octave_print_verbose_usage_and_exit (void)
+octave_print_verbose_usage_and_exit ()
 {
   std::cout << octave_name_version_copyright_copying_and_warranty ()
             << "\n\
@@ -103,7 +103,7 @@
 // Terse usage message.
 
 static void
-octave_print_terse_usage_and_exit (void)
+octave_print_terse_usage_and_exit ()
 {
   std::cerr << "\nusage: " << usage_string << "\n\n";
 
@@ -111,7 +111,7 @@
 }
 
 static void
-octave_print_version_and_exit (void)
+octave_print_version_and_exit ()
 {
   std::cout << octave_name_version_copyright_copying_warranty_and_bugs ()
             << "\n";
--- a/liboctave/array/Array-base.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Array-base.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 
 template <typename T, typename Alloc>
 typename Array<T, Alloc>::ArrayRep *
-Array<T, Alloc>::nil_rep (void)
+Array<T, Alloc>::nil_rep ()
 {
   static ArrayRep nr;
   return &nr;
@@ -106,7 +106,7 @@
 
 template <typename T, typename Alloc>
 void
-Array<T, Alloc>::clear (void)
+Array<T, Alloc>::clear ()
 {
   if (--m_rep->m_count == 0)
     delete m_rep;
@@ -136,7 +136,7 @@
 
 template <typename T, typename Alloc>
 Array<T, Alloc>
-Array<T, Alloc>::squeeze (void) const
+Array<T, Alloc>::squeeze () const
 {
   Array<T, Alloc> retval = *this;
 
@@ -312,6 +312,7 @@
 class rec_permute_helper
 {
 public:
+
   rec_permute_helper (const dim_vector& dv, const Array<octave_idx_type>& perm)
 
     : m_n (dv.ndims ()), m_top (0), m_dim (new octave_idx_type [2*m_n]),
@@ -350,13 +351,9 @@
 
   }
 
-  // No copying!
-
-  rec_permute_helper (const rec_permute_helper&) = delete;
-
-  rec_permute_helper& operator = (const rec_permute_helper&) = delete;
-
-  ~rec_permute_helper (void) { delete [] m_dim; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_permute_helper)
+
+  ~rec_permute_helper () { delete [] m_dim; }
 
   template <typename T>
   void permute (const T *src, T *dest) const { do_permute (src, dest, m_top); }
@@ -526,6 +523,7 @@
 class rec_index_helper
 {
 public:
+
   rec_index_helper (const dim_vector& dv, const Array<octave::idx_vector>& ia)
     : m_n (ia.numel ()), m_top (0), m_dim (new octave_idx_type [2*m_n]),
       m_cdim (m_dim + m_n), m_idx (new octave::idx_vector [m_n])
@@ -555,13 +553,9 @@
       }
   }
 
-  // No copying!
-
-  rec_index_helper (const rec_index_helper&) = delete;
-
-  rec_index_helper& operator = (const rec_index_helper&) = delete;
-
-  ~rec_index_helper (void) { delete [] m_idx; delete [] m_dim; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_index_helper)
+
+  ~rec_index_helper () { delete [] m_idx; delete [] m_dim; }
 
   template <typename T>
   void index (const T *src, T *dest) const { do_index (src, dest, m_top); }
@@ -646,6 +640,7 @@
 class rec_resize_helper
 {
 public:
+
   rec_resize_helper (const dim_vector& ndv, const dim_vector& odv)
     : m_cext (nullptr), m_sext (nullptr), m_dext (nullptr), m_n (0)
   {
@@ -671,13 +666,9 @@
     m_cext[0] *= ld;
   }
 
-  // No copying!
-
-  rec_resize_helper (const rec_resize_helper&) = delete;
-
-  rec_resize_helper& operator = (const rec_resize_helper&) = delete;
-
-  ~rec_resize_helper (void) { delete [] m_cext; }
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (rec_resize_helper)
+
+  ~rec_resize_helper () { delete [] m_cext; }
 
   template <typename T>
   void resize_fill (const T *src, T *dest, const T& rfv) const
@@ -905,7 +896,7 @@
 
 template <typename T, typename Alloc>
 T
-Array<T, Alloc>::resize_fill_value (void) const
+Array<T, Alloc>::resize_fill_value () const
 {
   static T zero = T ();
   return zero;
@@ -1622,7 +1613,7 @@
 
 template <typename T, typename Alloc>
 Array<T, Alloc>
-Array<T, Alloc>::transpose (void) const
+Array<T, Alloc>::transpose () const
 {
   assert (ndims () == 2);
 
@@ -1763,7 +1754,7 @@
 
 template <typename T, typename Alloc>
 T *
-Array<T, Alloc>::fortran_vec (void)
+Array<T, Alloc>::fortran_vec ()
 {
   make_unique ();
 
@@ -2222,7 +2213,7 @@
 
 template <typename T, typename Alloc>
 octave_idx_type
-Array<T, Alloc>::nnz (void) const
+Array<T, Alloc>::nnz () const
 {
   const T *src = data ();
   octave_idx_type nel = numel ();
@@ -2522,7 +2513,7 @@
     return Array<octave_idx_type> ();                                   \
   }                                                                     \
   template <> API octave_idx_type                                       \
-  Array<T>::nnz (void) const                                            \
+  Array<T>::nnz () const                                            \
   {                                                                     \
     return 0;                                                           \
   }                                                                     \
--- a/liboctave/array/Array-util.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Array-util.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -298,23 +298,14 @@
   return true;
 }
 
+// FIXME: Deprecated in Octave 9.
 bool
 all_ok (const Array<octave::idx_vector>& ra_idx)
 {
-  bool retval = true;
-
-  octave_idx_type n = ra_idx.numel ();
+  octave_unused_parameter (ra_idx);
 
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      if (! ra_idx(i))
-        {
-          retval = false;
-          break;
-        }
-    }
-
-  return retval;
+  // idx_vector objects are always valid once constructed
+  return true;
 }
 
 bool
@@ -410,18 +401,6 @@
 
   // FIXME: the solution using increment_index is not efficient.
 
-#if 0
-  octave_idx_type var = 1;
-  for (int i = 0; i < n_dims; i++)
-    {
-      std::cout << "idx: " << idx << ", var: " << var
-                << ", dims(" << i << "): " << dims(i) <<"\n";
-      retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
-      idx -= var * retval(i);
-      var = dims(i);
-    }
-#endif
-
   return retval;
 }
 
--- a/liboctave/array/Array-util.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Array-util.h	Fri Jun 23 20:51:51 2023 +0200
@@ -77,6 +77,7 @@
 
 extern OCTAVE_API bool vector_equivalent (const dim_vector& dv);
 
+OCTAVE_DEPRECATED (9, "all_ok (Array<octave::idx_vector>&) is obsolete and always returns true")
 extern OCTAVE_API bool all_ok (const Array<octave::idx_vector>& ra_idx);
 
 extern OCTAVE_API bool
--- a/liboctave/array/Array.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Array.h	Fri Jun 23 20:51:51 2023 +0200
@@ -160,7 +160,7 @@
     // Use new instead of setting data to 0 so that fortran_vec and
     // data always return valid addresses, even for zero-size arrays.
 
-    ArrayRep (void)
+    ArrayRep ()
       : Alloc (), m_data (allocate (0)), m_len (0), m_count (1) { }
 
     explicit ArrayRep (octave_idx_type len)
@@ -185,9 +185,9 @@
       std::copy_n (a.m_data, a.m_len, m_data);
     }
 
-    ~ArrayRep (void) { deallocate (m_data, m_len); }
+    ~ArrayRep () { deallocate (m_data, m_len); }
 
-    octave_idx_type numel (void) const { return m_len; }
+    octave_idx_type numel () const { return m_len; }
 
     // No assignment!
 
@@ -213,7 +213,7 @@
 
 public:
 
-  OCTARRAY_OVERRIDABLE_FUNC_API void make_unique (void)
+  OCTARRAY_OVERRIDABLE_FUNC_API void make_unique ()
   {
     if (m_rep->m_count > 1)
       {
@@ -267,12 +267,12 @@
 
 private:
 
-  static OCTARRAY_API typename Array<T, Alloc>::ArrayRep *nil_rep (void);
+  static OCTARRAY_API typename Array<T, Alloc>::ArrayRep *nil_rep ();
 
 public:
 
   //! Empty ctor (0 by 0).
-  Array (void)
+  Array ()
     : m_dimensions (), m_rep (nil_rep ()), m_slice_data (m_rep->m_data),
       m_slice_len (m_rep->m_len)
   {
@@ -348,7 +348,7 @@
 
 public:
 
-  virtual ~Array (void)
+  virtual ~Array ()
   {
     // Because we define a move constructor and a move assignment
     // operator, m_rep may be a nullptr here.  We should only need to
@@ -403,7 +403,7 @@
 
   OCTARRAY_API void fill (const T& val);
 
-  OCTARRAY_API void clear (void);
+  OCTARRAY_API void clear ();
   OCTARRAY_API void clear (const dim_vector& dv);
 
   void clear (octave_idx_type r, octave_idx_type c)
@@ -411,13 +411,13 @@
 
   //! Number of elements in the array.
   OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type
-  numel (void) const
+  numel () const
   { return m_slice_len; }
   //@}
 
   //! Return the array as a column vector.
   OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>
-  as_column (void) const
+  as_column () const
   {
     Array<T, Alloc> retval (*this);
     if (m_dimensions.ndims () != 2 || m_dimensions(1) != 1)
@@ -428,7 +428,7 @@
 
   //! Return the array as a row vector.
   OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>
-  as_row (void) const
+  as_row () const
   {
     Array<T, Alloc> retval (*this);
     if (m_dimensions.ndims () != 2 || m_dimensions(0) != 1)
@@ -439,7 +439,7 @@
 
   //! Return the array as a matrix.
   OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>
-  as_matrix (void) const
+  as_matrix () const
   {
     Array<T, Alloc> retval (*this);
     if (m_dimensions.ndims () != 2)
@@ -453,10 +453,10 @@
   //! Get the first dimension of the array (number of rows)
   //@{
   OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type
-  dim1 (void) const
+  dim1 () const
   { return m_dimensions(0); }
   OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type
-  rows (void) const
+  rows () const
   { return dim1 (); }
   //@}
 
@@ -464,11 +464,11 @@
   //!
   //! Get the second dimension of the array (number of columns)
   //@{
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim2 (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim2 () const
   { return m_dimensions(1); }
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type cols (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type cols () const
   { return dim2 (); }
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type columns (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type columns () const
   { return dim2 (); }
   //@}
 
@@ -476,9 +476,9 @@
   //!
   //! Get the third dimension of the array (number of pages)
   //@{
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim3 (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type dim3 () const
   { return m_dimensions.ndims () >= 3 ? m_dimensions(2) : 1; }
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type pages (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type pages () const
   { return dim3 (); }
   //@}
 
@@ -496,15 +496,15 @@
     return d >= ndims () ? 1 : m_dimensions(d);
   }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API std::size_t byte_size (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API std::size_t byte_size () const
   { return static_cast<std::size_t> (numel ()) * sizeof (T); }
 
   //! Return a const-reference so that dims ()(i) works efficiently.
-  OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector& dims (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API const dim_vector& dims () const
   { return m_dimensions; }
 
   //! Chop off leading singleton dimensions
-  OCTARRAY_API Array<T, Alloc> squeeze (void) const;
+  OCTARRAY_API Array<T, Alloc> squeeze () const;
 
   OCTARRAY_API octave_idx_type
   compute_index (octave_idx_type i, octave_idx_type j) const;
@@ -645,36 +645,30 @@
   ipermute (const Array<octave_idx_type>& vec) const
   { return permute (vec, true); }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API bool issquare (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API bool issquare () const
   { return (dim1 () == dim2 ()); }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API bool isempty (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API bool isempty () const
   { return numel () == 0; }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API bool isvector (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API bool isvector () const
   { return m_dimensions.isvector (); }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API bool is_nd_vector (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API bool is_nd_vector () const
   { return m_dimensions.is_nd_vector (); }
 
-  OCTARRAY_API Array<T, Alloc> transpose (void) const;
+  OCTARRAY_API Array<T, Alloc> transpose () const;
   OCTARRAY_API Array<T, Alloc> hermitian (T (*fcn) (const T&) = nullptr) const;
 
-  OCTARRAY_OVERRIDABLE_FUNC_API const T * data (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API const T * data () const
   { return m_slice_data; }
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead")
-  OCTARRAY_OVERRIDABLE_FUNC_API const T * fortran_vec (void) const
-  { return data (); }
-#endif
+  OCTARRAY_API T * fortran_vec ();
 
-  OCTARRAY_API T * fortran_vec (void);
-
-  OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared () const
   { return m_rep->m_count > 1; }
 
-  OCTARRAY_OVERRIDABLE_FUNC_API int ndims (void) const
+  OCTARRAY_OVERRIDABLE_FUNC_API int ndims () const
   { return m_dimensions.ndims (); }
 
   //@{
@@ -686,7 +680,7 @@
   OCTARRAY_API Array<T, Alloc> index (const Array<octave::idx_vector>& ia) const;
   //@}
 
-  virtual OCTARRAY_API T resize_fill_value (void) const;
+  virtual OCTARRAY_API T resize_fill_value () const;
 
   //@{
   //! Resizing (with fill).
@@ -792,7 +786,7 @@
   OCTARRAY_API Array<T, Alloc>&
   insert (const Array<T, Alloc>& a, octave_idx_type r, octave_idx_type c);
 
-  OCTARRAY_OVERRIDABLE_FUNC_API void maybe_economize (void)
+  OCTARRAY_OVERRIDABLE_FUNC_API void maybe_economize ()
   {
     if (m_rep->m_count == 1 && m_slice_len != m_rep->m_len)
       {
@@ -828,7 +822,7 @@
                                               sortmode mode = UNSORTED) const;
 
   //! Count nonzero elements.
-  OCTARRAY_API octave_idx_type nnz (void) const;
+  OCTARRAY_API octave_idx_type nnz () const;
 
   //! Find indices of (at most n) nonzero elements.  If n is specified,
   //! backward specifies search from backward.
--- a/liboctave/array/CColVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CColVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -196,19 +196,19 @@
 }
 
 ComplexRowVector
-ComplexColumnVector::hermitian (void) const
+ComplexColumnVector::hermitian () const
 {
   return MArray<Complex>::hermitian (std::conj);
 }
 
 ComplexRowVector
-ComplexColumnVector::transpose (void) const
+ComplexColumnVector::transpose () const
 {
   return MArray<Complex>::transpose ();
 }
 
 ColumnVector
-ComplexColumnVector::abs (void) const
+ComplexColumnVector::abs () const
 {
   return do_mx_unary_map<double, Complex, std::abs> (*this);
 }
@@ -420,7 +420,7 @@
 // other operations
 
 Complex
-ComplexColumnVector::min (void) const
+ComplexColumnVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -440,7 +440,7 @@
 }
 
 Complex
-ComplexColumnVector::max (void) const
+ComplexColumnVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
--- a/liboctave/array/CColVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CColVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 
 public:
 
-  ComplexColumnVector (void) : MArray<Complex> (dim_vector (0, 1)) { }
+  ComplexColumnVector () : MArray<Complex> (dim_vector (0, 1)) { }
 
   explicit ComplexColumnVector (octave_idx_type n)
     : MArray<Complex> (dim_vector (n, 1)) { }
@@ -67,6 +67,8 @@
     return *this;
   }
 
+  ~ComplexColumnVector () = default;
+
   OCTAVE_API bool operator == (const ComplexColumnVector& a) const;
   OCTAVE_API bool operator != (const ComplexColumnVector& a) const;
 
@@ -87,8 +89,8 @@
   OCTAVE_API ComplexColumnVector stack (const ColumnVector& a) const;
   OCTAVE_API ComplexColumnVector stack (const ComplexColumnVector& a) const;
 
-  OCTAVE_API ComplexRowVector hermitian (void) const;
-  OCTAVE_API ComplexRowVector transpose (void) const;
+  OCTAVE_API ComplexRowVector hermitian () const;
+  OCTAVE_API ComplexRowVector transpose () const;
 
   friend OCTAVE_API ComplexColumnVector conj (const ComplexColumnVector& a);
 
@@ -131,10 +133,10 @@
 
   // other operations
 
-  OCTAVE_API Complex min (void) const;
-  OCTAVE_API Complex max (void) const;
+  OCTAVE_API Complex min () const;
+  OCTAVE_API Complex max () const;
 
-  OCTAVE_API ColumnVector abs (void) const;
+  OCTAVE_API ColumnVector abs () const;
 
   // i/o
 
--- a/liboctave/array/CDiagMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CDiagMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -206,7 +206,7 @@
 }
 
 DiagMatrix
-ComplexDiagMatrix::abs (void) const
+ComplexDiagMatrix::abs () const
 {
   return DiagMatrix (extract_diag ().abs (), rows (), columns ());
 }
@@ -301,7 +301,7 @@
 }
 
 ComplexDiagMatrix
-ComplexDiagMatrix::inverse (void) const
+ComplexDiagMatrix::inverse () const
 {
   octave_idx_type info;
   return inverse (info);
@@ -320,7 +320,7 @@
   info = 0;
   octave_idx_type len = r;        // alias for readability
   octave_idx_type z_count  = 0;   // zeros
-  octave_idx_type nz_count = 0;   // non-zeros
+  octave_idx_type nz_count = 0;   // nonzeros
   for (octave_idx_type i = 0; i < len; i++)
     {
       if (xelem (i, i) == 0.0)
@@ -374,7 +374,7 @@
 }
 
 bool
-ComplexDiagMatrix::all_elements_are_real (void) const
+ComplexDiagMatrix::all_elements_are_real () const
 {
   return mx_inline_all_real (length (), data ());
 }
@@ -490,7 +490,7 @@
 // other operations
 
 ComplexDET
-ComplexDiagMatrix::determinant (void) const
+ComplexDiagMatrix::determinant () const
 {
   ComplexDET det (1.0);
   if (rows () != cols ())
@@ -504,7 +504,7 @@
 }
 
 double
-ComplexDiagMatrix::rcond (void) const
+ComplexDiagMatrix::rcond () const
 {
   ColumnVector av = extract_diag (0).map<double> (std::abs);
   double amx = av.max ();
--- a/liboctave/array/CDiagMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CDiagMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,13 +48,13 @@
   typedef Complex complex_elt_type;
   typedef Complex element_type;
 
-  ComplexDiagMatrix (void) = default;
+  ComplexDiagMatrix () = default;
 
   ComplexDiagMatrix (const ComplexDiagMatrix& a) = default;
 
   ComplexDiagMatrix& operator = (const ComplexDiagMatrix& a) = default;
 
-  ~ComplexDiagMatrix (void) = default;
+  ~ComplexDiagMatrix () = default;
 
   ComplexDiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<Complex> (r, c) { }
@@ -102,11 +102,11 @@
   OCTAVE_API ComplexDiagMatrix&
   fill (const ComplexRowVector& a, octave_idx_type beg);
 
-  ComplexDiagMatrix hermitian (void) const
+  ComplexDiagMatrix hermitian () const
   { return MDiagArray2<Complex>::hermitian (std::conj); }
-  ComplexDiagMatrix transpose (void) const
+  ComplexDiagMatrix transpose () const
   { return MDiagArray2<Complex>::transpose (); }
-  DiagMatrix abs (void) const;
+  DiagMatrix abs () const;
 
   friend OCTAVE_API ComplexDiagMatrix conj (const ComplexDiagMatrix& a);
 
@@ -125,10 +125,10 @@
   OCTAVE_API ComplexColumnVector column (char *s) const;
 
   OCTAVE_API ComplexDiagMatrix inverse (octave_idx_type& info) const;
-  OCTAVE_API ComplexDiagMatrix inverse (void) const;
+  OCTAVE_API ComplexDiagMatrix inverse () const;
   OCTAVE_API ComplexDiagMatrix pseudo_inverse (double tol = 0.0) const;
 
-  OCTAVE_API bool all_elements_are_real (void) const;
+  OCTAVE_API bool all_elements_are_real () const;
 
   // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
@@ -140,8 +140,8 @@
   ComplexColumnVector extract_diag (octave_idx_type k = 0) const
   { return MDiagArray2<Complex>::extract_diag (k); }
 
-  OCTAVE_API ComplexDET determinant (void) const;
-  OCTAVE_API double rcond (void) const;
+  OCTAVE_API ComplexDET determinant () const;
+  OCTAVE_API double rcond () const;
 
   // i/o
 
--- a/liboctave/array/CMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -171,7 +171,7 @@
 }
 
 bool
-ComplexMatrix::ishermitian (void) const
+ComplexMatrix::ishermitian () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -734,7 +734,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::inverse (void) const
+ComplexMatrix::inverse () const
 {
   octave_idx_type info;
   double rcon;
@@ -1042,7 +1042,7 @@
 #if defined (HAVE_FFTW)
 
 ComplexMatrix
-ComplexMatrix::fourier (void) const
+ComplexMatrix::fourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -1071,7 +1071,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::ifourier (void) const
+ComplexMatrix::ifourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -1100,7 +1100,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::fourier2d (void) const
+ComplexMatrix::fourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -1114,7 +1114,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::ifourier2d (void) const
+ComplexMatrix::ifourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -1130,7 +1130,7 @@
 #else
 
 ComplexMatrix
-ComplexMatrix::fourier (void) const
+ComplexMatrix::fourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1139,7 +1139,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::ifourier (void) const
+ComplexMatrix::ifourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1148,7 +1148,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::fourier2d (void) const
+ComplexMatrix::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1157,7 +1157,7 @@
 }
 
 ComplexMatrix
-ComplexMatrix::ifourier2d (void) const
+ComplexMatrix::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1168,7 +1168,7 @@
 #endif
 
 ComplexDET
-ComplexMatrix::determinant (void) const
+ComplexMatrix::determinant () const
 {
   octave_idx_type info;
   double rcon;
@@ -1347,7 +1347,7 @@
 }
 
 double
-ComplexMatrix::rcond (void) const
+ComplexMatrix::rcond () const
 {
   MatrixType mattype (*this);
   return rcond (mattype);
@@ -2821,7 +2821,7 @@
 }
 
 Matrix
-ComplexMatrix::abs (void) const
+ComplexMatrix::abs () const
 {
   return ComplexNDArray::abs ();
 }
@@ -2883,7 +2883,7 @@
 }
 
 ComplexColumnVector
-ComplexMatrix::row_min (void) const
+ComplexMatrix::row_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_min (dummy_idx);
@@ -2958,7 +2958,7 @@
 }
 
 ComplexColumnVector
-ComplexMatrix::row_max (void) const
+ComplexMatrix::row_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_max (dummy_idx);
@@ -3033,7 +3033,7 @@
 }
 
 ComplexRowVector
-ComplexMatrix::column_min (void) const
+ComplexMatrix::column_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_min (dummy_idx);
@@ -3108,7 +3108,7 @@
 }
 
 ComplexRowVector
-ComplexMatrix::column_max (void) const
+ComplexMatrix::column_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_max (dummy_idx);
@@ -3645,19 +3645,7 @@
 
   retval.clear (m, n);
   for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, 0) = x1(i);
-
-  // The last column is unused so temporarily store delta there
-  Complex *delta = &retval.xelem (0, n-1);
-  for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1.0);
-
-  for (octave_idx_type j = 1; j < n-1; j++)
-    for (octave_idx_type i = 0; i < m; i++)
-      retval.xelem (i, j) = x1(i) + static_cast<double> (j)*delta[i];
-
-  for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, n-1) = x2(i);
+    retval.insert (linspace (x1(i), x2(i), n), i, 0);
 
   return retval;
 }
--- a/liboctave/array/CMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,13 +60,13 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  ComplexMatrix (void) = default;
+  ComplexMatrix () = default;
 
   ComplexMatrix (const ComplexMatrix& a) = default;
 
   ComplexMatrix& operator = (const ComplexMatrix& a) = default;
 
-  ~ComplexMatrix (void) = default;
+  ~ComplexMatrix () = default;
 
   ComplexMatrix (octave_idx_type r, octave_idx_type c)
     : ComplexNDArray (dim_vector (r, c)) { }
@@ -116,7 +116,7 @@
   OCTAVE_API bool operator == (const ComplexMatrix& a) const;
   OCTAVE_API bool operator != (const ComplexMatrix& a) const;
 
-  OCTAVE_API bool ishermitian (void) const;
+  OCTAVE_API bool ishermitian () const;
 
   // destructive insert/delete/reorder operations
 
@@ -167,9 +167,9 @@
   OCTAVE_API ComplexMatrix stack (const ComplexColumnVector& a) const;
   OCTAVE_API ComplexMatrix stack (const ComplexDiagMatrix& a) const;
 
-  ComplexMatrix hermitian (void) const
+  ComplexMatrix hermitian () const
   { return MArray<Complex>::hermitian (std::conj); }
-  ComplexMatrix transpose (void) const
+  ComplexMatrix transpose () const
   { return MArray<Complex>::transpose (); }
 
   friend OCTAVE_API ComplexMatrix conj (const ComplexMatrix& a);
@@ -204,7 +204,7 @@
                           double& rcon, bool force, bool calc_cond) const;
 
 public:
-  OCTAVE_API ComplexMatrix inverse (void) const;
+  OCTAVE_API ComplexMatrix inverse () const;
   OCTAVE_API ComplexMatrix inverse (octave_idx_type& info) const;
   OCTAVE_API ComplexMatrix
   inverse (octave_idx_type& info, double& rcon,
@@ -219,13 +219,13 @@
 
   OCTAVE_API ComplexMatrix pseudo_inverse (double tol = 0.0) const;
 
-  OCTAVE_API ComplexMatrix fourier (void) const;
-  OCTAVE_API ComplexMatrix ifourier (void) const;
+  OCTAVE_API ComplexMatrix fourier () const;
+  OCTAVE_API ComplexMatrix ifourier () const;
 
-  OCTAVE_API ComplexMatrix fourier2d (void) const;
-  OCTAVE_API ComplexMatrix ifourier2d (void) const;
+  OCTAVE_API ComplexMatrix fourier2d () const;
+  OCTAVE_API ComplexMatrix ifourier2d () const;
 
-  OCTAVE_API ComplexDET determinant (void) const;
+  OCTAVE_API ComplexDET determinant () const;
   OCTAVE_API ComplexDET determinant (octave_idx_type& info) const;
   OCTAVE_API ComplexDET
   determinant (octave_idx_type& info, double& rcon,
@@ -234,7 +234,7 @@
   determinant (MatrixType& mattype, octave_idx_type& info, double& rcon,
                bool calc_cond = true) const;
 
-  OCTAVE_API double rcond (void) const;
+  OCTAVE_API double rcond () const;
   OCTAVE_API double rcond (MatrixType& mattype) const;
 
 private:
@@ -418,7 +418,7 @@
   OCTAVE_API ComplexMatrix prod (int dim = -1) const;
   OCTAVE_API ComplexMatrix sum (int dim = -1) const;
   OCTAVE_API ComplexMatrix sumsq (int dim = -1) const;
-  OCTAVE_API Matrix abs (void) const;
+  OCTAVE_API Matrix abs () const;
 
   OCTAVE_API ComplexMatrix diag (octave_idx_type k = 0) const;
 
@@ -428,14 +428,14 @@
   OCTAVE_API bool row_is_real_only (octave_idx_type) const;
   OCTAVE_API bool column_is_real_only (octave_idx_type) const;
 
-  OCTAVE_API ComplexColumnVector row_min (void) const;
-  OCTAVE_API ComplexColumnVector row_max (void) const;
+  OCTAVE_API ComplexColumnVector row_min () const;
+  OCTAVE_API ComplexColumnVector row_max () const;
 
   OCTAVE_API ComplexColumnVector row_min (Array<octave_idx_type>& index) const;
   OCTAVE_API ComplexColumnVector row_max (Array<octave_idx_type>& index) const;
 
-  OCTAVE_API ComplexRowVector column_min (void) const;
-  OCTAVE_API ComplexRowVector column_max (void) const;
+  OCTAVE_API ComplexRowVector column_min () const;
+  OCTAVE_API ComplexRowVector column_max () const;
 
   OCTAVE_API ComplexRowVector column_min (Array<octave_idx_type>& index) const;
   OCTAVE_API ComplexRowVector column_max (Array<octave_idx_type>& index) const;
--- a/liboctave/array/CNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -117,7 +117,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::fourier2d (void) const
+ComplexNDArray::fourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -137,7 +137,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::ifourier2d (void) const
+ComplexNDArray::ifourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -157,7 +157,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::fourierNd (void) const
+ComplexNDArray::fourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -172,7 +172,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::ifourierNd (void) const
+ComplexNDArray::ifourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -211,7 +211,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::fourier2d (void) const
+ComplexNDArray::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -220,7 +220,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::ifourier2d (void) const
+ComplexNDArray::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -229,7 +229,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::fourierNd (void) const
+ComplexNDArray::fourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -238,7 +238,7 @@
 }
 
 ComplexNDArray
-ComplexNDArray::ifourierNd (void) const
+ComplexNDArray::ifourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -251,7 +251,7 @@
 // unary operations
 
 boolNDArray
-ComplexNDArray::operator ! (void) const
+ComplexNDArray::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -262,13 +262,13 @@
 // FIXME: this is not quite the right thing.
 
 bool
-ComplexNDArray::any_element_is_nan (void) const
+ComplexNDArray::any_element_is_nan () const
 {
   return do_mx_check<Complex> (*this, mx_inline_any_nan);
 }
 
 bool
-ComplexNDArray::any_element_is_inf_or_nan (void) const
+ComplexNDArray::any_element_is_inf_or_nan () const
 {
   return ! do_mx_check<Complex> (*this, mx_inline_all_finite);
 }
@@ -276,7 +276,7 @@
 // Return true if no elements have imaginary components.
 
 bool
-ComplexNDArray::all_elements_are_real (void) const
+ComplexNDArray::all_elements_are_real () const
 {
   return do_mx_check<Complex> (*this, mx_inline_all_real);
 }
@@ -337,7 +337,7 @@
 }
 
 bool
-ComplexNDArray::too_large_for_float (void) const
+ComplexNDArray::too_large_for_float () const
 {
   return test_any (octave::too_large_for_float);
 }
@@ -475,25 +475,25 @@
 }
 
 NDArray
-ComplexNDArray::abs (void) const
+ComplexNDArray::abs () const
 {
   return do_mx_unary_map<double, Complex, std::abs> (*this);
 }
 
 boolNDArray
-ComplexNDArray::isnan (void) const
+ComplexNDArray::isnan () const
 {
   return do_mx_unary_map<bool, Complex, octave::math::isnan> (*this);
 }
 
 boolNDArray
-ComplexNDArray::isinf (void) const
+ComplexNDArray::isinf () const
 {
   return do_mx_unary_map<bool, Complex, octave::math::isinf> (*this);
 }
 
 boolNDArray
-ComplexNDArray::isfinite (void) const
+ComplexNDArray::isfinite () const
 {
   return do_mx_unary_map<bool, Complex, octave::math::isfinite> (*this);
 }
--- a/liboctave/array/CNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  ComplexNDArray (void) : MArray<Complex> () { }
+  ComplexNDArray () : MArray<Complex> () { }
 
   ComplexNDArray (const dim_vector& dv) : MArray<Complex> (dv) { }
 
@@ -62,17 +62,19 @@
     return *this;
   }
 
+  ~ComplexNDArray () = default;
+
   // unary operations
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
   // FIXME: this is not quite the right thing.
 
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool all_elements_are_real (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool all_elements_are_real () const;
   OCTAVE_API bool all_integers (double& max_val, double& min_val) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool too_large_for_float () const;
 
   OCTAVE_API boolNDArray all (int dim = -1) const;
   OCTAVE_API boolNDArray any (int dim = -1) const;
@@ -112,23 +114,23 @@
   OCTAVE_API ComplexNDArray&
   insert (const ComplexNDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  OCTAVE_API NDArray abs (void) const;
-  OCTAVE_API boolNDArray isnan (void) const;
-  OCTAVE_API boolNDArray isinf (void) const;
-  OCTAVE_API boolNDArray isfinite (void) const;
+  OCTAVE_API NDArray abs () const;
+  OCTAVE_API boolNDArray isnan () const;
+  OCTAVE_API boolNDArray isinf () const;
+  OCTAVE_API boolNDArray isfinite () const;
 
   friend OCTAVE_API ComplexNDArray conj (const ComplexNDArray& a);
 
   OCTAVE_API ComplexNDArray fourier (int dim = 1) const;
   OCTAVE_API ComplexNDArray ifourier (int dim = 1) const;
 
-  OCTAVE_API ComplexNDArray fourier2d (void) const;
-  OCTAVE_API ComplexNDArray ifourier2d (void) const;
+  OCTAVE_API ComplexNDArray fourier2d () const;
+  OCTAVE_API ComplexNDArray ifourier2d () const;
 
-  OCTAVE_API ComplexNDArray fourierNd (void) const;
-  OCTAVE_API ComplexNDArray ifourierNd (void) const;
+  OCTAVE_API ComplexNDArray fourierNd () const;
+  OCTAVE_API ComplexNDArray ifourierNd () const;
 
-  ComplexNDArray squeeze (void) const { return MArray<Complex>::squeeze (); }
+  ComplexNDArray squeeze () const { return MArray<Complex>::squeeze (); }
 
   static OCTAVE_API void
   increment_index (Array<octave_idx_type>& ra_idx,
@@ -146,14 +148,14 @@
   friend OCTAVE_API std::istream& operator >> (std::istream& is,
                                                ComplexNDArray& a);
 
-  //  bool all_elements_are_real (void) const;
+  //  bool all_elements_are_real () const;
   //  bool all_integers (double& max_val, double& min_val) const;
 
   OCTAVE_API ComplexNDArray diag (octave_idx_type k = 0) const;
 
   OCTAVE_API ComplexNDArray diag (octave_idx_type m, octave_idx_type n) const;
 
-  ComplexNDArray& changesign (void)
+  ComplexNDArray& changesign ()
   {
     MArray<Complex>::changesign ();
     return *this;
--- a/liboctave/array/CRowVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CRowVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -193,13 +193,13 @@
 }
 
 ComplexColumnVector
-ComplexRowVector::hermitian (void) const
+ComplexRowVector::hermitian () const
 {
   return MArray<Complex>::hermitian (std::conj);
 }
 
 ComplexColumnVector
-ComplexRowVector::transpose (void) const
+ComplexRowVector::transpose () const
 {
   return MArray<Complex>::transpose ();
 }
@@ -323,7 +323,7 @@
 // other operations
 
 Complex
-ComplexRowVector::min (void) const
+ComplexRowVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -343,7 +343,7 @@
 }
 
 Complex
-ComplexRowVector::max (void) const
+ComplexRowVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -436,6 +436,11 @@
       retval.resize (1, x2);
       return retval;
     }
+  else if (x1 == x2)
+    {
+      retval.resize (n_in, x2);
+      return retval;
+    }
 
   // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions
   // by 2 can be replaced by compiler with shift right instructions.
@@ -449,7 +454,17 @@
   retval.xelem (n-1) = x2;
 
   // Construct linspace symmetrically from both ends.
+  bool isnan_delta = false;
   Complex delta = (x2 - x1) / (n - 1.0);
+  if (octave::math::isinf (delta))
+    {
+      if (octave::math::isinf (delta.real ()))
+        delta.real (octave::numeric_limits<double>::NaN ());
+      if (octave::math::isinf (delta.imag ()))
+        delta.imag (octave::numeric_limits<double>::NaN ());
+      isnan_delta = true;
+    }
+
   unsigned_octave_idx_type n2 = n/2;
   for (unsigned_octave_idx_type i = 1; i < n2; i++)
     {
@@ -457,7 +472,22 @@
       retval.xelem (n-1-i) = x2 - static_cast<double> (i)*delta;
     }
   if (n % 2 == 1)  // Middle element if number of elements is odd.
-    retval.xelem (n2) = (x1 == -x2 ? 0 : (x1 + x2) / 2.0);
+    {
+      if (x1 == -x2)
+        retval.xelem (n2) = 0;
+      else
+        {
+          Complex c = (x1 + x2) / 2.0;
+          if (isnan_delta)
+            {
+              if (octave::math::isnan (delta.real ()))
+                c.real (octave::numeric_limits<double>::NaN ());
+              if (octave::math::isnan (delta.imag ()))
+                c.imag (octave::numeric_limits<double>::NaN ());
+            }
+          retval.xelem (n2) = c;
+        }
+    }
 
   return retval;
 }
--- a/liboctave/array/CRowVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CRowVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 
 public:
 
-  ComplexRowVector (void) : MArray<Complex> (dim_vector (1, 0)) { }
+  ComplexRowVector () : MArray<Complex> (dim_vector (1, 0)) { }
 
   explicit ComplexRowVector (octave_idx_type n)
     : MArray<Complex> (dim_vector (1, n)) { }
@@ -66,6 +66,8 @@
     return *this;
   }
 
+  ~ComplexRowVector () = default;
+
   OCTAVE_API bool operator == (const ComplexRowVector& a) const;
   OCTAVE_API bool operator != (const ComplexRowVector& a) const;
 
@@ -86,8 +88,8 @@
   OCTAVE_API ComplexRowVector append (const RowVector& a) const;
   OCTAVE_API ComplexRowVector append (const ComplexRowVector& a) const;
 
-  OCTAVE_API ComplexColumnVector hermitian (void) const;
-  OCTAVE_API ComplexColumnVector transpose (void) const;
+  OCTAVE_API ComplexColumnVector hermitian () const;
+  OCTAVE_API ComplexColumnVector transpose () const;
 
   friend OCTAVE_API ComplexRowVector conj (const ComplexRowVector& a);
 
@@ -114,8 +116,8 @@
 
   // other operations
 
-  OCTAVE_API Complex min (void) const;
-  OCTAVE_API Complex max (void) const;
+  OCTAVE_API Complex min () const;
+  OCTAVE_API Complex max () const;
 
   // i/o
 
--- a/liboctave/array/CSparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CSparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -139,7 +139,7 @@
 }
 
 bool
-SparseComplexMatrix::ishermitian (void) const
+SparseComplexMatrix::ishermitian () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -597,13 +597,13 @@
 }
 
 ComplexMatrix
-SparseComplexMatrix::matrix_value (void) const
+SparseComplexMatrix::matrix_value () const
 {
   return Sparse<Complex>::array_value ();
 }
 
 SparseComplexMatrix
-SparseComplexMatrix::hermitian (void) const
+SparseComplexMatrix::hermitian () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -657,7 +657,7 @@
 }
 
 SparseComplexMatrix
-SparseComplexMatrix::inverse (void) const
+SparseComplexMatrix::inverse () const
 {
   octave_idx_type info;
   double rcond;
@@ -1068,7 +1068,7 @@
 }
 
 ComplexDET
-SparseComplexMatrix::determinant (void) const
+SparseComplexMatrix::determinant () const
 {
   octave_idx_type info;
   double rcond;
@@ -7210,7 +7210,7 @@
 
 // unary operations
 SparseBoolMatrix
-SparseComplexMatrix::operator ! (void) const
+SparseComplexMatrix::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -7244,7 +7244,7 @@
 }
 
 SparseComplexMatrix
-SparseComplexMatrix::squeeze (void) const
+SparseComplexMatrix::squeeze () const
 {
   return MSparse<Complex>::squeeze ();
 }
@@ -7270,7 +7270,7 @@
 // other operations
 
 bool
-SparseComplexMatrix::any_element_is_nan (void) const
+SparseComplexMatrix::any_element_is_nan () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7285,7 +7285,7 @@
 }
 
 bool
-SparseComplexMatrix::any_element_is_inf_or_nan (void) const
+SparseComplexMatrix::any_element_is_inf_or_nan () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7302,7 +7302,7 @@
 // Return true if no elements have imaginary components.
 
 bool
-SparseComplexMatrix::all_elements_are_real (void) const
+SparseComplexMatrix::all_elements_are_real () const
 {
   return mx_inline_all_real (nnz (), data ());
 }
@@ -7350,7 +7350,7 @@
 }
 
 bool
-SparseComplexMatrix::too_large_for_float (void) const
+SparseComplexMatrix::too_large_for_float () const
 {
   return test_any (octave::too_large_for_float);
 }
@@ -7417,7 +7417,7 @@
 #undef COL_EXPR
 }
 
-SparseMatrix SparseComplexMatrix::abs (void) const
+SparseMatrix SparseComplexMatrix::abs () const
 {
   octave_idx_type nz = nnz ();
   octave_idx_type nc = cols ();
--- a/liboctave/array/CSparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/CSparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 
   typedef void (*solve_singularity_handler) (double rcond);
 
-  SparseComplexMatrix (void) : MSparse<Complex> () { }
+  SparseComplexMatrix () : MSparse<Complex> () { }
 
   SparseComplexMatrix (octave_idx_type r,
                        octave_idx_type c) : MSparse<Complex> (r, c) { }
@@ -105,10 +105,12 @@
     return *this;
   }
 
+  ~SparseComplexMatrix () = default;
+
   OCTAVE_API bool operator == (const SparseComplexMatrix& a) const;
   OCTAVE_API bool operator != (const SparseComplexMatrix& a) const;
 
-  OCTAVE_API bool ishermitian (void) const;
+  OCTAVE_API bool ishermitian () const;
 
   OCTAVE_API SparseComplexMatrix max (int dim = -1) const;
   OCTAVE_API SparseComplexMatrix
@@ -131,10 +133,10 @@
   OCTAVE_API SparseComplexMatrix
   concat (const SparseMatrix& rb, const Array<octave_idx_type>& ra_idx);
 
-  OCTAVE_API ComplexMatrix matrix_value (void) const;
+  OCTAVE_API ComplexMatrix matrix_value () const;
 
-  OCTAVE_API SparseComplexMatrix hermitian (void) const;  // complex conjugate transpose
-  SparseComplexMatrix transpose (void) const
+  OCTAVE_API SparseComplexMatrix hermitian () const;  // complex conjugate transpose
+  SparseComplexMatrix transpose () const
   { return MSparse<Complex>::transpose (); }
 
   friend OCTAVE_API SparseComplexMatrix conj (const SparseComplexMatrix& a);
@@ -155,7 +157,7 @@
                                 const bool calccond = true) const;
 
 public:
-  OCTAVE_API SparseComplexMatrix inverse (void) const;
+  OCTAVE_API SparseComplexMatrix inverse () const;
   OCTAVE_API SparseComplexMatrix inverse (MatrixType& mattype) const;
   OCTAVE_API SparseComplexMatrix
   inverse (MatrixType& mattype, octave_idx_type& info) const;
@@ -163,7 +165,7 @@
   inverse (MatrixType& mattype, octave_idx_type& info, double& rcond,
            bool force = false, bool calc_cond = true) const;
 
-  OCTAVE_API ComplexDET determinant (void) const;
+  OCTAVE_API ComplexDET determinant () const;
   OCTAVE_API ComplexDET determinant (octave_idx_type& info) const;
   OCTAVE_API ComplexDET
   determinant (octave_idx_type& info, double& rcond,
@@ -437,7 +439,7 @@
   solve (const ComplexColumnVector& b, octave_idx_type& info, double& rcond,
          solve_singularity_handler sing_handler) const;
 
-  OCTAVE_API SparseComplexMatrix squeeze (void) const;
+  OCTAVE_API SparseComplexMatrix squeeze () const;
 
   OCTAVE_API SparseComplexMatrix reshape (const dim_vector& new_dims) const;
 
@@ -447,13 +449,13 @@
   OCTAVE_API SparseComplexMatrix
   ipermute (const Array<octave_idx_type>& vec) const;
 
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool all_elements_are_real (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool all_elements_are_real () const;
   OCTAVE_API bool all_integers (double& max_val, double& min_val) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool too_large_for_float () const;
 
-  OCTAVE_API SparseBoolMatrix operator ! (void) const;
+  OCTAVE_API SparseBoolMatrix operator ! () const;
 
   OCTAVE_API SparseBoolMatrix all (int dim = -1) const;
   OCTAVE_API SparseBoolMatrix any (int dim = -1) const;
@@ -463,7 +465,7 @@
   OCTAVE_API SparseComplexMatrix prod (int dim = -1) const;
   OCTAVE_API SparseComplexMatrix sum (int dim = -1) const;
   OCTAVE_API SparseComplexMatrix sumsq (int dim = -1) const;
-  OCTAVE_API SparseMatrix abs (void) const;
+  OCTAVE_API SparseMatrix abs () const;
 
   OCTAVE_API SparseComplexMatrix diag (octave_idx_type k = 0) const;
 
--- a/liboctave/array/DiagArray2.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/DiagArray2.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -66,7 +66,7 @@
 
 template <typename T>
 DiagArray2<T>
-DiagArray2<T>::transpose (void) const
+DiagArray2<T>::transpose () const
 {
   return DiagArray2<T> (*this, m_d2, m_d1);
 }
@@ -113,7 +113,7 @@
 
 template <typename T>
 Array<T>
-DiagArray2<T>::array_value (void) const
+DiagArray2<T>::array_value () const
 {
   Array<T> result (dims (), T (0));
 
--- a/liboctave/array/DiagArray2.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/DiagArray2.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 
   using typename Array<T>::element_type;
 
-  DiagArray2 (void)
+  DiagArray2 ()
     : Array<T> (), m_d1 (0), m_d2 (0) { }
 
   DiagArray2 (octave_idx_type r, octave_idx_type c)
@@ -69,7 +69,7 @@
   DiagArray2 (const DiagArray2<U>& a)
     : Array<T> (a.extract_diag ()), m_d1 (a.dim1 ()), m_d2 (a.dim2 ()) { }
 
-  ~DiagArray2 (void) = default;
+  ~DiagArray2 () = default;
 
   DiagArray2<T>& operator = (const DiagArray2<T>& a)
   {
@@ -83,26 +83,26 @@
     return *this;
   }
 
-  octave_idx_type dim1 (void) const { return m_d1; }
-  octave_idx_type dim2 (void) const { return m_d2; }
+  octave_idx_type dim1 () const { return m_d1; }
+  octave_idx_type dim2 () const { return m_d2; }
 
-  octave_idx_type rows (void) const { return dim1 (); }
-  octave_idx_type cols (void) const { return dim2 (); }
-  octave_idx_type columns (void) const { return dim2 (); }
+  octave_idx_type rows () const { return dim1 (); }
+  octave_idx_type cols () const { return dim2 (); }
+  octave_idx_type columns () const { return dim2 (); }
 
-  octave_idx_type diag_length (void) const { return Array<T>::numel (); }
+  octave_idx_type diag_length () const { return Array<T>::numel (); }
   // FIXME: a dangerous ambiguity?
-  octave_idx_type length (void) const { return Array<T>::numel (); }
-  octave_idx_type nelem (void) const { return dim1 () * dim2 (); }
-  octave_idx_type numel (void) const { return nelem (); }
+  octave_idx_type length () const { return Array<T>::numel (); }
+  octave_idx_type nelem () const { return dim1 () * dim2 (); }
+  octave_idx_type numel () const { return nelem (); }
 
-  std::size_t byte_size (void) const { return Array<T>::byte_size (); }
+  std::size_t byte_size () const { return Array<T>::byte_size (); }
 
-  dim_vector dims (void) const { return dim_vector (m_d1, m_d2); }
+  dim_vector dims () const { return dim_vector (m_d1, m_d2); }
 
-  bool isempty (void) const { return numel () == 0; }
+  bool isempty () const { return numel () == 0; }
 
-  int ndims (void) const { return 2; }
+  int ndims () const { return 2; }
 
   OCTAVE_API Array<T> extract_diag (octave_idx_type k = 0) const;
 
@@ -161,19 +161,14 @@
     resize (n, m, Array<T>::resize_fill_value ());
   }
 
-  OCTAVE_API DiagArray2<T> transpose (void) const;
+  OCTAVE_API DiagArray2<T> transpose () const;
   OCTAVE_API DiagArray2<T> hermitian (T (*fcn) (const T&) = nullptr) const;
 
-  OCTAVE_API Array<T> array_value (void) const;
-
-  const T * data (void) const { return Array<T>::data (); }
+  OCTAVE_API Array<T> array_value () const;
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-  OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead")
-  const T * fortran_vec (void) const { return Array<T>::data (); }
-#endif
+  const T * data () const { return Array<T>::data (); }
 
-  T * fortran_vec (void) { return Array<T>::fortran_vec (); }
+  T * fortran_vec () { return Array<T>::fortran_vec (); }
 
   void print_info (std::ostream& os, const std::string& prefix) const
   { Array<T>::print_info (os, prefix); }
--- a/liboctave/array/MArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -213,7 +213,7 @@
 // N-dimensional array with math ops.
 template <typename T>
 void
-MArray<T>::changesign (void)
+MArray<T>::changesign ()
 {
   if (Array<T>::is_shared ())
     *this = - *this;
--- a/liboctave/array/MArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -63,7 +63,7 @@
 {
 public:
 
-  MArray (void) : Array<T> () { }
+  MArray () : Array<T> () { }
 
   explicit MArray (const dim_vector& dv)
     : Array<T> (dv) { }
@@ -76,7 +76,7 @@
   template <typename U>
   MArray (const Array<U>& a) : Array<T> (a) { }
 
-  ~MArray (void) = default;
+  ~MArray () = default;
 
   MArray<T>& operator = (const MArray<T>& a)
   {
@@ -94,9 +94,9 @@
   MArray<T> ipermute (const Array<octave_idx_type>& vec) const
   { return Array<T>::ipermute (vec); }
 
-  MArray squeeze (void) const { return Array<T>::squeeze (); }
+  MArray squeeze () const { return Array<T>::squeeze (); }
 
-  MArray<T> transpose (void) const
+  MArray<T> transpose () const
   { return Array<T>::transpose (); }
 
   MArray<T> hermitian (T (*fcn) (const T&) = nullptr) const
@@ -119,7 +119,7 @@
   idx_add_nd (const octave::idx_vector& idx, const MArray<T>& vals,
               int dim = -1);
 
-  OCTARRAY_API void changesign (void);
+  OCTARRAY_API void changesign ();
 
 private:
   OCTARRAY_API static void instantiation_guard ();
--- a/liboctave/array/MDiagArray2.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MDiagArray2.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,7 +56,7 @@
 {
 public:
 
-  MDiagArray2 (void) : DiagArray2<T> () { }
+  MDiagArray2 () : DiagArray2<T> () { }
 
   MDiagArray2 (octave_idx_type r, octave_idx_type c) : DiagArray2<T> (r, c) { }
 
@@ -75,7 +75,7 @@
   MDiagArray2 (const Array<T>& a, octave_idx_type r, octave_idx_type c)
     : DiagArray2<T> (a, r, c) { }
 
-  ~MDiagArray2 (void) = default;
+  ~MDiagArray2 () = default;
 
   MDiagArray2<T>& operator = (const MDiagArray2<T>& a)
   {
@@ -88,7 +88,7 @@
     return DiagArray2<T>::array_value ();
   }
 
-  octave_idx_type nnz (void) const
+  octave_idx_type nnz () const
   {
     const T *d = this->data ();
 
@@ -103,7 +103,7 @@
   MArray<T> diag (octave_idx_type k = 0) const
   { return DiagArray2<T>::extract_diag (k); }
 
-  MDiagArray2<T> transpose (void) const { return DiagArray2<T>::transpose (); }
+  MDiagArray2<T> transpose () const { return DiagArray2<T>::transpose (); }
   MDiagArray2<T> hermitian (T (*fcn) (const T&) = nullptr) const
   { return DiagArray2<T>::hermitian (fcn); }
 
--- a/liboctave/array/MSparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MSparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
 {
 public:
 
-  MSparse (void) : Sparse<T> () { }
+  MSparse () : Sparse<T> () { }
 
   MSparse (octave_idx_type n, octave_idx_type m) : Sparse<T> (n, m) { }
 
@@ -75,7 +75,7 @@
   MSparse (octave_idx_type r, octave_idx_type c, octave_idx_type num_nz)
     : Sparse<T> (r, c, num_nz) { }
 
-  ~MSparse (void) = default;
+  ~MSparse () = default;
 
   MSparse<T>& operator = (const MSparse<T>& a)
   {
@@ -95,9 +95,9 @@
     return *this;
   }
 
-  MSparse<T> transpose (void) const { return Sparse<T>::transpose (); }
+  MSparse<T> transpose () const { return Sparse<T>::transpose (); }
 
-  MSparse<T> squeeze (void) const { return Sparse<T>::squeeze (); }
+  MSparse<T> squeeze () const { return Sparse<T>::squeeze (); }
 
   MSparse<T> reshape (const dim_vector& new_dims) const
   { return Sparse<T>::reshape (new_dims); }
--- a/liboctave/array/MatrixType.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MatrixType.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,21 +41,21 @@
 #include "oct-locbuf.h"
 
 static void
-warn_cached (void)
+warn_cached ()
 {
   (*current_liboctave_warning_with_id_handler)
     ("Octave:matrix-type-info", "using cached matrix type");
 }
 
 static void
-warn_invalid (void)
+warn_invalid ()
 {
   (*current_liboctave_warning_with_id_handler)
     ("Octave:matrix-type-info", "invalid matrix type");
 }
 
 static void
-warn_calculating_sparse_type (void)
+warn_calculating_sparse_type ()
 {
   (*current_liboctave_warning_with_id_handler)
     ("Octave:matrix-type-info", "calculating sparse matrix type");
@@ -63,7 +63,7 @@
 
 // FIXME: There is a large code duplication here
 
-MatrixType::MatrixType (void)
+MatrixType::MatrixType ()
   : m_type (MatrixType::Unknown),
     m_sp_bandden (octave::sparse_params::get_bandden ()),
     m_bandden (0), m_upper_band (0), m_lower_band (0),
@@ -613,7 +613,7 @@
     warn_invalid ();
 }
 
-MatrixType::~MatrixType (void)
+MatrixType::~MatrixType ()
 {
   if (m_nperm != 0)
     {
@@ -900,7 +900,7 @@
 }
 
 void
-MatrixType::mark_as_symmetric (void)
+MatrixType::mark_as_symmetric ()
 {
   if (m_type == MatrixType::Tridiagonal
       || m_type == MatrixType::Tridiagonal_Hermitian)
@@ -917,7 +917,7 @@
 }
 
 void
-MatrixType::mark_as_unsymmetric (void)
+MatrixType::mark_as_unsymmetric ()
 {
   if (m_type == MatrixType::Tridiagonal
       || m_type == MatrixType::Tridiagonal_Hermitian)
@@ -952,7 +952,7 @@
 }
 
 void
-MatrixType::mark_as_unpermuted (void)
+MatrixType::mark_as_unpermuted ()
 {
   if (m_nperm)
     {
@@ -970,7 +970,7 @@
 }
 
 MatrixType
-MatrixType::transpose (void) const
+MatrixType::transpose () const
 {
   MatrixType retval (*this);
   if (m_type == MatrixType::Upper)
--- a/liboctave/array/MatrixType.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/MatrixType.h	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
     Rectangular
   };
 
-  OCTAVE_API MatrixType (void);
+  OCTAVE_API MatrixType ();
 
   OCTAVE_API MatrixType (const MatrixType& a);
 
@@ -78,7 +78,7 @@
   OCTAVE_API MatrixType (const matrix_type t, const octave_idx_type ku,
                          const octave_idx_type kl, bool _full = false);
 
-  OCTAVE_API ~MatrixType (void);
+  OCTAVE_API ~MatrixType ();
 
   OCTAVE_API MatrixType& operator = (const MatrixType& a);
 
@@ -96,77 +96,77 @@
 
   OCTAVE_API int type (const SparseComplexMatrix& a);
 
-  double band_density (void) const { return m_bandden; }
+  double band_density () const { return m_bandden; }
 
-  int nupper (void) const { return m_upper_band; }
+  int nupper () const { return m_upper_band; }
 
-  int nlower (void) const { return m_lower_band; }
+  int nlower () const { return m_lower_band; }
 
-  bool is_dense (void) const { return m_dense; }
+  bool is_dense () const { return m_dense; }
 
-  bool isdiag (void) const
+  bool isdiag () const
   { return (m_type == Diagonal || m_type == Permuted_Diagonal); }
 
-  bool istriu (void) const
+  bool istriu () const
   { return (m_type == Upper || m_type == Permuted_Upper); }
 
-  bool istril (void) const
+  bool istril () const
   { return (m_type == Lower || m_type == Permuted_Lower); }
 
-  bool isbanded (void) const
+  bool isbanded () const
   { return (m_type == Banded || m_type == Banded_Hermitian); }
 
-  bool is_tridiagonal (void) const
+  bool is_tridiagonal () const
   { return (m_type == Tridiagonal || m_type == Tridiagonal_Hermitian); }
 
-  bool ishermitian (void) const
+  bool ishermitian () const
   {
     return (m_type == Banded_Hermitian || m_type == Tridiagonal_Hermitian
             || m_type == Hermitian);
   }
 
-  bool is_rectangular (void) const { return (m_type == Rectangular); }
+  bool is_rectangular () const { return (m_type == Rectangular); }
 
-  bool is_known (void) const { return (m_type != Unknown); }
+  bool is_known () const { return (m_type != Unknown); }
 
-  bool is_unknown (void) const { return (m_type == Unknown); }
+  bool is_unknown () const { return (m_type == Unknown); }
 
-  OCTAVE_API void info (void) const;
+  OCTAVE_API void info () const;
 
-  octave_idx_type * triangular_perm (void) const { return m_perm; }
+  octave_idx_type * triangular_perm () const { return m_perm; }
 
-  void invalidate_type (void) { m_type = Unknown; }
+  void invalidate_type () { m_type = Unknown; }
 
-  void mark_as_diagonal (void) { m_type = Diagonal; }
+  void mark_as_diagonal () { m_type = Diagonal; }
 
-  void mark_as_permuted_diagonal (void) { m_type = Permuted_Diagonal; }
+  void mark_as_permuted_diagonal () { m_type = Permuted_Diagonal; }
 
-  void mark_as_upper_triangular (void) { m_type = Upper; }
+  void mark_as_upper_triangular () { m_type = Upper; }
 
-  void mark_as_lower_triangular (void) { m_type = Lower; }
+  void mark_as_lower_triangular () { m_type = Lower; }
 
-  void mark_as_tridiagonal (void) {m_type = Tridiagonal; }
+  void mark_as_tridiagonal () {m_type = Tridiagonal; }
 
   void mark_as_banded (const octave_idx_type ku, const octave_idx_type kl)
   { m_type = Banded; m_upper_band = ku; m_lower_band = kl; }
 
-  void mark_as_full (void) { m_type = Full; }
+  void mark_as_full () { m_type = Full; }
 
-  void mark_as_rectangular (void) { m_type = Rectangular; }
+  void mark_as_rectangular () { m_type = Rectangular; }
 
-  void mark_as_dense (void) { m_dense = true; }
+  void mark_as_dense () { m_dense = true; }
 
-  void mark_as_not_dense (void) { m_dense = false; }
+  void mark_as_not_dense () { m_dense = false; }
 
-  OCTAVE_API void mark_as_symmetric (void);
+  OCTAVE_API void mark_as_symmetric ();
 
-  OCTAVE_API void mark_as_unsymmetric (void);
+  OCTAVE_API void mark_as_unsymmetric ();
 
   OCTAVE_API void mark_as_permuted (const octave_idx_type np, const octave_idx_type *p);
 
-  OCTAVE_API void mark_as_unpermuted (void);
+  OCTAVE_API void mark_as_unpermuted ();
 
-  OCTAVE_API MatrixType transpose (void) const;
+  OCTAVE_API MatrixType transpose () const;
 
 private:
   void type (int new_typ) { m_type = static_cast<matrix_type> (new_typ); }
--- a/liboctave/array/PermMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/PermMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,7 +34,7 @@
 
 OCTAVE_NORETURN static
 void
-err_invalid_permutation (void)
+err_invalid_permutation ()
 {
   (*current_liboctave_error_handler) ("PermMatrix: invalid permutation vector");
 }
@@ -98,7 +98,7 @@
 }
 
 PermMatrix
-PermMatrix::transpose (void) const
+PermMatrix::transpose () const
 {
   octave_idx_type len = Array<octave_idx_type>::numel ();
 
@@ -111,13 +111,13 @@
 }
 
 PermMatrix
-PermMatrix::inverse (void) const
+PermMatrix::inverse () const
 {
   return transpose ();
 }
 
 octave_idx_type
-PermMatrix::determinant (void) const
+PermMatrix::determinant () const
 {
   // Determine the sign of a permutation in linear time.
   // Is this widely known?
--- a/liboctave/array/PermMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/PermMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -38,13 +38,13 @@
 {
 public:
 
-  PermMatrix (void) = default;
+  PermMatrix () = default;
 
   PermMatrix (const PermMatrix& m) = default;
 
   PermMatrix& operator = (const PermMatrix& m) = default;
 
-  ~PermMatrix (void) = default;
+  ~PermMatrix () = default;
 
   OCTAVE_API PermMatrix (octave_idx_type n);
 
@@ -54,33 +54,33 @@
   OCTAVE_API PermMatrix (const octave::idx_vector& idx, bool colp,
                          octave_idx_type n = 0);
 
-  octave_idx_type dim1 (void) const
+  octave_idx_type dim1 () const
   { return Array<octave_idx_type>::numel (); }
-  octave_idx_type dim2 (void) const
+  octave_idx_type dim2 () const
   { return Array<octave_idx_type>::numel (); }
 
-  octave_idx_type rows (void) const { return dim1 (); }
-  octave_idx_type cols (void) const { return dim2 (); }
-  octave_idx_type columns (void) const { return dim2 (); }
+  octave_idx_type rows () const { return dim1 (); }
+  octave_idx_type cols () const { return dim2 (); }
+  octave_idx_type columns () const { return dim2 (); }
 
-  octave_idx_type perm_length (void) const
+  octave_idx_type perm_length () const
   { return Array<octave_idx_type>::numel (); }
   // FIXME: a dangerous ambiguity?
-  octave_idx_type length (void) const
+  octave_idx_type length () const
   { return perm_length (); }
 
-  octave_idx_type numel (void) const { return dim1 () * dim2 (); }
+  octave_idx_type numel () const { return dim1 () * dim2 (); }
 
-  std::size_t byte_size (void) const
+  std::size_t byte_size () const
   { return Array<octave_idx_type>::byte_size (); }
 
-  dim_vector dims (void) const { return dim_vector (dim1 (), dim2 ()); }
+  dim_vector dims () const { return dim_vector (dim1 (), dim2 ()); }
 
-  bool isempty (void) const { return numel () == 0; }
+  bool isempty () const { return numel () == 0; }
 
-  int ndims (void) const { return 2; }
+  int ndims () const { return 2; }
 
-  const Array<octave_idx_type>& col_perm_vec (void) const
+  const Array<octave_idx_type>& col_perm_vec () const
   { return *this; }
 
   octave_idx_type
@@ -99,17 +99,17 @@
   }
 
   // These are, in fact, super-fast.
-  OCTAVE_API PermMatrix transpose (void) const;
-  OCTAVE_API PermMatrix inverse (void) const;
+  OCTAVE_API PermMatrix transpose () const;
+  OCTAVE_API PermMatrix inverse () const;
 
   // Determinant, i.e., the sign of permutation.
-  OCTAVE_API octave_idx_type determinant (void) const;
+  OCTAVE_API octave_idx_type determinant () const;
 
   // Efficient integer power of a permutation.
   OCTAVE_API PermMatrix power (octave_idx_type n) const;
 
-  bool is_col_perm (void) const { return true; }
-  bool is_row_perm (void) const { return false; }
+  bool is_col_perm () const { return true; }
+  bool is_row_perm () const { return false; }
 
   void print_info (std::ostream& os, const std::string& prefix) const
   { Array<octave_idx_type>::print_info (os, prefix); }
--- a/liboctave/array/Range.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Range.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -302,104 +302,44 @@
 
 template <>
 bool
-range<double>::all_elements_are_ints (void) const
+range<double>::all_elements_are_ints () const
 {
   return xall_elements_are_ints (m_base, m_increment, m_final, m_numel);
 }
 
 template <>
 bool
-range<float>::all_elements_are_ints (void) const
+range<float>::all_elements_are_ints () const
 {
   return xall_elements_are_ints (m_base, m_increment, m_final, m_numel);
 }
 
 template <>
 void
-range<double>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<float>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-// For now, only define for float and double.
-
-#if 0
-
-template <>
-void
-range<octave_int8>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<octave_int16>::init (void)
+range<double>::init ()
 {
   xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
 }
 
 template <>
 void
-range<octave_int32>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<octave_int64>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<octave_uint8>::init (void)
+range<float>::init ()
 {
   xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
 }
 
-template <>
-void
-range<octave_uint16>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<octave_uint32>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-template <>
-void
-range<octave_uint64>::init (void)
-{
-  xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel);
-}
-
-#endif
+// For now, only define for float and double.
 
 template <>
 bool
-range<double>::is_storable (void) const
+range<double>::is_storable () const
 {
   return xis_storable (m_base, m_limit, m_numel);
 }
 
 template <>
 bool
-range<float>::is_storable (void) const
+range<float>::is_storable () const
 {
   return xis_storable (m_base, m_limit, m_numel);
 }
@@ -410,7 +350,7 @@
 {
   // Note that the order of the following checks matters.
 
-  // If there are no elements, there can be no non-zero elements.
+  // If there are no elements, there can be no nonzero elements.
   if (nel == 0)
     return 0;
 
@@ -440,566 +380,16 @@
 
 template <>
 octave_idx_type
-range<double>::nnz (void) const
+range<double>::nnz () const
 {
   return xnnz (m_base, m_limit, m_increment, m_final, m_numel);
 }
 
 template <>
 octave_idx_type
-range<float>::nnz (void) const
+range<float>::nnz () const
 {
   return xnnz (m_base, m_limit, m_increment, m_final, m_numel);
 }
 
 OCTAVE_END_NAMESPACE(octave)
-
-bool
-Range::all_elements_are_ints (void) const
-{
-  // If the base and increment are ints, the final value in the range will also
-  // be an integer, even if the limit is not.  If there is one or fewer
-  // elements only the base needs to be an integer.
-
-  return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc))
-          && (octave::math::nint_big (m_base) == m_base || m_numel < 1)
-          && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1));
-}
-
-octave_idx_type
-Range::nnz (void) const
-{
-  octave_idx_type retval = 0;
-
-  if (! isempty ())
-    {
-      if ((m_base > 0.0 && m_limit > 0.0) || (m_base < 0.0 && m_limit < 0.0))
-        {
-          // All elements have the same sign, hence there are no zeros.
-          retval = m_numel;
-        }
-      else if (m_inc != 0.0)
-        {
-          if (m_base == 0.0 || m_limit == 0.0)
-            // Exactly one zero at beginning or end of range.
-            retval = m_numel - 1;
-          else if ((m_base / m_inc) != std::floor (m_base / m_inc))
-            // Range crosses negative/positive without hitting zero.
-            retval = m_numel;
-          else
-            // Range crosses negative/positive and hits zero.
-            retval = m_numel - 1;
-        }
-      else
-        {
-          // All elements are equal (m_inc = 0) but not positive or negative,
-          // therefore all elements are zero.
-          retval = 0;
-        }
-    }
-
-  return retval;
-}
-
-Matrix
-Range::matrix_value (void) const
-{
-  Matrix retval (1, m_numel);
-
-  if (m_numel > 0)
-    {
-      // The first element must always be *exactly* the base.
-      // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).
-      retval(0) = m_base;
-
-      double b = m_base;
-      double increment = m_inc;
-      for (octave_idx_type i = 1; i < m_numel - 1; i++)
-        retval.xelem (i) = b + i * increment;
-
-      retval.xelem (m_numel - 1) = m_limit;
-    }
-
-  return retval;
-}
-
-double
-Range::checkelem (octave_idx_type i) const
-{
-  if (i < 0 || i >= m_numel)
-    octave::err_index_out_of_range (2, 2, i+1, m_numel, dims ());
-
-  if (i == 0)
-    return m_base;
-  else if (i < m_numel - 1)
-    return m_base + i * m_inc;
-  else
-    return m_limit;
-}
-
-double
-Range::checkelem (octave_idx_type i, octave_idx_type j) const
-{
-  // Ranges are *always* row vectors.
-  if (i != 0)
-    octave::err_index_out_of_range (1, 1, i+1, m_numel, dims ());
-
-  return checkelem (j);
-}
-
-double
-Range::elem (octave_idx_type i) const
-{
-  if (i == 0)
-    return m_base;
-  else if (i < m_numel - 1)
-    return m_base + i * m_inc;
-  else
-    return m_limit;
-}
-
-Array<double>
-Range::index (const octave::idx_vector& idx) const
-{
-  Array<double> retval;
-
-  octave_idx_type n = m_numel;
-
-  if (idx.is_colon ())
-    {
-      retval = matrix_value ().reshape (dim_vector (m_numel, 1));
-    }
-  else
-    {
-      if (idx.extent (n) != n)
-        octave::err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); // throws
-
-      dim_vector idx_dims = idx.orig_dimensions ();
-      octave_idx_type idx_len = idx.length (n);
-
-      // taken from Array.cc.
-      if (n != 1 && idx_dims.isvector ())
-        idx_dims = dim_vector (1, idx_len);
-
-      retval.clear (idx_dims);
-
-      // Loop over all values in IDX, executing the lambda expression
-      // for each index value.
-
-      double *array = retval.fortran_vec ();
-
-      idx.loop (n, [=, &array] (idx_vector i)
-      {
-        if (i == 0)
-          *array++ = m_base;
-        else if (i < m_numel - 1)
-          *array++ = m_base + i * m_inc;
-        else
-          *array++ = m_limit;
-      });
-    }
-
-  return retval;
-}
-
-// NOTE: max and min only return useful values if numel > 0.
-//       do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0.
-
-double
-Range::min (void) const
-{
-  double retval = 0.0;
-  if (m_numel > 0)
-    {
-      if (m_inc > 0)
-        retval = m_base;
-      else
-        {
-          retval = m_base + (m_numel - 1) * m_inc;
-
-          // Require '<=' test.  See note in max ().
-          if (retval <= m_limit)
-            retval = m_limit;
-        }
-
-    }
-  return retval;
-}
-
-double
-Range::max (void) const
-{
-  double retval = 0.0;
-  if (m_numel > 0)
-    {
-      if (m_inc > 0)
-        {
-          retval = m_base + (m_numel - 1) * m_inc;
-
-          // On some machines (x86 with extended precision floating point
-          // arithmetic, for example) it is possible that we can overshoot the
-          // limit by approximately the machine precision even though we were
-          // very careful in our calculation of the number of elements.
-          // Therefore, we clip the result to the limit if it overshoots.
-          // The test also includes equality (>= m_limit) to have expressions
-          // such as -5:1:-0 result in a -0 endpoint.
-          if (retval >= m_limit)
-            retval = m_limit;
-        }
-      else
-        retval = m_base;
-    }
-  return retval;
-}
-
-void
-Range::sort_internal (bool ascending)
-{
-  if ((ascending && m_base > m_limit && m_inc < 0.0)
-      || (! ascending && m_base < m_limit && m_inc > 0.0))
-    {
-      std::swap (m_base, m_limit);
-      m_inc = -m_inc;
-    }
-}
-
-void
-Range::sort_internal (Array<octave_idx_type>& sidx, bool ascending)
-{
-  octave_idx_type nel = numel ();
-
-  sidx.resize (dim_vector (1, nel));
-
-  octave_idx_type *psidx = sidx.fortran_vec ();
-
-  bool reverse = false;
-
-  if ((ascending && m_base > m_limit && m_inc < 0.0)
-      || (! ascending && m_base < m_limit && m_inc > 0.0))
-    {
-      std::swap (m_base, m_limit);
-      m_inc = -m_inc;
-      reverse = true;
-    }
-
-  octave_idx_type tmp = (reverse ? nel - 1 : 0);
-  octave_idx_type stp = (reverse ? -1 : 1);
-
-  for (octave_idx_type i = 0; i < nel; i++, tmp += stp)
-    psidx[i] = tmp;
-}
-
-Matrix
-Range::diag (octave_idx_type k) const
-{
-  return matrix_value ().diag (k);
-}
-
-Range
-Range::sort (octave_idx_type dim, sortmode mode) const
-{
-  Range retval = *this;
-
-  if (dim == 1)
-    {
-      if (mode == ASCENDING)
-        retval.sort_internal (true);
-      else if (mode == DESCENDING)
-        retval.sort_internal (false);
-    }
-  else if (dim != 0)
-    (*current_liboctave_error_handler) ("Range::sort: invalid dimension");
-
-  return retval;
-}
-
-Range
-Range::sort (Array<octave_idx_type>& sidx, octave_idx_type dim,
-             sortmode mode) const
-{
-  Range retval = *this;
-
-  if (dim == 1)
-    {
-      if (mode == ASCENDING)
-        retval.sort_internal (sidx, true);
-      else if (mode == DESCENDING)
-        retval.sort_internal (sidx, false);
-    }
-  else if (dim != 0)
-    (*current_liboctave_error_handler) ("Range::sort: invalid dimension");
-
-  return retval;
-}
-
-sortmode
-Range::issorted (sortmode mode) const
-{
-  if (m_numel > 1 && m_inc > 0)
-    mode = (mode == DESCENDING) ? UNSORTED : ASCENDING;
-  else if (m_numel > 1 && m_inc < 0)
-    mode = (mode == ASCENDING) ? UNSORTED : DESCENDING;
-  else
-    mode = (mode == UNSORTED) ? ASCENDING : mode;
-
-  return mode;
-}
-
-void
-Range::set_base (double b)
-{
-  if (m_base != b)
-    {
-      m_base = b;
-
-      init ();
-    }
-}
-
-void
-Range::set_limit (double l)
-{
-  if (m_limit != l)
-    {
-      m_limit = l;
-
-      init ();
-    }
-}
-
-void
-Range::set_inc (double i)
-{
-  if (m_inc != i)
-    {
-      m_inc = i;
-
-      init ();
-    }
-}
-
-std::ostream&
-operator << (std::ostream& os, const Range& a)
-{
-  double b = a.base ();
-  double increment = a.increment ();
-  octave_idx_type nel = a.numel ();
-
-  if (nel > 1)
-    {
-      // First element must be the base *exactly* (e.g., -0).
-      os << b << ' ';
-      for (octave_idx_type i = 1; i < nel-1; i++)
-        os << b + i * increment << ' ';
-    }
-
-  // Print out the last element exactly, rather than a calculated last element.
-  os << a.m_limit << "\n";
-
-  return os;
-}
-
-std::istream&
-operator >> (std::istream& is, Range& a)
-{
-  is >> a.m_base;
-  if (is)
-    {
-      double tmp_limit;
-      is >> tmp_limit;
-
-      if (is)
-        is >> a.m_inc;
-
-      // Clip the m_limit to the true limit, rebuild numel, clear cache
-      a.set_limit (tmp_limit);
-    }
-
-  return is;
-}
-
-// DEPRECATED in Octave 7.
-Range operator - (const Range& r)
-{
-  return Range (-r.base (), -r.limit (), -r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator + (double x, const Range& r)
-{
-  return Range (x + r.base (), x + r.limit (), r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator + (const Range& r, double x)
-{
-  return Range (r.base () + x, r.limit () + x, r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator - (double x, const Range& r)
-{
-  return Range (x - r.base (), x - r.limit (), -r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator - (const Range& r, double x)
-{
-  return Range (r.base () - x, r.limit () - x, r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator * (double x, const Range& r)
-{
-  return Range (x * r.base (), x * r.limit (), x * r.increment (), r.numel ());
-}
-
-// DEPRECATED in Octave 7.
-Range operator * (const Range& r, double x)
-{
-  return Range (r.base () * x, r.limit () * x, r.increment () * x, r.numel ());
-}
-
-// C  See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5.
-// C
-// C===Tolerant FLOOR function.
-// C
-// C    X  -  is given as a Double Precision argument to be operated on.
-// C          It is assumed that X is represented with M mantissa bits.
-// C    CT -  is   given   as   a   Comparison   Tolerance   such   that
-// C          0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between
-// C          X and A whole number is  less  than  CT,  then  TFLOOR  is
-// C          returned   as   this   whole   number.   By  treating  the
-// C          floating-point numbers as a finite ordered set  note  that
-// C          the  heuristic  EPS=2.**(-(M-1))   and   CT=3*EPS   causes
-// C          arguments  of  TFLOOR/TCEIL to be treated as whole numbers
-// C          if they are  exactly  whole  numbers  or  are  immediately
-// C          adjacent to whole number representations.  Since EPS,  the
-// C          "distance"  between  floating-point  numbers  on  the unit
-// C          interval, and M, the number of bits in X'S mantissa, exist
-// C          on  every  floating-point   computer,   TFLOOR/TCEIL   are
-// C          consistently definable on every floating-point computer.
-// C
-// C          For more information see the following references:
-// C    (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL  QUOTE
-// C        QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5.
-// C    (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling",  APL
-// C        QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through
-// C        FL5, the history of five years of evolutionary development of
-// C        FL5 - the seven lines of code below - by open collaboration
-// C        and corroboration of the mathematical-computing community.
-// C
-// C  Penn State University Center for Academic Computing
-// C  H. D. Knoble - August, 1978.
-
-static inline double
-tfloor (double x, double ct)
-{
-// C---------FLOOR(X) is the largest integer algebraically less than
-// C         or equal to X; that is, the unfuzzy FLOOR function.
-
-//  DINT (X) = X - DMOD (X, 1.0);
-//  FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0);
-
-// C---------Hagerty's FL5 function follows...
-
-  double q = 1.0;
-
-  if (x < 0.0)
-    q = 1.0 - ct;
-
-  double rmax = q / (2.0 - ct);
-
-  double t1 = 1.0 + std::floor (x);
-  t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1);
-  t1 = (rmax < t1 ? rmax : t1);
-  t1 = (ct > t1 ? ct : t1);
-  t1 = std::floor (x + t1);
-
-  if (x <= 0.0 || (t1 - x) < rmax)
-    return t1;
-  else
-    return t1 - 1.0;
-}
-
-static inline bool
-teq (double u, double v,
-     double ct = 3.0 * std::numeric_limits<double>::epsilon ())
-{
-  double tu = std::abs (u);
-  double tv = std::abs (v);
-
-  return std::abs (u - v) < ((tu > tv ? tu : tv) * ct);
-}
-
-octave_idx_type
-Range::numel_internal (void) const
-{
-  octave_idx_type retval = -1;
-
-  if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc)
-      || octave::math::isnan (m_limit))
-    retval = -2;
-  else if (octave::math::isinf (m_limit)
-           && ((m_inc > 0 && m_limit > 0)
-               || (m_inc < 0 && m_limit < 0)))
-    retval = std::numeric_limits<octave_idx_type>::max () - 1;
-  else if (m_inc == 0
-           || (m_limit > m_base && m_inc < 0)
-           || (m_limit < m_base && m_inc > 0))
-    {
-      retval = 0;
-    }
-  else
-    {
-      double ct = 3.0 * std::numeric_limits<double>::epsilon ();
-
-      double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct);
-
-      octave_idx_type n_elt = (tmp > 0.0
-                               ? static_cast<octave_idx_type> (tmp) : 0);
-
-      // If the final element that we would compute for the range is equal to
-      // the limit of the range, or is an adjacent floating point number,
-      // accept it.  Otherwise, try a range with one fewer element.  If that
-      // fails, try again with one more element.
-      //
-      // I'm not sure this is very good, but it seems to work better than just
-      // using tfloor as above.  For example, without it, the expression
-      // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9].
-
-      if (! teq (m_base + (n_elt - 1) * m_inc, m_limit))
-        {
-          if (teq (m_base + (n_elt - 2) * m_inc, m_limit))
-            n_elt--;
-          else if (teq (m_base + n_elt * m_inc, m_limit))
-            n_elt++;
-        }
-
-      retval = ((n_elt < std::numeric_limits<octave_idx_type>::max ())
-                ? n_elt : -1);
-    }
-
-  return retval;
-}
-
-double
-Range::limit_internal (void) const
-{
-  double new_limit = m_inc > 0 ? max () : min ();
-
-  // If result must be an integer then force the new_limit to be one.
-  if (all_elements_are_ints ())
-    new_limit = std::round (new_limit);
-
-  return new_limit;
-}
-
-void
-Range::init (void)
-{
-  m_numel = numel_internal ();
-
-  if (! octave::math::isinf (m_limit))
-    m_limit = limit_internal ();
-}
--- a/liboctave/array/Range.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Range.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 {
 public:
 
-  range (void)
+  range ()
     : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0),
       m_reverse (false)
   { }
@@ -101,58 +101,37 @@
     // purpose of this strange constructor form.
 
     T final_val = (reverse ? base - (numel - 1) * increment
-                   : base + (numel - 1) * increment);
+                           : base + (numel - 1) * increment);
 
     return range<T> (base, increment, final_val, numel, reverse);
   }
 
-  range (const range<T>& r)
-    : m_base (r.m_base), m_increment (r.m_increment),
-      m_limit (r.m_limit), m_final (r.m_final),
-      m_numel (r.m_numel), m_reverse (r.m_reverse)
-  { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (range)
 
-  range<T>& operator = (const range<T>& r)
-  {
-    if (this != &r)
-      {
-        m_base = r.m_base;
-        m_increment = r.m_increment;
-        m_limit = r.m_limit;
-        m_final = r.m_final;
-        m_numel = r.m_numel;
-        m_reverse = r.m_reverse;
-      }
+  T base () const { return m_base; }
+  T increment () const { return m_increment; }
+  T limit () const { return m_limit; }
+  bool reverse () const { return m_reverse; }
 
-    return *this;
-  }
-
-  ~range (void) = default;
+  T final_value () const { return m_final; }
 
-  T base (void) const { return m_base; }
-  T increment (void) const { return m_increment; }
-  T limit (void) const { return m_limit; }
-  bool reverse (void) const { return m_reverse; }
-
-  T final_value (void) const { return m_final; }
-
-  T min (void) const
+  T min () const
   {
     return (m_numel > 0
             ? ((m_reverse ? m_increment > T (0)
-                : m_increment > T (0)) ? base () : final_value ())
+                          : m_increment > T (0)) ? base () : final_value ())
             : T (0));
   }
 
-  T max (void) const
+  T max () const
   {
     return (m_numel > 0
             ? ((m_reverse ? m_increment < T (0)
-                : m_increment > T (0)) ? final_value () : base ())
+                          : m_increment > T (0)) ? final_value () : base ())
             : T (0));
   }
 
-  octave_idx_type numel (void) const { return m_numel; }
+  octave_idx_type numel () const { return m_numel; }
 
   // To support things like "for i = 1:Inf; ...; end" that are
   // required for Matlab compatibility, creation of a range object
@@ -162,26 +141,26 @@
   // us to easily distinguish ranges with an infinite number of
   // elements.  There are specializations for double and float.
 
-  bool is_storable (void) const { return true; }
+  bool is_storable () const { return true; }
 
-  dim_vector dims (void) const { return dim_vector (1, m_numel); }
+  dim_vector dims () const { return dim_vector (1, m_numel); }
 
-  octave_idx_type rows (void) const { return 1; }
+  octave_idx_type rows () const { return 1; }
 
-  octave_idx_type cols (void) const { return numel (); }
-  octave_idx_type columns (void) const { return numel (); }
+  octave_idx_type cols () const { return numel (); }
+  octave_idx_type columns () const { return numel (); }
 
-  bool isempty (void) const { return numel () == 0; }
+  bool isempty () const { return numel () == 0; }
 
-  bool all_elements_are_ints (void) const { return true; }
+  bool all_elements_are_ints () const { return true; }
 
   sortmode issorted (sortmode mode = ASCENDING) const
   {
     if (m_numel > 1 && (m_reverse ? m_increment < T (0)
-                        : m_increment > T (0)))
+                                  : m_increment > T (0)))
       mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING);
     else if (m_numel > 1 && (m_reverse ? m_increment > T (0)
-                             : m_increment < T (0)))
+                                       : m_increment < T (0)))
       mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING);
     else
       mode = ((mode == UNSORTED) ? ASCENDING : mode);
@@ -189,7 +168,7 @@
     return mode;
   }
 
-  OCTAVE_API octave_idx_type nnz (void) const;
+  OCTAVE_API octave_idx_type nnz () const;
 
   // Support for single-index subscripting, without generating matrix cache.
 
@@ -203,7 +182,7 @@
       return (m_numel == 1 ? final_value () : m_base);
     else if (i < m_numel - 1)
       return (m_reverse ? m_base + T (i) * m_increment
-              : m_base + T (i) * m_increment);
+                        : m_base + T (i) * m_increment);
     else
       return final_value ();
   }
@@ -224,7 +203,7 @@
       return (m_numel == 1 ? final_value () : m_base);
     else if (i < m_numel - 1)
       return (m_reverse ? m_base - T (i) * m_increment
-              : m_base + T (i) * m_increment);
+                        : m_base + T (i) * m_increment);
     else
       return final_value ();
   }
@@ -280,7 +259,7 @@
             *array++ = (m_numel == 0 ? m_final : m_base);
           else if (i < m_numel - 1)
             *array++ = (m_reverse ? m_base - T (i) * m_increment
-                        : m_base + T (i) * m_increment);
+                                  : m_base + T (i) * m_increment);
           else
             *array++ = m_final;
         });
@@ -294,7 +273,7 @@
     return array_value ().diag (k);
   }
 
-  Array<T> array_value (void) const
+  Array<T> array_value () const
   {
     octave_idx_type nel = numel ();
 
@@ -338,7 +317,7 @@
   // These calculations are appropriate for integer ranges.  There are
   // specializations for double and float.
 
-  void init (void)
+  void init ()
   {
     if (m_reverse)
       {
@@ -365,225 +344,22 @@
 
 // Specializations defined externally.
 
-template <> OCTAVE_API bool range<double>::all_elements_are_ints (void) const;
-template <> OCTAVE_API bool range<float>::all_elements_are_ints (void) const;
+template <> OCTAVE_API bool range<double>::all_elements_are_ints () const;
+template <> OCTAVE_API bool range<float>::all_elements_are_ints () const;
 
-template <> OCTAVE_API void range<double>::init (void);
-template <> OCTAVE_API void range<float>::init (void);
+template <> OCTAVE_API void range<double>::init ();
+template <> OCTAVE_API void range<float>::init ();
 
 // For now, only define for floating point types.  However, we only
 // need range<float> as a temporary local variable in make_float_range
 // in ov.cc.
 
-#if 0
+template <> OCTAVE_API bool range<double>::is_storable () const;
+template <> OCTAVE_API bool range<float>::is_storable () const;
 
-template <> OCTAVE_API void range<octave_int8>::init (void);
-template <> OCTAVE_API void range<octave_int16>::init (void);
-template <> OCTAVE_API void range<octave_int32>::init (void);
-template <> OCTAVE_API void range<octave_int64>::init (void);
-template <> OCTAVE_API void range<octave_uint8>::init (void);
-template <> OCTAVE_API void range<octave_uint16>::init (void);
-template <> OCTAVE_API void range<octave_uint32>::init (void);
-template <> OCTAVE_API void range<octave_uint64>::init (void);
-
-#endif
-
-template <> OCTAVE_API bool range<double>::is_storable (void) const;
-template <> OCTAVE_API bool range<float>::is_storable (void) const;
-
-template <> OCTAVE_API octave_idx_type range<double>::nnz (void) const;
-template <> OCTAVE_API octave_idx_type range<float>::nnz (void) const;
+template <> OCTAVE_API octave_idx_type range<double>::nnz () const;
+template <> OCTAVE_API octave_idx_type range<float>::nnz () const;
 
 OCTAVE_END_NAMESPACE(octave)
 
-class
-Range
-{
-public:
-
-  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
-  Range (void)
-    : m_base (0), m_limit (0), m_inc (0), m_numel (0)
-  { }
-
-  // Assume range is already properly constructed, so just copy internal
-  // values.  However, we set LIMIT to the computed final value because
-  // that mimics the behavior of the other Range class constructors that
-  // reset limit to the computed final value.
-
-  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
-  Range (const octave::range<double>& r)
-    : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()),
-      m_numel (r.numel ())
-  { }
-
-  Range (const Range& r) = default;
-
-  Range& operator = (const Range& r) = default;
-
-  ~Range (void) = default;
-
-  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
-  Range (double b, double l)
-    : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ())
-  {
-    if (! octave::math::isinf (m_limit))
-      m_limit = limit_internal ();
-  }
-
-  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
-  Range (double b, double l, double i)
-    : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ())
-  {
-    if (! octave::math::isinf (m_limit))
-      m_limit = limit_internal ();
-  }
-
-  // NOTE: The following constructor may be deprecated and removed after
-  // the arithmetic operators are removed.
-
-  // For operators' usage (to preserve element count) and to create
-  // constant row vectors (obsolete usage).
-
-  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
-  Range (double b, double i, octave_idx_type n)
-    : m_base (b), m_limit (b + (n-1) * i), m_inc (i), m_numel (n)
-  {
-    if (! octave::math::isinf (m_limit))
-      m_limit = limit_internal ();
-  }
-
-  // The range has a finite number of elements.
-  bool ok (void) const
-  {
-    return (octave::math::isfinite (m_limit)
-            && (m_numel >= 0 || m_numel == -2));
-  }
-
-  double base (void) const { return m_base; }
-  double limit (void) const { return m_limit; }
-  double inc (void) const { return m_inc; }
-  double increment (void) const { return m_inc; }
-
-  // We adjust the limit to be the final value, so return that.  We
-  // could introduce a new variable to store the final value separately,
-  // but it seems like that would just add confusion.  If we changed
-  // the meaning of the limit function, we would change the behavior of
-  // programs that expect limit to be the final value instead of the
-  // value of the limit when the range was created.  This problem will
-  // be fixed with the new template range class.
-  double final_value (void) const { return m_limit; }
-
-  octave_idx_type numel (void) const { return m_numel; }
-
-  dim_vector dims (void) const { return dim_vector (1, m_numel); }
-
-  octave_idx_type rows (void) const { return 1; }
-
-  octave_idx_type cols (void) const { return numel (); }
-  octave_idx_type columns (void) const { return numel (); }
-
-  bool isempty (void) const { return numel () == 0; }
-
-  OCTAVE_API bool all_elements_are_ints (void) const;
-
-  OCTAVE_API Matrix matrix_value (void) const;
-
-  OCTAVE_API double min (void) const;
-  OCTAVE_API double max (void) const;
-
-  OCTAVE_API void sort_internal (bool ascending = true);
-  OCTAVE_API void sort_internal (Array<octave_idx_type>& sidx, bool ascending = true);
-
-  OCTAVE_API Matrix diag (octave_idx_type k = 0) const;
-
-  OCTAVE_API Range sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
-  OCTAVE_API Range sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
-                         sortmode mode = ASCENDING) const;
-
-  OCTAVE_API sortmode issorted (sortmode mode = ASCENDING) const;
-
-  OCTAVE_API octave_idx_type nnz (void) const;
-
-  // Support for single-index subscripting, without generating matrix cache.
-
-  OCTAVE_API double checkelem (octave_idx_type i) const;
-  OCTAVE_API double checkelem (octave_idx_type i, octave_idx_type j) const;
-
-  OCTAVE_API double elem (octave_idx_type i) const;
-  double elem (octave_idx_type /* i */, octave_idx_type j) const
-  { return elem (j); }
-
-  double operator () (octave_idx_type i) const { return elem (i); }
-  double operator () (octave_idx_type i, octave_idx_type j) const
-  { return elem (i, j); }
-
-  OCTAVE_API Array<double> index (const octave::idx_vector& i) const;
-
-  OCTAVE_API void set_base (double b);
-
-  OCTAVE_API void set_limit (double l);
-
-  OCTAVE_API void set_inc (double i);
-
-  friend OCTAVE_API std::ostream& operator << (std::ostream& os,
-                                               const Range& r);
-  friend OCTAVE_API std::istream& operator >> (std::istream& is, Range& r);
-
-  friend OCTAVE_API Range operator - (const Range& r);
-  friend OCTAVE_API Range operator + (double x, const Range& r);
-  friend OCTAVE_API Range operator + (const Range& r, double x);
-  friend OCTAVE_API Range operator - (double x, const Range& r);
-  friend OCTAVE_API Range operator - (const Range& r, double x);
-  friend OCTAVE_API Range operator * (double x, const Range& r);
-  friend OCTAVE_API Range operator * (const Range& r, double x);
-
-private:
-
-  double m_base;
-  double m_limit;
-  double m_inc;
-
-  octave_idx_type m_numel;
-
-  OCTAVE_API octave_idx_type numel_internal (void) const;
-
-  OCTAVE_API double limit_internal (void) const;
-
-  OCTAVE_API void init (void);
-
-protected:
-
-  // NOTE: The following constructor may be removed when the arithmetic
-  // operators are removed.
-
-  // For operators' usage (to allow all values to be set directly).
-  Range (double b, double l, double i, octave_idx_type n)
-    : m_base (b), m_limit (l), m_inc (i), m_numel (n)
-  { }
-};
-
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator - (const Range& r);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator + (double x, const Range& r);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator + (const Range& r, double x);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator - (double x, const Range& r);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator - (const Range& r, double x);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator * (double x, const Range& r);
-
-OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable")
-extern OCTAVE_API Range operator * (const Range& r, double x);
 #endif
-
-#endif
--- a/liboctave/array/Sparse-C.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Sparse-C.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -64,6 +64,3 @@
 
 INSTANTIATE_SPARSE (Complex);
 
-#if 0
-template std::ostream& operator << (std::ostream&, const Sparse<Complex>&);
-#endif
--- a/liboctave/array/Sparse-b.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Sparse-b.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,13 +36,10 @@
 template <>
 OCTAVE_API
 bool
-Sparse<bool>::SparseRep::any_element_is_nan (void) const
+Sparse<bool>::SparseRep::any_element_is_nan () const
 {
   return false;
 }
 
 INSTANTIATE_SPARSE (bool);
 
-#if 0
-template std::ostream& operator << (std::ostream&, const Sparse<bool>&);
-#endif
--- a/liboctave/array/Sparse-d.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Sparse-d.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,6 +52,3 @@
 
 INSTANTIATE_SPARSE (double);
 
-#if 0
-template std::ostream& operator << (std::ostream&, const Sparse<double>&);
-#endif
--- a/liboctave/array/Sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
 
 template <typename T, typename Alloc>
 OCTAVE_API typename Sparse<T, Alloc>::SparseRep *
-Sparse<T, Alloc>::nil_rep (void)
+Sparse<T, Alloc>::nil_rep ()
 {
   static typename Sparse<T, Alloc>::SparseRep nr;
   return &nr;
@@ -176,7 +176,7 @@
 template <typename T, typename Alloc>
 OCTAVE_API
 bool
-Sparse<T, Alloc>::SparseRep::indices_ok (void) const
+Sparse<T, Alloc>::SparseRep::indices_ok () const
 {
   return sparse_indices_ok (m_ridx, m_cidx, m_nrows, m_ncols, nnz ());
 }
@@ -184,7 +184,7 @@
 template <typename T, typename Alloc>
 OCTAVE_API
 bool
-Sparse<T, Alloc>::SparseRep::any_element_is_nan (void) const
+Sparse<T, Alloc>::SparseRep::any_element_is_nan () const
 {
   octave_idx_type nz = nnz ();
 
@@ -705,7 +705,7 @@
 
 template <typename T, typename Alloc>
 OCTAVE_API
-Sparse<T, Alloc>::~Sparse (void)
+Sparse<T, Alloc>::~Sparse ()
 {
   if (--m_rep->m_count == 0)
     delete m_rep;
@@ -1138,7 +1138,7 @@
 template <typename T, typename Alloc>
 OCTAVE_API
 Sparse<T, Alloc>
-Sparse<T, Alloc>::transpose (void) const
+Sparse<T, Alloc>::transpose () const
 {
   assert (ndims () == 2);
 
--- a/liboctave/array/Sparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/Sparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -76,7 +76,7 @@
     octave_idx_type m_ncols;
     octave::refcount<octave_idx_type> m_count;
 
-    SparseRep (void)
+    SparseRep ()
       : Alloc (), m_data (T_allocate (1)), m_ridx (idx_type_allocate (1)),
         m_cidx (idx_type_allocate (1)),
         m_nzmax (1), m_nrows (0), m_ncols (0), m_count (1)
@@ -141,19 +141,19 @@
       std::copy_n (a.m_cidx, m_ncols + 1, m_cidx);
     }
 
-    ~SparseRep (void)
+    ~SparseRep ()
     {
       T_deallocate (m_data, m_nzmax);
       idx_type_deallocate (m_ridx, m_nzmax);
       idx_type_deallocate (m_cidx, m_ncols + 1);
     }
 
-    octave_idx_type nzmax (void) const { return m_nzmax; }
-    octave_idx_type nnz (void) const { return m_cidx[m_ncols]; }
+    octave_idx_type nzmax () const { return m_nzmax; }
+    octave_idx_type nnz () const { return m_cidx[m_ncols]; }
 
-    octave_idx_type rows (void) const { return m_nrows; }
-    octave_idx_type cols (void) const { return m_ncols; }
-    octave_idx_type columns (void) const { return m_ncols; }
+    octave_idx_type rows () const { return m_nrows; }
+    octave_idx_type cols () const { return m_ncols; }
+    octave_idx_type columns () const { return m_ncols; }
 
     OCTAVE_API T& elem (octave_idx_type r, octave_idx_type c);
 
@@ -175,12 +175,12 @@
 
     OCTAVE_API void change_length (octave_idx_type nz);
 
-    OCTAVE_API bool indices_ok (void) const;
+    OCTAVE_API bool indices_ok () const;
 
-    OCTAVE_API bool any_element_is_nan (void) const;
+    OCTAVE_API bool any_element_is_nan () const;
 
     // Prefer nzmax.
-    octave_idx_type length (void) const { return m_nzmax; }
+    octave_idx_type length () const { return m_nzmax; }
 
     template <typename U, typename A> friend class Sparse;
 
@@ -231,7 +231,7 @@
 
   //--------------------------------------------------------------------
 
-  void make_unique (void)
+  void make_unique ()
   {
     if (m_rep->m_count > 1)
       {
@@ -252,11 +252,11 @@
 
 private:
 
-  static OCTAVE_API typename Sparse<T, Alloc>::SparseRep * nil_rep (void);
+  static OCTAVE_API typename Sparse<T, Alloc>::SparseRep * nil_rep ();
 
 public:
 
-  Sparse (void)
+  Sparse ()
     : m_rep (nil_rep ()), m_dimensions (dim_vector (0, 0))
   {
     m_rep->m_count++;
@@ -327,30 +327,30 @@
   // Sparsify a normal matrix
   OCTAVE_API Sparse (const Array<T>& a);
 
-  virtual ~Sparse (void);
+  virtual ~Sparse ();
 
   OCTAVE_API Sparse<T, Alloc>& operator = (const Sparse<T, Alloc>& a);
 
   //! Amount of storage for nonzero elements.
   //! This may differ from the actual number of elements, see nnz().
-  octave_idx_type nzmax (void) const { return m_rep->nzmax (); }
+  octave_idx_type nzmax () const { return m_rep->nzmax (); }
 
   //! Actual number of nonzero terms.
-  octave_idx_type nnz (void) const { return m_rep->nnz (); }
+  octave_idx_type nnz () const { return m_rep->nnz (); }
 
   // Querying the number of elements (incl. zeros) may overflow the index type,
   // so don't do it unless you really need it.
-  octave_idx_type numel (void) const
+  octave_idx_type numel () const
   {
     return m_dimensions.safe_numel ();
   }
 
-  octave_idx_type dim1 (void) const { return m_dimensions(0); }
-  octave_idx_type dim2 (void) const { return m_dimensions(1); }
+  octave_idx_type dim1 () const { return m_dimensions(0); }
+  octave_idx_type dim2 () const { return m_dimensions(1); }
 
-  octave_idx_type rows (void) const { return dim1 (); }
-  octave_idx_type cols (void) const { return dim2 (); }
-  octave_idx_type columns (void) const { return dim2 (); }
+  octave_idx_type rows () const { return dim1 (); }
+  octave_idx_type cols () const { return dim2 (); }
+  octave_idx_type columns () const { return dim2 (); }
 
   octave_idx_type get_row_index (octave_idx_type k) { return ridx (k); }
   octave_idx_type get_col_index (octave_idx_type k)
@@ -361,16 +361,16 @@
     return ret;
   }
 
-  std::size_t byte_size (void) const
+  std::size_t byte_size () const
   {
     return (static_cast<std::size_t> (cols () + 1) * sizeof (octave_idx_type)
             + static_cast<std::size_t> (nzmax ())
             * (sizeof (T) + sizeof (octave_idx_type)));
   }
 
-  dim_vector dims (void) const { return m_dimensions; }
+  dim_vector dims () const { return m_dimensions; }
 
-  Sparse<T, Alloc> squeeze (void) const { return *this; }
+  Sparse<T, Alloc> squeeze () const { return *this; }
 
   OCTAVE_API octave_idx_type
   compute_index (const Array<octave_idx_type>& ra_idx) const;
@@ -565,48 +565,48 @@
   OCTAVE_API Sparse<T, Alloc>&
   insert (const Sparse<T, Alloc>& a, const Array<octave_idx_type>& idx);
 
-  bool issquare (void) const { return (dim1 () == dim2 ()); }
+  bool issquare () const { return (dim1 () == dim2 ()); }
 
-  bool isempty (void) const { return (rows () < 1 || cols () < 1); }
+  bool isempty () const { return (rows () < 1 || cols () < 1); }
 
-  OCTAVE_API Sparse<T, Alloc> transpose (void) const;
+  OCTAVE_API Sparse<T, Alloc> transpose () const;
 
-  T * data (void) { make_unique (); return m_rep->m_data; }
+  T * data () { make_unique (); return m_rep->m_data; }
   T& data (octave_idx_type i) { make_unique (); return m_rep->data (i); }
-  T * xdata (void) { return m_rep->m_data; }
+  T * xdata () { return m_rep->m_data; }
   T& xdata (octave_idx_type i) { return m_rep->data (i); }
 
   T data (octave_idx_type i) const { return m_rep->data (i); }
   // FIXME: shouldn't this be returning const T*?
-  T * data (void) const { return m_rep->m_data; }
+  T * data () const { return m_rep->m_data; }
 
-  octave_idx_type * ridx (void) { make_unique (); return m_rep->m_ridx; }
+  octave_idx_type * ridx () { make_unique (); return m_rep->m_ridx; }
   octave_idx_type& ridx (octave_idx_type i)
   {
     make_unique (); return m_rep->ridx (i);
   }
 
-  octave_idx_type * xridx (void) { return m_rep->m_ridx; }
+  octave_idx_type * xridx () { return m_rep->m_ridx; }
   octave_idx_type& xridx (octave_idx_type i) { return m_rep->ridx (i); }
 
   octave_idx_type ridx (octave_idx_type i) const { return m_rep->cridx (i); }
   // FIXME: shouldn't this be returning const octave_idx_type*?
-  octave_idx_type * ridx (void) const { return m_rep->m_ridx; }
+  octave_idx_type * ridx () const { return m_rep->m_ridx; }
 
-  octave_idx_type * cidx (void) { make_unique (); return m_rep->m_cidx; }
+  octave_idx_type * cidx () { make_unique (); return m_rep->m_cidx; }
   octave_idx_type& cidx (octave_idx_type i)
   {
     make_unique (); return m_rep->cidx (i);
   }
 
-  octave_idx_type * xcidx (void) { return m_rep->m_cidx; }
+  octave_idx_type * xcidx () { return m_rep->m_cidx; }
   octave_idx_type& xcidx (octave_idx_type i) { return m_rep->cidx (i); }
 
   octave_idx_type cidx (octave_idx_type i) const { return m_rep->ccidx (i); }
   // FIXME: shouldn't this be returning const octave_idx_type*?
-  octave_idx_type * cidx (void) const { return m_rep->m_cidx; }
+  octave_idx_type * cidx () const { return m_rep->m_cidx; }
 
-  octave_idx_type ndims (void) const { return m_dimensions.ndims (); }
+  octave_idx_type ndims () const { return m_dimensions.ndims (); }
 
   OCTAVE_API void delete_elements (const octave::idx_vector& i);
 
@@ -649,7 +649,7 @@
   static OCTAVE_API Sparse<T, Alloc>
   cat (int dim, octave_idx_type n, const Sparse<T, Alloc> *sparse_list);
 
-  OCTAVE_API Array<T> array_value (void) const;
+  OCTAVE_API Array<T> array_value () const;
 
   // Generic any/all test functionality with arbitrary predicate.
   template <typename F, bool zero>
@@ -746,9 +746,9 @@
   map (U (&fcn) (const T&)) const
   { return map<U, U (&) (const T&)> (fcn); }
 
-  bool indices_ok (void) const { return m_rep->indices_ok (); }
+  bool indices_ok () const { return m_rep->indices_ok (); }
 
-  bool any_element_is_nan (void) const
+  bool any_element_is_nan () const
   { return m_rep->any_element_is_nan (); }
 };
 
--- a/liboctave/array/boolMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -63,7 +63,7 @@
 // unary operations
 
 boolMatrix
-boolMatrix::operator ! (void) const
+boolMatrix::operator ! () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
--- a/liboctave/array/boolMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,13 +39,13 @@
 {
 public:
 
-  boolMatrix (void) = default;
+  boolMatrix () = default;
 
   boolMatrix (const boolMatrix& a) = default;
 
   boolMatrix& operator = (const boolMatrix& a) = default;
 
-  ~boolMatrix (void) = default;
+  ~boolMatrix () = default;
 
   boolMatrix (octave_idx_type r, octave_idx_type c)
     : boolNDArray (dim_vector (r, c)) { }
@@ -63,7 +63,7 @@
   OCTAVE_API bool operator == (const boolMatrix& a) const;
   OCTAVE_API bool operator != (const boolMatrix& a) const;
 
-  boolMatrix transpose (void) const { return Array<bool>::transpose (); }
+  boolMatrix transpose () const { return Array<bool>::transpose (); }
 
   // destructive insert/delete/reorder operations
 
@@ -72,20 +72,12 @@
 
   // unary operations
 
-  OCTAVE_API boolMatrix operator ! (void) const;
+  OCTAVE_API boolMatrix operator ! () const;
 
   // other operations
 
   OCTAVE_API boolMatrix diag (octave_idx_type k = 0) const;
 
-#if 0
-  // i/o
-
-  friend OCTAVE_API std::ostream&
-  operator << (std::ostream& os, const Matrix& a);
-  friend OCTAVE_API std::istream& operator >> (std::istream& is, Matrix& a);
-#endif
-
   void resize (octave_idx_type nr, octave_idx_type nc, bool rfv = false)
   {
     Array<bool>::resize (dim_vector (nr, nc), rfv);
--- a/liboctave/array/boolNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,13 +39,13 @@
 // unary operations
 
 boolNDArray
-boolNDArray::operator ! (void) const
+boolNDArray::operator ! () const
 {
   return do_mx_unary_op<bool, bool> (*this, mx_inline_not);
 }
 
 boolNDArray&
-boolNDArray::invert (void)
+boolNDArray::invert ()
 {
   if (is_shared ())
     *this = ! *this;
--- a/liboctave/array/boolNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 
   typedef boolMatrix matrix_type;
 
-  boolNDArray (void) : Array<bool> () { }
+  boolNDArray () : Array<bool> () { }
 
   boolNDArray (const dim_vector& dv) : Array<bool> (dv) { }
 
@@ -58,13 +58,15 @@
     return *this;
   }
 
+  ~boolNDArray () = default;
+
   // unary operations
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
-  OCTAVE_API boolNDArray& invert (void);
+  OCTAVE_API boolNDArray& invert ();
 
-  bool any_element_is_nan (void) const { return false; }
+  bool any_element_is_nan () const { return false; }
 
   // FIXME: this is not quite the right thing.
 
@@ -79,7 +81,7 @@
   OCTAVE_API boolNDArray&
   insert (const boolNDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  boolNDArray squeeze (void) const { return Array<bool>::squeeze (); }
+  boolNDArray squeeze () const { return Array<bool>::squeeze (); }
 
   static OCTAVE_API void
   increment_index (Array<octave_idx_type>& ra_idx,
@@ -94,7 +96,7 @@
   // friend std::ostream& operator << (std::ostream& os, const NDArray& a);
   // friend std::istream& operator >> (std::istream& is, NDArray& a);
 
-  //  bool all_elements_are_real (void) const;
+  //  bool all_elements_are_real () const;
   //  bool all_integers (double& max_val, double& min_val) const;
 
   OCTAVE_API boolNDArray diag (octave_idx_type k = 0) const;
--- a/liboctave/array/boolSparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolSparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -102,7 +102,7 @@
 // unary operations
 
 SparseBoolMatrix
-SparseBoolMatrix::operator ! (void) const
+SparseBoolMatrix::operator ! () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -245,7 +245,7 @@
 }
 
 boolMatrix
-SparseBoolMatrix::matrix_value (void) const
+SparseBoolMatrix::matrix_value () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -284,7 +284,7 @@
 }
 
 SparseBoolMatrix
-SparseBoolMatrix::squeeze (void) const
+SparseBoolMatrix::squeeze () const
 {
   return Sparse<bool>::squeeze ();
 }
--- a/liboctave/array/boolSparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/boolSparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
   // Corresponding dense matrix type for this sparse matrix type.
   typedef boolMatrix dense_matrix_type;
 
-  SparseBoolMatrix (void) : Sparse<bool> () { }
+  SparseBoolMatrix () : Sparse<bool> () { }
 
   SparseBoolMatrix (octave_idx_type r, octave_idx_type c)
     : Sparse<bool> (r, c) { }
@@ -83,10 +83,12 @@
     return *this;
   }
 
+  ~SparseBoolMatrix () = default;
+
   OCTAVE_API bool operator == (const SparseBoolMatrix& a) const;
   OCTAVE_API bool operator != (const SparseBoolMatrix& a) const;
 
-  SparseBoolMatrix transpose (void) const
+  SparseBoolMatrix transpose () const
   { return Sparse<bool>::transpose (); }
 
   // destructive insert/delete/reorder operations
@@ -102,9 +104,9 @@
 
   OCTAVE_API SparseBoolMatrix diag (octave_idx_type k = 0) const;
 
-  OCTAVE_API boolMatrix matrix_value (void) const;
+  OCTAVE_API boolMatrix matrix_value () const;
 
-  OCTAVE_API SparseBoolMatrix squeeze (void) const;
+  OCTAVE_API SparseBoolMatrix squeeze () const;
 
   OCTAVE_API SparseBoolMatrix
   index (const octave::idx_vector& i, bool resize_ok) const;
@@ -123,7 +125,7 @@
 
   // unary operations
 
-  OCTAVE_API SparseBoolMatrix operator ! (void) const;
+  OCTAVE_API SparseBoolMatrix operator ! () const;
 
   // other operations
 
--- a/liboctave/array/chMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/chMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,13 +44,13 @@
 
 public:
 
-  charMatrix (void) = default;
+  charMatrix () = default;
 
   charMatrix (const charMatrix& a) = default;
 
   charMatrix& operator = (const charMatrix& a) = default;
 
-  ~charMatrix (void) = default;
+  ~charMatrix () = default;
 
   charMatrix (octave_idx_type r, octave_idx_type c)
     : charNDArray (dim_vector (r, c)) { }
@@ -77,7 +77,7 @@
   OCTAVE_API bool operator == (const charMatrix& a) const;
   OCTAVE_API bool operator != (const charMatrix& a) const;
 
-  charMatrix transpose (void) const { return Array<char>::transpose (); }
+  charMatrix transpose () const { return Array<char>::transpose (); }
 
   // destructive insert/delete/reorder operations
 
@@ -100,13 +100,6 @@
     Array<char>::resize (dim_vector (nr, nc), rfv);
   }
 
-#if 0
-  // i/o
-
-  friend OCTAVE_API std::ostream&
-  operator << (std::ostream& os, const Matrix& a);
-  friend OCTAVE_API std::istream& operator >> (std::istream& is, Matrix& a);
-#endif
 };
 
 MS_CMP_OP_DECLS (charMatrix, char, OCTAVE_API)
--- a/liboctave/array/chNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/chNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
   typedef charMatrix matrix_type;
 
-  charNDArray (void) : Array<char> () { }
+  charNDArray () : Array<char> () { }
 
   charNDArray (const dim_vector& dv) : Array<char> (dv) { }
 
@@ -66,7 +66,9 @@
     return *this;
   }
 
-  bool any_element_is_nan (void) const { return false; }
+  ~charNDArray () = default;
+
+  bool any_element_is_nan () const { return false; }
 
   // FIXME: this is not quite the right thing.
 
@@ -89,7 +91,7 @@
   OCTAVE_API charNDArray&
   insert (const charNDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  charNDArray squeeze (void) const { return Array<char>::squeeze (); }
+  charNDArray squeeze () const { return Array<char>::squeeze (); }
 
   static OCTAVE_API void
   increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/dColVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dColVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -122,13 +122,13 @@
 }
 
 RowVector
-ColumnVector::transpose (void) const
+ColumnVector::transpose () const
 {
   return MArray<double>::transpose ();
 }
 
 ColumnVector
-ColumnVector::abs (void) const
+ColumnVector::abs () const
 {
   return do_mx_unary_map<double, double, std::abs> (*this);
 }
@@ -242,7 +242,7 @@
 // other operations
 
 double
-ColumnVector::min (void) const
+ColumnVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -258,7 +258,7 @@
 }
 
 double
-ColumnVector::max (void) const
+ColumnVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
--- a/liboctave/array/dColVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dColVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  ColumnVector (void) : MArray<double> (dim_vector (0, 1)) { }
+  ColumnVector () : MArray<double> (dim_vector (0, 1)) { }
 
   explicit ColumnVector (octave_idx_type n)
     : MArray<double> (dim_vector (n, 1)) { }
@@ -59,6 +59,8 @@
     return *this;
   }
 
+  ~ColumnVector () = default;
+
   OCTAVE_API bool operator == (const ColumnVector& a) const;
   OCTAVE_API bool operator != (const ColumnVector& a) const;
 
@@ -72,7 +74,7 @@
 
   OCTAVE_API ColumnVector stack (const ColumnVector& a) const;
 
-  OCTAVE_API RowVector transpose (void) const;
+  OCTAVE_API RowVector transpose () const;
 
   friend OCTAVE_API ColumnVector real (const ComplexColumnVector& a);
   friend OCTAVE_API ColumnVector imag (const ComplexColumnVector& a);
@@ -97,10 +99,10 @@
 
   // other operations
 
-  OCTAVE_API double min (void) const;
-  OCTAVE_API double max (void) const;
+  OCTAVE_API double min () const;
+  OCTAVE_API double max () const;
 
-  OCTAVE_API ColumnVector abs (void) const;
+  OCTAVE_API ColumnVector abs () const;
 
   // i/o
 
--- a/liboctave/array/dDiagMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dDiagMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -125,7 +125,7 @@
 }
 
 DiagMatrix
-DiagMatrix::abs (void) const
+DiagMatrix::abs () const
 {
   return DiagMatrix (extract_diag ().abs (), rows (), columns ());
 }
@@ -224,7 +224,7 @@
 }
 
 DiagMatrix
-DiagMatrix::inverse (void) const
+DiagMatrix::inverse () const
 {
   octave_idx_type info;
   return inverse (info);
@@ -243,7 +243,7 @@
   info = 0;
   octave_idx_type len = r;        // alias for readability
   octave_idx_type z_count  = 0;   // zeros
-  octave_idx_type nz_count = 0;   // non-zeros
+  octave_idx_type nz_count = 0;   // nonzeros
   for (octave_idx_type i = 0; i < len; i++)
     {
       if (xelem (i, i) == 0.0)
@@ -328,7 +328,7 @@
 // other operations
 
 DET
-DiagMatrix::determinant (void) const
+DiagMatrix::determinant () const
 {
   DET det (1.0);
   if (rows () != cols ())
@@ -342,7 +342,7 @@
 }
 
 double
-DiagMatrix::rcond (void) const
+DiagMatrix::rcond () const
 {
   ColumnVector av = extract_diag (0).map<double> (fabs);
   double amx = av.max ();
--- a/liboctave/array/dDiagMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dDiagMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,13 +42,13 @@
 
   typedef Matrix full_matrix_type;
 
-  DiagMatrix (void) = default;
+  DiagMatrix () = default;
 
   DiagMatrix (const DiagMatrix& a) = default;
 
   DiagMatrix& operator = (const DiagMatrix& a) = default;
 
-  ~DiagMatrix (void) = default;
+  ~DiagMatrix () = default;
 
   DiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<double> (r, c) { }
@@ -77,9 +77,9 @@
   OCTAVE_API DiagMatrix& fill (const ColumnVector& a, octave_idx_type beg);
   OCTAVE_API DiagMatrix& fill (const RowVector& a, octave_idx_type beg);
 
-  DiagMatrix transpose (void) const
+  DiagMatrix transpose () const
   { return MDiagArray2<double>::transpose (); }
-  DiagMatrix abs (void) const;
+  DiagMatrix abs () const;
 
   friend OCTAVE_API DiagMatrix real (const ComplexDiagMatrix& a);
   friend OCTAVE_API DiagMatrix imag (const ComplexDiagMatrix& a);
@@ -98,7 +98,7 @@
   OCTAVE_API ColumnVector column (octave_idx_type i) const;
   OCTAVE_API ColumnVector column (char *s) const;
 
-  OCTAVE_API DiagMatrix inverse (void) const;
+  OCTAVE_API DiagMatrix inverse () const;
   OCTAVE_API DiagMatrix inverse (octave_idx_type& info) const;
   OCTAVE_API DiagMatrix pseudo_inverse (double tol = 0.0) const;
 
@@ -107,8 +107,8 @@
   ColumnVector extract_diag (octave_idx_type k = 0) const
   { return MDiagArray2<double>::extract_diag (k); }
 
-  OCTAVE_API DET determinant (void) const;
-  OCTAVE_API double rcond (void) const;
+  OCTAVE_API DET determinant () const;
+  OCTAVE_API double rcond () const;
 
   // i/o
 
--- a/liboctave/array/dMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -133,7 +133,7 @@
 }
 
 bool
-Matrix::issymmetric (void) const
+Matrix::issymmetric () const
 {
   if (issquare () && rows () > 0)
     {
@@ -448,7 +448,7 @@
 }
 
 Matrix
-Matrix::inverse (void) const
+Matrix::inverse () const
 {
   octave_idx_type info;
   double rcon;
@@ -731,7 +731,7 @@
 #if defined (HAVE_FFTW)
 
 ComplexMatrix
-Matrix::fourier (void) const
+Matrix::fourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -760,7 +760,7 @@
 }
 
 ComplexMatrix
-Matrix::ifourier (void) const
+Matrix::ifourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -790,7 +790,7 @@
 }
 
 ComplexMatrix
-Matrix::fourier2d (void) const
+Matrix::fourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -802,7 +802,7 @@
 }
 
 ComplexMatrix
-Matrix::ifourier2d (void) const
+Matrix::ifourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -817,7 +817,7 @@
 #else
 
 ComplexMatrix
-Matrix::fourier (void) const
+Matrix::fourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -826,7 +826,7 @@
 }
 
 ComplexMatrix
-Matrix::ifourier (void) const
+Matrix::ifourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -835,7 +835,7 @@
 }
 
 ComplexMatrix
-Matrix::fourier2d (void) const
+Matrix::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -844,7 +844,7 @@
 }
 
 ComplexMatrix
-Matrix::ifourier2d (void) const
+Matrix::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -855,7 +855,7 @@
 #endif
 
 DET
-Matrix::determinant (void) const
+Matrix::determinant () const
 {
   octave_idx_type info;
   double rcon;
@@ -1026,7 +1026,7 @@
 }
 
 double
-Matrix::rcond (void) const
+Matrix::rcond () const
 {
   MatrixType mattype (*this);
   return rcond (mattype);
@@ -2398,7 +2398,7 @@
 }
 
 Matrix
-Matrix::abs (void) const
+Matrix::abs () const
 {
   return NDArray::abs ();
 }
@@ -2426,7 +2426,7 @@
 }
 
 ColumnVector
-Matrix::row_min (void) const
+Matrix::row_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_min (dummy_idx);
@@ -2481,7 +2481,7 @@
 }
 
 ColumnVector
-Matrix::row_max (void) const
+Matrix::row_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_max (dummy_idx);
@@ -2536,7 +2536,7 @@
 }
 
 RowVector
-Matrix::column_min (void) const
+Matrix::column_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_min (dummy_idx);
@@ -2591,7 +2591,7 @@
 }
 
 RowVector
-Matrix::column_max (void) const
+Matrix::column_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_max (dummy_idx);
@@ -3029,19 +3029,7 @@
 
   retval.clear (m, n);
   for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, 0) = x1(i);
-
-  // The last column is unused so temporarily store delta there
-  double *delta = &retval.xelem (0, n-1);
-  for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1);
-
-  for (octave_idx_type j = 1; j < n-1; j++)
-    for (octave_idx_type i = 0; i < m; i++)
-      retval.xelem (i, j) = x1(i) + j*delta[i];
-
-  for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, n-1) = x2(i);
+    retval.insert (linspace (x1(i), x2(i), n), i, 0);
 
   return retval;
 }
--- a/liboctave/array/dMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,13 +59,13 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  Matrix (void) = default;
+  Matrix () = default;
 
   Matrix (const Matrix& a) = default;
 
   Matrix& operator = (const Matrix& a) = default;
 
-  ~Matrix (void) = default;
+  ~Matrix () = default;
 
   Matrix (octave_idx_type r, octave_idx_type c)
     : NDArray (dim_vector (r, c)) { }
@@ -103,7 +103,7 @@
   OCTAVE_API bool operator == (const Matrix& a) const;
   OCTAVE_API bool operator != (const Matrix& a) const;
 
-  OCTAVE_API bool issymmetric (void) const;
+  OCTAVE_API bool issymmetric () const;
 
   // destructive insert/delete/reorder operations
 
@@ -136,8 +136,8 @@
 
   friend class ComplexMatrix;
 
-  Matrix hermitian (void) const { return MArray<double>::transpose (); }
-  Matrix transpose (void) const { return MArray<double>::transpose (); }
+  Matrix hermitian () const { return MArray<double>::transpose (); }
+  Matrix transpose () const { return MArray<double>::transpose (); }
 
   // resize is the destructive equivalent for this one
 
@@ -168,7 +168,7 @@
                    bool force, bool calc_cond) const;
 
 public:
-  OCTAVE_API Matrix inverse (void) const;
+  OCTAVE_API Matrix inverse () const;
   OCTAVE_API Matrix inverse (octave_idx_type& info) const;
   OCTAVE_API Matrix
   inverse (octave_idx_type& info, double& rcon, bool force = false,
@@ -182,13 +182,13 @@
 
   OCTAVE_API Matrix pseudo_inverse (double tol = 0.0) const;
 
-  OCTAVE_API ComplexMatrix fourier (void) const;
-  OCTAVE_API ComplexMatrix ifourier (void) const;
+  OCTAVE_API ComplexMatrix fourier () const;
+  OCTAVE_API ComplexMatrix ifourier () const;
 
-  OCTAVE_API ComplexMatrix fourier2d (void) const;
-  OCTAVE_API ComplexMatrix ifourier2d (void) const;
+  OCTAVE_API ComplexMatrix fourier2d () const;
+  OCTAVE_API ComplexMatrix ifourier2d () const;
 
-  OCTAVE_API DET determinant (void) const;
+  OCTAVE_API DET determinant () const;
   OCTAVE_API DET determinant (octave_idx_type& info) const;
   OCTAVE_API DET
   determinant (octave_idx_type& info, double& rcon,
@@ -197,7 +197,7 @@
   determinant (MatrixType& mattype, octave_idx_type& info,
                double& rcon, bool calc_cond = true) const;
 
-  OCTAVE_API double rcond (void) const;
+  OCTAVE_API double rcond () const;
   OCTAVE_API double rcond (MatrixType& mattype) const;
 
 private:
@@ -371,20 +371,20 @@
   OCTAVE_API Matrix prod (int dim = -1) const;
   OCTAVE_API Matrix sum (int dim = -1) const;
   OCTAVE_API Matrix sumsq (int dim = -1) const;
-  OCTAVE_API Matrix abs (void) const;
+  OCTAVE_API Matrix abs () const;
 
   OCTAVE_API Matrix diag (octave_idx_type k = 0) const;
 
   OCTAVE_API DiagMatrix diag (octave_idx_type m, octave_idx_type n) const;
 
-  OCTAVE_API ColumnVector row_min (void) const;
-  OCTAVE_API ColumnVector row_max (void) const;
+  OCTAVE_API ColumnVector row_min () const;
+  OCTAVE_API ColumnVector row_max () const;
 
   OCTAVE_API ColumnVector row_min (Array<octave_idx_type>& index) const;
   OCTAVE_API ColumnVector row_max (Array<octave_idx_type>& index) const;
 
-  OCTAVE_API RowVector column_min (void) const;
-  OCTAVE_API RowVector column_max (void) const;
+  OCTAVE_API RowVector column_min () const;
+  OCTAVE_API RowVector column_max () const;
 
   OCTAVE_API RowVector column_min (Array<octave_idx_type>& index) const;
   OCTAVE_API RowVector column_max (Array<octave_idx_type>& index) const;
--- a/liboctave/array/dNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -158,7 +158,7 @@
 }
 
 ComplexNDArray
-NDArray::fourier2d (void) const
+NDArray::fourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -178,7 +178,7 @@
 }
 
 ComplexNDArray
-NDArray::ifourier2d (void) const
+NDArray::ifourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -197,7 +197,7 @@
 }
 
 ComplexNDArray
-NDArray::fourierNd (void) const
+NDArray::fourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -212,7 +212,7 @@
 }
 
 ComplexNDArray
-NDArray::ifourierNd (void) const
+NDArray::ifourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -252,7 +252,7 @@
 }
 
 ComplexNDArray
-NDArray::fourier2d (void) const
+NDArray::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -261,7 +261,7 @@
 }
 
 ComplexNDArray
-NDArray::ifourier2d (void) const
+NDArray::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -270,7 +270,7 @@
 }
 
 ComplexNDArray
-NDArray::fourierNd (void) const
+NDArray::fourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -279,7 +279,7 @@
 }
 
 ComplexNDArray
-NDArray::ifourierNd (void) const
+NDArray::ifourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -292,7 +292,7 @@
 // unary operations
 
 boolNDArray
-NDArray::operator ! (void) const
+NDArray::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -315,31 +315,31 @@
 }
 
 bool
-NDArray::any_element_is_nan (void) const
+NDArray::any_element_is_nan () const
 {
   return do_mx_check<double> (*this, mx_inline_any_nan);
 }
 
 bool
-NDArray::any_element_is_inf_or_nan (void) const
+NDArray::any_element_is_inf_or_nan () const
 {
   return ! do_mx_check<double> (*this, mx_inline_all_finite);
 }
 
 bool
-NDArray::any_element_not_one_or_zero (void) const
+NDArray::any_element_not_one_or_zero () const
 {
   return ! test_all (octave::is_one_or_zero);
 }
 
 bool
-NDArray::all_elements_are_zero (void) const
+NDArray::all_elements_are_zero () const
 {
   return test_all (octave::is_zero);
 }
 
 bool
-NDArray::all_elements_are_int_or_inf_or_nan (void) const
+NDArray::all_elements_are_int_or_inf_or_nan () const
 {
   return test_all (octave::is_int_or_inf_or_nan);
 }
@@ -378,13 +378,13 @@
 }
 
 bool
-NDArray::all_integers (void) const
+NDArray::all_integers () const
 {
   return test_all (octave::math::isinteger);
 }
 
 bool
-NDArray::too_large_for_float (void) const
+NDArray::too_large_for_float () const
 {
   return test_any (octave::too_large_for_float);
 }
@@ -567,25 +567,25 @@
 }
 
 NDArray
-NDArray::abs (void) const
+NDArray::abs () const
 {
   return do_mx_unary_map<double, double, std::abs> (*this);
 }
 
 boolNDArray
-NDArray::isnan (void) const
+NDArray::isnan () const
 {
   return do_mx_unary_map<bool, double, octave::math::isnan> (*this);
 }
 
 boolNDArray
-NDArray::isinf (void) const
+NDArray::isinf () const
 {
   return do_mx_unary_map<bool, double, octave::math::isinf> (*this);
 }
 
 boolNDArray
-NDArray::isfinite (void) const
+NDArray::isfinite () const
 {
   return do_mx_unary_map<bool, double, octave::math::isfinite> (*this);
 }
--- a/liboctave/array/dNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 public:
 
-  NDArray (void) : MArray<double> () { }
+  NDArray () : MArray<double> () { }
 
   NDArray (const dim_vector& dv) : MArray<double> (dv) { }
 
@@ -69,20 +69,22 @@
     return *this;
   }
 
+  ~NDArray () = default;
+
   // unary operations
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
   OCTAVE_API bool any_element_is_negative (bool = false) const;
   OCTAVE_API bool any_element_is_positive (bool = false) const;
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool any_element_not_one_or_zero (void) const;
-  OCTAVE_API bool all_elements_are_zero (void) const;
-  OCTAVE_API bool all_elements_are_int_or_inf_or_nan (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool any_element_not_one_or_zero () const;
+  OCTAVE_API bool all_elements_are_zero () const;
+  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;
   OCTAVE_API bool all_integers (double& max_val, double& min_val) const;
-  OCTAVE_API bool all_integers (void) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool all_integers () const;
+  OCTAVE_API bool too_large_for_float () const;
 
   // FIXME: this is not quite the right thing.
 
@@ -121,26 +123,26 @@
   OCTAVE_API NDArray&
   insert (const NDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  OCTAVE_API NDArray abs (void) const;
-  OCTAVE_API boolNDArray isnan (void) const;
-  OCTAVE_API boolNDArray isinf (void) const;
-  OCTAVE_API boolNDArray isfinite (void) const;
+  OCTAVE_API NDArray abs () const;
+  OCTAVE_API boolNDArray isnan () const;
+  OCTAVE_API boolNDArray isinf () const;
+  OCTAVE_API boolNDArray isfinite () const;
 
   OCTAVE_API ComplexNDArray fourier (int dim = 1) const;
   OCTAVE_API ComplexNDArray ifourier (int dim = 1) const;
 
-  OCTAVE_API ComplexNDArray fourier2d (void) const;
-  OCTAVE_API ComplexNDArray ifourier2d (void) const;
+  OCTAVE_API ComplexNDArray fourier2d () const;
+  OCTAVE_API ComplexNDArray ifourier2d () const;
 
-  OCTAVE_API ComplexNDArray fourierNd (void) const;
-  OCTAVE_API ComplexNDArray ifourierNd (void) const;
+  OCTAVE_API ComplexNDArray fourierNd () const;
+  OCTAVE_API ComplexNDArray ifourierNd () const;
 
   friend OCTAVE_API NDArray real (const ComplexNDArray& a);
   friend OCTAVE_API NDArray imag (const ComplexNDArray& a);
 
   friend class ComplexNDArray;
 
-  NDArray squeeze (void) const { return MArray<double>::squeeze (); }
+  NDArray squeeze () const { return MArray<double>::squeeze (); }
 
   static OCTAVE_API void
   increment_index (Array<octave_idx_type>& ra_idx,
@@ -159,7 +161,7 @@
 
   OCTAVE_API NDArray diag (octave_idx_type m, octave_idx_type n) const;
 
-  NDArray& changesign (void)
+  NDArray& changesign ()
   {
     MArray<double>::changesign ();
     return *this;
--- a/liboctave/array/dRowVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dRowVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -123,7 +123,7 @@
 }
 
 ColumnVector
-RowVector::transpose (void) const
+RowVector::transpose () const
 {
   return MArray<double>::transpose ();
 }
@@ -204,7 +204,7 @@
 // other operations
 
 double
-RowVector::min (void) const
+RowVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -220,7 +220,7 @@
 }
 
 double
-RowVector::max (void) const
+RowVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -279,6 +279,11 @@
       retval.resize (1, x2);
       return retval;
     }
+  else if (x1 == x2)
+    {
+      retval.resize (n_in, x2);
+      return retval;
+    }
 
   // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions
   // by 2 can be replaced by compiler with shift right instructions.
@@ -292,7 +297,14 @@
   retval.xelem (n-1) = x2;
 
   // Construct linspace symmetrically from both ends.
+  bool isnan_delta = false;
   double delta = (x2 - x1) / (n - 1);
+  if (octave::math::isinf (delta))
+    {
+      delta = octave::numeric_limits<double>::NaN ();
+      isnan_delta = true;
+    }
+
   unsigned_octave_idx_type n2 = n/2;
   for (unsigned_octave_idx_type i = 1; i < n2; i++)
     {
@@ -300,7 +312,14 @@
       retval.xelem (n-1-i) = x2 - i*delta;
     }
   if (n % 2 == 1)  // Middle element if number of elements is odd.
-    retval.xelem (n2) = (x1 == -x2 ? 0 : (x1 + x2) / 2);
+    {
+      if (x1 == -x2)
+        retval.xelem (n2) = 0;
+      else if (isnan_delta)
+        retval.xelem (n2) = octave::numeric_limits<double>::NaN ();
+      else
+        retval.xelem (n2) = (x1 + x2) / 2;
+    }
 
   return retval;
 }
--- a/liboctave/array/dRowVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dRowVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  RowVector (void) : MArray<double> (dim_vector (1, 0)) { }
+  RowVector () : MArray<double> (dim_vector (1, 0)) { }
 
   explicit RowVector (octave_idx_type n)
     : MArray<double> (dim_vector (1, n)) { }
@@ -59,6 +59,8 @@
     return *this;
   }
 
+  ~RowVector () = default;
+
   OCTAVE_API bool operator == (const RowVector& a) const;
   OCTAVE_API bool operator != (const RowVector& a) const;
 
@@ -71,7 +73,7 @@
 
   OCTAVE_API RowVector append (const RowVector& a) const;
 
-  OCTAVE_API ColumnVector transpose (void) const;
+  OCTAVE_API ColumnVector transpose () const;
 
   friend OCTAVE_API RowVector real (const ComplexRowVector& a);
   friend OCTAVE_API RowVector imag (const ComplexRowVector& a);
@@ -88,8 +90,8 @@
 
   // other operations
 
-  OCTAVE_API double min (void) const;
-  OCTAVE_API double max (void) const;
+  OCTAVE_API double min () const;
+  OCTAVE_API double max () const;
 
   // i/o
 
--- a/liboctave/array/dSparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dSparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -128,7 +128,7 @@
 }
 
 bool
-SparseMatrix::issymmetric (void) const
+SparseMatrix::issymmetric () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -600,7 +600,7 @@
 */
 
 SparseMatrix
-SparseMatrix::inverse (void) const
+SparseMatrix::inverse () const
 {
   octave_idx_type info;
   double rcond;
@@ -1009,7 +1009,7 @@
 }
 
 DET
-SparseMatrix::determinant (void) const
+SparseMatrix::determinant () const
 {
   octave_idx_type info;
   double rcond;
@@ -7216,7 +7216,7 @@
 }
 
 bool
-SparseMatrix::any_element_is_nan (void) const
+SparseMatrix::any_element_is_nan () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7231,7 +7231,7 @@
 }
 
 bool
-SparseMatrix::any_element_is_inf_or_nan (void) const
+SparseMatrix::any_element_is_inf_or_nan () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7246,7 +7246,7 @@
 }
 
 bool
-SparseMatrix::any_element_not_one_or_zero (void) const
+SparseMatrix::any_element_not_one_or_zero () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7261,7 +7261,7 @@
 }
 
 bool
-SparseMatrix::all_elements_are_zero (void) const
+SparseMatrix::all_elements_are_zero () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7273,7 +7273,7 @@
 }
 
 bool
-SparseMatrix::all_elements_are_int_or_inf_or_nan (void) const
+SparseMatrix::all_elements_are_int_or_inf_or_nan () const
 {
   octave_idx_type nel = nnz ();
 
@@ -7321,13 +7321,13 @@
 }
 
 bool
-SparseMatrix::too_large_for_float (void) const
+SparseMatrix::too_large_for_float () const
 {
   return test_any (octave::too_large_for_float);
 }
 
 SparseBoolMatrix
-SparseMatrix::operator ! (void) const
+SparseMatrix::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -7423,7 +7423,7 @@
 }
 
 SparseMatrix
-SparseMatrix::abs (void) const
+SparseMatrix::abs () const
 {
   octave_idx_type nz = nnz ();
 
@@ -7442,7 +7442,7 @@
 }
 
 Matrix
-SparseMatrix::matrix_value (void) const
+SparseMatrix::matrix_value () const
 {
   return Sparse<double>::array_value ();
 }
@@ -7477,7 +7477,7 @@
 }
 
 SparseMatrix
-SparseMatrix::squeeze (void) const
+SparseMatrix::squeeze () const
 {
   return MSparse<double>::squeeze ();
 }
--- a/liboctave/array/dSparse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dSparse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 
   typedef void (*solve_singularity_handler) (double rcond);
 
-  SparseMatrix (void) : MSparse<double> () { }
+  SparseMatrix () : MSparse<double> () { }
 
   SparseMatrix (octave_idx_type r, octave_idx_type c)
     : MSparse<double> (r, c) { }
@@ -95,10 +95,12 @@
     return *this;
   }
 
+  ~SparseMatrix () = default;
+
   OCTAVE_API bool operator == (const SparseMatrix& a) const;
   OCTAVE_API bool operator != (const SparseMatrix& a) const;
 
-  OCTAVE_API bool issymmetric (void) const;
+  OCTAVE_API bool issymmetric () const;
 
   OCTAVE_API SparseMatrix max (int dim = -1) const;
   OCTAVE_API SparseMatrix max (Array<octave_idx_type>& index, int dim = -1) const;
@@ -121,11 +123,11 @@
   friend OCTAVE_API SparseMatrix real (const SparseComplexMatrix& a);
   friend OCTAVE_API SparseMatrix imag (const SparseComplexMatrix& a);
 
-  SparseMatrix transpose (void) const
+  SparseMatrix transpose () const
   {
     return MSparse<double>::transpose ();
   }
-  SparseMatrix hermitian (void) const { return transpose (); }
+  SparseMatrix hermitian () const { return transpose (); }
 
   // extract row or column i.
 
@@ -143,7 +145,7 @@
             const bool force = false, const bool calccond = true) const;
 
 public:
-  OCTAVE_API SparseMatrix inverse (void) const;
+  OCTAVE_API SparseMatrix inverse () const;
   OCTAVE_API SparseMatrix inverse (MatrixType& mattype) const;
   OCTAVE_API SparseMatrix
   inverse (MatrixType& mattype, octave_idx_type& info) const;
@@ -151,7 +153,7 @@
   inverse (MatrixType& mattype, octave_idx_type& info, double& rcond,
            bool force = false, bool calc_cond = true) const;
 
-  OCTAVE_API DET determinant (void) const;
+  OCTAVE_API DET determinant () const;
   OCTAVE_API DET determinant (octave_idx_type& info) const;
   OCTAVE_API DET determinant (octave_idx_type& info, double& rcond,
                               bool calc_cond = true) const;
@@ -420,15 +422,15 @@
   // other operations
 
   OCTAVE_API bool any_element_is_negative (bool = false) const;
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool any_element_not_one_or_zero (void) const;
-  OCTAVE_API bool all_elements_are_zero (void) const;
-  OCTAVE_API bool all_elements_are_int_or_inf_or_nan (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool any_element_not_one_or_zero () const;
+  OCTAVE_API bool all_elements_are_zero () const;
+  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;
   OCTAVE_API bool all_integers (double& max_val, double& min_val) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool too_large_for_float () const;
 
-  OCTAVE_API SparseBoolMatrix operator ! (void) const;
+  OCTAVE_API SparseBoolMatrix operator ! () const;
 
   OCTAVE_API SparseBoolMatrix all (int dim = -1) const;
   OCTAVE_API SparseBoolMatrix any (int dim = -1) const;
@@ -438,13 +440,13 @@
   OCTAVE_API SparseMatrix prod (int dim = -1) const;
   OCTAVE_API SparseMatrix sum (int dim = -1) const;
   OCTAVE_API SparseMatrix sumsq (int dim = -1) const;
-  OCTAVE_API SparseMatrix abs (void) const;
+  OCTAVE_API SparseMatrix abs () const;
 
   OCTAVE_API SparseMatrix diag (octave_idx_type k = 0) const;
 
-  OCTAVE_API Matrix matrix_value (void) const;
+  OCTAVE_API Matrix matrix_value () const;
 
-  OCTAVE_API SparseMatrix squeeze (void) const;
+  OCTAVE_API SparseMatrix squeeze () const;
 
   OCTAVE_API SparseMatrix reshape (const dim_vector& new_dims) const;
 
--- a/liboctave/array/dim-vector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dim-vector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,13 +41,13 @@
 // Currently 1 is subtracted to allow safe conversion of any 2D Array into
 // Sparse, but this offset may change in the future.
 octave_idx_type
-dim_vector::dim_max (void)
+dim_vector::dim_max ()
 {
   return std::numeric_limits<octave_idx_type>::max () - 1;
 }
 
 void
-dim_vector::chop_all_singletons (void)
+dim_vector::chop_all_singletons ()
 {
   int j = 0;
   int nd = ndims ();
@@ -83,7 +83,7 @@
 }
 
 int
-dim_vector::num_ones (void) const
+dim_vector::num_ones () const
 {
   int retval = 0;
 
@@ -95,7 +95,7 @@
 }
 
 octave_idx_type
-dim_vector::safe_numel (void) const
+dim_vector::safe_numel () const
 {
   octave_idx_type idx_max = dim_max ();
   octave_idx_type n = 1;
@@ -114,7 +114,7 @@
 }
 
 dim_vector
-dim_vector::squeeze (void) const
+dim_vector::squeeze () const
 {
   dim_vector new_dims = *this;
   new_dims.chop_all_singletons ();
@@ -263,7 +263,7 @@
 }
 
 Array<octave_idx_type>
-dim_vector::as_array (void) const
+dim_vector::as_array () const
 {
   octave_idx_type nd = ndims ();
 
--- a/liboctave/array/dim-vector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/dim-vector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -161,13 +161,13 @@
 
   octave_idx_type elem (int i) const { return xelem (i); }
 
-  void chop_trailing_singletons (void)
+  void chop_trailing_singletons ()
   {
     while (m_num_dims > 2 && xelem(m_num_dims-1) == 1)
       m_num_dims--;
   }
 
-  OCTAVE_API void chop_all_singletons (void);
+  OCTAVE_API void chop_all_singletons ();
 
 private:
 
@@ -179,9 +179,9 @@
 
 public:
 
-  static OCTAVE_API octave_idx_type dim_max (void);
+  static OCTAVE_API octave_idx_type dim_max ();
 
-  explicit dim_vector (void)
+  explicit dim_vector ()
     : m_num_dims (2), m_dims (new octave_idx_type [m_num_dims])
   {
     std::fill_n (m_dims, m_num_dims, 0);
@@ -239,7 +239,7 @@
     return *this;
   }
 
-  ~dim_vector (void)
+  ~dim_vector ()
   {
     // Because we define a move constructor and a move assignment
     // operator, m_dims may be a nullptr here.  We should only need to
@@ -254,7 +254,7 @@
   //! elements in the dim_vector including trailing singletons.  It is also
   //! the number of dimensions an Array with this dim_vector would have.
 
-  octave_idx_type ndims (void) const { return m_num_dims; }
+  octave_idx_type ndims () const { return m_num_dims; }
 
   //! Number of dimensions.
   //! Synonymous with ndims().
@@ -263,7 +263,7 @@
   //! instead to avoid confusion.  Array does not have length because of its
   //! odd definition as length of the longest dimension.
 
-  int length (void) const { return ndims (); }
+  int length () const { return ndims (); }
 
   octave_idx_type& operator () (int i) { return elem (i); }
 
@@ -297,31 +297,31 @@
 
   OCTAVE_API std::string str (char sep = 'x') const;
 
-  bool all_zero (void) const
+  bool all_zero () const
   {
     return std::all_of (m_dims, m_dims + ndims (),
                         [] (octave_idx_type dim) { return dim == 0; });
   }
 
-  bool empty_2d (void) const
+  bool empty_2d () const
   {
     return ndims () == 2 && (xelem (0) == 0 || xelem (1) == 0);
   }
 
-  bool zero_by_zero (void) const
+  bool zero_by_zero () const
   {
     return ndims () == 2 && xelem (0) == 0 && xelem (1) == 0;
   }
 
-  bool any_zero (void) const
+  bool any_zero () const
   {
     return std::any_of (m_dims, m_dims + ndims (),
                         [] (octave_idx_type dim) { return dim == 0; });
   }
 
-  OCTAVE_API int num_ones (void) const;
+  OCTAVE_API int num_ones () const;
 
-  bool all_ones (void) const
+  bool all_ones () const
   {
     return (num_ones () == ndims ());
   }
@@ -352,15 +352,15 @@
   //! function that is iterating over an array using octave_idx_type
   //! indices.
 
-  OCTAVE_API octave_idx_type safe_numel (void) const;
+  OCTAVE_API octave_idx_type safe_numel () const;
 
-  bool any_neg (void) const
+  bool any_neg () const
   {
     return std::any_of (m_dims, m_dims + ndims (),
                         [] (octave_idx_type dim) { return dim < 0; });
   }
 
-  OCTAVE_API dim_vector squeeze (void) const;
+  OCTAVE_API dim_vector squeeze () const;
 
   //! This corresponds to cat().
   OCTAVE_API bool concat (const dim_vector& dvb, int dim);
@@ -376,7 +376,7 @@
 
   OCTAVE_API dim_vector redim (int n) const;
 
-  dim_vector as_column (void) const
+  dim_vector as_column () const
   {
     if (ndims () == 2 && xelem (1) == 1)
       return *this;
@@ -384,7 +384,7 @@
       return dim_vector (numel (), 1);
   }
 
-  dim_vector as_row (void) const
+  dim_vector as_row () const
   {
     if (ndims () == 2 && xelem (0) == 1)
       return *this;
@@ -392,12 +392,12 @@
       return dim_vector (1, numel ());
   }
 
-  bool isvector (void) const
+  bool isvector () const
   {
     return (ndims () == 2 && (xelem (0) == 1 || xelem (1) == 1));
   }
 
-  bool is_nd_vector (void) const
+  bool is_nd_vector () const
   {
     int num_non_one = 0;
 
@@ -485,7 +485,7 @@
 
   //! Return cumulative dimensions.
 
-  dim_vector cumulative (void) const
+  dim_vector cumulative () const
   {
     int nd = ndims ();
     dim_vector retval = alloc (nd);
@@ -513,7 +513,7 @@
   friend OCTAVE_API bool
   operator == (const dim_vector& a, const dim_vector& b);
 
-  OCTAVE_API Array<octave_idx_type> as_array (void) const;
+  OCTAVE_API Array<octave_idx_type> as_array () const;
 };
 
 inline bool
--- a/liboctave/array/fCColVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCColVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -198,19 +198,19 @@
 }
 
 FloatComplexRowVector
-FloatComplexColumnVector::hermitian (void) const
+FloatComplexColumnVector::hermitian () const
 {
   return MArray<FloatComplex>::hermitian (std::conj);
 }
 
 FloatComplexRowVector
-FloatComplexColumnVector::transpose (void) const
+FloatComplexColumnVector::transpose () const
 {
   return MArray<FloatComplex>::transpose ();
 }
 
 FloatColumnVector
-FloatComplexColumnVector::abs (void) const
+FloatComplexColumnVector::abs () const
 {
   return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
 }
@@ -421,7 +421,7 @@
 // other operations
 
 FloatComplex
-FloatComplexColumnVector::min (void) const
+FloatComplexColumnVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -441,7 +441,7 @@
 }
 
 FloatComplex
-FloatComplexColumnVector::max (void) const
+FloatComplexColumnVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
--- a/liboctave/array/fCColVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCColVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 
 public:
 
-  FloatComplexColumnVector (void)
+  FloatComplexColumnVector ()
     : MArray<FloatComplex> (dim_vector (0, 1)) { }
 
   explicit FloatComplexColumnVector (octave_idx_type n)
@@ -69,6 +69,8 @@
     return *this;
   }
 
+  ~FloatComplexColumnVector () = default;
+
   OCTAVE_API bool operator == (const FloatComplexColumnVector& a) const;
   OCTAVE_API bool operator != (const FloatComplexColumnVector& a) const;
 
@@ -90,8 +92,8 @@
   OCTAVE_API FloatComplexColumnVector
   stack (const FloatComplexColumnVector& a) const;
 
-  OCTAVE_API FloatComplexRowVector hermitian (void) const;
-  OCTAVE_API FloatComplexRowVector transpose (void) const;
+  OCTAVE_API FloatComplexRowVector hermitian () const;
+  OCTAVE_API FloatComplexRowVector transpose () const;
 
   friend OCTAVE_API FloatComplexColumnVector
   OCTAVE_API conj (const FloatComplexColumnVector& a);
@@ -137,10 +139,10 @@
 
   // other operations
 
-  OCTAVE_API FloatComplex min (void) const;
-  OCTAVE_API FloatComplex max (void) const;
+  OCTAVE_API FloatComplex min () const;
+  OCTAVE_API FloatComplex max () const;
 
-  OCTAVE_API FloatColumnVector abs (void) const;
+  OCTAVE_API FloatColumnVector abs () const;
 
   // i/o
 
--- a/liboctave/array/fCDiagMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCDiagMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -209,7 +209,7 @@
 }
 
 FloatDiagMatrix
-FloatComplexDiagMatrix::abs (void) const
+FloatComplexDiagMatrix::abs () const
 {
   return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());
 }
@@ -305,7 +305,7 @@
 }
 
 FloatComplexDiagMatrix
-FloatComplexDiagMatrix::inverse (void) const
+FloatComplexDiagMatrix::inverse () const
 {
   octave_idx_type info;
   return inverse (info);
@@ -358,7 +358,7 @@
 }
 
 bool
-FloatComplexDiagMatrix::all_elements_are_real (void) const
+FloatComplexDiagMatrix::all_elements_are_real () const
 {
   return mx_inline_all_real (length (), data ());
 }
@@ -474,7 +474,7 @@
 // other operations
 
 FloatComplexDET
-FloatComplexDiagMatrix::determinant (void) const
+FloatComplexDiagMatrix::determinant () const
 {
   FloatComplexDET det (1.0f);
   if (rows () != cols ())
@@ -488,7 +488,7 @@
 }
 
 float
-FloatComplexDiagMatrix::rcond (void) const
+FloatComplexDiagMatrix::rcond () const
 {
   FloatColumnVector av = extract_diag (0).map<float> (std::abs);
   float amx = av.max ();
--- a/liboctave/array/fCDiagMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCDiagMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -48,13 +48,13 @@
   typedef FloatComplex complex_elt_type;
   typedef FloatComplex element_type;
 
-  FloatComplexDiagMatrix (void) = default;
+  FloatComplexDiagMatrix () = default;
 
   FloatComplexDiagMatrix (const FloatComplexDiagMatrix& a) = default;
 
   FloatComplexDiagMatrix& operator = (const FloatComplexDiagMatrix& a) = default;
 
-  ~FloatComplexDiagMatrix (void) = default;
+  ~FloatComplexDiagMatrix () = default;
 
   FloatComplexDiagMatrix (octave_idx_type r,
                           octave_idx_type c)
@@ -105,11 +105,11 @@
   OCTAVE_API FloatComplexDiagMatrix&
   fill (const FloatComplexRowVector& a, octave_idx_type beg);
 
-  FloatComplexDiagMatrix hermitian (void) const
+  FloatComplexDiagMatrix hermitian () const
   { return MDiagArray2<FloatComplex>::hermitian (std::conj); }
-  FloatComplexDiagMatrix transpose (void) const
+  FloatComplexDiagMatrix transpose () const
   { return MDiagArray2<FloatComplex>::transpose (); }
-  OCTAVE_API FloatDiagMatrix abs (void) const;
+  OCTAVE_API FloatDiagMatrix abs () const;
 
   friend OCTAVE_API FloatComplexDiagMatrix
   conj (const FloatComplexDiagMatrix& a);
@@ -129,10 +129,10 @@
   OCTAVE_API FloatComplexColumnVector column (char *s) const;
 
   OCTAVE_API FloatComplexDiagMatrix inverse (octave_idx_type& info) const;
-  OCTAVE_API FloatComplexDiagMatrix inverse (void) const;
+  OCTAVE_API FloatComplexDiagMatrix inverse () const;
   OCTAVE_API FloatComplexDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
-  OCTAVE_API bool all_elements_are_real (void) const;
+  OCTAVE_API bool all_elements_are_real () const;
 
   // diagonal matrix by diagonal matrix -> diagonal matrix operations
 
@@ -144,8 +144,8 @@
   FloatComplexColumnVector extract_diag (octave_idx_type k = 0) const
   { return MDiagArray2<FloatComplex>::extract_diag (k); }
 
-  OCTAVE_API FloatComplexDET determinant (void) const;
-  OCTAVE_API float rcond (void) const;
+  OCTAVE_API FloatComplexDET determinant () const;
+  OCTAVE_API float rcond () const;
 
   // i/o
 
--- a/liboctave/array/fCMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -171,7 +171,7 @@
 }
 
 bool
-FloatComplexMatrix::ishermitian (void) const
+FloatComplexMatrix::ishermitian () const
 {
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -737,7 +737,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::inverse (void) const
+FloatComplexMatrix::inverse () const
 {
   octave_idx_type info;
   float rcon;
@@ -1045,7 +1045,7 @@
 #if defined (HAVE_FFTW)
 
 FloatComplexMatrix
-FloatComplexMatrix::fourier (void) const
+FloatComplexMatrix::fourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -1074,7 +1074,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::ifourier (void) const
+FloatComplexMatrix::ifourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -1103,7 +1103,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::fourier2d (void) const
+FloatComplexMatrix::fourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -1117,7 +1117,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::ifourier2d (void) const
+FloatComplexMatrix::ifourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -1133,7 +1133,7 @@
 #else
 
 FloatComplexMatrix
-FloatComplexMatrix::fourier (void) const
+FloatComplexMatrix::fourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1142,7 +1142,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::ifourier (void) const
+FloatComplexMatrix::ifourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1151,7 +1151,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::fourier2d (void) const
+FloatComplexMatrix::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1160,7 +1160,7 @@
 }
 
 FloatComplexMatrix
-FloatComplexMatrix::ifourier2d (void) const
+FloatComplexMatrix::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -1171,7 +1171,7 @@
 #endif
 
 FloatComplexDET
-FloatComplexMatrix::determinant (void) const
+FloatComplexMatrix::determinant () const
 {
   octave_idx_type info;
   float rcon;
@@ -1350,7 +1350,7 @@
 }
 
 float
-FloatComplexMatrix::rcond (void) const
+FloatComplexMatrix::rcond () const
 {
   MatrixType mattype (*this);
   return rcond (mattype);
@@ -2849,7 +2849,7 @@
   return FloatComplexNDArray::sumsq (dim);
 }
 
-FloatMatrix FloatComplexMatrix::abs (void) const
+FloatMatrix FloatComplexMatrix::abs () const
 {
   return FloatComplexNDArray::abs ();
 }
@@ -2915,7 +2915,7 @@
 }
 
 FloatComplexColumnVector
-FloatComplexMatrix::row_min (void) const
+FloatComplexMatrix::row_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_min (dummy_idx);
@@ -2990,7 +2990,7 @@
 }
 
 FloatComplexColumnVector
-FloatComplexMatrix::row_max (void) const
+FloatComplexMatrix::row_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_max (dummy_idx);
@@ -3065,7 +3065,7 @@
 }
 
 FloatComplexRowVector
-FloatComplexMatrix::column_min (void) const
+FloatComplexMatrix::column_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_min (dummy_idx);
@@ -3140,7 +3140,7 @@
 }
 
 FloatComplexRowVector
-FloatComplexMatrix::column_max (void) const
+FloatComplexMatrix::column_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_max (dummy_idx);
@@ -3676,19 +3676,7 @@
 
   retval.clear (m, n);
   for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, 0) = x1(i);
-
-  // The last column is unused so temporarily store delta there
-  FloatComplex *delta = &retval.xelem (0, n-1);
-  for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1.0f);
-
-  for (octave_idx_type j = 1; j < n-1; j++)
-    for (octave_idx_type i = 0; i < m; i++)
-      retval.xelem (i, j) = x1(i) + static_cast<float> (j)*delta[i];
-
-  for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, n-1) = x2(i);
+    retval.insert (linspace (x1(i), x2(i), n), i, 0);
 
   return retval;
 }
--- a/liboctave/array/fCMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,13 +60,13 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatComplexMatrix (void) = default;
+  FloatComplexMatrix () = default;
 
   FloatComplexMatrix (const FloatComplexMatrix& a) = default;
 
   FloatComplexMatrix& operator = (const FloatComplexMatrix& a) = default;
 
-  ~FloatComplexMatrix (void) = default;
+  ~FloatComplexMatrix () = default;
 
   FloatComplexMatrix (octave_idx_type r, octave_idx_type c)
     : FloatComplexNDArray (dim_vector (r, c)) { }
@@ -120,7 +120,7 @@
   OCTAVE_API bool operator == (const FloatComplexMatrix& a) const;
   OCTAVE_API bool operator != (const FloatComplexMatrix& a) const;
 
-  OCTAVE_API bool ishermitian (void) const;
+  OCTAVE_API bool ishermitian () const;
 
   // destructive insert/delete/reorder operations
 
@@ -175,9 +175,9 @@
   OCTAVE_API FloatComplexMatrix stack (const FloatComplexColumnVector& a) const;
   OCTAVE_API FloatComplexMatrix stack (const FloatComplexDiagMatrix& a) const;
 
-  FloatComplexMatrix hermitian (void) const
+  FloatComplexMatrix hermitian () const
   { return MArray<FloatComplex>::hermitian (std::conj); }
-  FloatComplexMatrix transpose (void) const
+  FloatComplexMatrix transpose () const
   { return MArray<FloatComplex>::transpose (); }
 
   friend OCTAVE_API FloatComplexMatrix conj (const FloatComplexMatrix& a);
@@ -212,7 +212,7 @@
                                float& rcon, bool force, bool calc_cond) const;
 
 public:
-  OCTAVE_API FloatComplexMatrix inverse (void) const;
+  OCTAVE_API FloatComplexMatrix inverse () const;
   OCTAVE_API FloatComplexMatrix inverse (octave_idx_type& info) const;
   OCTAVE_API FloatComplexMatrix
   inverse (octave_idx_type& info, float& rcon, bool force = false,
@@ -227,13 +227,13 @@
 
   OCTAVE_API FloatComplexMatrix pseudo_inverse (float tol = 0.0) const;
 
-  OCTAVE_API FloatComplexMatrix fourier (void) const;
-  OCTAVE_API FloatComplexMatrix ifourier (void) const;
+  OCTAVE_API FloatComplexMatrix fourier () const;
+  OCTAVE_API FloatComplexMatrix ifourier () const;
 
-  OCTAVE_API FloatComplexMatrix fourier2d (void) const;
-  OCTAVE_API FloatComplexMatrix ifourier2d (void) const;
+  OCTAVE_API FloatComplexMatrix fourier2d () const;
+  OCTAVE_API FloatComplexMatrix ifourier2d () const;
 
-  OCTAVE_API FloatComplexDET determinant (void) const;
+  OCTAVE_API FloatComplexDET determinant () const;
   OCTAVE_API FloatComplexDET determinant (octave_idx_type& info) const;
   OCTAVE_API FloatComplexDET
   determinant (octave_idx_type& info, float& rcon,
@@ -242,7 +242,7 @@
   determinant (MatrixType& mattype, octave_idx_type& info,
                float& rcon, bool calc_cond = true) const;
 
-  OCTAVE_API float rcond (void) const;
+  OCTAVE_API float rcond () const;
   OCTAVE_API float rcond (MatrixType& mattype) const;
 
 private:
@@ -426,7 +426,7 @@
 
   // unary operations
 
-  OCTAVE_API boolMatrix operator ! (void) const;
+  OCTAVE_API boolMatrix operator ! () const;
 
   // other operations
 
@@ -438,7 +438,7 @@
   OCTAVE_API FloatComplexMatrix prod (int dim = -1) const;
   OCTAVE_API FloatComplexMatrix sum (int dim = -1) const;
   OCTAVE_API FloatComplexMatrix sumsq (int dim = -1) const;
-  OCTAVE_API FloatMatrix abs (void) const;
+  OCTAVE_API FloatMatrix abs () const;
 
   OCTAVE_API FloatComplexMatrix diag (octave_idx_type k = 0) const;
 
@@ -448,16 +448,16 @@
   OCTAVE_API bool row_is_real_only (octave_idx_type) const;
   OCTAVE_API bool column_is_real_only (octave_idx_type) const;
 
-  OCTAVE_API FloatComplexColumnVector row_min (void) const;
-  OCTAVE_API FloatComplexColumnVector row_max (void) const;
+  OCTAVE_API FloatComplexColumnVector row_min () const;
+  OCTAVE_API FloatComplexColumnVector row_max () const;
 
   OCTAVE_API FloatComplexColumnVector
   row_min (Array<octave_idx_type>& index) const;
   OCTAVE_API FloatComplexColumnVector
   row_max (Array<octave_idx_type>& index) const;
 
-  OCTAVE_API FloatComplexRowVector column_min (void) const;
-  OCTAVE_API FloatComplexRowVector column_max (void) const;
+  OCTAVE_API FloatComplexRowVector column_min () const;
+  OCTAVE_API FloatComplexRowVector column_max () const;
 
   OCTAVE_API FloatComplexRowVector
   column_min (Array<octave_idx_type>& index) const;
--- a/liboctave/array/fCNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -117,7 +117,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::fourier2d (void) const
+FloatComplexNDArray::fourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -137,7 +137,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::ifourier2d (void) const
+FloatComplexNDArray::ifourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -157,7 +157,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::fourierNd (void) const
+FloatComplexNDArray::fourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -172,7 +172,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::ifourierNd (void) const
+FloatComplexNDArray::ifourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -211,7 +211,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::fourier2d (void) const
+FloatComplexNDArray::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -220,7 +220,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::ifourier2d (void) const
+FloatComplexNDArray::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -229,7 +229,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::fourierNd (void) const
+FloatComplexNDArray::fourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -238,7 +238,7 @@
 }
 
 FloatComplexNDArray
-FloatComplexNDArray::ifourierNd (void) const
+FloatComplexNDArray::ifourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -251,7 +251,7 @@
 // unary operations
 
 boolNDArray
-FloatComplexNDArray::operator ! (void) const
+FloatComplexNDArray::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -262,13 +262,13 @@
 // FIXME: this is not quite the right thing.
 
 bool
-FloatComplexNDArray::any_element_is_nan (void) const
+FloatComplexNDArray::any_element_is_nan () const
 {
   return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);
 }
 
 bool
-FloatComplexNDArray::any_element_is_inf_or_nan (void) const
+FloatComplexNDArray::any_element_is_inf_or_nan () const
 {
   return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);
 }
@@ -276,7 +276,7 @@
 // Return true if no elements have imaginary components.
 
 bool
-FloatComplexNDArray::all_elements_are_real (void) const
+FloatComplexNDArray::all_elements_are_real () const
 {
   return do_mx_check<FloatComplex> (*this, mx_inline_all_real);
 }
@@ -337,7 +337,7 @@
 }
 
 bool
-FloatComplexNDArray::too_large_for_float (void) const
+FloatComplexNDArray::too_large_for_float () const
 {
   return false;
 }
@@ -487,25 +487,25 @@
 }
 
 FloatNDArray
-FloatComplexNDArray::abs (void) const
+FloatComplexNDArray::abs () const
 {
   return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
 }
 
 boolNDArray
-FloatComplexNDArray::isnan (void) const
+FloatComplexNDArray::isnan () const
 {
   return do_mx_unary_map<bool, FloatComplex, octave::math::isnan> (*this);
 }
 
 boolNDArray
-FloatComplexNDArray::isinf (void) const
+FloatComplexNDArray::isinf () const
 {
   return do_mx_unary_map<bool, FloatComplex, octave::math::isinf> (*this);
 }
 
 boolNDArray
-FloatComplexNDArray::isfinite (void) const
+FloatComplexNDArray::isfinite () const
 {
   return do_mx_unary_map<bool, FloatComplex, octave::math::isfinite> (*this);
 }
--- a/liboctave/array/fCNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  FloatComplexNDArray (void) : MArray<FloatComplex> () { }
+  FloatComplexNDArray () : MArray<FloatComplex> () { }
 
   FloatComplexNDArray (const dim_vector& dv) : MArray<FloatComplex> (dv) { }
 
@@ -63,17 +63,19 @@
     return *this;
   }
 
+  ~FloatComplexNDArray () = default;
+
   // unary operations
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
   // FIXME: this is not quite the right thing.
 
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool all_elements_are_real (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool all_elements_are_real () const;
   OCTAVE_API bool all_integers (float& max_val, float& min_val) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool too_large_for_float () const;
 
   OCTAVE_API boolNDArray all (int dim = -1) const;
   OCTAVE_API boolNDArray any (int dim = -1) const;
@@ -114,23 +116,23 @@
   OCTAVE_API FloatComplexNDArray&
   insert (const FloatComplexNDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  OCTAVE_API FloatNDArray abs (void) const;
-  OCTAVE_API boolNDArray isnan (void) const;
-  OCTAVE_API boolNDArray isinf (void) const;
-  OCTAVE_API boolNDArray isfinite (void) const;
+  OCTAVE_API FloatNDArray abs () const;
+  OCTAVE_API boolNDArray isnan () const;
+  OCTAVE_API boolNDArray isinf () const;
+  OCTAVE_API boolNDArray isfinite () const;
 
   friend OCTAVE_API FloatComplexNDArray conj (const FloatComplexNDArray& a);
 
   OCTAVE_API FloatComplexNDArray fourier (int dim = 1) const;
   OCTAVE_API FloatComplexNDArray ifourier (int dim = 1) const;
 
-  OCTAVE_API FloatComplexNDArray fourier2d (void) const;
-  OCTAVE_API FloatComplexNDArray ifourier2d (void) const;
+  OCTAVE_API FloatComplexNDArray fourier2d () const;
+  OCTAVE_API FloatComplexNDArray ifourier2d () const;
 
-  OCTAVE_API FloatComplexNDArray fourierNd (void) const;
-  OCTAVE_API FloatComplexNDArray ifourierNd (void) const;
+  OCTAVE_API FloatComplexNDArray fourierNd () const;
+  OCTAVE_API FloatComplexNDArray ifourierNd () const;
 
-  FloatComplexNDArray squeeze (void) const
+  FloatComplexNDArray squeeze () const
   { return MArray<FloatComplex>::squeeze (); }
 
   static OCTAVE_API void
@@ -147,7 +149,7 @@
   friend OCTAVE_API std::istream& operator >> (std::istream& is,
                                                FloatComplexNDArray& a);
 
-  //  bool all_elements_are_real (void) const;
+  //  bool all_elements_are_real () const;
   //  bool all_integers (float& max_val, float& min_val) const;
 
   OCTAVE_API FloatComplexNDArray diag (octave_idx_type k = 0) const;
@@ -155,7 +157,7 @@
   OCTAVE_API FloatComplexNDArray
   diag (octave_idx_type m, octave_idx_type n) const;
 
-  FloatComplexNDArray& changesign (void)
+  FloatComplexNDArray& changesign ()
   {
     MArray<FloatComplex>::changesign ();
     return *this;
--- a/liboctave/array/fCRowVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCRowVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -194,13 +194,13 @@
 }
 
 FloatComplexColumnVector
-FloatComplexRowVector::hermitian (void) const
+FloatComplexRowVector::hermitian () const
 {
   return MArray<FloatComplex>::hermitian (std::conj);
 }
 
 FloatComplexColumnVector
-FloatComplexRowVector::transpose (void) const
+FloatComplexRowVector::transpose () const
 {
   return MArray<FloatComplex>::transpose ();
 }
@@ -324,7 +324,7 @@
 // other operations
 
 FloatComplex
-FloatComplexRowVector::min (void) const
+FloatComplexRowVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -344,7 +344,7 @@
 }
 
 FloatComplex
-FloatComplexRowVector::max (void) const
+FloatComplexRowVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -438,6 +438,11 @@
       retval.resize (1, x2);
       return retval;
     }
+  else if (x1 == x2)
+    {
+      retval.resize (n_in, x2);
+      return retval;
+    }
 
   // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions
   // by 2 can be replaced by compiler with shift right instructions.
@@ -451,7 +456,17 @@
   retval.xelem (n-1) = x2;
 
   // Construct linspace symmetrically from both ends.
+  bool isnan_delta = false;
   FloatComplex delta = (x2 - x1) / (n - 1.0f);
+  if (octave::math::isinf (delta))
+    {
+      if (octave::math::isinf (delta.real ()))
+        delta.real (octave::numeric_limits<float>::NaN ());
+      if (octave::math::isinf (delta.imag ()))
+        delta.imag (octave::numeric_limits<float>::NaN ());
+      isnan_delta = true;
+    }
+
   unsigned_octave_idx_type n2 = n/2;
   for (unsigned_octave_idx_type i = 1; i < n2; i++)
     {
@@ -459,7 +474,22 @@
       retval.xelem (n-1-i) = x2 - static_cast<float> (i)*delta;
     }
   if (n % 2 == 1)  // Middle element if number of elements is odd.
-    retval.xelem (n2) = (x1 == -x2 ? 0 : (x1 + x2) / 2.0f);
+    {
+      if (x1 == -x2)
+        retval.xelem (n2) = 0;
+      else
+        {
+          FloatComplex c = (x1 + x2) / 2.0f;
+          if (isnan_delta)
+            {
+              if (octave::math::isnan (delta.real ()))
+                c.real (octave::numeric_limits<float>::NaN ());
+              if (octave::math::isnan (delta.imag ()))
+                c.imag (octave::numeric_limits<float>::NaN ());
+            }
+          retval.xelem (n2) = c;
+        }
+    }
 
   return retval;
 }
--- a/liboctave/array/fCRowVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fCRowVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 
 public:
 
-  FloatComplexRowVector (void)
+  FloatComplexRowVector ()
     : MArray<FloatComplex> (dim_vector (1, 0)) { }
 
   explicit FloatComplexRowVector (octave_idx_type n)
@@ -70,6 +70,8 @@
     return *this;
   }
 
+  ~FloatComplexRowVector () = default;
+
   OCTAVE_API bool operator == (const FloatComplexRowVector& a) const;
   OCTAVE_API bool operator != (const FloatComplexRowVector& a) const;
 
@@ -91,8 +93,8 @@
   OCTAVE_API FloatComplexRowVector
   append (const FloatComplexRowVector& a) const;
 
-  OCTAVE_API FloatComplexColumnVector hermitian (void) const;
-  OCTAVE_API FloatComplexColumnVector transpose (void) const;
+  OCTAVE_API FloatComplexColumnVector hermitian () const;
+  OCTAVE_API FloatComplexColumnVector transpose () const;
 
   friend OCTAVE_API FloatComplexRowVector
   conj (const FloatComplexRowVector& a);
@@ -120,8 +122,8 @@
 
   // other operations
 
-  OCTAVE_API FloatComplex min (void) const;
-  OCTAVE_API FloatComplex max (void) const;
+  OCTAVE_API FloatComplex min () const;
+  OCTAVE_API FloatComplex max () const;
 
   // i/o
 
--- a/liboctave/array/fColVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fColVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -122,13 +122,13 @@
 }
 
 FloatRowVector
-FloatColumnVector::transpose (void) const
+FloatColumnVector::transpose () const
 {
   return MArray<float>::transpose ();
 }
 
 FloatColumnVector
-FloatColumnVector::abs (void) const
+FloatColumnVector::abs () const
 {
   return do_mx_unary_map<float, float, std::abs> (*this);
 }
@@ -242,7 +242,7 @@
 // other operations
 
 float
-FloatColumnVector::min (void) const
+FloatColumnVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -258,7 +258,7 @@
 }
 
 float
-FloatColumnVector::max (void) const
+FloatColumnVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
--- a/liboctave/array/fColVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fColVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  FloatColumnVector (void) : MArray<float> (dim_vector (0, 1)) { }
+  FloatColumnVector () : MArray<float> (dim_vector (0, 1)) { }
 
   explicit FloatColumnVector (octave_idx_type n)
     : MArray<float> (dim_vector (n, 1)) { }
@@ -62,6 +62,8 @@
     return *this;
   }
 
+  ~FloatColumnVector () = default;
+
   OCTAVE_API bool operator == (const FloatColumnVector& a) const;
   OCTAVE_API bool operator != (const FloatColumnVector& a) const;
 
@@ -76,7 +78,7 @@
 
   OCTAVE_API FloatColumnVector stack (const FloatColumnVector& a) const;
 
-  OCTAVE_API FloatRowVector transpose (void) const;
+  OCTAVE_API FloatRowVector transpose () const;
 
   friend OCTAVE_API FloatColumnVector real (const FloatComplexColumnVector& a);
   friend OCTAVE_API FloatColumnVector imag (const FloatComplexColumnVector& a);
@@ -101,10 +103,10 @@
 
   // other operations
 
-  OCTAVE_API float min (void) const;
-  OCTAVE_API float max (void) const;
+  OCTAVE_API float min () const;
+  OCTAVE_API float max () const;
 
-  OCTAVE_API FloatColumnVector abs (void) const;
+  OCTAVE_API FloatColumnVector abs () const;
 
   // i/o
 
--- a/liboctave/array/fDiagMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fDiagMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -125,7 +125,7 @@
 }
 
 FloatDiagMatrix
-FloatDiagMatrix::abs (void) const
+FloatDiagMatrix::abs () const
 {
   return FloatDiagMatrix (extract_diag ().abs (), rows (), columns ());
 }
@@ -224,7 +224,7 @@
 }
 
 FloatDiagMatrix
-FloatDiagMatrix::inverse (void) const
+FloatDiagMatrix::inverse () const
 {
   octave_idx_type info;
   return inverse (info);
@@ -306,7 +306,7 @@
 // other operations
 
 FloatDET
-FloatDiagMatrix::determinant (void) const
+FloatDiagMatrix::determinant () const
 {
   FloatDET det (1.0f);
   if (rows () != cols ())
@@ -320,7 +320,7 @@
 }
 
 float
-FloatDiagMatrix::rcond (void) const
+FloatDiagMatrix::rcond () const
 {
   FloatColumnVector av = extract_diag (0).map<float> (fabsf);
   float amx = av.max ();
--- a/liboctave/array/fDiagMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fDiagMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,13 +42,13 @@
 
   typedef FloatMatrix full_matrix_type;
 
-  FloatDiagMatrix (void) = default;
+  FloatDiagMatrix () = default;
 
   FloatDiagMatrix (const FloatDiagMatrix& a) = default;
 
   FloatDiagMatrix& operator = (const FloatDiagMatrix& a) = default;
 
-  ~FloatDiagMatrix (void) = default;
+  ~FloatDiagMatrix () = default;
 
   FloatDiagMatrix (octave_idx_type r, octave_idx_type c)
     : MDiagArray2<float> (r, c) { }
@@ -79,10 +79,10 @@
   OCTAVE_API FloatDiagMatrix&
   fill (const FloatRowVector& a, octave_idx_type beg);
 
-  FloatDiagMatrix transpose (void) const
+  FloatDiagMatrix transpose () const
   { return MDiagArray2<float>::transpose (); }
 
-  OCTAVE_API FloatDiagMatrix abs (void) const;
+  OCTAVE_API FloatDiagMatrix abs () const;
 
   friend OCTAVE_API FloatDiagMatrix real (const FloatComplexDiagMatrix& a);
   friend OCTAVE_API FloatDiagMatrix imag (const FloatComplexDiagMatrix& a);
@@ -101,7 +101,7 @@
   OCTAVE_API FloatColumnVector column (octave_idx_type i) const;
   OCTAVE_API FloatColumnVector column (char *s) const;
 
-  OCTAVE_API FloatDiagMatrix inverse (void) const;
+  OCTAVE_API FloatDiagMatrix inverse () const;
   OCTAVE_API FloatDiagMatrix inverse (octave_idx_type& info) const;
   OCTAVE_API FloatDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
@@ -110,8 +110,8 @@
   FloatColumnVector extract_diag (octave_idx_type k = 0) const
   { return MDiagArray2<float>::extract_diag (k); }
 
-  OCTAVE_API FloatDET determinant (void) const;
-  OCTAVE_API float rcond (void) const;
+  OCTAVE_API FloatDET determinant () const;
+  OCTAVE_API float rcond () const;
 
   // i/o
 
--- a/liboctave/array/fMatrix.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fMatrix.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -135,7 +135,7 @@
 }
 
 bool
-FloatMatrix::issymmetric (void) const
+FloatMatrix::issymmetric () const
 {
   if (issquare () && rows () > 0)
     {
@@ -454,7 +454,7 @@
 }
 
 FloatMatrix
-FloatMatrix::inverse (void) const
+FloatMatrix::inverse () const
 {
   octave_idx_type info;
   float rcon;
@@ -737,7 +737,7 @@
 #if defined (HAVE_FFTW)
 
 FloatComplexMatrix
-FloatMatrix::fourier (void) const
+FloatMatrix::fourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -766,7 +766,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::ifourier (void) const
+FloatMatrix::ifourier () const
 {
   std::size_t nr = rows ();
   std::size_t nc = cols ();
@@ -796,7 +796,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::fourier2d (void) const
+FloatMatrix::fourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -808,7 +808,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::ifourier2d (void) const
+FloatMatrix::ifourier2d () const
 {
   dim_vector dv (rows (), cols ());
 
@@ -823,7 +823,7 @@
 #else
 
 FloatComplexMatrix
-FloatMatrix::fourier (void) const
+FloatMatrix::fourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -832,7 +832,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::ifourier (void) const
+FloatMatrix::ifourier () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -841,7 +841,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::fourier2d (void) const
+FloatMatrix::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -850,7 +850,7 @@
 }
 
 FloatComplexMatrix
-FloatMatrix::ifourier2d (void) const
+FloatMatrix::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -861,7 +861,7 @@
 #endif
 
 FloatDET
-FloatMatrix::determinant (void) const
+FloatMatrix::determinant () const
 {
   octave_idx_type info;
   float rcon;
@@ -1035,7 +1035,7 @@
 }
 
 float
-FloatMatrix::rcond (void) const
+FloatMatrix::rcond () const
 {
   MatrixType mattype (*this);
   return rcond (mattype);
@@ -2408,7 +2408,7 @@
 }
 
 FloatMatrix
-FloatMatrix::abs (void) const
+FloatMatrix::abs () const
 {
   return FloatNDArray::abs ();
 }
@@ -2436,7 +2436,7 @@
 }
 
 FloatColumnVector
-FloatMatrix::row_min (void) const
+FloatMatrix::row_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_min (dummy_idx);
@@ -2491,7 +2491,7 @@
 }
 
 FloatColumnVector
-FloatMatrix::row_max (void) const
+FloatMatrix::row_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return row_max (dummy_idx);
@@ -2546,7 +2546,7 @@
 }
 
 FloatRowVector
-FloatMatrix::column_min (void) const
+FloatMatrix::column_min () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_min (dummy_idx);
@@ -2601,7 +2601,7 @@
 }
 
 FloatRowVector
-FloatMatrix::column_max (void) const
+FloatMatrix::column_max () const
 {
   Array<octave_idx_type> dummy_idx;
   return column_max (dummy_idx);
@@ -3035,19 +3035,7 @@
 
   retval.clear (m, n);
   for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, 0) = x1(i);
-
-  // The last column is unused so temporarily store delta there
-  float *delta = &retval.xelem (0, n-1);
-  for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1);
-
-  for (octave_idx_type j = 1; j < n-1; j++)
-    for (octave_idx_type i = 0; i < m; i++)
-      retval.xelem (i, j) = x1(i) + j*delta[i];
-
-  for (octave_idx_type i = 0; i < m; i++)
-    retval.xelem (i, n-1) = x2(i);
+    retval.insert (linspace (x1(i), x2(i), n), i, 0);
 
   return retval;
 }
--- a/liboctave/array/fMatrix.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fMatrix.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,13 +59,13 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatMatrix (void) = default;
+  FloatMatrix () = default;
 
   FloatMatrix (const FloatMatrix& a) = default;
 
   FloatMatrix& operator = (const FloatMatrix& a) = default;
 
-  ~FloatMatrix (void) = default;
+  ~FloatMatrix () = default;
 
   FloatMatrix (octave_idx_type r, octave_idx_type c)
     : FloatNDArray (dim_vector (r, c)) { }
@@ -103,7 +103,7 @@
   OCTAVE_API bool operator == (const FloatMatrix& a) const;
   OCTAVE_API bool operator != (const FloatMatrix& a) const;
 
-  OCTAVE_API bool issymmetric (void) const;
+  OCTAVE_API bool issymmetric () const;
 
   // destructive insert/delete/reorder operations
 
@@ -136,8 +136,8 @@
 
   friend class FloatComplexMatrix;
 
-  FloatMatrix hermitian (void) const { return MArray<float>::transpose (); }
-  FloatMatrix transpose (void) const { return MArray<float>::transpose (); }
+  FloatMatrix hermitian () const { return MArray<float>::transpose (); }
+  FloatMatrix transpose () const { return MArray<float>::transpose (); }
 
   // resize is the destructive equivalent for this one
 
@@ -168,7 +168,7 @@
                         float& rcon, bool force, bool calc_cond) const;
 
 public:
-  OCTAVE_API FloatMatrix inverse (void) const;
+  OCTAVE_API FloatMatrix inverse () const;
   OCTAVE_API FloatMatrix inverse (octave_idx_type& info) const;
   OCTAVE_API FloatMatrix
   inverse (octave_idx_type& info, float& rcon, bool force = false,
@@ -183,13 +183,13 @@
 
   OCTAVE_API FloatMatrix pseudo_inverse (float tol = 0.0) const;
 
-  OCTAVE_API FloatComplexMatrix fourier (void) const;
-  OCTAVE_API FloatComplexMatrix ifourier (void) const;
+  OCTAVE_API FloatComplexMatrix fourier () const;
+  OCTAVE_API FloatComplexMatrix ifourier () const;
 
-  OCTAVE_API FloatComplexMatrix fourier2d (void) const;
-  OCTAVE_API FloatComplexMatrix ifourier2d (void) const;
+  OCTAVE_API FloatComplexMatrix fourier2d () const;
+  OCTAVE_API FloatComplexMatrix ifourier2d () const;
 
-  OCTAVE_API FloatDET determinant (void) const;
+  OCTAVE_API FloatDET determinant () const;
   OCTAVE_API FloatDET determinant (octave_idx_type& info) const;
   OCTAVE_API FloatDET
   determinant (octave_idx_type& info, float& rcon,
@@ -198,7 +198,7 @@
   determinant (MatrixType& mattype, octave_idx_type& info, float& rcon,
                bool calc_cond = true) const;
 
-  OCTAVE_API float rcond (void) const;
+  OCTAVE_API float rcond () const;
   OCTAVE_API float rcond (MatrixType& mattype) const;
 
 private:
@@ -374,20 +374,20 @@
   OCTAVE_API FloatMatrix prod (int dim = -1) const;
   OCTAVE_API FloatMatrix sum (int dim = -1) const;
   OCTAVE_API FloatMatrix sumsq (int dim = -1) const;
-  OCTAVE_API FloatMatrix abs (void) const;
+  OCTAVE_API FloatMatrix abs () const;
 
   OCTAVE_API FloatMatrix diag (octave_idx_type k = 0) const;
 
   OCTAVE_API FloatDiagMatrix diag (octave_idx_type m, octave_idx_type n) const;
 
-  OCTAVE_API FloatColumnVector row_min (void) const;
-  OCTAVE_API FloatColumnVector row_max (void) const;
+  OCTAVE_API FloatColumnVector row_min () const;
+  OCTAVE_API FloatColumnVector row_max () const;
 
   OCTAVE_API FloatColumnVector row_min (Array<octave_idx_type>& index) const;
   OCTAVE_API FloatColumnVector row_max (Array<octave_idx_type>& index) const;
 
-  OCTAVE_API FloatRowVector column_min (void) const;
-  OCTAVE_API FloatRowVector column_max (void) const;
+  OCTAVE_API FloatRowVector column_min () const;
+  OCTAVE_API FloatRowVector column_max () const;
 
   OCTAVE_API FloatRowVector column_min (Array<octave_idx_type>& index) const;
   OCTAVE_API FloatRowVector column_max (Array<octave_idx_type>& index) const;
--- a/liboctave/array/fNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -116,7 +116,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::fourier2d (void) const
+FloatNDArray::fourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -136,7 +136,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::ifourier2d (void) const
+FloatNDArray::ifourier2d () const
 {
   dim_vector dv = dims ();
   if (dv.ndims () < 2)
@@ -155,7 +155,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::fourierNd (void) const
+FloatNDArray::fourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -170,7 +170,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::ifourierNd (void) const
+FloatNDArray::ifourierNd () const
 {
   dim_vector dv = dims ();
   int rank = dv.ndims ();
@@ -209,7 +209,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::fourier2d (void) const
+FloatNDArray::fourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -218,7 +218,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::ifourier2d (void) const
+FloatNDArray::ifourier2d () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -227,7 +227,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::fourierNd (void) const
+FloatNDArray::fourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -236,7 +236,7 @@
 }
 
 FloatComplexNDArray
-FloatNDArray::ifourierNd (void) const
+FloatNDArray::ifourierNd () const
 {
   (*current_liboctave_error_handler)
     ("support for FFTW was unavailable or disabled when liboctave was built");
@@ -249,7 +249,7 @@
 // unary operations
 
 boolNDArray
-FloatNDArray::operator ! (void) const
+FloatNDArray::operator ! () const
 {
   if (any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -272,31 +272,31 @@
 }
 
 bool
-FloatNDArray::any_element_is_nan (void) const
+FloatNDArray::any_element_is_nan () const
 {
   return do_mx_check<float> (*this, mx_inline_any_nan);
 }
 
 bool
-FloatNDArray::any_element_is_inf_or_nan (void) const
+FloatNDArray::any_element_is_inf_or_nan () const
 {
   return ! do_mx_check<float> (*this, mx_inline_all_finite);
 }
 
 bool
-FloatNDArray::any_element_not_one_or_zero (void) const
+FloatNDArray::any_element_not_one_or_zero () const
 {
   return ! test_all (octave::is_one_or_zero);
 }
 
 bool
-FloatNDArray::all_elements_are_zero (void) const
+FloatNDArray::all_elements_are_zero () const
 {
   return test_all (octave::is_zero);
 }
 
 bool
-FloatNDArray::all_elements_are_int_or_inf_or_nan (void) const
+FloatNDArray::all_elements_are_int_or_inf_or_nan () const
 {
   return test_all (octave::is_int_or_inf_or_nan);
 }
@@ -335,13 +335,13 @@
 }
 
 bool
-FloatNDArray::all_integers (void) const
+FloatNDArray::all_integers () const
 {
   return test_all (octave::math::isinteger);
 }
 
 bool
-FloatNDArray::too_large_for_float (void) const
+FloatNDArray::too_large_for_float () const
 {
   return false;
 }
@@ -535,25 +535,25 @@
 }
 
 FloatNDArray
-FloatNDArray::abs (void) const
+FloatNDArray::abs () const
 {
   return do_mx_unary_map<float, float, std::abs> (*this);
 }
 
 boolNDArray
-FloatNDArray::isnan (void) const
+FloatNDArray::isnan () const
 {
   return do_mx_unary_map<bool, float, octave::math::isnan> (*this);
 }
 
 boolNDArray
-FloatNDArray::isinf (void) const
+FloatNDArray::isinf () const
 {
   return do_mx_unary_map<bool, float, octave::math::isinf> (*this);
 }
 
 boolNDArray
-FloatNDArray::isfinite (void) const
+FloatNDArray::isfinite () const
 {
   return do_mx_unary_map<bool, float, octave::math::isfinite> (*this);
 }
--- a/liboctave/array/fNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 public:
 
-  FloatNDArray (void) : MArray<float> () { }
+  FloatNDArray () : MArray<float> () { }
 
   FloatNDArray (const dim_vector& dv) : MArray<float> (dv) { }
 
@@ -66,20 +66,22 @@
     return *this;
   }
 
+  ~FloatNDArray () = default;
+
   // unary operations
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
   OCTAVE_API bool any_element_is_negative (bool = false) const;
   OCTAVE_API bool any_element_is_positive (bool = false) const;
-  OCTAVE_API bool any_element_is_nan (void) const;
-  OCTAVE_API bool any_element_is_inf_or_nan (void) const;
-  OCTAVE_API bool any_element_not_one_or_zero (void) const;
-  OCTAVE_API bool all_elements_are_zero (void) const;
-  OCTAVE_API bool all_elements_are_int_or_inf_or_nan (void) const;
+  OCTAVE_API bool any_element_is_nan () const;
+  OCTAVE_API bool any_element_is_inf_or_nan () const;
+  OCTAVE_API bool any_element_not_one_or_zero () const;
+  OCTAVE_API bool all_elements_are_zero () const;
+  OCTAVE_API bool all_elements_are_int_or_inf_or_nan () const;
   OCTAVE_API bool all_integers (float& max_val, float& min_val) const;
-  OCTAVE_API bool all_integers (void) const;
-  OCTAVE_API bool too_large_for_float (void) const;
+  OCTAVE_API bool all_integers () const;
+  OCTAVE_API bool too_large_for_float () const;
 
   // FIXME: this is not quite the right thing.
 
@@ -121,26 +123,26 @@
   OCTAVE_API FloatNDArray&
   insert (const FloatNDArray& a, const Array<octave_idx_type>& ra_idx);
 
-  OCTAVE_API FloatNDArray abs (void) const;
-  OCTAVE_API boolNDArray isnan (void) const;
-  OCTAVE_API boolNDArray isinf (void) const;
-  OCTAVE_API boolNDArray isfinite (void) const;
+  OCTAVE_API FloatNDArray abs () const;
+  OCTAVE_API boolNDArray isnan () const;
+  OCTAVE_API boolNDArray isinf () const;
+  OCTAVE_API boolNDArray isfinite () const;
 
   OCTAVE_API FloatComplexNDArray fourier (int dim = 1) const;
   OCTAVE_API FloatComplexNDArray ifourier (int dim = 1) const;
 
-  OCTAVE_API FloatComplexNDArray fourier2d (void) const;
-  OCTAVE_API FloatComplexNDArray ifourier2d (void) const;
+  OCTAVE_API FloatComplexNDArray fourier2d () const;
+  OCTAVE_API FloatComplexNDArray ifourier2d () const;
 
-  OCTAVE_API FloatComplexNDArray fourierNd (void) const;
-  OCTAVE_API FloatComplexNDArray ifourierNd (void) const;
+  OCTAVE_API FloatComplexNDArray fourierNd () const;
+  OCTAVE_API FloatComplexNDArray ifourierNd () const;
 
   friend OCTAVE_API FloatNDArray real (const FloatComplexNDArray& a);
   friend OCTAVE_API FloatNDArray imag (const FloatComplexNDArray& a);
 
   friend class FloatComplexNDArray;
 
-  FloatNDArray squeeze (void) const { return MArray<float>::squeeze (); }
+  FloatNDArray squeeze () const { return MArray<float>::squeeze (); }
 
   static OCTAVE_API void
   increment_index (Array<octave_idx_type>& ra_idx,
@@ -160,7 +162,7 @@
 
   OCTAVE_API FloatNDArray diag (octave_idx_type m, octave_idx_type n) const;
 
-  FloatNDArray& changesign (void)
+  FloatNDArray& changesign ()
   {
     MArray<float>::changesign ();
     return *this;
--- a/liboctave/array/fRowVector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fRowVector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -123,7 +123,7 @@
 }
 
 FloatColumnVector
-FloatRowVector::transpose (void) const
+FloatRowVector::transpose () const
 {
   return MArray<float>::transpose ();
 }
@@ -204,7 +204,7 @@
 // other operations
 
 float
-FloatRowVector::min (void) const
+FloatRowVector::min () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -220,7 +220,7 @@
 }
 
 float
-FloatRowVector::max (void) const
+FloatRowVector::max () const
 {
   octave_idx_type len = numel ();
   if (len == 0)
@@ -279,6 +279,11 @@
       retval.resize (1, x2);
       return retval;
     }
+  else if (x1 == x2)
+    {
+      retval.resize (n_in, x2);
+      return retval;
+    }
 
   // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions
   // by 2 can be replaced by compiler with shift right instructions.
@@ -292,7 +297,14 @@
   retval.xelem (n-1) = x2;
 
   // Construct linspace symmetrically from both ends.
+  bool isnan_delta = false;
   float delta = (x2 - x1) / (n - 1);
+  if (octave::math::isinf (delta))
+    {
+      delta = octave::numeric_limits<float>::NaN ();
+      isnan_delta = true;
+    }
+
   unsigned_octave_idx_type n2 = n/2;
   for (unsigned_octave_idx_type i = 1; i < n2; i++)
     {
@@ -300,7 +312,14 @@
       retval.xelem (n-1-i) = x2 - i*delta;
     }
   if (n % 2 == 1)  // Middle element if number of elements is odd.
-    retval.xelem (n2) = (x1 == -x2 ? 0 : (x1 + x2) / 2);
+    {
+      if (x1 == -x2)
+        retval.xelem (n2) = 0;
+      else if (isnan_delta)
+        retval.xelem (n2) = octave::numeric_limits<float>::NaN ();
+      else
+        retval.xelem (n2) = (x1 + x2) / 2;
+    }
 
   return retval;
 }
--- a/liboctave/array/fRowVector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/fRowVector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  FloatRowVector (void) : MArray<float> (dim_vector (1, 0)) { }
+  FloatRowVector () : MArray<float> (dim_vector (1, 0)) { }
 
   explicit FloatRowVector (octave_idx_type n)
     : MArray<float> (dim_vector (1, n)) { }
@@ -60,6 +60,8 @@
     return *this;
   }
 
+  ~FloatRowVector () = default;
+
   OCTAVE_API bool operator == (const FloatRowVector& a) const;
   OCTAVE_API bool operator != (const FloatRowVector& a) const;
 
@@ -74,7 +76,7 @@
 
   OCTAVE_API FloatRowVector append (const FloatRowVector& a) const;
 
-  OCTAVE_API FloatColumnVector transpose (void) const;
+  OCTAVE_API FloatColumnVector transpose () const;
 
   friend OCTAVE_API FloatRowVector real (const FloatComplexRowVector& a);
   friend OCTAVE_API FloatRowVector imag (const FloatComplexRowVector& a);
@@ -94,8 +96,8 @@
 
   // other operations
 
-  OCTAVE_API float min (void) const;
-  OCTAVE_API float max (void) const;
+  OCTAVE_API float min () const;
+  OCTAVE_API float max () const;
 
   // i/o
 
--- a/liboctave/array/idx-vector.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/idx-vector.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,24 +44,24 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-OCTAVE_NORETURN static void err_invalid_range (void)
+OCTAVE_NORETURN static void err_invalid_range ()
 {
   (*current_liboctave_error_handler) ("invalid range used as index");
 }
 
-OCTAVE_NORETURN static void err_index_out_of_range (void)
+OCTAVE_NORETURN static void err_index_out_of_range ()
 {
   (*current_liboctave_error_handler)
     ("internal error: idx_vector index out of range");
 }
 
-idx_vector::idx_vector_rep *idx_vector::nil_rep (void)
+idx_vector::idx_vector_rep *idx_vector::nil_rep ()
 {
   static idx_vector_rep ivr;
   return &ivr;
 }
 
-Array<octave_idx_type> idx_vector::idx_base_rep::as_array (void)
+Array<octave_idx_type> idx_vector::idx_base_rep::as_array ()
 {
   (*current_liboctave_error_handler)
     ("internal error: as_array not allowed for this index class");
@@ -191,13 +191,13 @@
   return os;
 }
 
-range<double> idx_vector::idx_range_rep::unconvert (void) const
+range<double> idx_vector::idx_range_rep::unconvert () const
 {
   return range<double>::make_n_element_range
          (static_cast<double> (m_start+1), static_cast<double> (m_step), m_len);
 }
 
-Array<octave_idx_type> idx_vector::idx_range_rep::as_array (void)
+Array<octave_idx_type> idx_vector::idx_range_rep::as_array ()
 {
   Array<octave_idx_type> retval (dim_vector (1, m_len));
   for (octave_idx_type i = 0; i < m_len; i++)
@@ -279,12 +279,12 @@
   return os << m_data;
 }
 
-double idx_vector::idx_scalar_rep::unconvert (void) const
+double idx_vector::idx_scalar_rep::unconvert () const
 {
   return m_data + 1;
 }
 
-Array<octave_idx_type> idx_vector::idx_scalar_rep::as_array (void)
+Array<octave_idx_type> idx_vector::idx_scalar_rep::as_array ()
 {
   return Array<octave_idx_type> (dim_vector (1, 1), m_data);
 }
@@ -414,7 +414,7 @@
     }
 }
 
-idx_vector::idx_vector_rep::~idx_vector_rep (void)
+idx_vector::idx_vector_rep::~idx_vector_rep ()
 {
   if (m_aowner)
     delete m_aowner;
@@ -581,7 +581,7 @@
   return os;
 }
 
-Array<double> idx_vector::idx_vector_rep::unconvert (void) const
+Array<double> idx_vector::idx_vector_rep::unconvert () const
 {
   Array<double> retval (m_orig_dims);
   for (octave_idx_type i = 0; i < m_len; i++)
@@ -589,7 +589,7 @@
   return retval;
 }
 
-Array<octave_idx_type> idx_vector::idx_vector_rep::as_array (void)
+Array<octave_idx_type> idx_vector::idx_vector_rep::as_array ()
 {
   if (m_aowner)
     return *m_aowner;
@@ -645,7 +645,7 @@
   m_data = bnda.data ();
 }
 
-idx_vector::idx_mask_rep::~idx_mask_rep (void)
+idx_vector::idx_mask_rep::~idx_mask_rep ()
 {
   if (m_aowner)
     delete m_aowner;
@@ -693,7 +693,7 @@
   return os;
 }
 
-Array<bool> idx_vector::idx_mask_rep::unconvert (void) const
+Array<bool> idx_vector::idx_mask_rep::unconvert () const
 {
   if (m_aowner)
     return *m_aowner;
@@ -706,7 +706,7 @@
     }
 }
 
-Array<octave_idx_type> idx_vector::idx_mask_rep::as_array (void)
+Array<octave_idx_type> idx_vector::idx_mask_rep::as_array ()
 {
   if (m_aowner)
     return m_aowner->find ().reshape (m_orig_dims);
@@ -967,7 +967,7 @@
   return res;
 }
 
-octave_idx_type idx_vector::increment (void) const
+octave_idx_type idx_vector::increment () const
 {
   octave_idx_type retval = 0;
 
@@ -996,7 +996,7 @@
   return retval;
 }
 
-const octave_idx_type *idx_vector::raw (void)
+const octave_idx_type *idx_vector::raw ()
 {
   if (m_rep->idx_class () != class_vector)
     *this = idx_vector (as_array (), extent (0));
@@ -1157,7 +1157,7 @@
   return retval;
 }
 
-idx_vector idx_vector::unmask (void) const
+idx_vector idx_vector::unmask () const
 {
   if (idx_class () == class_mask)
     {
@@ -1224,12 +1224,12 @@
     }
 }
 
-Array<octave_idx_type> idx_vector::as_array (void) const
+Array<octave_idx_type> idx_vector::as_array () const
 {
   return m_rep->as_array ();
 }
 
-bool idx_vector::isvector (void) const
+bool idx_vector::isvector () const
 {
   return idx_class () != class_vector || orig_dimensions ().isvector ();
 }
--- a/liboctave/array/idx-vector.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/idx-vector.h	Fri Jun 23 20:51:51 2023 +0200
@@ -78,15 +78,11 @@
   {
   public:
 
-    idx_base_rep (void) : m_count (1) { }
-
-    // No copying!
+    idx_base_rep () : m_count (1) { }
 
-    idx_base_rep (const idx_base_rep&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (idx_base_rep)
 
-    idx_base_rep& operator = (const idx_base_rep&) = delete;
-
-    virtual ~idx_base_rep (void) = default;
+    virtual ~idx_base_rep () = default;
 
     // Non-range-checking element query.
     virtual octave_idx_type xelem (octave_idx_type i) const = 0;
@@ -101,7 +97,7 @@
     virtual octave_idx_type extent (octave_idx_type n) const = 0;
 
     // Index class.
-    virtual idx_class_type idx_class (void) const { return class_invalid; }
+    virtual idx_class_type idx_class () const { return class_invalid; }
 
     // Sorts, maybe uniqifies, and returns a clone object pointer.
     virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0;
@@ -112,12 +108,12 @@
     virtual bool is_colon_equiv (octave_idx_type) const { return false; }
 
     // The original dimensions of object (used when subscribing by matrices).
-    virtual dim_vector orig_dimensions (void) const { return dim_vector (); }
+    virtual dim_vector orig_dimensions () const { return dim_vector (); }
 
     // i/o
     virtual std::ostream& print (std::ostream& os) const = 0;
 
-    virtual Array<octave_idx_type> as_array (void);
+    virtual Array<octave_idx_type> as_array ();
 
     refcount<octave_idx_type> m_count;
   };
@@ -127,15 +123,13 @@
   {
   public:
 
-    idx_colon_rep (void) = default;
+    idx_colon_rep () = default;
 
     OCTAVE_API idx_colon_rep (char c);
 
-    // No copying!
+    OCTAVE_DISABLE_COPY_MOVE (idx_colon_rep)
 
-    idx_colon_rep (const idx_colon_rep& idx) = delete;
-
-    idx_colon_rep& operator = (const idx_colon_rep& idx) = delete;
+    ~idx_colon_rep () = default;
 
     octave_idx_type xelem (octave_idx_type i) const { return i; }
 
@@ -145,7 +139,7 @@
 
     octave_idx_type extent (octave_idx_type n) const { return n; }
 
-    idx_class_type idx_class (void) const { return class_colon; }
+    idx_class_type idx_class () const { return class_colon; }
 
     idx_base_rep * sort_uniq_clone (bool = false)
     { m_count++; return this; }
@@ -165,7 +159,7 @@
   {
   public:
 
-    idx_range_rep (void) = delete;
+    idx_range_rep () = delete;
 
     idx_range_rep (octave_idx_type start, octave_idx_type len,
                    octave_idx_type step, direct)
@@ -178,11 +172,9 @@
 
     OCTAVE_API idx_range_rep (const range<double>&);
 
-    // No copying!
+    OCTAVE_DISABLE_COPY_MOVE (idx_range_rep)
 
-    idx_range_rep (const idx_range_rep& idx) = delete;
-
-    idx_range_rep& operator = (const idx_range_rep& idx) = delete;
+    ~idx_range_rep () = default;
 
     octave_idx_type xelem (octave_idx_type i) const
     { return m_start + i * m_step; }
@@ -196,7 +188,7 @@
       return m_len ? std::max (n, m_start + 1 + (m_step < 0 ? 0 : m_step * (m_len - 1))) : n;
     }
 
-    idx_class_type idx_class (void) const { return class_range; }
+    idx_class_type idx_class () const { return class_range; }
 
     OCTAVE_API idx_base_rep * sort_uniq_clone (bool uniq = false);
 
@@ -205,18 +197,18 @@
     bool is_colon_equiv (octave_idx_type n) const
     { return m_start == 0 && m_step == 1 && m_len == n; }
 
-    dim_vector orig_dimensions (void) const
+    dim_vector orig_dimensions () const
     { return dim_vector (1, m_len); }
 
-    octave_idx_type get_start (void) const { return m_start; }
+    octave_idx_type get_start () const { return m_start; }
 
-    octave_idx_type get_step (void) const { return m_step; }
+    octave_idx_type get_step () const { return m_step; }
 
     OCTAVE_API std::ostream& print (std::ostream& os) const;
 
-    OCTAVE_API range<double> unconvert (void) const;
+    OCTAVE_API range<double> unconvert () const;
 
-    OCTAVE_API Array<octave_idx_type> as_array (void);
+    OCTAVE_API Array<octave_idx_type> as_array ();
 
   private:
 
@@ -228,15 +220,13 @@
   {
   public:
 
-    idx_scalar_rep (void) = delete;
+    idx_scalar_rep () = delete;
 
     idx_scalar_rep (octave_idx_type i, direct) : idx_base_rep (), m_data (i) { }
 
-    // No copying!
+    OCTAVE_DISABLE_COPY_MOVE (idx_scalar_rep)
 
-    idx_scalar_rep (const idx_scalar_rep& idx) = delete;
-
-    idx_scalar_rep& operator = (const idx_scalar_rep& idx) = delete;
+    ~idx_scalar_rep () = default;
 
     // Zero-based constructor.
     OCTAVE_API idx_scalar_rep (octave_idx_type i);
@@ -253,7 +243,7 @@
     octave_idx_type extent (octave_idx_type n) const
     { return std::max (n, m_data + 1); }
 
-    idx_class_type idx_class (void) const { return class_scalar; }
+    idx_class_type idx_class () const { return class_scalar; }
 
     idx_base_rep * sort_uniq_clone (bool = false)
     { m_count++; return this; }
@@ -263,15 +253,15 @@
     bool is_colon_equiv (octave_idx_type n) const
     { return n == 1 && m_data == 0; }
 
-    dim_vector orig_dimensions (void) const { return dim_vector (1, 1); }
+    dim_vector orig_dimensions () const { return dim_vector (1, 1); }
 
-    octave_idx_type get_data (void) const { return m_data; }
+    octave_idx_type get_data () const { return m_data; }
 
     OCTAVE_API std::ostream& print (std::ostream& os) const;
 
-    OCTAVE_API double unconvert (void) const;
+    OCTAVE_API double unconvert () const;
 
-    OCTAVE_API Array<octave_idx_type> as_array (void);
+    OCTAVE_API Array<octave_idx_type> as_array ();
 
   private:
 
@@ -283,7 +273,7 @@
   {
   public:
 
-    idx_vector_rep (void)
+    idx_vector_rep ()
       : m_data (nullptr), m_len (0), m_ext (0), m_aowner (nullptr), m_orig_dims () { }
 
     // Direct constructor.
@@ -308,13 +298,9 @@
 
     OCTAVE_API idx_vector_rep (const Sparse<bool>&);
 
-    // No copying!
-
-    idx_vector_rep (const idx_vector_rep& idx) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (idx_vector_rep)
 
-    idx_vector_rep& operator = (const idx_vector_rep& idx) = delete;
-
-    ~idx_vector_rep (void);
+    ~idx_vector_rep ();
 
     octave_idx_type xelem (octave_idx_type i) const { return m_data[i]; }
 
@@ -325,21 +311,21 @@
     octave_idx_type extent (octave_idx_type n) const
     { return std::max (n, m_ext); }
 
-    idx_class_type idx_class (void) const { return class_vector; }
+    idx_class_type idx_class () const { return class_vector; }
 
     idx_base_rep * sort_uniq_clone (bool uniq = false);
 
     OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);
 
-    dim_vector orig_dimensions (void) const { return m_orig_dims; }
+    dim_vector orig_dimensions () const { return m_orig_dims; }
 
-    const octave_idx_type * get_data (void) const { return m_data; }
+    const octave_idx_type * get_data () const { return m_data; }
 
     OCTAVE_API std::ostream& print (std::ostream& os) const;
 
-    OCTAVE_API Array<double> unconvert (void) const;
+    OCTAVE_API Array<double> unconvert () const;
 
-    OCTAVE_API Array<octave_idx_type> as_array (void);
+    OCTAVE_API Array<octave_idx_type> as_array ();
 
   private:
 
@@ -364,7 +350,7 @@
   {
   public:
 
-    idx_mask_rep (void) = delete;
+    idx_mask_rep () = delete;
 
     // Direct constructor.
     idx_mask_rep (bool *data, octave_idx_type len,
@@ -377,13 +363,9 @@
 
     OCTAVE_API idx_mask_rep (const Array<bool>&, octave_idx_type = -1);
 
-    // No copying!
-
-    idx_mask_rep (const idx_mask_rep& idx) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (idx_mask_rep)
 
-    idx_mask_rep& operator = (const idx_mask_rep& idx) = delete;
-
-    OCTAVE_API ~idx_mask_rep (void);
+    OCTAVE_API ~idx_mask_rep ();
 
     octave_idx_type xelem (octave_idx_type i) const;
 
@@ -394,25 +376,25 @@
     octave_idx_type extent (octave_idx_type n) const
     { return std::max (n, m_ext); }
 
-    idx_class_type idx_class (void) const { return class_mask; }
+    idx_class_type idx_class () const { return class_mask; }
 
     idx_base_rep * sort_uniq_clone (bool = false)
     { m_count++; return this; }
 
     OCTAVE_API idx_base_rep * sort_idx (Array<octave_idx_type>&);
 
-    dim_vector orig_dimensions (void) const { return m_orig_dims; }
+    dim_vector orig_dimensions () const { return m_orig_dims; }
 
     bool is_colon_equiv (octave_idx_type n) const
     { return m_len == n && m_ext == n; }
 
-    const bool * get_data (void) const { return m_data; }
+    const bool * get_data () const { return m_data; }
 
     OCTAVE_API std::ostream& print (std::ostream& os) const;
 
-    OCTAVE_API Array<bool> unconvert (void) const;
+    OCTAVE_API Array<bool> unconvert () const;
 
-    OCTAVE_API Array<octave_idx_type> as_array (void);
+    OCTAVE_API Array<octave_idx_type> as_array ();
 
   private:
 
@@ -441,12 +423,12 @@
 
   // The shared empty vector representation (for fast default
   // constructor).
-  static OCTAVE_API idx_vector_rep * nil_rep (void);
+  static OCTAVE_API idx_vector_rep * nil_rep ();
 
 public:
 
   // Fast empty constructor.
-  idx_vector (void) : m_rep (nil_rep ()) { m_rep->m_count++; }
+  idx_vector () : m_rep (nil_rep ()) { m_rep->m_count++; }
 
   // Zero-based constructors (for use from C++).
   idx_vector (octave_idx_type i) : m_rep (new idx_scalar_rep (i)) { }
@@ -514,7 +496,7 @@
 
   idx_vector (const idx_vector& a) : m_rep (a.m_rep) { m_rep->m_count++; }
 
-  ~idx_vector (void)
+  ~idx_vector ()
   {
     if (--m_rep->m_count == 0 && m_rep != nil_rep ())
       delete m_rep;
@@ -533,7 +515,7 @@
     return *this;
   }
 
-  idx_class_type idx_class (void) const { return m_rep->idx_class (); }
+  idx_class_type idx_class () const { return m_rep->idx_class (); }
 
   octave_idx_type length (octave_idx_type n = 0) const
   { return m_rep->length (n); }
@@ -552,15 +534,16 @@
 
   // FIXME: idx_vector objects are either created successfully or an
   // error is thrown, so this method no longer makes sense.
-  operator bool (void) const { return true; }
+  OCTAVE_DEPRECATED (9, "idx_vector::bool () is obsolete and always returns true")
+  operator bool () const { return true; }
 
-  bool is_colon (void) const
+  bool is_colon () const
   { return m_rep->idx_class () == class_colon; }
 
-  bool is_scalar (void) const
+  bool is_scalar () const
   { return m_rep->idx_class () == class_scalar; }
 
-  bool is_range (void) const
+  bool is_range () const
   { return m_rep->idx_class () == class_range; }
 
   bool is_colon_equiv (octave_idx_type n) const
@@ -572,15 +555,15 @@
   idx_vector sorted (Array<octave_idx_type>& sidx) const
   { return idx_vector (m_rep->sort_idx (sidx)); }
 
-  dim_vector orig_dimensions (void) const { return m_rep->orig_dimensions (); }
+  dim_vector orig_dimensions () const { return m_rep->orig_dimensions (); }
 
-  octave_idx_type orig_rows (void) const
+  octave_idx_type orig_rows () const
   { return orig_dimensions () (0); }
 
-  octave_idx_type orig_columns (void) const
+  octave_idx_type orig_columns () const
   { return orig_dimensions () (1); }
 
-  int orig_empty (void) const
+  int orig_empty () const
   { return (! is_colon () && orig_dimensions ().any_zero ()); }
 
   // i/o
@@ -976,7 +959,7 @@
 
   // Returns the increment for ranges and colon, 0 for scalars and empty
   // vectors, 1st difference otherwise.
-  OCTAVE_API octave_idx_type increment (void) const;
+  OCTAVE_API octave_idx_type increment () const;
 
   OCTAVE_API idx_vector
   complement (octave_idx_type n) const;
@@ -991,20 +974,20 @@
   OCTAVE_API void copy_data (octave_idx_type *data) const;
 
   // If the index is a mask, convert it to index vector.
-  OCTAVE_API idx_vector unmask (void) const;
+  OCTAVE_API idx_vector unmask () const;
 
   // Unconverts the index to a scalar, Range, double array or a mask.
   OCTAVE_API void
   unconvert (idx_class_type& iclass, double& scalar, range<double>& range,
              Array<double>& array, Array<bool>& mask) const;
 
-  OCTAVE_API Array<octave_idx_type> as_array (void) const;
+  OCTAVE_API Array<octave_idx_type> as_array () const;
 
   // Raw pointer to index array.  This is non-const because it may be
   // necessary to mutate the index.
-  const OCTAVE_API octave_idx_type * raw (void);
+  const OCTAVE_API octave_idx_type * raw ();
 
-  OCTAVE_API bool isvector (void) const;
+  OCTAVE_API bool isvector () const;
 
   // FIXME: these are here for compatibility.  They should be removed
   // when no longer in use.
@@ -1021,9 +1004,9 @@
   void sort (bool uniq = false)
   { *this = sorted (uniq); }
 
-  OCTAVE_API octave_idx_type ones_count (void) const;
+  OCTAVE_API octave_idx_type ones_count () const;
 
-  octave_idx_type max (void) const { return extent (1) - 1; }
+  octave_idx_type max () const { return extent (1) - 1; }
 
 private:
 
--- a/liboctave/array/intNDArray.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/intNDArray.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 
 template <typename T>
 boolNDArray
-intNDArray<T>::operator ! (void) const
+intNDArray<T>::operator ! () const
 {
   boolNDArray b (this->dims ());
 
@@ -48,7 +48,7 @@
 
 template <typename T>
 bool
-intNDArray<T>::any_element_not_one_or_zero (void) const
+intNDArray<T>::any_element_not_one_or_zero () const
 {
   octave_idx_type nel = this->numel ();
 
@@ -180,7 +180,7 @@
 
 template <typename T>
 intNDArray<T>
-intNDArray<T>::abs (void) const
+intNDArray<T>::abs () const
 {
   octave_idx_type nel = this->numel ();
   intNDArray<T> ret (this->dims ());
@@ -196,7 +196,7 @@
 
 template <typename T>
 intNDArray<T>
-intNDArray<T>::signum (void) const
+intNDArray<T>::signum () const
 {
   octave_idx_type nel = this->numel ();
   intNDArray<T> ret (this->dims ());
--- a/liboctave/array/intNDArray.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/array/intNDArray.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,13 +41,13 @@
 
   using typename MArray<T>::element_type;
 
-  intNDArray (void) = default;
+  intNDArray () = default;
 
   intNDArray (const intNDArray<T>& a) = default;
 
   intNDArray& operator = (const intNDArray<T>& a) = default;
 
-  ~intNDArray (void) = default;
+  ~intNDArray () = default;
 
   intNDArray (T val) : MArray<T> (dim_vector (1, 1), val) { }
 
@@ -65,16 +65,16 @@
   template <typename U>
   intNDArray (const intNDArray<U>& a) : MArray<T> (a) { }
 
-  OCTAVE_API boolNDArray operator ! (void) const;
+  OCTAVE_API boolNDArray operator ! () const;
 
-  bool any_element_is_nan (void) const { return false; }
-  OCTAVE_API bool any_element_not_one_or_zero (void) const;
+  bool any_element_is_nan () const { return false; }
+  OCTAVE_API bool any_element_not_one_or_zero () const;
 
   OCTAVE_API intNDArray diag (octave_idx_type k = 0) const;
 
   OCTAVE_API intNDArray diag (octave_idx_type m, octave_idx_type n) const;
 
-  intNDArray& changesign (void)
+  intNDArray& changesign ()
   {
     MArray<T>::changesign ();
     return *this;
@@ -106,13 +106,13 @@
 
   OCTAVE_API intNDArray diff (octave_idx_type order = 1, int dim = -1) const;
 
-  OCTAVE_API intNDArray abs (void) const;
-  OCTAVE_API intNDArray signum (void) const;
+  OCTAVE_API intNDArray abs () const;
+  OCTAVE_API intNDArray signum () const;
 
-  intNDArray squeeze (void) const
+  intNDArray squeeze () const
   { return intNDArray<T> (MArray<T>::squeeze ()); }
 
-  intNDArray transpose (void) const
+  intNDArray transpose () const
   { return intNDArray<T> (MArray<T>::transpose ()); }
 
   OCTAVE_API intNDArray
--- a/liboctave/liboctave-build-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/liboctave-build-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,6 +30,6 @@
 
 #include <string>
 
-extern OCTAVE_API std::string liboctave_hg_id (void);
+extern OCTAVE_API std::string liboctave_hg_id ();
 
 #endif
--- a/liboctave/liboctave-build-info.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/liboctave-build-info.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 #include "liboctave-build-info.h"
 
 std::string
-liboctave_hg_id (void)
+liboctave_hg_id ()
 {
   return "%OCTAVE_HG_ID%";
 }
--- a/liboctave/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -108,7 +108,7 @@
   $(%canon_reldir%_util_libutil_la_SOURCES) \
   $(LIBOCTAVE_TEMPLATE_SRC)
 
-LIBOCTAVE_TST_FILES_SRC := $(shell $(SHELL) $(srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(LIBOCTAVE_TST_SRC))
+LIBOCTAVE_TST_FILES_SRC := $(shell $(SHELL) build-aux/find-files-with-tests.sh "$(srcdir)" $(LIBOCTAVE_TST_SRC))
 
 LIBOCTAVE_TST_FILES := $(addsuffix -tst,$(LIBOCTAVE_TST_FILES_SRC))
 
--- a/liboctave/numeric/CollocWt.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/CollocWt.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -402,7 +402,7 @@
   return *this;
 }
 
-void CollocWt::init (void)
+void CollocWt::init ()
 {
   // Check for possible errors.
 
--- a/liboctave/numeric/CollocWt.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/CollocWt.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  CollocWt (void)
+  CollocWt ()
     : m_n (0), m_inc_left (0), m_inc_right (0), m_lb (0.0), m_rb (1.0),
       m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (),
       m_initialized (false)
@@ -77,7 +77,7 @@
 
   CollocWt& operator = (const CollocWt& a) = default;
 
-  ~CollocWt (void) = default;
+  ~CollocWt () = default;
 
   CollocWt& resize (octave_idx_type nc)
   {
@@ -86,14 +86,14 @@
     return *this;
   }
 
-  CollocWt& add_left (void)
+  CollocWt& add_left ()
   {
     m_inc_left = 1;
     m_initialized = false;
     return *this;
   }
 
-  CollocWt& delete_left (void)
+  CollocWt& delete_left ()
   {
     m_inc_left = 0;
     m_initialized = false;
@@ -102,14 +102,14 @@
 
   CollocWt& set_left (double val);
 
-  CollocWt& add_right (void)
+  CollocWt& add_right ()
   {
     m_inc_right = 1;
     m_initialized = false;
     return *this;
   }
 
-  CollocWt& delete_right (void)
+  CollocWt& delete_right ()
   {
     m_inc_right = 0;
     m_initialized = false;
@@ -132,20 +132,20 @@
     return *this;
   }
 
-  octave_idx_type ncol (void) const { return m_n; }
+  octave_idx_type ncol () const { return m_n; }
 
-  octave_idx_type left_included (void) const { return m_inc_left; }
-  octave_idx_type right_included (void) const { return m_inc_right; }
+  octave_idx_type left_included () const { return m_inc_left; }
+  octave_idx_type right_included () const { return m_inc_right; }
 
-  double left (void) const { return m_lb; }
-  double right (void) const { return m_rb; }
+  double left () const { return m_lb; }
+  double right () const { return m_rb; }
 
-  double width (void) const { return m_rb - m_lb; }
+  double width () const { return m_rb - m_lb; }
 
-  double alpha (void) const { return m_alpha; }
-  double beta (void) const { return m_beta; }
+  double alpha () const { return m_alpha; }
+  double beta () const { return m_beta; }
 
-  ColumnVector roots (void)
+  ColumnVector roots ()
   {
     if (! m_initialized)
       init ();
@@ -153,7 +153,7 @@
     return m_r;
   }
 
-  ColumnVector quad (void)
+  ColumnVector quad ()
   {
     if (! m_initialized)
       init ();
@@ -161,9 +161,9 @@
     return m_q;
   }
 
-  ColumnVector quad_weights (void) { return quad (); }
+  ColumnVector quad_weights () { return quad (); }
 
-  Matrix first (void)
+  Matrix first ()
   {
     if (! m_initialized)
       init ();
@@ -171,7 +171,7 @@
     return m_A;
   }
 
-  Matrix second (void)
+  Matrix second ()
   {
     if (! m_initialized)
       init ();
@@ -202,16 +202,11 @@
 
   bool m_initialized;
 
-  void init (void);
+  void init ();
 
   void error (const char *msg);
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::CollocWt' instead")
-typedef octave::CollocWt CollocWt;
 #endif
-
-#endif
--- a/liboctave/numeric/DAE.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DAE.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  DAE (void)
+  DAE ()
     : base_diff_alg_eqn (), DAEFunc () { }
 
   DAE (const ColumnVector& xx, double tt, DAEFunc& f)
@@ -60,7 +60,7 @@
     return *this;
   }
 
-  virtual ~DAE (void) = default;
+  virtual ~DAE () = default;
 };
 
 #endif
--- a/liboctave/numeric/DAEFunc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DAEFunc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
                                 const ColumnVector& xdot,
                                 double t, double cj);
 
-  DAEFunc (void)
+  DAEFunc ()
     : m_fcn (nullptr), m_jac (nullptr), m_reset (true) { }
 
   DAEFunc (DAERHSFunc f)
@@ -70,9 +70,9 @@
     return *this;
   }
 
-  virtual ~DAEFunc (void) = default;
+  virtual ~DAEFunc () = default;
 
-  DAERHSFunc function (void) const { return m_fcn; }
+  DAERHSFunc function () const { return m_fcn; }
 
   DAEFunc& set_function (DAERHSFunc f)
   {
@@ -81,7 +81,7 @@
     return *this;
   }
 
-  DAEJacFunc jacobian_function (void) const { return m_jac; }
+  DAEJacFunc jacobian_function () const { return m_jac; }
 
   DAEFunc& set_jacobian_function (DAEJacFunc j)
   {
--- a/liboctave/numeric/DAERT.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DAERT.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  DAERT (void)
+  DAERT ()
     : base_diff_alg_eqn (), DAERTFunc () { }
 
   DAERT (const ColumnVector& xx, double tt, DAERTFunc& f)
@@ -61,7 +61,7 @@
     return *this;
   }
 
-  virtual ~DAERT (void) = default;
+  virtual ~DAERT () = default;
 
   void initialize (const ColumnVector& xx, const ColumnVector& xxdot,
                    double tt)
--- a/liboctave/numeric/DAERTFunc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DAERTFunc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 
   typedef ColumnVector (*DAERTConstrFunc) (const ColumnVector& x, double t);
 
-  DAERTFunc (void)
+  DAERTFunc ()
     : DAEFunc (), m_constr (nullptr), m_reset (true) { }
 
   DAERTFunc (DAERHSFunc f)
@@ -66,9 +66,9 @@
     return *this;
   }
 
-  virtual ~DAERTFunc (void) = default;
+  virtual ~DAERTFunc () = default;
 
-  DAERTConstrFunc constraint_function (void) const { return m_constr; }
+  DAERTConstrFunc constraint_function () const { return m_constr; }
 
   DAERTFunc& set_constraint_function (DAERTConstrFunc cf)
   {
--- a/liboctave/numeric/DASPK.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASPK.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -692,7 +692,7 @@
 }
 
 std::string
-DASPK::error_message (void) const
+DASPK::error_message () const
 {
   std::string retval;
 
--- a/liboctave/numeric/DASPK.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASPK.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 {
 public:
 
-  DASPK (void)
+  DASPK ()
     : DAE (), DASPK_options (), m_initialized (false), m_liw (0), m_lrw (0),
       m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol () { }
 
@@ -56,7 +56,7 @@
       m_liw (0), m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (),
       m_rel_tol () { }
 
-  ~DASPK (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASPK)
 
   ColumnVector do_integrate (double t);
 
@@ -69,7 +69,7 @@
   Matrix integrate (const ColumnVector& tout, Matrix& xdot_out,
                     const ColumnVector& tcrit);
 
-  std::string error_message (void) const;
+  std::string error_message () const;
 
 private:
 
--- a/liboctave/numeric/DASRT.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASRT.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -551,7 +551,7 @@
 }
 
 std::string
-DASRT::error_message (void) const
+DASRT::error_message () const
 {
   std::string retval;
 
--- a/liboctave/numeric/DASRT.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASRT.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  DASRT_result (void)
+  DASRT_result ()
     : m_x (), m_xdot (), m_t () { }
 
   DASRT_result (const Matrix& x, const Matrix& xdot, const ColumnVector& t)
@@ -59,11 +59,11 @@
     return *this;
   }
 
-  ~DASRT_result (void) = default;
+  ~DASRT_result () = default;
 
-  Matrix state (void) const { return m_x; }
-  Matrix deriv (void) const { return m_xdot; }
-  ColumnVector times (void) const { return m_t; }
+  Matrix state () const { return m_x; }
+  Matrix deriv () const { return m_xdot; }
+  ColumnVector times () const { return m_t; }
 
 private:
 
@@ -78,7 +78,7 @@
 {
 public:
 
-  DASRT (void)
+  DASRT ()
     : DAERT (), DASRT_options (), m_initialized (false),
       m_liw (0), m_lrw (0), m_ng (0), m_info (), m_iwork (), m_jroot (),
       m_rwork (), m_abs_tol (), m_rel_tol ()
@@ -97,14 +97,14 @@
       m_rwork (), m_abs_tol (), m_rel_tol ()
   { }
 
-  ~DASRT (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASRT)
 
   DASRT_result integrate (const ColumnVector& tout);
 
   DASRT_result integrate (const ColumnVector& tout,
                           const ColumnVector& tcrit);
 
-  std::string error_message (void) const;
+  std::string error_message () const;
 
 private:
 
--- a/liboctave/numeric/DASSL.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASSL.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -499,7 +499,7 @@
 }
 
 std::string
-DASSL::error_message (void) const
+DASSL::error_message () const
 {
   std::string retval;
 
--- a/liboctave/numeric/DASSL.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DASSL.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 {
 public:
 
-  DASSL (void)
+  DASSL ()
     : DAE (), DASSL_options (), m_initialized (false), m_liw (0), m_lrw (0),
       m_info (), m_iwork (), m_rwork (), m_abs_tol (), m_rel_tol () { }
 
@@ -56,7 +56,7 @@
       m_liw (0), m_lrw (0), m_info (), m_iwork (), m_rwork (), m_abs_tol (),
       m_rel_tol () { }
 
-  ~DASSL (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DASSL)
 
   ColumnVector do_integrate (double t);
 
@@ -69,7 +69,7 @@
   Matrix integrate (const ColumnVector& tout, Matrix& xdot_out,
                     const ColumnVector& tcrit);
 
-  std::string error_message (void) const;
+  std::string error_message () const;
 
 private:
 
--- a/liboctave/numeric/DET.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/DET.h	Fri Jun 23 20:51:51 2023 +0200
@@ -57,17 +57,10 @@
     m_e2 += f;
   }
 
-  base_det (const base_det& a) : m_c2 (a.m_c2), m_e2 (a.m_e2) { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (base_det)
 
-  base_det& operator = (const base_det& a)
-  {
-    m_c2 = a.m_c2;
-    m_e2 = a.m_e2;
-    return *this;
-  }
-
-  T coef (void) const { return m_c2; }
-  int exp (void) const { return m_e2; }
+  T coef () const { return m_c2; }
+  int exp () const { return m_e2; }
 
   T value () const { return m_c2 * static_cast<T> (std::ldexp (1.0, m_e2)); }
   operator T () const { return value (); }
--- a/liboctave/numeric/EIG.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/EIG.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 
 public:
 
-  EIG (void) : m_lambda (), m_v (), m_w () { }
+  EIG () : m_lambda (), m_v (), m_w () { }
 
   EIG (const Matrix& a, bool calc_rev = true,
        bool calc_lev = true, bool balance = true)
@@ -116,11 +116,11 @@
     return *this;
   }
 
-  ~EIG (void) = default;
+  ~EIG () = default;
 
-  ComplexColumnVector eigenvalues (void) const { return m_lambda; }
-  ComplexMatrix right_eigenvectors (void) const { return m_v; }
-  ComplexMatrix left_eigenvectors (void) const { return m_w; }
+  ComplexColumnVector eigenvalues () const { return m_lambda; }
+  ComplexMatrix right_eigenvectors () const { return m_v; }
+  ComplexMatrix left_eigenvectors () const { return m_w; }
 
   friend std::ostream&  operator << (std::ostream& os, const EIG& a);
 
--- a/liboctave/numeric/LSODE.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/LSODE.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -348,7 +348,7 @@
 }
 
 std::string
-LSODE::error_message (void) const
+LSODE::error_message () const
 {
   std::string retval;
 
--- a/liboctave/numeric/LSODE.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/LSODE.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 {
 public:
 
-  LSODE (void)
+  LSODE ()
     : ODE (), LSODE_options (), m_initialized (false), m_method_flag (0),
       m_itask (0), m_iopt (0), m_itol (0), m_liw (0), m_lrw (0),
       m_iwork (), m_rwork (), m_rel_tol (0.0), m_abs_tol () { }
@@ -49,7 +49,7 @@
       m_method_flag (0), m_itask (0), m_iopt (0), m_itol (0), m_liw (0),
       m_lrw (0), m_iwork (), m_rwork (), m_rel_tol (0.0), m_abs_tol () { }
 
-  ~LSODE (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (LSODE)
 
   ColumnVector do_integrate (double t);
 
@@ -57,7 +57,7 @@
 
   Matrix do_integrate (const ColumnVector& tout, const ColumnVector& tcrit);
 
-  std::string error_message (void) const;
+  std::string error_message () const;
 
 private:
 
--- a/liboctave/numeric/ODE.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/ODE.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  ODE (void)
+  ODE ()
     : base_diff_eqn (), ODEFunc () { }
 
   ODE (const ColumnVector& s, double tm, const ODEFunc& f)
@@ -56,7 +56,7 @@
     return *this;
   }
 
-  virtual ~ODE (void) = default;
+  virtual ~ODE () = default;
 
   // Derived classes must provide functions to actually do the
   // integration.
--- a/liboctave/numeric/ODEFunc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/ODEFunc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,7 @@
   typedef ColumnVector (*ODERHSFunc) (const ColumnVector&, double);
   typedef Matrix (*ODEJacFunc) (const ColumnVector&, double);
 
-  ODEFunc (void)
+  ODEFunc ()
     : m_fcn (nullptr), m_jac (nullptr), m_reset (true) { }
 
   ODEFunc (ODERHSFunc f)
@@ -61,9 +61,9 @@
     return *this;
   }
 
-  virtual ~ODEFunc (void) = default;
+  virtual ~ODEFunc () = default;
 
-  ODERHSFunc function (void) const { return m_fcn; }
+  ODERHSFunc function () const { return m_fcn; }
 
   ODEFunc& set_function (ODERHSFunc f)
   {
@@ -72,7 +72,7 @@
     return *this;
   }
 
-  ODEJacFunc jacobian_function (void) const { return m_jac; }
+  ODEJacFunc jacobian_function () const { return m_jac; }
 
   ODEFunc& set_jacobian_function (ODEJacFunc j)
   {
--- a/liboctave/numeric/ODES.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/ODES.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 {
 public:
 
-  ODES (void)
+  ODES ()
     : base_diff_eqn (), ODESFunc (), m_xdot (), m_theta () { }
 
   ODES (const ColumnVector& s, double tm, ODESFunc& f)
@@ -65,9 +65,9 @@
     return *this;
   }
 
-  ~ODES (void) = default;
+  ~ODES () = default;
 
-  ColumnVector parameter_vector (void) { return m_theta; }
+  ColumnVector parameter_vector () { return m_theta; }
 
   OCTAVE_API void initialize (const ColumnVector& x, double t);
 
--- a/liboctave/numeric/ODESFunc.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/ODESFunc.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
   typedef Matrix (*ODES_jsub) (const ColumnVector& x, double,
                                const ColumnVector& theta);
 
-  ODESFunc (void)
+  ODESFunc ()
     : m_fsub (nullptr), m_bsub (nullptr), m_jsub (nullptr) { }
 
   ODESFunc (ODES_fsub f)
@@ -78,9 +78,9 @@
     return *this;
   }
 
-  virtual ~ODESFunc (void) = default;
+  virtual ~ODESFunc () = default;
 
-  ODES_fsub fsub_function (void) const { return m_fsub; }
+  ODES_fsub fsub_function () const { return m_fsub; }
 
   ODESFunc& set_fsub_function (ODES_fsub f)
   {
@@ -88,7 +88,7 @@
     return *this;
   }
 
-  ODES_bsub bsub_function (void) const { return m_bsub; }
+  ODES_bsub bsub_function () const { return m_bsub; }
 
   ODESFunc& set_bsub_function (ODES_bsub b)
   {
@@ -96,7 +96,7 @@
     return *this;
   }
 
-  ODES_jsub jsub_function (void) const { return m_jsub; }
+  ODES_jsub jsub_function () const { return m_jsub; }
 
   ODESFunc& set_jsub_function (ODES_jsub j)
   {
--- a/liboctave/numeric/Quad.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/Quad.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,22 +42,26 @@
 {
 public:
 
+  Quad () = delete;
+
   Quad (integrand_fcn fcn)
     : Quad_options (), m_f (fcn), m_ff () { }
 
   Quad (float_integrand_fcn fcn)
     : Quad_options (), m_f (), m_ff (fcn) { }
 
-  virtual ~Quad (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE (Quad)
 
-  virtual double integrate (void)
+  virtual ~Quad () = default;
+
+  virtual double integrate ()
   {
     octave_idx_type ier, neval;
     double abserr;
     return do_integrate (ier, neval, abserr);
   }
 
-  virtual float float_integrate (void)
+  virtual float float_integrate ()
   {
     octave_idx_type ier, neval;
     float abserr;
@@ -120,6 +124,8 @@
 {
 public:
 
+  DefQuad () = delete;
+
   DefQuad (integrand_fcn fcn)
     : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0), m_singularities ()
   { }
@@ -137,7 +143,7 @@
     : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0),
       m_singularities (sing) { }
 
-  ~DefQuad (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (DefQuad)
 
   double do_integrate (octave_idx_type& ier, octave_idx_type& neval,
                        double& abserr);
@@ -161,13 +167,15 @@
 
   enum IntegralType { bound_to_inf, neg_inf_to_bound, doubly_infinite };
 
+  IndefQuad () = delete;
+
   IndefQuad (integrand_fcn fcn)
     : Quad (fcn), m_bound (0.0), m_type (bound_to_inf) { }
 
   IndefQuad (integrand_fcn fcn, double b, IntegralType t)
     : Quad (fcn), m_bound (b), m_type (t) { }
 
-  ~IndefQuad (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (IndefQuad)
 
   double do_integrate (octave_idx_type& ier, octave_idx_type& neval,
                        double& abserr);
@@ -187,6 +195,8 @@
 {
 public:
 
+  FloatDefQuad () = delete;
+
   FloatDefQuad (float_integrand_fcn fcn)
     : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0), m_singularities ()
   { }
@@ -204,7 +214,7 @@
     : Quad (fcn), m_lower_limit (0.0), m_upper_limit (1.0),
       m_singularities (sing) { }
 
-  ~FloatDefQuad (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (FloatDefQuad)
 
   OCTAVE_NORETURN double do_integrate (octave_idx_type& ier,
                                        octave_idx_type& neval, double& abserr);
@@ -228,13 +238,15 @@
 
   enum IntegralType { bound_to_inf, neg_inf_to_bound, doubly_infinite };
 
+  FloatIndefQuad () = delete;
+
   FloatIndefQuad (float_integrand_fcn fcn)
     : Quad (fcn), m_bound (0.0), m_type (bound_to_inf) { }
 
   FloatIndefQuad (float_integrand_fcn fcn, double b, IntegralType t)
     : Quad (fcn), m_bound (b), m_type (t) { }
 
-  ~FloatIndefQuad (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (FloatIndefQuad)
 
   OCTAVE_NORETURN double do_integrate (octave_idx_type& ier,
                                        octave_idx_type& neval, double& abserr);
--- a/liboctave/numeric/aepbalance.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/aepbalance.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -74,7 +74,7 @@
 
 template <>
 OCTAVE_API Matrix
-aepbalance<Matrix>::balancing_matrix (void) const
+aepbalance<Matrix>::balancing_matrix () const
 {
   F77_INT n = to_f77_int (m_balanced_mat.rows ());
 
@@ -126,7 +126,7 @@
 
 template <>
 OCTAVE_API FloatMatrix
-aepbalance<FloatMatrix>::balancing_matrix (void) const
+aepbalance<FloatMatrix>::balancing_matrix () const
 {
   F77_INT n = to_f77_int (m_balanced_mat.rows ());
 
@@ -179,7 +179,7 @@
 
 template <>
 OCTAVE_API ComplexMatrix
-aepbalance<ComplexMatrix>::balancing_matrix (void) const
+aepbalance<ComplexMatrix>::balancing_matrix () const
 {
   F77_INT n = to_f77_int (m_balanced_mat.rows ());
 
@@ -233,7 +233,7 @@
 
 template <>
 OCTAVE_API FloatComplexMatrix
-aepbalance<FloatComplexMatrix>::balancing_matrix (void) const
+aepbalance<FloatComplexMatrix>::balancing_matrix () const
 {
   F77_INT n = to_f77_int (m_balanced_mat.rows ());
 
--- a/liboctave/numeric/aepbalance.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/aepbalance.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
   typedef typename MT::real_column_vector_type VT;
 
-  aepbalance (void) : m_balanced_mat (), m_scale (), m_ilo (), m_ihi (), m_job () { }
+  aepbalance () : m_balanced_mat (), m_scale (), m_ilo (), m_ihi (), m_job () { }
 
   OCTAVE_API aepbalance (const MT& a, bool noperm = false, bool noscal = false);
 
@@ -65,16 +65,16 @@
     return *this;
   }
 
-  virtual ~aepbalance (void) = default;
+  virtual ~aepbalance () = default;
 
-  OCTAVE_API MT balancing_matrix (void) const;
+  OCTAVE_API MT balancing_matrix () const;
 
-  MT balanced_matrix (void) const
+  MT balanced_matrix () const
   {
     return m_balanced_mat;
   }
 
-  VT permuting_vector (void) const
+  VT permuting_vector () const
   {
     octave_idx_type n = m_balanced_mat.rows ();
 
@@ -98,7 +98,7 @@
     return pv;
   }
 
-  VT scaling_vector (void) const
+  VT scaling_vector () const
   {
     octave_idx_type n = m_balanced_mat.rows ();
 
--- a/liboctave/numeric/base-dae.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/base-dae.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,7 +35,7 @@
 {
 public:
 
-  base_diff_alg_eqn (void)
+  base_diff_alg_eqn ()
     : base_diff_eqn (), m_xdot () { }
 
   base_diff_alg_eqn (const ColumnVector& xx, double tt)
@@ -48,7 +48,7 @@
   base_diff_alg_eqn (const base_diff_alg_eqn& a)
     : base_diff_eqn (a), m_xdot (a.m_xdot) { }
 
-  virtual ~base_diff_alg_eqn (void) = default;
+  virtual ~base_diff_alg_eqn () = default;
 
   base_diff_alg_eqn& operator = (const base_diff_alg_eqn& a)
   {
@@ -73,7 +73,7 @@
     m_xdot = xdot0;
   }
 
-  ColumnVector state_derivative (void) { return m_xdot; }
+  ColumnVector state_derivative () { return m_xdot; }
 
 protected:
 
--- a/liboctave/numeric/base-de.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/base-de.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 {
 public:
 
-  base_diff_eqn (void)
+  base_diff_eqn ()
     : m_x (), m_t (0.0), m_stop_time (0.0), m_stop_time_set (false),
       m_restart (true), m_integration_error (false), m_istate (0) { }
 
@@ -49,7 +49,7 @@
     : m_x (a.m_x), m_t (a.m_t), m_stop_time (0.0), m_stop_time_set (false),
       m_restart (true), m_integration_error (false), m_istate (0) { }
 
-  virtual ~base_diff_eqn (void) = default;
+  virtual ~base_diff_eqn () = default;
 
   base_diff_eqn& operator = (const base_diff_eqn& a)
   {
@@ -76,11 +76,11 @@
     force_restart ();
   }
 
-  octave_idx_type size (void) const { return m_x.numel (); }
+  octave_idx_type size () const { return m_x.numel (); }
 
-  ColumnVector state (void) const { return m_x; }
+  ColumnVector state () const { return m_x; }
 
-  double time (void) const { return m_t; }
+  double time () const { return m_t; }
 
   void set_stop_time (double tt)
   {
@@ -89,19 +89,19 @@
     force_restart ();
   }
 
-  void clear_stop_time (void)
+  void clear_stop_time ()
   {
     m_stop_time_set = false;
     force_restart ();
   }
 
-  virtual void force_restart (void) { m_restart = true; }
+  virtual void force_restart () { m_restart = true; }
 
-  bool integration_ok (void) const { return ! m_integration_error; }
+  bool integration_ok () const { return ! m_integration_error; }
 
-  octave_idx_type integration_state (void) const { return m_istate; }
+  octave_idx_type integration_state () const { return m_istate; }
 
-  virtual std::string error_message (void) const = 0;
+  virtual std::string error_message () const = 0;
 
 protected:
 
--- a/liboctave/numeric/chol.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/chol.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -247,7 +247,7 @@
 // Compute the inverse of a matrix using the Cholesky factorization.
 template <typename T>
 T
-chol<T>::inverse (void) const
+chol<T>::inverse () const
 {
   return chol2inv_internal (m_chol_mat, m_is_upper);
 }
--- a/liboctave/numeric/chol.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/chol.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
   typedef typename T::column_vector_type VT;
   typedef typename T::real_elt_type COND_T;
 
-  chol (void) : m_chol_mat (), m_rcond (0), m_is_upper (true) { }
+  chol () : m_chol_mat (), m_rcond (0), m_is_upper (true) { }
 
   chol (const T& a, bool upper = true, bool calc_cond = false)
     : m_chol_mat (), m_rcond (0)
@@ -56,27 +56,14 @@
     info = init (a, upper, calc_cond);
   }
 
-  chol (const chol& a)
-    : m_chol_mat (a.m_chol_mat), m_rcond (a.m_rcond), m_is_upper (a.m_is_upper) { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (chol)
 
-  chol& operator = (const chol& a)
-  {
-    if (this != &a)
-      {
-        m_chol_mat = a.m_chol_mat;
-        m_rcond = a.m_rcond;
-        m_is_upper = a.m_is_upper;
-      }
+  T chol_matrix () const { return m_chol_mat; }
 
-    return *this;
-  }
-
-  T chol_matrix (void) const { return m_chol_mat; }
-
-  COND_T rcond (void) const { return m_rcond; }
+  COND_T rcond () const { return m_rcond; }
 
   // Compute the inverse of a matrix using the Cholesky factorization.
-  OCTAVE_API T inverse (void) const;
+  OCTAVE_API T inverse () const;
 
   OCTAVE_API void set (const T& R);
 
--- a/liboctave/numeric/eigs-base.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/eigs-base.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 #if defined (HAVE_ARPACK)
 
 static void
-warn_convergence (void)
+warn_convergence ()
 {
   (*current_liboctave_warning_with_id_handler)
     ("Octave:convergence",
--- a/liboctave/numeric/fEIG.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/fEIG.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 
 public:
 
-  FloatEIG (void) : m_lambda (), m_v (), m_w () { }
+  FloatEIG () : m_lambda (), m_v (), m_w () { }
 
   FloatEIG (const FloatMatrix& a, bool calc_rev = true,
             bool calc_lev = true, bool balance = true)
@@ -116,11 +116,11 @@
     return *this;
   }
 
-  ~FloatEIG (void) = default;
+  ~FloatEIG () = default;
 
-  FloatComplexColumnVector eigenvalues (void) const { return m_lambda; }
-  FloatComplexMatrix right_eigenvectors (void) const { return m_v; }
-  FloatComplexMatrix left_eigenvectors (void) const { return m_w; }
+  FloatComplexColumnVector eigenvalues () const { return m_lambda; }
+  FloatComplexMatrix right_eigenvectors () const { return m_v; }
+  FloatComplexMatrix left_eigenvectors () const { return m_w; }
 
   friend std::ostream&  operator << (std::ostream& os, const FloatEIG& a);
 
--- a/liboctave/numeric/gepbalance.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/gepbalance.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
   typedef typename T::real_matrix_type RT;
 
-  gepbalance (void)
+  gepbalance ()
     : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (),
       m_balancing_mat2 ()
   { }
@@ -74,15 +74,15 @@
     return *this;
   }
 
-  ~gepbalance (void) = default;
+  ~gepbalance () = default;
 
-  T balanced_matrix (void) const { return m_balanced_mat; }
+  T balanced_matrix () const { return m_balanced_mat; }
 
-  T balanced_matrix2 (void) const { return m_balanced_mat2; }
+  T balanced_matrix2 () const { return m_balanced_mat2; }
 
-  RT balancing_matrix (void) const { return m_balancing_mat; }
+  RT balancing_matrix () const { return m_balancing_mat; }
 
-  RT balancing_matrix2 (void) const { return m_balancing_mat2; }
+  RT balancing_matrix2 () const { return m_balancing_mat2; }
 
 private:
 
--- a/liboctave/numeric/gsvd.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/gsvd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -53,7 +53,7 @@
 #define xSTRINGIZE(x) #x
 #define STRINGIZE(x) xSTRINGIZE(x)
 
-static void initialize_gsvd (void)
+static void initialize_gsvd ()
 {
   if (gsvd_initialized)
     return;
@@ -436,7 +436,7 @@
 
 template <typename T>
 T
-gsvd<T>::left_singular_matrix_A (void) const
+gsvd<T>::left_singular_matrix_A () const
 {
   if (m_type == gsvd::Type::sigma_only)
     (*current_liboctave_error_handler)
@@ -447,7 +447,7 @@
 
 template <typename T>
 T
-gsvd<T>::left_singular_matrix_B (void) const
+gsvd<T>::left_singular_matrix_B () const
 {
   if (m_type == gsvd::Type::sigma_only)
     (*current_liboctave_error_handler)
@@ -458,7 +458,7 @@
 
 template <typename T>
 T
-gsvd<T>::right_singular_matrix (void) const
+gsvd<T>::right_singular_matrix () const
 {
   if (m_type == gsvd::Type::sigma_only)
     (*current_liboctave_error_handler)
--- a/liboctave/numeric/gsvd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/gsvd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
     sigma_only
   };
 
-  gsvd (void) : m_sigmaA (), m_sigmaB (), m_left_smA (), m_left_smB (), m_right_sm ()
+  gsvd () : m_sigmaA (), m_sigmaB (), m_left_smA (), m_left_smB (), m_right_sm ()
   { }
 
   gsvd (const T& a, const T& b,
@@ -73,18 +73,18 @@
     return *this;
   }
 
-  ~gsvd (void) = default;
+  ~gsvd () = default;
 
   typename T::real_matrix_type
-  singular_values_A (void) const { return m_sigmaA; }
+  singular_values_A () const { return m_sigmaA; }
 
   typename T::real_matrix_type
-  singular_values_B (void) const { return m_sigmaB; }
+  singular_values_B () const { return m_sigmaB; }
 
-  T left_singular_matrix_A (void) const;
-  T left_singular_matrix_B (void) const;
+  T left_singular_matrix_A () const;
+  T left_singular_matrix_B () const;
 
-  T right_singular_matrix (void) const;
+  T right_singular_matrix () const;
 
 private:
   typedef typename T::value_type P;
--- a/liboctave/numeric/hess.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/hess.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 public:
 
-  hess (void)
+  hess ()
     : m_hess_mat (), m_unitary_hess_mat ()
   { }
 
@@ -71,11 +71,11 @@
     return *this;
   }
 
-  ~hess (void) = default;
+  ~hess () = default;
 
-  T hess_matrix (void) const { return m_hess_mat; }
+  T hess_matrix () const { return m_hess_mat; }
 
-  T unitary_hess_matrix (void) const { return m_unitary_hess_mat; }
+  T unitary_hess_matrix () const { return m_unitary_hess_mat; }
 
 private:
 
--- a/liboctave/numeric/lu.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/lu.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -65,14 +65,14 @@
 
 template <typename T>
 bool
-lu<T>::packed (void) const
+lu<T>::packed () const
 {
   return m_L.dims () == dim_vector ();
 }
 
 template <typename T>
 void
-lu<T>::unpack (void)
+lu<T>::unpack ()
 {
   if (packed ())
     {
@@ -93,7 +93,7 @@
 
 template <typename T>
 T
-lu<T>::L (void) const
+lu<T>::L () const
 {
   if (packed ())
     {
@@ -120,7 +120,7 @@
 
 template <typename T>
 T
-lu<T>::U (void) const
+lu<T>::U () const
 {
   if (packed ())
     {
@@ -144,7 +144,7 @@
 
 template <typename T>
 T
-lu<T>::Y (void) const
+lu<T>::Y () const
 {
   if (! packed ())
     (*current_liboctave_error_handler)
@@ -155,7 +155,7 @@
 
 template <typename T>
 Array<octave_idx_type>
-lu<T>::getp (void) const
+lu<T>::getp () const
 {
   if (packed ())
     {
@@ -186,14 +186,14 @@
 
 template <typename T>
 PermMatrix
-lu<T>::P (void) const
+lu<T>::P () const
 {
   return PermMatrix (getp (), false);
 }
 
 template <typename T>
 ColumnVector
-lu<T>::P_vec (void) const
+lu<T>::P_vec () const
 {
   octave_idx_type a_nr = m_a_fact.rows ();
 
@@ -209,7 +209,7 @@
 
 template <typename T>
 bool
-lu<T>::regular (void) const
+lu<T>::regular () const
 {
   bool retval = true;
 
--- a/liboctave/numeric/lu.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/lu.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,7 +45,7 @@
   typedef typename T::column_vector_type VT;
   typedef typename T::element_type ELT_T;
 
-  lu (void)
+  lu ()
     : m_a_fact (), m_L (), m_ipvt () { }
 
   OCTAVE_API lu (const T& a);
@@ -67,23 +67,23 @@
     return *this;
   }
 
-  virtual ~lu (void) = default;
+  virtual ~lu () = default;
 
-  OCTAVE_API bool packed (void) const;
+  OCTAVE_API bool packed () const;
 
-  OCTAVE_API void unpack (void);
+  OCTAVE_API void unpack ();
 
-  OCTAVE_API T L (void) const;
+  OCTAVE_API T L () const;
 
-  OCTAVE_API T U (void) const;
+  OCTAVE_API T U () const;
 
-  OCTAVE_API T Y (void) const;
+  OCTAVE_API T Y () const;
 
-  OCTAVE_API PermMatrix P (void) const;
+  OCTAVE_API PermMatrix P () const;
 
-  OCTAVE_API ColumnVector P_vec (void) const;
+  OCTAVE_API ColumnVector P_vec () const;
 
-  OCTAVE_API bool regular (void) const;
+  OCTAVE_API bool regular () const;
 
   OCTAVE_API void update (const VT& u, const VT& v);
 
@@ -97,7 +97,7 @@
 
   // The result of getp is passed to other Octave Matrix functions,
   // so we use octave_idx_type.
-  OCTAVE_API Array<octave_idx_type> getp (void) const;
+  OCTAVE_API Array<octave_idx_type> getp () const;
 
   T m_a_fact;
   T m_L;
--- a/liboctave/numeric/oct-convn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-convn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -158,152 +158,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline NDArray
-convn (const NDArray& a, const NDArray& b, convn_type ct)
-{
-  return octave::convn (a, b, static_cast<octave::convn_type> (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline Matrix
-convn (const Matrix& a, const Matrix& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline Matrix
-convn (const Matrix& a, const ColumnVector& c, const RowVector& r,
-       convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
-
-// double complex X double real
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexNDArray
-convn (const ComplexNDArray& a, const NDArray& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexMatrix
-convn (const ComplexMatrix& a, const Matrix& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexMatrix
-convn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r,
-       convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
-
-// double complex X double complex
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexNDArray
-convn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexMatrix
-convn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline ComplexMatrix
-convn (const ComplexMatrix& a, const ComplexColumnVector& c,
-       const ComplexRowVector& r, convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
-
-// float real X float real
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatNDArray
-convn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatMatrix
-convn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatMatrix
-convn (const FloatMatrix& a, const FloatColumnVector& c,
-       const FloatRowVector& r, convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
-
-// float complex X float real
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexNDArray
-convn (const FloatComplexNDArray& a, const FloatNDArray& b,
-       convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexMatrix
-convn (const FloatComplexMatrix& a, const FloatMatrix& b,
-       convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexMatrix
-convn (const FloatComplexMatrix& a, const FloatColumnVector& c,
-       const FloatRowVector& r, convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
-
-// float complex X float complex
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexNDArray
-convn (const FloatComplexNDArray& a, const FloatComplexNDArray& b,
-       convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexMatrix
-convn (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
-       convn_type ct)
-{
-  return octave::convn (a, b, octave::convert_enum (ct));
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::convn' instead")
-inline FloatComplexMatrix
-convn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c,
-       const FloatComplexRowVector& r, convn_type ct)
-{
-  return octave::convn (a, c, r, octave::convert_enum (ct));
-}
 #endif
-
-#endif
--- a/liboctave/numeric/oct-fftw.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-fftw.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -65,7 +65,7 @@
 
 // Note that it is profitable to store the FFTW3 plans, for small FFTs.
 
-fftw_planner::fftw_planner (void)
+fftw_planner::fftw_planner ()
   : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),
     m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)
 {
@@ -97,7 +97,7 @@
   fftw_import_system_wisdom ();
 }
 
-fftw_planner::~fftw_planner (void)
+fftw_planner::~fftw_planner ()
 {
   fftw_plan *plan_p;
 
@@ -115,7 +115,7 @@
 }
 
 bool
-fftw_planner::instance_ok (void)
+fftw_planner::instance_ok ()
 {
   bool retval = true;
 
@@ -395,7 +395,7 @@
 }
 
 fftw_planner::FftwMethod
-fftw_planner::do_method (void)
+fftw_planner::do_method ()
 {
   return m_meth;
 }
@@ -427,7 +427,7 @@
 
 float_fftw_planner *float_fftw_planner::s_instance = nullptr;
 
-float_fftw_planner::float_fftw_planner (void)
+float_fftw_planner::float_fftw_planner ()
   : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0),
     m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1)
 {
@@ -454,7 +454,7 @@
   fftwf_import_system_wisdom ();
 }
 
-float_fftw_planner::~float_fftw_planner (void)
+float_fftw_planner::~float_fftw_planner ()
 {
   fftwf_plan *plan_p;
 
@@ -472,7 +472,7 @@
 }
 
 bool
-float_fftw_planner::instance_ok (void)
+float_fftw_planner::instance_ok ()
 {
   bool retval = true;
 
@@ -750,7 +750,7 @@
 }
 
 float_fftw_planner::FftwMethod
-float_fftw_planner::do_method (void)
+float_fftw_planner::do_method ()
 {
   return m_meth;
 }
@@ -1135,7 +1135,7 @@
 #endif
 
 std::string
-fftw_version (void)
+fftw_version ()
 {
 #if defined (HAVE_FFTW)
   return ::fftw_version;
@@ -1145,7 +1145,7 @@
 }
 
 std::string
-fftwf_version (void)
+fftwf_version ()
 {
 #if defined (HAVE_FFTW)
   return ::fftwf_version;
--- a/liboctave/numeric/oct-fftw.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-fftw.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,17 +43,13 @@
 {
 protected:
 
-  fftw_planner (void);
+  fftw_planner ();
 
 public:
 
-  // No copying!
-
-  fftw_planner (const fftw_planner&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (fftw_planner)
 
-  fftw_planner& operator = (const fftw_planner&) = delete;
-
-  ~fftw_planner (void);
+  ~fftw_planner ();
 
   enum FftwMethod
   {
@@ -65,7 +61,7 @@
     HYBRID
   };
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
   static void *
   create_plan (int dir, const int rank, const dim_vector& dims,
@@ -90,7 +86,7 @@
            : nullptr;
   }
 
-  static FftwMethod method (void)
+  static FftwMethod method ()
   {
     static FftwMethod dummy;
 
@@ -106,7 +102,7 @@
 
   static void threads (int nt);
 
-  static int threads (void)
+  static int threads ()
   {
     return instance_ok () ? s_instance->m_nthreads : 0;
   }
@@ -115,7 +111,7 @@
 
   static fftw_planner *s_instance;
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   { delete s_instance; s_instance = nullptr; }
 
   void *
@@ -129,7 +125,7 @@
                   octave_idx_type howmany, octave_idx_type stride,
                   octave_idx_type dist, const double *in, Complex *out);
 
-  FftwMethod do_method (void);
+  FftwMethod do_method ();
 
   FftwMethod do_method (FftwMethod meth);
 
@@ -189,18 +185,13 @@
 {
 protected:
 
-  float_fftw_planner (void);
+  float_fftw_planner ();
 
 public:
 
-  // No copying!
-
-  float_fftw_planner (const float_fftw_planner&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (float_fftw_planner)
 
-  float_fftw_planner&
-  operator = (const float_fftw_planner&) = delete;
-
-  ~float_fftw_planner (void);
+  ~float_fftw_planner ();
 
   enum FftwMethod
   {
@@ -212,7 +203,7 @@
     HYBRID
   };
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
   static void *
   create_plan (int dir, const int rank, const dim_vector& dims,
@@ -237,7 +228,7 @@
            : nullptr;
   }
 
-  static FftwMethod method (void)
+  static FftwMethod method ()
   {
     static FftwMethod dummy;
 
@@ -253,7 +244,7 @@
 
   static void threads (int nt);
 
-  static int threads (void)
+  static int threads ()
   {
     return instance_ok () ? s_instance->m_nthreads : 0;
   }
@@ -262,7 +253,7 @@
 
   static float_fftw_planner *s_instance;
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   { delete s_instance; s_instance = nullptr; }
 
   void *
@@ -276,7 +267,7 @@
                   octave_idx_type howmany, octave_idx_type stride,
                   octave_idx_type dist, const float *in, FloatComplex *out);
 
-  FftwMethod do_method (void);
+  FftwMethod do_method ();
 
   FftwMethod do_method (FftwMethod meth);
 
@@ -336,13 +327,7 @@
 {
 public:
 
-  fftw (void) = delete;
-
-  // No copying.
-
-  fftw (const fftw&) = delete;
-
-  fftw& operator = (const fftw&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (fftw)
 
   static int fft (const double *in, Complex *out, std::size_t npts,
                   std::size_t nsamples = 1, octave_idx_type stride = 1,
@@ -378,8 +363,8 @@
                      const dim_vector&);
 };
 
-extern OCTAVE_API std::string fftw_version (void);
-extern OCTAVE_API std::string fftwf_version (void);
+extern OCTAVE_API std::string fftw_version ();
+extern OCTAVE_API std::string fftwf_version ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/liboctave/numeric/oct-norm.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-norm.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -75,9 +75,11 @@
 class norm_accumulator_p
 {
 public:
-  norm_accumulator_p () { } // we need this one for Array
+
   norm_accumulator_p (R pp) : m_p(pp), m_scl(0), m_sum(1) { }
 
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (norm_accumulator_p)
+
   template <typename U>
   void accum (U val)
   {
@@ -106,9 +108,11 @@
 class norm_accumulator_mp
 {
 public:
-  norm_accumulator_mp () { } // we need this one for Array
+
   norm_accumulator_mp (R pp) : m_p(pp), m_scl(0), m_sum(1) { }
 
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (norm_accumulator_mp)
+
   template <typename U>
   void accum (U val)
   {
@@ -137,8 +141,11 @@
 class norm_accumulator_2
 {
 public:
+
   norm_accumulator_2 () : m_scl(0), m_sum(1) { }
 
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_2)
+
   void accum (R val)
   {
     R t = std::abs (val);
@@ -175,7 +182,11 @@
 class norm_accumulator_1
 {
 public:
+
   norm_accumulator_1 () : m_sum (0) { }
+
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_1)
+
   template <typename U>
   void accum (U val)
   {
@@ -193,7 +204,11 @@
 class norm_accumulator_inf
 {
 public:
+
   norm_accumulator_inf () : m_max (0) { }
+
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_inf)
+
   template <typename U>
   void accum (U val)
   {
@@ -214,7 +229,11 @@
 class norm_accumulator_minf
 {
 public:
+
   norm_accumulator_minf () : m_min (numeric_limits<R>::Inf ()) { }
+
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_minf)
+
   template <typename U>
   void accum (U val)
   {
@@ -235,7 +254,11 @@
 class norm_accumulator_0
 {
 public:
+
   norm_accumulator_0 () : m_num (0) { }
+
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (norm_accumulator_0)
+
   template <typename U>
   void accum (U val)
   {
@@ -321,29 +344,29 @@
 
 // now the dispatchers
 #define DEFINE_DISPATCHER(FCN_NAME, ARG_TYPE, RES_TYPE)         \
-  template <typename T, typename R>                             \
-  RES_TYPE FCN_NAME (const ARG_TYPE& v, R p)                    \
-  {                                                             \
-    RES_TYPE res;                                               \
-    if (p == 2)                                                 \
-      FCN_NAME (v, res, norm_accumulator_2<R> ());              \
-    else if (p == 1)                                            \
-      FCN_NAME (v, res, norm_accumulator_1<R> ());              \
-    else if (lo_ieee_isinf (p))                                 \
-      {                                                         \
-        if (p > 0)                                              \
-          FCN_NAME (v, res, norm_accumulator_inf<R> ());        \
-        else                                                    \
-          FCN_NAME (v, res, norm_accumulator_minf<R> ());       \
-      }                                                         \
-    else if (p == 0)                                            \
-      FCN_NAME (v, res, norm_accumulator_0<R> ());              \
-    else if (p > 0)                                             \
-      FCN_NAME (v, res, norm_accumulator_p<R> (p));             \
-    else                                                        \
-      FCN_NAME (v, res, norm_accumulator_mp<R> (p));            \
-    return res;                                                 \
-  }
+template <typename T, typename R>                             \
+RES_TYPE FCN_NAME (const ARG_TYPE& v, R p)                    \
+{                                                             \
+  RES_TYPE res;                                               \
+  if (p == 2)                                                 \
+    FCN_NAME (v, res, norm_accumulator_2<R> ());              \
+  else if (p == 1)                                            \
+    FCN_NAME (v, res, norm_accumulator_1<R> ());              \
+  else if (lo_ieee_isinf (p))                                 \
+    {                                                         \
+      if (p > 0)                                              \
+        FCN_NAME (v, res, norm_accumulator_inf<R> ());        \
+      else                                                    \
+        FCN_NAME (v, res, norm_accumulator_minf<R> ());       \
+    }                                                         \
+  else if (p == 0)                                            \
+    FCN_NAME (v, res, norm_accumulator_0<R> ());              \
+  else if (p > 0)                                             \
+    FCN_NAME (v, res, norm_accumulator_p<R> (p));             \
+  else                                                        \
+    FCN_NAME (v, res, norm_accumulator_mp<R> (p));            \
+  return res;                                                 \
+}
 
 DEFINE_DISPATCHER (vector_norm, MArray<T>, R)
 DEFINE_DISPATCHER (column_norms, MArray<T>, MArray<R>)
@@ -511,10 +534,6 @@
 template <typename MatrixT, typename VectorT, typename R>
 R svd_matrix_norm (const MatrixT& m, R p, VectorT)
 {
-  // NOTE: The octave:: namespace tags are needed for the following
-  // function calls until the deprecated inline functions are removed
-  // from oct-norm.h.
-
   R res = 0;
   if (p == 2)
     {
@@ -522,9 +541,9 @@
       res = fact.singular_values () (0, 0);
     }
   else if (p == 1)
-    res = octave::xcolnorms (m, static_cast<R> (1)).max ();
+    res = xcolnorms (m, static_cast<R> (1)).max ();
   else if (lo_ieee_isinf (p) && p > 1)
-    res = octave::xrownorms (m, static_cast<R> (1)).max ();
+    res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
       VectorT x;
@@ -541,15 +560,11 @@
 template <typename MatrixT, typename VectorT, typename R>
 R matrix_norm (const MatrixT& m, R p, VectorT)
 {
-  // NOTE: The octave:: namespace tags are needed for the following
-  // function calls until the deprecated inline functions are removed
-  // from oct-norm.h.
-
   R res = 0;
   if (p == 1)
-    res = octave::xcolnorms (m, static_cast<R> (1)).max ();
+    res = xcolnorms (m, static_cast<R> (1)).max ();
   else if (lo_ieee_isinf (p) && p > 1)
-    res = octave::xrownorms (m, static_cast<R> (1)).max ();
+    res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
       VectorT x;
@@ -565,22 +580,22 @@
 // and finally, here's what we've promised in the header file
 
 #define DEFINE_XNORM_FCNS(PREFIX, RTYPE)                                \
-  RTYPE xnorm (const PREFIX##ColumnVector& x, RTYPE p)                  \
-  {                                                                     \
-    return vector_norm (x, p);                                          \
-  }                                                                     \
-  RTYPE xnorm (const PREFIX##RowVector& x, RTYPE p)                     \
-  {                                                                     \
-    return vector_norm (x, p);                                          \
-  }                                                                     \
-  RTYPE xnorm (const PREFIX##Matrix& x, RTYPE p)                        \
-  {                                                                     \
-    return svd_matrix_norm (x, p, PREFIX##Matrix ());                   \
-  }                                                                     \
-  RTYPE xfrobnorm (const PREFIX##Matrix& x)                             \
-  {                                                                     \
-    return vector_norm (x, static_cast<RTYPE> (2));                     \
-  }
+RTYPE xnorm (const PREFIX##ColumnVector& x, RTYPE p)                  \
+{                                                                     \
+  return vector_norm (x, p);                                          \
+}                                                                     \
+RTYPE xnorm (const PREFIX##RowVector& x, RTYPE p)                     \
+{                                                                     \
+  return vector_norm (x, p);                                          \
+}                                                                     \
+RTYPE xnorm (const PREFIX##Matrix& x, RTYPE p)                        \
+{                                                                     \
+  return svd_matrix_norm (x, p, PREFIX##Matrix ());                   \
+}                                                                     \
+RTYPE xfrobnorm (const PREFIX##Matrix& x)                             \
+{                                                                     \
+  return vector_norm (x, static_cast<RTYPE> (2));                     \
+}
 
 DEFINE_XNORM_FCNS(, double)
 DEFINE_XNORM_FCNS(Complex, double)
@@ -599,38 +614,38 @@
 }
 
 #define DEFINE_XNORM_SPARSE_FCNS(PREFIX, RTYPE)                 \
-  RTYPE xnorm (const Sparse##PREFIX##Matrix& x, RTYPE p)        \
-  {                                                             \
-    return matrix_norm (x, p, PREFIX##Matrix ());               \
-  }                                                             \
-  RTYPE xfrobnorm (const Sparse##PREFIX##Matrix& x)             \
-  {                                                             \
-    RTYPE res;                                                  \
-    array_norm_2 (x.data (), x.nnz (), res);                    \
-    return res;                                                 \
-  }
+RTYPE xnorm (const Sparse##PREFIX##Matrix& x, RTYPE p)        \
+{                                                             \
+  return matrix_norm (x, p, PREFIX##Matrix ());               \
+}                                                             \
+RTYPE xfrobnorm (const Sparse##PREFIX##Matrix& x)             \
+{                                                             \
+  RTYPE res;                                                  \
+  array_norm_2 (x.data (), x.nnz (), res);                    \
+  return res;                                                 \
+}
 
 DEFINE_XNORM_SPARSE_FCNS(, double)
 DEFINE_XNORM_SPARSE_FCNS(Complex, double)
 
 #define DEFINE_COLROW_NORM_FCNS(PREFIX, RPREFIX, RTYPE)         \
-  RPREFIX##RowVector                                            \
-  xcolnorms (const PREFIX##Matrix& m, RTYPE p)                  \
-  {                                                             \
-    return column_norms (m, p);                                 \
-  }                                                             \
-  RPREFIX##ColumnVector                                         \
-  xrownorms (const PREFIX##Matrix& m, RTYPE p)                  \
-  {                                                             \
-    return row_norms (m, p);                                    \
-  }                                                             \
+RPREFIX##RowVector                                            \
+xcolnorms (const PREFIX##Matrix& m, RTYPE p)                  \
+{                                                             \
+  return column_norms (m, p);                                 \
+}                                                             \
+RPREFIX##ColumnVector                                         \
+xrownorms (const PREFIX##Matrix& m, RTYPE p)                  \
+{                                                             \
+  return row_norms (m, p);                                    \
+}                                                             \
 
-DEFINE_COLROW_NORM_FCNS(,, double)
-DEFINE_COLROW_NORM_FCNS(Complex,, double)
+DEFINE_COLROW_NORM_FCNS(, , double)
+DEFINE_COLROW_NORM_FCNS(Complex, , double)
 DEFINE_COLROW_NORM_FCNS(Float, Float, float)
 DEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float)
 
-DEFINE_COLROW_NORM_FCNS(Sparse,, double)
-DEFINE_COLROW_NORM_FCNS(SparseComplex,, double)
+DEFINE_COLROW_NORM_FCNS(Sparse, , double)
+DEFINE_COLROW_NORM_FCNS(SparseComplex, , double)
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/numeric/oct-norm.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-norm.h	Fri Jun 23 20:51:51 2023 +0200
@@ -32,14 +32,6 @@
 
 #include "oct-cmplx.h"
 
-// The remaining includes can be removed when the deprecated functions
-// at the end of this file are removed.
-
-#include "dColVector.h"
-#include "dRowVector.h"
-#include "fColVector.h"
-#include "fRowVector.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 extern OCTAVE_API double xnorm (const ColumnVector&, double p = 2);
@@ -88,198 +80,4 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const ColumnVector& v, double p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const RowVector& v, double p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const Matrix& m, double p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline double xfrobnorm (const Matrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const ComplexColumnVector& v, double p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const ComplexRowVector& v, double p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const ComplexMatrix& m, double p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline double xfrobnorm (const ComplexMatrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatColumnVector& v, float p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatRowVector& v, float p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatMatrix& m, float p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline float xfrobnorm (const FloatMatrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatComplexColumnVector& v, float p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatComplexRowVector& v, float p = 2)
-{
-  return octave::xnorm (v, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline float xnorm (const FloatComplexMatrix& m, float p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline float xfrobnorm (const FloatComplexMatrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const SparseMatrix& m, double p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline double xfrobnorm (const SparseMatrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead")
-inline double xnorm (const SparseComplexMatrix& m, double p = 2)
-{
-  return octave::xnorm (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead")
-inline double xfrobnorm (const SparseComplexMatrix& m)
-{
-  return octave::xfrobnorm (m);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline RowVector xcolnorms (const Matrix& m, double p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline ColumnVector xrownorms (const Matrix& m, double p = 2)
-{
-  return octave::xrownorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline RowVector xcolnorms (const ComplexMatrix& m, double p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline ColumnVector xrownorms (const ComplexMatrix& m, double p = 2)
-{
-  return octave::xrownorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline FloatRowVector xcolnorms (const FloatMatrix& m, float p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline FloatColumnVector xrownorms (const FloatMatrix& m, float p = 2)
-{
-  return octave::xrownorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline FloatRowVector xcolnorms (const FloatComplexMatrix& m, float p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline FloatColumnVector xrownorms (const FloatComplexMatrix& m, float p = 2)
-{
-  return octave::xrownorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline RowVector xcolnorms (const SparseMatrix& m, double p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline ColumnVector xrownorms (const SparseMatrix& m, double p = 2)
-{
-  return octave::xrownorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead")
-inline RowVector xcolnorms (const SparseComplexMatrix& m, double p = 2)
-{
-  return octave::xcolnorms (m, p);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead")
-inline ColumnVector xrownorms (const SparseComplexMatrix& m, double p = 2)
-{
-  return octave::xrownorms (m, p);
-}
 #endif
-
-#endif
--- a/liboctave/numeric/oct-rand.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-rand.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,9 +48,9 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-rand *rand::m_instance = nullptr;
+rand *rand::s_instance = nullptr;
 
-rand::rand (void)
+rand::rand ()
   : m_current_distribution (uniform_dist), m_use_old_generators (false),
     m_rand_states ()
 {
@@ -59,20 +59,20 @@
   initialize_mersenne_twister ();
 }
 
-bool rand::instance_ok (void)
+bool rand::instance_ok ()
 {
   bool retval = true;
 
-  if (! m_instance)
+  if (! s_instance)
     {
-      m_instance = new rand ();
+      s_instance = new rand ();
       singleton_cleanup_list::add (cleanup_instance);
     }
 
   return retval;
 }
 
-double rand::do_seed (void)
+double rand::do_seed ()
 {
   union d2i { double d; int32_t i[2]; };
   union d2i u;
@@ -135,7 +135,7 @@
   F77_FUNC (setsd, SETSD) (i0, i1);
 }
 
-void rand::do_reset (void)
+void rand::do_reset ()
 {
   m_use_old_generators = true;
   initialize_ranlib_generators ();
@@ -187,7 +187,7 @@
     m_rand_states[old_dist] = saved_state;
 }
 
-std::string rand::do_distribution (void)
+std::string rand::do_distribution ()
 {
   std::string retval;
 
@@ -255,35 +255,35 @@
     }
 }
 
-void rand::do_uniform_distribution (void)
+void rand::do_uniform_distribution ()
 {
   switch_to_generator (uniform_dist);
 
   F77_FUNC (setcgn, SETCGN) (uniform_dist);
 }
 
-void rand::do_normal_distribution (void)
+void rand::do_normal_distribution ()
 {
   switch_to_generator (normal_dist);
 
   F77_FUNC (setcgn, SETCGN) (normal_dist);
 }
 
-void rand::do_exponential_distribution (void)
+void rand::do_exponential_distribution ()
 {
   switch_to_generator (expon_dist);
 
   F77_FUNC (setcgn, SETCGN) (expon_dist);
 }
 
-void rand::do_poisson_distribution (void)
+void rand::do_poisson_distribution ()
 {
   switch_to_generator (poisson_dist);
 
   F77_FUNC (setcgn, SETCGN) (poisson_dist);
 }
 
-void rand::do_gamma_distribution (void)
+void rand::do_gamma_distribution ()
 {
   switch_to_generator (gamma_dist);
 
@@ -291,7 +291,7 @@
 }
 
 template <>
-OCTAVE_API double rand::uniform<double> (void)
+OCTAVE_API double rand::uniform<double> ()
 {
   double retval;
 
@@ -304,7 +304,7 @@
 }
 
 template <>
-OCTAVE_API double rand::normal<double> (void)
+OCTAVE_API double rand::normal<double> ()
 {
   double retval;
 
@@ -317,7 +317,7 @@
 }
 
 template <>
-OCTAVE_API double rand::exponential<double> (void)
+OCTAVE_API double rand::exponential<double> ()
 {
   double retval;
 
@@ -370,7 +370,7 @@
 }
 
 template <>
-OCTAVE_API float rand::uniform<float> (void)
+OCTAVE_API float rand::uniform<float> ()
 {
   float retval;
 
@@ -383,7 +383,7 @@
 }
 
 template <>
-OCTAVE_API float rand::normal<float> (void)
+OCTAVE_API float rand::normal<float> ()
 {
   float retval;
 
@@ -396,7 +396,7 @@
 }
 
 template <>
-OCTAVE_API float rand::exponential<float> (void)
+OCTAVE_API float rand::exponential<float> ()
 {
   float retval;
 
@@ -549,7 +549,7 @@
 // technique used below will cycle monthly, but it does seem to
 // work ok to give fairly different seeds each time Octave starts.
 
-void rand::initialize_ranlib_generators (void)
+void rand::initialize_ranlib_generators ()
 {
   sys::localtime tm;
   int stored_distribution = m_current_distribution;
@@ -569,7 +569,7 @@
   F77_FUNC (setcgn, SETCGN) (stored_distribution);
 }
 
-void rand::initialize_mersenne_twister (void)
+void rand::initialize_mersenne_twister ()
 {
   uint32NDArray s;
 
@@ -598,7 +598,7 @@
   set_internal_state (m_rand_states[m_current_distribution]);
 }
 
-uint32NDArray rand::get_internal_state (void)
+uint32NDArray rand::get_internal_state ()
 {
   uint32NDArray s (dim_vector (MT_N + 1, 1));
 
@@ -607,7 +607,7 @@
   return s;
 }
 
-void rand::save_state (void)
+void rand::save_state ()
 {
   m_rand_states[m_current_distribution] = get_internal_state ();
 }
@@ -664,21 +664,21 @@
     {
     case uniform_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; });
+        std::generate_n (v, len, []() { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; });
       else
         rand_uniform<double> (len, v);
       break;
 
     case normal_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; });
+        std::generate_n (v, len, []() { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; });
       else
         rand_normal<double> (len, v);
       break;
 
     case expon_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; });
+        std::generate_n (v, len, []() { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; });
       else
         rand_exponential<double> (len, v);
       break;
@@ -693,7 +693,7 @@
               // workaround bug in ignpoi, by calling with different Mu
               double tmp;
               F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp);
-              std::generate_n (v, len, [a](void) { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; });
+              std::generate_n (v, len, [a]() { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; });
             }
         }
       else
@@ -706,7 +706,7 @@
           if (a <= 0.0 || ! math::isfinite (a))
             std::fill_n (v, len, numeric_limits<double>::NaN ());
           else
-            std::generate_n (v, len, [a](void) { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; });
+            std::generate_n (v, len, [a]() { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; });
         }
       else
         rand_gamma<double> (a, len, v);
@@ -732,21 +732,21 @@
     {
     case uniform_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; });
+        std::generate_n (v, len, []() { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; });
       else
         rand_uniform<float> (len, v);
       break;
 
     case normal_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; });
+        std::generate_n (v, len, []() { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; });
       else
         rand_normal<float> (len, v);
       break;
 
     case expon_dist:
       if (m_use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; });
+        std::generate_n (v, len, []() { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; });
       else
         rand_exponential<float> (len, v);
       break;
@@ -761,7 +761,7 @@
               // workaround bug in ignpoi, by calling with different Mu
               float tmp;
               F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp);
-              std::generate_n (v, len, [a](void) { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; });
+              std::generate_n (v, len, [a]() { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; });
             }
         }
       else
@@ -774,7 +774,7 @@
           if (a <= 0.0f || ! math::isfinite (a))
             std::fill_n (v, len, numeric_limits<float>::NaN ());
           else
-            std::generate_n (v, len, [a](void) { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; });
+            std::generate_n (v, len, [a]() { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; });
         }
       else
         rand_gamma<float> (a, len, v);
--- a/liboctave/numeric/oct-rand.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-rand.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,39 +45,41 @@
 {
 protected:
 
-  OCTAVE_API rand (void);
+  OCTAVE_API rand ();
 
 public:
 
-  ~rand (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (rand)
 
-  static bool instance_ok (void);
+  ~rand () = default;
+
+  static bool instance_ok ();
 
   // Return the current seed.
-  static double seed (void)
+  static double seed ()
   {
     return (instance_ok ()
-            ? m_instance->do_seed () : numeric_limits<double>::NaN ());
+            ? s_instance->do_seed () : numeric_limits<double>::NaN ());
   }
 
   // Set the seed.
   static void seed (double s)
   {
     if (instance_ok ())
-      m_instance->do_seed (s);
+      s_instance->do_seed (s);
   }
 
   // Reset the seed.
-  static void reset (void)
+  static void reset ()
   {
     if (instance_ok ())
-      m_instance->do_reset ();
+      s_instance->do_reset ();
   }
 
   // Return the current state.
   static uint32NDArray state (const std::string& d = "")
   {
-    return instance_ok () ? m_instance->do_state (d) : uint32NDArray ();
+    return instance_ok () ? s_instance->do_state (d) : uint32NDArray ();
   }
 
   // Set the current state/
@@ -85,20 +87,20 @@
                      const std::string& d = "")
   {
     if (instance_ok ())
-      m_instance->do_state (s, d);
+      s_instance->do_state (s, d);
   }
 
   // Reset the current state/
   static void reset (const std::string& d)
   {
     if (instance_ok ())
-      m_instance->do_reset (d);
+      s_instance->do_reset (d);
   }
 
   // Return the current distribution.
-  static std::string distribution (void)
+  static std::string distribution ()
   {
-    return instance_ok () ? m_instance->do_distribution () : "";
+    return instance_ok () ? s_instance->do_distribution () : "";
   }
 
   // Set the current distribution.  May be either "uniform" (the
@@ -106,70 +108,70 @@
   static void distribution (const std::string& d)
   {
     if (instance_ok ())
-      m_instance->do_distribution (d);
+      s_instance->do_distribution (d);
   }
 
-  static void uniform_distribution (void)
+  static void uniform_distribution ()
   {
     if (instance_ok ())
-      m_instance->do_uniform_distribution ();
+      s_instance->do_uniform_distribution ();
   }
 
-  static void normal_distribution (void)
+  static void normal_distribution ()
   {
     if (instance_ok ())
-      m_instance->do_normal_distribution ();
+      s_instance->do_normal_distribution ();
   }
 
-  static void exponential_distribution (void)
+  static void exponential_distribution ()
   {
     if (instance_ok ())
-      m_instance->do_exponential_distribution ();
+      s_instance->do_exponential_distribution ();
   }
 
-  static void poisson_distribution (void)
+  static void poisson_distribution ()
   {
     if (instance_ok ())
-      m_instance->do_poisson_distribution ();
+      s_instance->do_poisson_distribution ();
   }
 
-  static void gamma_distribution (void)
+  static void gamma_distribution ()
   {
     if (instance_ok ())
-      m_instance->do_gamma_distribution ();
+      s_instance->do_gamma_distribution ();
   }
 
   // Return the next number from the sequence.
   static double scalar (double a = 1.0)
   {
     return (instance_ok ()
-            ? m_instance->do_scalar (a) : numeric_limits<double>::NaN ());
+            ? s_instance->do_scalar (a) : numeric_limits<double>::NaN ());
   }
 
   // Return the next number from the sequence.
   static float float_scalar (float a = 1.0)
   {
     return (instance_ok ()
-            ? m_instance->do_scalar (a) : numeric_limits<float>::NaN ());
+            ? s_instance->do_scalar (a) : numeric_limits<float>::NaN ());
   }
 
   // Return an array of numbers from the sequence.
   static Array<double> vector (octave_idx_type n, double a = 1.0)
   {
-    return instance_ok () ? m_instance->do_vector (n, a) : Array<double> ();
+    return instance_ok () ? s_instance->do_vector (n, a) : Array<double> ();
   }
 
   // Return an array of numbers from the sequence.
   static Array<float> float_vector (octave_idx_type n, float a = 1.0)
   {
-    return instance_ok () ? m_instance->do_vector (n, a) : Array<float> ();
+    return instance_ok () ? s_instance->do_vector (n, a) : Array<float> ();
   }
 
   // Return an N-dimensional array of numbers from the sequence,
   // filled in column major order.
   static NDArray nd_array (const dim_vector& dims, double a = 1.0)
   {
-    return instance_ok () ? m_instance->do_nd_array (dims, a) : NDArray ();
+    return instance_ok () ? s_instance->do_nd_array (dims, a) : NDArray ();
   }
 
   // Return an N-dimensional array of numbers from the sequence,
@@ -177,15 +179,15 @@
   static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0)
   {
     return (instance_ok ()
-            ? m_instance->do_float_nd_array (dims, a) : FloatNDArray ());
+            ? s_instance->do_float_nd_array (dims, a) : FloatNDArray ());
   }
 
 private:
 
-  static rand *m_instance;
+  static rand *s_instance;
 
-  static void cleanup_instance (void)
-  { delete m_instance; m_instance = nullptr; }
+  static void cleanup_instance ()
+  { delete s_instance; s_instance = nullptr; }
 
   enum
   {
@@ -208,7 +210,7 @@
   std::map<int, uint32NDArray> m_rand_states;
 
   // Return the current seed.
-  OCTAVE_API double do_seed (void);
+  OCTAVE_API double do_seed ();
 
   // Set the seed.
   OCTAVE_API void do_seed (double s);
@@ -226,30 +228,30 @@
   OCTAVE_API void do_reset (const std::string& d);
 
   // Return the current distribution.
-  OCTAVE_API std::string do_distribution (void);
+  OCTAVE_API std::string do_distribution ();
 
   // Set the current distribution.  May be either "uniform" (the
   // default), "normal", "exponential", "poisson", or "gamma".
   OCTAVE_API void do_distribution (const std::string& d);
 
-  OCTAVE_API void do_uniform_distribution (void);
+  OCTAVE_API void do_uniform_distribution ();
 
-  OCTAVE_API void do_normal_distribution (void);
+  OCTAVE_API void do_normal_distribution ();
 
-  OCTAVE_API void do_exponential_distribution (void);
+  OCTAVE_API void do_exponential_distribution ();
 
-  OCTAVE_API void do_poisson_distribution (void);
+  OCTAVE_API void do_poisson_distribution ();
 
-  OCTAVE_API void do_gamma_distribution (void);
+  OCTAVE_API void do_gamma_distribution ();
 
   // The following templates only make sense for double and float
   // types.
 
-  template <typename T> OCTAVE_API T uniform (void);
+  template <typename T> OCTAVE_API T uniform ();
 
-  template <typename T> OCTAVE_API T normal (void);
+  template <typename T> OCTAVE_API T normal ();
 
-  template <typename T> OCTAVE_API T exponential (void);
+  template <typename T> OCTAVE_API T exponential ();
 
   template <typename T> OCTAVE_API T poisson (T a);
 
@@ -273,13 +275,13 @@
 
   // Some helper functions.
 
-  OCTAVE_API void initialize_ranlib_generators (void);
+  OCTAVE_API void initialize_ranlib_generators ();
 
-  OCTAVE_API void initialize_mersenne_twister (void);
+  OCTAVE_API void initialize_mersenne_twister ();
 
-  OCTAVE_API uint32NDArray get_internal_state (void);
+  OCTAVE_API uint32NDArray get_internal_state ();
 
-  OCTAVE_API void save_state (void);
+  OCTAVE_API void save_state ();
 
   OCTAVE_API int get_dist_id (const std::string& d);
 
--- a/liboctave/numeric/oct-spparms.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-spparms.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
 
 sparse_params *sparse_params::s_instance = nullptr;
 
-bool sparse_params::instance_ok (void)
+bool sparse_params::instance_ok ()
 {
   bool retval = true;
 
@@ -52,24 +52,24 @@
   return retval;
 }
 
-void sparse_params::defaults (void)
+void sparse_params::defaults ()
 {
   if (instance_ok ())
     s_instance->do_defaults ();
 }
 
-void sparse_params::tight (void)
+void sparse_params::tight ()
 {
   if (instance_ok ())
     s_instance->do_tight ();
 }
 
-string_vector sparse_params::get_keys (void)
+string_vector sparse_params::get_keys ()
 {
   return instance_ok () ? s_instance->do_get_keys () : string_vector ();
 }
 
-ColumnVector sparse_params::get_vals (void)
+ColumnVector sparse_params::get_vals ()
 {
   return instance_ok () ? s_instance->do_get_vals () : ColumnVector ();
 }
@@ -90,7 +90,7 @@
           ? s_instance->do_get_key (key) : numeric_limits<double>::NaN ());
 }
 
-double sparse_params::get_bandden (void)
+double sparse_params::get_bandden ()
 {
   return instance_ok () ? s_instance->do_get_bandden () : 0.0;
 }
@@ -101,7 +101,7 @@
     s_instance->do_print_info (os, prefix);
 }
 
-void sparse_params::do_defaults (void)
+void sparse_params::do_defaults ()
 {
   m_params(0) = 0;      // spumoni
   m_params(1) = 1;      // ths_rel
@@ -118,7 +118,7 @@
   m_params(12) = 0.001; // sym_tol
 }
 
-void sparse_params::do_tight (void)
+void sparse_params::do_tight ()
 {
   m_params(0) = 0;      // spumoni
   m_params(1) = 1;      // ths_rel
@@ -135,7 +135,7 @@
   m_params(12) = 0.001; // sym_tol
 }
 
-void sparse_params::init_keys (void)
+void sparse_params::init_keys ()
 {
   m_keys(0) = "spumoni";
   m_keys(1) = "ths_rel";
@@ -152,7 +152,7 @@
   m_keys(12) = "sym_tol";
 }
 
-double sparse_params::do_get_bandden (void)
+double sparse_params::do_get_bandden ()
 {
   return m_params(10);
 }
--- a/liboctave/numeric/oct-spparms.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/oct-spparms.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 {
 protected:
 
-  sparse_params (void)
+  sparse_params ()
     : m_params (OCTAVE_SPARSE_CONTROLS_SIZE),
       m_keys (OCTAVE_SPARSE_CONTROLS_SIZE)
   {
@@ -57,17 +57,17 @@
 
   sparse_params& operator = (const sparse_params&) = default;
 
-  ~sparse_params (void) = default;
+  ~sparse_params () = default;
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
-  static void defaults (void);
+  static void defaults ();
 
-  static void tight (void);
+  static void tight ();
 
-  static string_vector get_keys (void);
+  static string_vector get_keys ();
 
-  static ColumnVector get_vals (void);
+  static ColumnVector get_vals ();
 
   static bool set_vals (const Array<double>& vals);
 
@@ -75,7 +75,7 @@
 
   static double get_key (const std::string& key);
 
-  static double get_bandden (void);
+  static double get_bandden ();
 
   static void print_info (std::ostream& os, const std::string& prefix);
 
@@ -87,19 +87,19 @@
 
   static sparse_params *s_instance;
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   {
     delete s_instance;
     s_instance = nullptr;
   }
 
-  void do_defaults (void);
+  void do_defaults ();
 
-  void do_tight (void);
+  void do_tight ();
 
-  string_vector do_get_keys (void) const { return m_keys; }
+  string_vector do_get_keys () const { return m_keys; }
 
-  ColumnVector do_get_vals (void) const { return m_params; }
+  ColumnVector do_get_vals () const { return m_params; }
 
   bool do_set_vals (const Array<double>& vals);
 
@@ -107,18 +107,13 @@
 
   double do_get_key (const std::string& key);
 
-  double do_get_bandden (void);
+  double do_get_bandden ();
 
   void do_print_info (std::ostream& os, const std::string& prefix) const;
 
-  void init_keys (void);
+  void init_keys ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-OCTAVE_DEPRECATED (7, "use 'octave::sparse_params' instead")
-typedef octave::sparse_params octave_sparse_params;
 #endif
-
-#endif
--- a/liboctave/numeric/qr.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/qr.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -70,7 +70,7 @@
 
 template <typename T>
 typename qr<T>::type
-qr<T>::get_type (void) const
+qr<T>::get_type () const
 {
   type retval;
 
@@ -86,7 +86,7 @@
 
 template <typename T>
 bool
-qr<T>::regular (void) const
+qr<T>::regular () const
 {
   bool retval = true;
 
@@ -109,7 +109,7 @@
 // Replacement update methods.
 
 void
-warn_qrupdate_once (void)
+warn_qrupdate_once ()
 {
   static bool warned = false;
 
--- a/liboctave/numeric/qr.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/qr.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,7 +51,7 @@
     economy
   };
 
-  qr (void) : m_q (), m_r () { }
+  qr () : m_q (), m_r () { }
 
   qr (const T& a, type qr_type = qr::std)
     : m_q (), m_r ()
@@ -74,15 +74,15 @@
     return *this;
   }
 
-  virtual ~qr (void) = default;
+  virtual ~qr () = default;
 
-  T Q (void) const { return m_q; }
+  T Q () const { return m_q; }
 
-  T R (void) const { return m_r; }
+  T R () const { return m_r; }
 
-  OCTAVE_API type get_type (void) const;
+  OCTAVE_API type get_type () const;
 
-  OCTAVE_API bool regular (void) const;
+  OCTAVE_API bool regular () const;
 
   OCTAVE_API void init (const T& a, type qr_type);
 
@@ -113,7 +113,7 @@
   form (octave_idx_type n, T& afact, ELT_T *tau, type qr_type);
 };
 
-extern OCTAVE_API void warn_qrupdate_once (void);
+extern OCTAVE_API void warn_qrupdate_once ();
 
 OCTAVE_END_NAMESPACE(math)
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/numeric/qrp.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/qrp.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -113,7 +113,7 @@
 template <>
 OCTAVE_API
 RowVector
-qrp<Matrix>::Pvec (void) const
+qrp<Matrix>::Pvec () const
 {
   Array<double> pa (m_p.col_perm_vec ());
   RowVector pv (MArray<double> (pa) + 1.0);
@@ -184,7 +184,7 @@
 template <>
 OCTAVE_API
 FloatRowVector
-qrp<FloatMatrix>::Pvec (void) const
+qrp<FloatMatrix>::Pvec () const
 {
   Array<float> pa (m_p.col_perm_vec ());
   FloatRowVector pv (MArray<float> (pa) + 1.0f);
@@ -263,7 +263,7 @@
 template <>
 OCTAVE_API
 RowVector
-qrp<ComplexMatrix>::Pvec (void) const
+qrp<ComplexMatrix>::Pvec () const
 {
   Array<double> pa (m_p.col_perm_vec ());
   RowVector pv (MArray<double> (pa) + 1.0);
@@ -342,7 +342,7 @@
 template <>
 OCTAVE_API
 FloatRowVector
-qrp<FloatComplexMatrix>::Pvec (void) const
+qrp<FloatComplexMatrix>::Pvec () const
 {
   Array<float> pa (m_p.col_perm_vec ());
   FloatRowVector pv (MArray<float> (pa) + 1.0f);
--- a/liboctave/numeric/qrp.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/qrp.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,7 +45,7 @@
 
   typedef typename qr<T>::type type;
 
-  qrp (void) : qr<T> (), m_p () { }
+  qrp () : qr<T> (), m_p () { }
 
   OCTAVE_API qrp (const T&, type = qr<T>::std);
 
@@ -62,13 +62,13 @@
     return *this;
   }
 
-  ~qrp (void) = default;
+  ~qrp () = default;
 
   OCTAVE_API void init (const T&, type = qr<T>::std);
 
-  PermMatrix P (void) const { return m_p; }
+  PermMatrix P () const { return m_p; }
 
-  OCTAVE_API RV_T Pvec (void) const;
+  OCTAVE_API RV_T Pvec () const;
 
 private:
 
--- a/liboctave/numeric/randmtzig.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/randmtzig.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -121,7 +121,7 @@
 
    === Mersenne Twister ===
    random initial state:
-   void init_mersenne_twister (void)
+   void init_mersenne_twister ()
 
    // 32-bit initial state:
    void init_mersenne_twister (uint32_t s)
@@ -135,18 +135,18 @@
    // restores state from array
    void set_mersenne_twister_state (uint32_t save[MT_N+1])
 
-   static uint32_t randmt (void)               returns 32-bit unsigned int
+   static uint32_t randmt ()               returns 32-bit unsigned int
 
    === inline generators ===
-   static uint32_t randi32 (void)   returns 32-bit unsigned int
-   static uint64_t randi53 (void)   returns 53-bit unsigned int
-   static uint64_t randi54 (void)   returns 54-bit unsigned int
-   static float randu24 (void)      returns 24-bit uniform in (0,1)
-   static double randu53 (void)     returns 53-bit uniform in (0,1)
+   static uint32_t randi32 ()   returns 32-bit unsigned int
+   static uint64_t randi53 ()   returns 53-bit unsigned int
+   static uint64_t randi54 ()   returns 54-bit unsigned int
+   static float randu24 ()      returns 24-bit uniform in (0,1)
+   static double randu53 ()     returns 53-bit uniform in (0,1)
 
-   double rand_uniform (void)       returns M-bit uniform in (0,1)
-   double rand_normal (void)        returns M-bit standard normal
-   double rand_exponential (void)   returns N-bit standard exponential
+   double rand_uniform ()       returns M-bit uniform in (0,1)
+   double rand_normal ()        returns M-bit standard normal
+   double rand_exponential ()   returns N-bit standard exponential
 
    === Array generators ===
    void rand_uniform (octave_idx_type, double [])
@@ -257,7 +257,7 @@
   initf = 1;
 }
 
-void init_mersenne_twister (void)
+void init_mersenne_twister ()
 {
   uint32_t entropy[MT_N];
   int n = 0;
@@ -321,7 +321,7 @@
   save[MT_N] = left;
 }
 
-static void next_state (void)
+static void next_state ()
 {
   uint32_t *p = state;
   int j;
@@ -346,7 +346,7 @@
 }
 
 /* generates a random number on [0,0xffffffff]-interval */
-static uint32_t randmt (void)
+static uint32_t randmt ()
 {
   uint32_t y;
 
@@ -366,7 +366,7 @@
 /* Select which 32 bit generator to use */
 #define randi32 randmt
 
-static uint64_t randi53 (void)
+static uint64_t randi53 ()
 {
   const uint32_t lo = randi32 ();
   const uint32_t hi = randi32 () & 0x1FFFFF;
@@ -381,7 +381,7 @@
 #endif
 }
 
-static uint64_t randi54 (void)
+static uint64_t randi54 ()
 {
   const uint32_t lo = randi32 ();
   const uint32_t hi = randi32 () & 0x3FFFFF;
@@ -397,7 +397,7 @@
 }
 
 /* generates a random number on (0,1)-real-interval */
-static float randu24 (void)
+static float randu24 ()
 {
   uint32_t i;
 
@@ -411,7 +411,7 @@
 }
 
 /* generates a random number on (0,1) with 53-bit resolution */
-static double randu53 (void)
+static double randu53 ()
 {
   int32_t a, b;
 
@@ -428,7 +428,7 @@
 /* Determine mantissa for uniform doubles */
 template <>
 OCTAVE_API double
-rand_uniform<double> (void)
+rand_uniform<double> ()
 {
   return randu53 ();
 }
@@ -436,7 +436,7 @@
 /* Determine mantissa for uniform floats */
 template <>
 OCTAVE_API float
-rand_uniform<float> (void)
+rand_uniform<float> ()
 {
   return randu24 ();
 }
@@ -503,7 +503,7 @@
   so I'm not going to try and optimize further.
 */
 
-void create_ziggurat_tables (void)
+void create_ziggurat_tables ()
 {
   int i;
   double x, x1;
@@ -582,7 +582,7 @@
  */
 
 
-template <> OCTAVE_API double rand_normal<double> (void)
+template <> OCTAVE_API double rand_normal<double> ()
 {
                                                    if (initt)
                                                    create_ziggurat_tables ();
@@ -646,7 +646,7 @@
     }
 }
 
-template <> OCTAVE_API double rand_exponential<double> (void)
+template <> OCTAVE_API double rand_exponential<double> ()
 {
                                                         if (initt)
                                                         create_ziggurat_tables ();
@@ -674,17 +674,17 @@
 
 template <> OCTAVE_API void rand_uniform<double> (octave_idx_type n, double *p)
 {
-                                                  std::generate_n (p, n, [](void) { return rand_uniform<double> (); });
+                                                  std::generate_n (p, n, []() { return rand_uniform<double> (); });
 }
 
 template <> OCTAVE_API void rand_normal (octave_idx_type n, double *p)
 {
-                                         std::generate_n (p, n, [](void) { return rand_normal<double> (); });
+                                         std::generate_n (p, n, []() { return rand_normal<double> (); });
 }
 
 template <> OCTAVE_API void rand_exponential (octave_idx_type n, double *p)
 {
-                                              std::generate_n (p, n, [](void) { return rand_exponential<double> (); });
+                                              std::generate_n (p, n, []() { return rand_exponential<double> (); });
 }
 
 #undef ZIGINT
@@ -706,7 +706,7 @@
 static ZIGINT fke[ZIGGURAT_TABLE_SIZE];
 static float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE];
 
-static void create_ziggurat_float_tables (void)
+static void create_ziggurat_float_tables ()
 {
   int i;
   float x, x1;
@@ -784,7 +784,7 @@
  * distribution is exp(-0.5*x*x)
  */
 
-template <> OCTAVE_API float rand_normal<float> (void)
+template <> OCTAVE_API float rand_normal<float> ()
 {
                                                  if (inittf)
                                                  create_ziggurat_float_tables ();
@@ -824,7 +824,7 @@
     }
 }
 
-template <> OCTAVE_API float rand_exponential<float> (void)
+template <> OCTAVE_API float rand_exponential<float> ()
 {
                                                       if (inittf)
                                                       create_ziggurat_float_tables ();
@@ -852,17 +852,17 @@
 
 template <> OCTAVE_API void rand_uniform (octave_idx_type n, float *p)
 {
-                                          std::generate_n (p, n, [](void) { return rand_uniform<float> (); });
+                                          std::generate_n (p, n, []() { return rand_uniform<float> (); });
 }
 
 template <> OCTAVE_API void rand_normal (octave_idx_type n, float *p)
 {
-                                         std::generate_n (p, n, [](void) { return rand_normal<float> (); });
+                                         std::generate_n (p, n, []() { return rand_normal<float> (); });
 }
 
 template <> OCTAVE_API void rand_exponential (octave_idx_type n, float *p)
 {
-                                              std::generate_n (p, n, [](void) { return rand_exponential<float> (); });
+                                              std::generate_n (p, n, []() { return rand_exponential<float> (); });
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/numeric/randmtzig.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/randmtzig.h	Fri Jun 23 20:51:51 2023 +0200
@@ -75,7 +75,7 @@
 
 // Mersenne Twister.
 
-extern OCTAVE_API void init_mersenne_twister (void);
+extern OCTAVE_API void init_mersenne_twister ();
 extern OCTAVE_API void init_mersenne_twister (const uint32_t seed);
 extern OCTAVE_API void init_mersenne_twister (const uint32_t *init_key,
                                               const int key_length);
@@ -83,22 +83,22 @@
 extern OCTAVE_API void set_mersenne_twister_state (const uint32_t *save);
 extern OCTAVE_API void get_mersenne_twister_state (uint32_t *save);
 
-template <typename T> OCTAVE_API T rand_uniform (void);
-template <typename T> OCTAVE_API T rand_normal (void);
-template <typename T> OCTAVE_API T rand_exponential (void);
+template <typename T> OCTAVE_API T rand_uniform ();
+template <typename T> OCTAVE_API T rand_normal ();
+template <typename T> OCTAVE_API T rand_exponential ();
 
 template <typename T> OCTAVE_API void rand_uniform (octave_idx_type n, T *p);
 template <typename T> OCTAVE_API void rand_normal (octave_idx_type n, T *p);
 template <typename T> OCTAVE_API void
 rand_exponential (octave_idx_type n, T *p);
 
-template <> OCTAVE_API double rand_uniform<double> (void);
-template <> OCTAVE_API double rand_normal<double> (void);
-template <> OCTAVE_API double rand_exponential<double> (void);
+template <> OCTAVE_API double rand_uniform<double> ();
+template <> OCTAVE_API double rand_normal<double> ();
+template <> OCTAVE_API double rand_exponential<double> ();
 
-template <> OCTAVE_API float rand_uniform<float> (void);
-template <> OCTAVE_API float rand_normal<float> (void);
-template <> OCTAVE_API float rand_exponential<float> (void);
+template <> OCTAVE_API float rand_uniform<float> ();
+template <> OCTAVE_API float rand_normal<float> ();
+template <> OCTAVE_API float rand_exponential<float> ();
 
 template <> OCTAVE_API void
 rand_uniform<double> (octave_idx_type n, double *p);
--- a/liboctave/numeric/schur.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/schur.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,7 +47,7 @@
 {
 public:
 
-  schur (void) : m_schur_mat (), m_unitary_schur_mat () { }
+  schur () : m_schur_mat (), m_unitary_schur_mat () { }
 
   schur (const T& a, const std::string& ord, bool calc_unitary = true)
     : m_schur_mat (), m_unitary_schur_mat ()
@@ -84,11 +84,11 @@
     return *this;
   }
 
-  ~schur (void) = default;
+  ~schur () = default;
 
-  T schur_matrix (void) const { return m_schur_mat; }
+  T schur_matrix () const { return m_schur_mat; }
 
-  T unitary_schur_matrix (void) const { return m_unitary_schur_mat; }
+  T unitary_schur_matrix () const { return m_unitary_schur_mat; }
 
 protected:
 
--- a/liboctave/numeric/sparse-chol.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-chol.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 {
 public:
 
-  sparse_chol_rep (void)
+  sparse_chol_rep ()
     : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0)
 #if defined (HAVE_CHOLMOD)
     , m_L (nullptr), m_common ()
@@ -76,13 +76,9 @@
     info = init (a, natural, force);
   }
 
-  // No copying!
-
-  sparse_chol_rep (const sparse_chol_rep&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (sparse_chol_rep)
 
-  sparse_chol_rep& operator = (const sparse_chol_rep&) = delete;
-
-  ~sparse_chol_rep (void)
+  ~sparse_chol_rep ()
   {
 #if defined (HAVE_CHOLMOD)
     if (m_L)
@@ -93,13 +89,13 @@
   }
 
 #if defined (HAVE_CHOLMOD)
-  cholmod_sparse * L (void) const
+  cholmod_sparse * L () const
   {
     return m_L;
   }
 #endif
 
-  octave_idx_type P (void) const
+  octave_idx_type P () const
   {
 #if defined (HAVE_CHOLMOD)
     return (m_minor_p == static_cast<octave_idx_type> (m_L->ncol) ?
@@ -109,13 +105,13 @@
 #endif
   }
 
-  RowVector perm (void) const { return m_perm + 1; }
+  RowVector perm () const { return m_perm + 1; }
 
-  SparseMatrix Q (void) const;
+  SparseMatrix Q () const;
 
-  bool is_positive_definite (void) const { return m_is_pd; }
+  bool is_positive_definite () const { return m_is_pd; }
 
-  double rcond (void) const { return m_rcond; }
+  double rcond () const { return m_rcond; }
 
 private:
 
@@ -186,18 +182,18 @@
 // Must provide a specialization for this function.
 template <typename T>
 int
-get_xtype (void);
+get_xtype ();
 
 template <>
 inline int
-get_xtype<double> (void)
+get_xtype<double> ()
 {
   return CHOLMOD_REAL;
 }
 
 template <>
 inline int
-get_xtype<Complex> (void)
+get_xtype<Complex> ()
 {
   return CHOLMOD_COMPLEX;
 }
@@ -352,7 +348,7 @@
 
 template <typename chol_type>
 SparseMatrix
-sparse_chol<chol_type>::sparse_chol_rep::Q (void) const
+sparse_chol<chol_type>::sparse_chol_rep::Q () const
 {
 #if defined (HAVE_CHOLMOD)
 
@@ -378,7 +374,7 @@
 }
 
 template <typename chol_type>
-sparse_chol<chol_type>::sparse_chol (void)
+sparse_chol<chol_type>::sparse_chol ()
   : m_rep (new typename sparse_chol<chol_type>::sparse_chol_rep ())
 { }
 
@@ -414,7 +410,7 @@
 
 template <typename chol_type>
 chol_type
-sparse_chol<chol_type>::L (void) const
+sparse_chol<chol_type>::L () const
 {
 #if defined (HAVE_CHOLMOD)
 
@@ -445,42 +441,42 @@
 
 template <typename chol_type>
 octave_idx_type
-sparse_chol<chol_type>::P (void) const
+sparse_chol<chol_type>::P () const
 {
   return m_rep->P ();
 }
 
 template <typename chol_type>
 RowVector
-sparse_chol<chol_type>::perm (void) const
+sparse_chol<chol_type>::perm () const
 {
   return m_rep->perm ();
 }
 
 template <typename chol_type>
 SparseMatrix
-sparse_chol<chol_type>::Q (void) const
+sparse_chol<chol_type>::Q () const
 {
   return m_rep->Q ();
 }
 
 template <typename chol_type>
 bool
-sparse_chol<chol_type>::is_positive_definite (void) const
+sparse_chol<chol_type>::is_positive_definite () const
 {
   return m_rep->is_positive_definite ();
 }
 
 template <typename chol_type>
 double
-sparse_chol<chol_type>::rcond (void) const
+sparse_chol<chol_type>::rcond () const
 {
   return m_rep->rcond ();
 }
 
 template <typename chol_type>
 chol_type
-sparse_chol<chol_type>::inverse (void) const
+sparse_chol<chol_type>::inverse () const
 {
   chol_type retval;
 
--- a/liboctave/numeric/sparse-chol.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-chol.h	Fri Jun 23 20:51:51 2023 +0200
@@ -50,7 +50,7 @@
 {
 public:
 
-  sparse_chol (void);
+  sparse_chol ();
 
   sparse_chol (const chol_type& a, bool natural, bool force);
 
@@ -63,26 +63,26 @@
 
   sparse_chol (const sparse_chol<chol_type>& a) = default;
 
-  virtual ~sparse_chol (void) = default;
+  virtual ~sparse_chol () = default;
 
   sparse_chol<chol_type>&
   operator = (const sparse_chol<chol_type>& a) = default;
 
-  chol_type L (void) const;
+  chol_type L () const;
 
-  chol_type R (void) const { return L ().hermitian (); }
+  chol_type R () const { return L ().hermitian (); }
 
-  octave_idx_type P (void) const;
+  octave_idx_type P () const;
 
-  RowVector perm (void) const;
+  RowVector perm () const;
 
-  SparseMatrix Q (void) const;
+  SparseMatrix Q () const;
 
-  bool is_positive_definite (void) const;
+  bool is_positive_definite () const;
 
-  double rcond (void) const;
+  double rcond () const;
 
-  chol_type inverse (void) const;
+  chol_type inverse () const;
 
 protected:
 
--- a/liboctave/numeric/sparse-lu.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-lu.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -863,7 +863,7 @@
 
 template <typename lu_type>
 lu_type
-sparse_lu<lu_type>::Y (void) const
+sparse_lu<lu_type>::Y () const
 {
   octave_idx_type nr = m_L.rows ();
   octave_idx_type nz = m_L.cols ();
@@ -900,7 +900,7 @@
 
 template <typename lu_type>
 SparseMatrix
-sparse_lu<lu_type>::Pr (void) const
+sparse_lu<lu_type>::Pr () const
 {
   octave_idx_type nr = m_L.rows ();
 
@@ -920,7 +920,7 @@
 
 template <typename lu_type>
 ColumnVector
-sparse_lu<lu_type>::Pr_vec (void) const
+sparse_lu<lu_type>::Pr_vec () const
 {
   octave_idx_type nr = m_L.rows ();
 
@@ -934,14 +934,14 @@
 
 template <typename lu_type>
 PermMatrix
-sparse_lu<lu_type>::Pr_mat (void) const
+sparse_lu<lu_type>::Pr_mat () const
 {
   return PermMatrix (m_P, false);
 }
 
 template <typename lu_type>
 SparseMatrix
-sparse_lu<lu_type>::Pc (void) const
+sparse_lu<lu_type>::Pc () const
 {
   octave_idx_type nc = m_U.cols ();
 
@@ -961,7 +961,7 @@
 
 template <typename lu_type>
 ColumnVector
-sparse_lu<lu_type>::Pc_vec (void) const
+sparse_lu<lu_type>::Pc_vec () const
 {
   octave_idx_type nc = m_U.cols ();
 
@@ -975,7 +975,7 @@
 
 template <typename lu_type>
 PermMatrix
-sparse_lu<lu_type>::Pc_mat (void) const
+sparse_lu<lu_type>::Pc_mat () const
 {
   return PermMatrix (m_Q, true);
 }
--- a/liboctave/numeric/sparse-lu.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-lu.h	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 
   typedef typename lu_type::element_type lu_elt_type;
 
-  sparse_lu (void)
+  sparse_lu ()
     : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () { }
 
   OCTAVE_API
@@ -84,33 +84,33 @@
     return *this;
   }
 
-  virtual ~sparse_lu (void) = default;
+  virtual ~sparse_lu () = default;
 
-  lu_type L (void) const { return m_L; }
+  lu_type L () const { return m_L; }
 
-  lu_type U (void) const { return m_U; }
+  lu_type U () const { return m_U; }
 
-  SparseMatrix R (void) const { return m_R; }
+  SparseMatrix R () const { return m_R; }
 
-  OCTAVE_API lu_type Y (void) const;
+  OCTAVE_API lu_type Y () const;
 
-  OCTAVE_API SparseMatrix Pc (void) const;
+  OCTAVE_API SparseMatrix Pc () const;
 
-  OCTAVE_API SparseMatrix Pr (void) const;
+  OCTAVE_API SparseMatrix Pr () const;
 
-  OCTAVE_API ColumnVector Pc_vec (void) const;
+  OCTAVE_API ColumnVector Pc_vec () const;
 
-  OCTAVE_API ColumnVector Pr_vec (void) const;
+  OCTAVE_API ColumnVector Pr_vec () const;
 
-  OCTAVE_API PermMatrix Pc_mat (void) const;
+  OCTAVE_API PermMatrix Pc_mat () const;
 
-  OCTAVE_API PermMatrix Pr_mat (void) const;
+  OCTAVE_API PermMatrix Pr_mat () const;
 
-  const octave_idx_type * row_perm (void) const { return m_P.data (); }
+  const octave_idx_type * row_perm () const { return m_P.data (); }
 
-  const octave_idx_type * col_perm (void) const { return m_Q.data (); }
+  const octave_idx_type * col_perm () const { return m_Q.data (); }
 
-  double rcond (void) const { return m_cond; }
+  double rcond () const { return m_cond; }
 
 protected:
 
--- a/liboctave/numeric/sparse-qr.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-qr.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -75,15 +75,11 @@
 
   sparse_qr_rep (const SPARSE_T& a, int order);
 
-  // No copying!
-
-  sparse_qr_rep (const sparse_qr_rep&) = delete;
-
-  sparse_qr_rep& operator = (const sparse_qr_rep&) = delete;
-
-  ~sparse_qr_rep (void);
-
-  bool ok (void) const
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (sparse_qr_rep)
+
+  ~sparse_qr_rep ();
+
+  bool ok () const
   {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
     return (m_H && m_Htau && m_HPinv && m_R && m_E);
@@ -94,13 +90,13 @@
 #endif
   }
 
-  SPARSE_T V (void) const;
-
-  ColumnVector Pinv (void) const;
-
-  ColumnVector P (void) const;
-
-  ColumnVector E (void) const;
+  SPARSE_T V () const;
+
+  ColumnVector Pinv () const;
+
+  ColumnVector P () const;
+
+  ColumnVector E () const;
 
   SPARSE_T R (bool econ) const;
 
@@ -149,7 +145,7 @@
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::sparse_qr_rep::Pinv (void) const
+sparse_qr<SPARSE_T>::sparse_qr_rep::Pinv () const
 {
 #if defined (HAVE_CXSPARSE)
 
@@ -169,7 +165,7 @@
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::sparse_qr_rep::P (void) const
+sparse_qr<SPARSE_T>::sparse_qr_rep::P () const
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
@@ -199,7 +195,7 @@
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::sparse_qr_rep::E (void) const
+sparse_qr<SPARSE_T>::sparse_qr_rep::E () const
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
@@ -570,7 +566,7 @@
 #endif
 
 template <>
-sparse_qr<SparseMatrix>::sparse_qr_rep::~sparse_qr_rep (void)
+sparse_qr<SparseMatrix>::sparse_qr_rep::~sparse_qr_rep ()
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
@@ -591,7 +587,7 @@
 
 template <>
 SparseMatrix
-sparse_qr<SparseMatrix>::sparse_qr_rep::V (void) const
+sparse_qr<SparseMatrix>::sparse_qr_rep::V () const
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
@@ -1507,7 +1503,7 @@
 #endif
 
 template <>
-sparse_qr<SparseComplexMatrix>::sparse_qr_rep::~sparse_qr_rep (void)
+sparse_qr<SparseComplexMatrix>::sparse_qr_rep::~sparse_qr_rep ()
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
@@ -1528,7 +1524,7 @@
 
 template <>
 SparseComplexMatrix
-sparse_qr<SparseComplexMatrix>::sparse_qr_rep::V (void) const
+sparse_qr<SparseComplexMatrix>::sparse_qr_rep::V () const
 {
 #if defined (HAVE_CXSPARSE)
   // Drop zeros from V and sort
@@ -2675,7 +2671,7 @@
 }
 
 template <typename SPARSE_T>
-sparse_qr<SPARSE_T>::sparse_qr (void)
+sparse_qr<SPARSE_T>::sparse_qr ()
   : m_rep (new sparse_qr_rep (SPARSE_T (), 0))
 { }
 
@@ -2686,35 +2682,35 @@
 
 template <typename SPARSE_T>
 bool
-sparse_qr<SPARSE_T>::ok (void) const
+sparse_qr<SPARSE_T>::ok () const
 {
   return m_rep->ok ();
 }
 
 template <typename SPARSE_T>
 SPARSE_T
-sparse_qr<SPARSE_T>::V (void) const
+sparse_qr<SPARSE_T>::V () const
 {
   return m_rep->V ();
 }
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::Pinv (void) const
+sparse_qr<SPARSE_T>::Pinv () const
 {
   return m_rep->P ();
 }
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::P (void) const
+sparse_qr<SPARSE_T>::P () const
 {
   return m_rep->P ();
 }
 
 template <typename SPARSE_T>
 ColumnVector
-sparse_qr<SPARSE_T>::E (void) const
+sparse_qr<SPARSE_T>::E () const
 {
   return m_rep->E();
 }
@@ -2722,7 +2718,7 @@
 
 template <typename SPARSE_T>
 SparseMatrix
-sparse_qr<SPARSE_T>::E_MAT (void) const
+sparse_qr<SPARSE_T>::E_MAT () const
 {
   ColumnVector perm = m_rep->E ();
   octave_idx_type nrows = perm.rows ();
@@ -3226,11 +3222,11 @@
 //explicit instantiations of member function E_MAT
 template
 OCTAVE_API SparseMatrix
-sparse_qr<SparseMatrix>::E_MAT (void) const;
+sparse_qr<SparseMatrix>::E_MAT () const;
 
 template
 OCTAVE_API SparseMatrix
-sparse_qr<SparseComplexMatrix>::E_MAT (void) const;
+sparse_qr<SparseComplexMatrix>::E_MAT () const;
 
 template <typename SPARSE_T>
 template <typename RHS_T, typename RET_T>
@@ -3250,33 +3246,33 @@
 
 // Explicitly instantiate all member functions
 
-template OCTAVE_API sparse_qr<SparseMatrix>::sparse_qr (void);
+template OCTAVE_API sparse_qr<SparseMatrix>::sparse_qr ();
 template OCTAVE_API
 sparse_qr<SparseMatrix>::sparse_qr (const SparseMatrix& a, int order);
-template OCTAVE_API bool sparse_qr<SparseMatrix>::ok (void) const;
-template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::E (void) const;
-template OCTAVE_API SparseMatrix sparse_qr<SparseMatrix>::V (void) const;
-template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::Pinv (void) const;
-template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::P (void) const;
+template OCTAVE_API bool sparse_qr<SparseMatrix>::ok () const;
+template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::E () const;
+template OCTAVE_API SparseMatrix sparse_qr<SparseMatrix>::V () const;
+template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::Pinv () const;
+template OCTAVE_API ColumnVector sparse_qr<SparseMatrix>::P () const;
 template OCTAVE_API SparseMatrix
 sparse_qr<SparseMatrix>::R (bool econ) const;
 template OCTAVE_API Matrix
 sparse_qr<SparseMatrix>::C (const Matrix& b, bool econ) const;
 template OCTAVE_API Matrix sparse_qr<SparseMatrix>::Q (bool econ) const;
 
-template OCTAVE_API sparse_qr<SparseComplexMatrix>::sparse_qr (void);
+template OCTAVE_API sparse_qr<SparseComplexMatrix>::sparse_qr ();
 template OCTAVE_API
 sparse_qr<SparseComplexMatrix>::sparse_qr
 (const SparseComplexMatrix& a, int order);
-template OCTAVE_API bool sparse_qr<SparseComplexMatrix>::ok (void) const;
+template OCTAVE_API bool sparse_qr<SparseComplexMatrix>::ok () const;
 template OCTAVE_API ColumnVector
-sparse_qr<SparseComplexMatrix>::E (void) const;
+sparse_qr<SparseComplexMatrix>::E () const;
 template OCTAVE_API SparseComplexMatrix
-sparse_qr<SparseComplexMatrix>::V (void) const;
+sparse_qr<SparseComplexMatrix>::V () const;
 template OCTAVE_API ColumnVector
-sparse_qr<SparseComplexMatrix>::Pinv (void) const;
+sparse_qr<SparseComplexMatrix>::Pinv () const;
 template OCTAVE_API ColumnVector
-sparse_qr<SparseComplexMatrix>::P (void) const;
+sparse_qr<SparseComplexMatrix>::P () const;
 template OCTAVE_API SparseComplexMatrix
 sparse_qr<SparseComplexMatrix>::R (bool econ) const;
 template OCTAVE_API ComplexMatrix
--- a/liboctave/numeric/sparse-qr.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/sparse-qr.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,7 +49,7 @@
 {
 public:
 
-  OCTAVE_API sparse_qr (void);
+  OCTAVE_API sparse_qr ();
 
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
   // order = 7 selects SPQR default ordering
@@ -60,22 +60,22 @@
 
   sparse_qr (const sparse_qr& a) = default;
 
-  ~sparse_qr (void) = default;
+  ~sparse_qr () = default;
 
   sparse_qr& operator = (const sparse_qr& a) = default;
 
-  OCTAVE_API bool ok (void) const;
+  OCTAVE_API bool ok () const;
 
-  OCTAVE_API ColumnVector E (void) const;
+  OCTAVE_API ColumnVector E () const;
 
   // constructs permutation matrix from permutation vector rep -> E()
   OCTAVE_API SparseMatrix E_MAT () const;
 
-  OCTAVE_API SPARSE_T V (void) const;
+  OCTAVE_API SPARSE_T V () const;
 
-  OCTAVE_API ColumnVector Pinv (void) const;
+  OCTAVE_API ColumnVector Pinv () const;
 
-  OCTAVE_API ColumnVector P (void) const;
+  OCTAVE_API ColumnVector P () const;
 
   OCTAVE_API SPARSE_T R (bool econ = false) const;
 
--- a/liboctave/numeric/svd.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/svd.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,8 @@
 gejsv_lwork
 {
 public:
-  gejsv_lwork () = delete;
+
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (gejsv_lwork)
 
   // Unfortunately, dgejsv and sgejsv do not provide estimation of 'lwork'.
   // Thus, we have to estimate it according to corresponding LAPACK
@@ -307,7 +308,7 @@
 
 template <typename T>
 T
-svd<T>::left_singular_matrix (void) const
+svd<T>::left_singular_matrix () const
 {
   if (m_type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
@@ -318,7 +319,7 @@
 
 template <typename T>
 T
-svd<T>::right_singular_matrix (void) const
+svd<T>::right_singular_matrix () const
 {
   if (m_type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
--- a/liboctave/numeric/svd.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/numeric/svd.h	Fri Jun 23 20:51:51 2023 +0200
@@ -57,7 +57,7 @@
     GEJSV
   };
 
-  svd (void)
+  svd ()
     : m_type (), m_driver (), m_left_sm (), m_sigma (), m_right_sm ()
   { }
 
@@ -83,13 +83,13 @@
     return *this;
   }
 
-  ~svd (void) = default;
+  ~svd () = default;
 
-  T left_singular_matrix (void) const;
+  T left_singular_matrix () const;
 
-  DM_T singular_values (void) const { return m_sigma; }
+  DM_T singular_values () const { return m_sigma; }
 
-  T right_singular_matrix (void) const;
+  T right_singular_matrix () const;
 
 private:
 
--- a/liboctave/system/child-list.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/child-list.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
   m_list.append (child (pid, f));
 }
 
-void child_list::reap (void)
+void child_list::reap ()
 {
   // Mark the record for PID invalid.
 
@@ -70,7 +70,7 @@
 
 // Wait on our children and record any changes in their status.
 
-bool child_list::wait (void)
+bool child_list::wait ()
 {
   bool retval = false;
 
--- a/liboctave/system/child-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/child-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -56,7 +56,7 @@
 
   child& operator = (const child&) = default;
 
-  ~child (void) = default;
+  ~child () = default;
 
   // The process ID of this child.
   pid_t m_pid;
@@ -76,15 +76,15 @@
 {
 public:
 
-  child_list (void) { }
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (child_list)
 
   void insert (pid_t pid, child::child_event_handler f);
 
   void remove (pid_t pid);
 
-  void reap (void);
+  void reap ();
 
-  bool wait (void);
+  bool wait ();
 
 private:
 
--- a/liboctave/system/dir-ops.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/dir-ops.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -70,7 +70,7 @@
 }
 
 string_vector
-dir_entry::read (void)
+dir_entry::read ()
 {
   string_vector retval;
 
@@ -90,7 +90,7 @@
 }
 
 bool
-dir_entry::close (void)
+dir_entry::close ()
 {
   bool retval = true;
 
@@ -105,7 +105,7 @@
 }
 
 unsigned int
-dir_entry::max_name_length (void)
+dir_entry::max_name_length ()
 {
   return octave_name_max_wrapper ();
 }
--- a/liboctave/system/dir-ops.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/dir-ops.h	Fri Jun 23 20:51:51 2023 +0200
@@ -73,21 +73,21 @@
     return *this;
   }
 
-  ~dir_entry (void) { close (); }
+  ~dir_entry () { close (); }
 
   bool open (const std::string& = "");
 
-  string_vector read (void);
+  string_vector read ();
 
-  bool close (void);
+  bool close ();
 
-  bool ok (void) const { return m_dir && ! m_fail; }
+  bool ok () const { return m_dir && ! m_fail; }
 
   operator bool () const { return ok (); }
 
-  std::string error (void) const { return ok () ? "" : m_errmsg; }
+  std::string error () const { return ok () ? "" : m_errmsg; }
 
-  static unsigned int max_name_length (void);
+  static unsigned int max_name_length ();
 
 private:
 
--- a/liboctave/system/file-ops.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/file-ops.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -219,7 +219,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(file_ops)
 
-char dev_sep_char (void)
+char dev_sep_char ()
 {
 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
   return ':';
@@ -228,7 +228,7 @@
 #endif
 }
 
-char dir_sep_char (void)
+char dir_sep_char ()
 {
 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
   return '\\';
@@ -237,7 +237,7 @@
 #endif
 }
 
-std::string dir_sep_str (void)
+std::string dir_sep_str ()
 {
 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
   return R"(\)";
@@ -246,7 +246,7 @@
 #endif
 }
 
-std::string dir_sep_chars (void)
+std::string dir_sep_chars ()
 {
 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
   return R"(/\)";
@@ -569,6 +569,26 @@
 
   msg = "";
 
+  // Do nothing if source and target are the same file.
+  if (same_file (to, from))
+    return 0;
+
+  // The behavior of std::rename with existing target is not defined by the
+  // standard.  Implementations differ vastly.  For Octave, use the following
+  // for the case that the target already exists:
+  // If the source and the target are regular files, overwrite the target.
+  // In other cases, fail.
+  if (file_exists (to))
+    {
+      if (file_exists (to, false) && file_exists (from, false))
+        unlink (to);
+      else
+        {
+          msg = "Target already exists.";
+          return status;
+        }
+    }
+
 #if defined (OCTAVE_USE_WINDOWS_API)
   std::wstring wfrom = u8_to_wstring (from);
   std::wstring wto = u8_to_wstring (to);
--- a/liboctave/system/file-ops.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/file-ops.h	Fri Jun 23 20:51:51 2023 +0200
@@ -75,15 +75,15 @@
 // text which identified this tilde starter in LEN, excluding the
 // tilde itself.
 
-extern OCTAVE_API char dev_sep_char (void);
+extern OCTAVE_API char dev_sep_char ();
 
 extern OCTAVE_API bool is_dev_sep (char c);
 
-extern OCTAVE_API char dir_sep_char (void);
+extern OCTAVE_API char dir_sep_char ();
 
-extern OCTAVE_API std::string dir_sep_str (void);
+extern OCTAVE_API std::string dir_sep_str ();
 
-extern OCTAVE_API std::string dir_sep_chars (void);
+extern OCTAVE_API std::string dir_sep_chars ();
 
 extern OCTAVE_API bool is_dir_sep (char c);
 
--- a/liboctave/system/file-stat.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/file-stat.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -50,43 +50,43 @@
 // initialized, they should throw an exception.
 
 bool
-base_file_stat::is_blk (void) const
+base_file_stat::is_blk () const
 {
   return exists () && is_blk (m_mode);
 }
 
 bool
-base_file_stat::is_chr (void) const
+base_file_stat::is_chr () const
 {
   return exists () && is_chr (m_mode);
 }
 
 bool
-base_file_stat::is_dir (void) const
+base_file_stat::is_dir () const
 {
   return exists () && is_dir (m_mode);
 }
 
 bool
-base_file_stat::is_fifo (void) const
+base_file_stat::is_fifo () const
 {
   return exists () && is_fifo (m_mode);
 }
 
 bool
-base_file_stat::is_lnk (void) const
+base_file_stat::is_lnk () const
 {
   return exists () && is_lnk (m_mode);
 }
 
 bool
-base_file_stat::is_reg (void) const
+base_file_stat::is_reg () const
 {
   return exists () && is_reg (m_mode);
 }
 
 bool
-base_file_stat::is_sock (void) const
+base_file_stat::is_sock () const
 {
   return exists () && is_sock (m_mode);
 }
@@ -134,25 +134,25 @@
 }
 
 bool
-base_file_stat::have_struct_stat_st_rdev (void)
+base_file_stat::have_struct_stat_st_rdev ()
 {
   return ::octave_have_struct_stat_st_rdev ();
 }
 
 bool
-base_file_stat::have_struct_stat_st_blksize (void)
+base_file_stat::have_struct_stat_st_blksize ()
 {
   return octave_have_struct_stat_st_blksize ();
 }
 
 bool
-base_file_stat::have_struct_stat_st_blocks (void)
+base_file_stat::have_struct_stat_st_blocks ()
 {
   return octave_have_struct_stat_st_blocks ();
 }
 
 std::string
-base_file_stat::mode_as_string (void) const
+base_file_stat::mode_as_string () const
 {
   char buf[12];
 
--- a/liboctave/system/file-stat.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/file-stat.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 {
 public:
 
-  base_file_stat (void)
+  base_file_stat ()
     : m_initialized (false), m_fail (false), m_errmsg (), m_mode (),
       m_ino (), m_dev (), m_nlink (), m_uid (), m_gid (),
       m_size (), m_atime (), m_mtime (), m_ctime (), m_rdev (),
@@ -86,7 +86,7 @@
   // The minimum difference in file time stamp values.
   // FIXME: This value should come from the filesystem itself.
   //        How can we get that info?
-  sys::time time_resolution (void) const
+  sys::time time_resolution () const
   {
     static sys::time resolution (1.0);
     return resolution;
@@ -97,13 +97,13 @@
   // should all return 0 (or the equivalent, for the given object)
   // which is likely not meaningful.
 
-  bool is_blk (void) const;
-  bool is_chr (void) const;
-  bool is_dir (void) const;
-  bool is_fifo (void) const;
-  bool is_lnk (void) const;
-  bool is_reg (void) const;
-  bool is_sock (void) const;
+  bool is_blk () const;
+  bool is_chr () const;
+  bool is_dir () const;
+  bool is_fifo () const;
+  bool is_lnk () const;
+  bool is_reg () const;
+  bool is_sock () const;
 
   static bool is_blk (mode_t mode);
   static bool is_chr (mode_t mode);
@@ -113,40 +113,40 @@
   static bool is_reg (mode_t mode);
   static bool is_sock (mode_t mode);
 
-  static bool have_struct_stat_st_rdev (void);
-  static bool have_struct_stat_st_blksize (void);
-  static bool have_struct_stat_st_blocks (void);
+  static bool have_struct_stat_st_rdev ();
+  static bool have_struct_stat_st_blksize ();
+  static bool have_struct_stat_st_blocks ();
 
-  ino_t ino (void) const { return m_ino; }
-  dev_t dev (void) const { return m_dev; }
+  ino_t ino () const { return m_ino; }
+  dev_t dev () const { return m_dev; }
 
-  nlink_t nlink (void) const { return m_nlink; }
+  nlink_t nlink () const { return m_nlink; }
 
-  uid_t uid (void) const { return m_uid; }
-  gid_t gid (void) const { return m_gid; }
+  uid_t uid () const { return m_uid; }
+  gid_t gid () const { return m_gid; }
 
-  off_t size (void) const { return m_size; }
+  off_t size () const { return m_size; }
 
-  sys::time atime (void) const { return m_atime; }
-  sys::time mtime (void) const { return m_mtime; }
-  sys::time ctime (void) const { return m_ctime; }
+  sys::time atime () const { return m_atime; }
+  sys::time mtime () const { return m_mtime; }
+  sys::time ctime () const { return m_ctime; }
 
-  dev_t rdev (void) const { return m_rdev; }
+  dev_t rdev () const { return m_rdev; }
 
-  long blksize (void) const { return m_blksize; }
-  long blocks (void) const { return m_blocks; }
+  long blksize () const { return m_blksize; }
+  long blocks () const { return m_blocks; }
 
-  mode_t mode (void) const { return m_mode; }
+  mode_t mode () const { return m_mode; }
 
-  std::string mode_as_string (void) const;
+  std::string mode_as_string () const;
 
-  bool ok (void) const { return m_initialized && ! m_fail; }
+  bool ok () const { return m_initialized && ! m_fail; }
 
   operator bool () const { return ok (); }
 
-  bool exists (void) const { return ok (); }
+  bool exists () const { return ok (); }
 
-  std::string error (void) const { return ok () ? "" : m_errmsg; }
+  std::string error () const { return ok () ? "" : m_errmsg; }
 
   // Has the file referenced by this object been modified since TIME?
   bool is_newer (const sys::time& time) const { return m_mtime > time; }
@@ -157,7 +157,7 @@
 
 protected:
 
-  virtual ~base_file_stat (void) = default;
+  virtual ~base_file_stat () = default;
 
   // TRUE means we have already called stat.
   bool m_initialized;
@@ -237,7 +237,7 @@
 
   // This destructor must remain as an empty destructor defined in the
   // cpp file rather than in the header file (bug #50234).
-  ~file_stat (void);
+  ~file_stat ();
 
   void get_stats (bool force = false)
   {
@@ -275,27 +275,14 @@
 {
 public:
 
+  file_fstat () = delete;
+
   file_fstat (int n) : base_file_stat (), m_fid (n)
   {
     update_internal ();
   }
 
-  file_fstat (const file_fstat& fs)
-    : base_file_stat (fs), m_fid (fs.m_fid) { }
-
-  file_fstat& operator = (const file_fstat& fs)
-  {
-    if (this != &fs)
-      {
-        base_file_stat::operator = (fs);
-
-        m_fid = fs.m_fid;
-      }
-
-    return *this;
-  }
-
-  ~file_fstat (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (file_fstat)
 
   void get_stats (bool force = false)
   {
--- a/liboctave/system/lo-sysdep.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/lo-sysdep.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,6 +33,7 @@
 
 #include "dir-ops.h"
 #include "file-ops.h"
+#include "file-stat.h"
 #include "lo-error.h"
 #include "lo-sysdep.h"
 #include "localcharset-wrapper.h"
@@ -68,7 +69,7 @@
 }
 
 std::string
-getcwd (void)
+getcwd ()
 {
   std::string retval;
 
@@ -308,8 +309,202 @@
   return strcmp (buf1, buf2);
 }
 
+static std::string
+get_formatted_last_error ()
+{
+  std::string msg = "";
+
+  DWORD last_error = GetLastError ();
+
+  wchar_t *error_text = nullptr;
+  FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  nullptr, last_error,
+                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  reinterpret_cast <wchar_t *> (&error_text), 0, nullptr);
+
+  if (error_text != nullptr)
+    {
+      msg = u8_from_wstring (error_text);
+      LocalFree (error_text);
+    }
+  else
+    msg = "Unknown error.";
+
+  return msg;
+}
 #endif
 
+bool
+file_exists (const std::string& filename, bool is_dir)
+{
+  // Check if a file with the given name exists on the file system.  If is_dir
+  // is true (the default), also return true if filename refers to a directory.
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::wstring w_fn = u8_to_wstring (filename);
+
+  DWORD f_attr = GetFileAttributesW (w_fn.c_str ());
+
+  return ((f_attr != INVALID_FILE_ATTRIBUTES)
+          && (is_dir || ! (f_attr & FILE_ATTRIBUTE_DIRECTORY)));
+
+#else
+  file_stat fs (filename);
+
+  return (fs && (fs.is_reg () || (is_dir && fs.is_dir ())));
+
+#endif
+}
+
+bool
+file_exists (const std::string& filename, bool is_dir, std::string& msg)
+{
+  // Check if a file with the given name exists on the file system.  If is_dir
+  // is true (the default), also return true if filename refers to a directory.
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::wstring w_fn = u8_to_wstring (filename);
+
+  DWORD f_attr = GetFileAttributesW (w_fn.c_str ());
+
+  if (f_attr == INVALID_FILE_ATTRIBUTES)
+    msg = get_formatted_last_error ();
+
+  return ((f_attr != INVALID_FILE_ATTRIBUTES)
+          && (is_dir || ! (f_attr & FILE_ATTRIBUTE_DIRECTORY)));
+
+#else
+  file_stat fs (filename);
+
+  if (! fs)
+    msg = fs.error ();
+
+  return (fs && (fs.is_reg () || (is_dir && fs.is_dir ())));
+
+#endif
+}
+
+bool
+dir_exists (const std::string& dirname)
+{
+  // Check if a directory with the given name exists on the file system.
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::wstring w_dn = u8_to_wstring (dirname);
+
+  DWORD f_attr = GetFileAttributesW (w_dn.c_str ());
+
+  return ((f_attr != INVALID_FILE_ATTRIBUTES)
+          && (f_attr & FILE_ATTRIBUTE_DIRECTORY));
+
+#else
+  file_stat fs (dirname);
+
+  return (fs && fs.is_dir ());
+
+#endif
+}
+
+bool
+dir_exists (const std::string& dirname, std::string& msg)
+{
+  // Check if a directory with the given name exists on the file system.
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::wstring w_dn = u8_to_wstring (dirname);
+
+  DWORD f_attr = GetFileAttributesW (w_dn.c_str ());
+
+  if (f_attr == INVALID_FILE_ATTRIBUTES)
+    msg = get_formatted_last_error ();
+
+  return ((f_attr != INVALID_FILE_ATTRIBUTES)
+          && (f_attr & FILE_ATTRIBUTE_DIRECTORY));
+
+#else
+  file_stat fs (dirname);
+
+  if (! fs)
+    msg = fs.error ();
+
+  return (fs && fs.is_dir ());
+
+#endif
+}
+
+// Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
+
+bool same_file (const std::string& file1, const std::string& file2)
+{
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+  // FIXME: When Octave switches to C++17, consider replacing this function
+  //        by https://en.cppreference.com/w/cpp/filesystem/equivalent.
+
+  bool retval = false;
+
+  std::wstring file1w = sys::u8_to_wstring (file1);
+  std::wstring file2w = sys::u8_to_wstring (file2);
+  const wchar_t *f1 = file1w.c_str ();
+  const wchar_t *f2 = file2w.c_str ();
+
+  bool f1_is_dir = GetFileAttributesW (f1) & FILE_ATTRIBUTE_DIRECTORY;
+  bool f2_is_dir = GetFileAttributesW (f2) & FILE_ATTRIBUTE_DIRECTORY;
+
+  // Windows native code
+  // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx
+
+  DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+  HANDLE hfile1
+    = CreateFileW (f1, 0, share, 0, OPEN_EXISTING,
+                   f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
+
+  if (hfile1 != INVALID_HANDLE_VALUE)
+    {
+      HANDLE hfile2
+        = CreateFileW (f2, 0, share, 0, OPEN_EXISTING,
+                       f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
+
+      if (hfile2 != INVALID_HANDLE_VALUE)
+        {
+          BY_HANDLE_FILE_INFORMATION hfi1;
+          BY_HANDLE_FILE_INFORMATION hfi2;
+
+          if (GetFileInformationByHandle (hfile1, &hfi1)
+              && GetFileInformationByHandle (hfile2, &hfi2))
+            {
+              retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber
+                        && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh
+                        && hfi1.nFileIndexLow == hfi2.nFileIndexLow
+                        && hfi1.nFileSizeHigh == hfi2.nFileSizeHigh
+                        && hfi1.nFileSizeLow == hfi2.nFileSizeLow
+                        && hfi1.ftLastWriteTime.dwLowDateTime
+                        == hfi2.ftLastWriteTime.dwLowDateTime
+                        && hfi1.ftLastWriteTime.dwHighDateTime
+                        == hfi2.ftLastWriteTime.dwHighDateTime);
+            }
+
+          CloseHandle (hfile2);
+        }
+
+      CloseHandle (hfile1);
+    }
+
+  return retval;
+
+#else
+
+  // POSIX Code
+
+  sys::file_stat fs_file1 (file1);
+  sys::file_stat fs_file2 (file2);
+
+  return (fs_file1 && fs_file2
+          && fs_file1.ino () == fs_file2.ino ()
+          && fs_file1.dev () == fs_file2.dev ());
+
+#endif
+}
+
 std::FILE *
 fopen (const std::string& filename, const std::string& mode)
 {
--- a/liboctave/system/lo-sysdep.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/lo-sysdep.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 
 extern OCTAVE_API int system (const std::string& cmd_str);
 
-extern OCTAVE_API std::string getcwd (void);
+extern OCTAVE_API std::string getcwd ();
 
 extern OCTAVE_API int chdir (const std::string&);
 
@@ -51,6 +51,20 @@
 get_dirlist (const std::string& dirname, string_vector& dirlist,
              std::string& msg);
 
+extern OCTAVE_API bool
+file_exists (const std::string& filename, bool is_dir = true);
+
+extern OCTAVE_API bool
+file_exists (const std::string& filename, bool is_dir, std::string& msg);
+
+extern OCTAVE_API bool dir_exists (const std::string& dirname);
+
+extern OCTAVE_API bool
+dir_exists (const std::string& dirname, std::string& msg);
+
+extern OCTAVE_API bool
+same_file (const std::string& f, const std::string& g);
+
 extern OCTAVE_API std::FILE *
 fopen (const std::string& name, const std::string& mode);
 
--- a/liboctave/system/lo-sysinfo.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/lo-sysinfo.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-std::string blas_version (void)
+std::string blas_version ()
 {
   dynamic_library dyn_libs ("");
 
@@ -73,7 +73,7 @@
     }
 
   // OpenBLAS
-  typedef char *(*open_fcn_type) (void);
+  typedef char *(*open_fcn_type) ();
   open_fcn_type open_f_ptr = reinterpret_cast<open_fcn_type>
                              (dyn_libs.search ("openblas_get_config"));
 
@@ -160,7 +160,7 @@
   return retval;
 }
 
-std::string lapack_version (void)
+std::string lapack_version ()
 {
   std::string retval = "unknown LAPACK";
 
--- a/liboctave/system/lo-sysinfo.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/lo-sysinfo.h	Fri Jun 23 20:51:51 2023 +0200
@@ -34,9 +34,9 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-extern OCTAVE_API std::string blas_version (void);
+extern OCTAVE_API std::string blas_version ();
 
-extern OCTAVE_API std::string lapack_version (void);
+extern OCTAVE_API std::string lapack_version ();
 
 OCTAVE_END_NAMESPACE(sys)
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/system/mach-info.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/mach-info.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(mach_info)
 
-static float_format get_float_format (void)
+static float_format get_float_format ()
 {
   switch (octave_get_float_format ())
     {
@@ -57,26 +57,26 @@
     }
 }
 
-static bool is_big_endian (void)
+static bool is_big_endian ()
 {
   return octave_is_big_endian ();
 }
 
-float_format native_float_format (void)
+float_format native_float_format ()
 {
   static float_format fmt = get_float_format ();
 
   return fmt;
 }
 
-bool words_big_endian (void)
+bool words_big_endian ()
 {
   static bool big_endian = is_big_endian ();
 
   return big_endian;
 }
 
-bool words_little_endian (void)
+bool words_little_endian ()
 {
   static bool little_endian = ! is_big_endian ();
 
--- a/liboctave/system/mach-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/mach-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,11 +44,11 @@
   flt_fmt_ieee_big_endian = 2,
 };
 
-OCTAVE_API float_format native_float_format (void);
+OCTAVE_API float_format native_float_format ();
 
-OCTAVE_API bool words_big_endian (void);
+OCTAVE_API bool words_big_endian ();
 
-OCTAVE_API bool words_little_endian (void);
+OCTAVE_API bool words_little_endian ();
 
 OCTAVE_API float_format string_to_float_format (const std::string&);
 
--- a/liboctave/system/oct-env.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-env.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -69,7 +69,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-env::env (void)
+env::env ()
   : m_follow_symbolic_links (true), m_verbatim_pwd (true),
     m_current_directory (), m_prog_name (), m_prog_invocation_name (),
     m_user_name (), m_host_name ()
@@ -83,16 +83,16 @@
   do_get_host_name ();
 }
 
-env *env::m_instance = nullptr;
+env *env::s_instance = nullptr;
 
 bool
-env::instance_ok (void)
+env::instance_ok ()
 {
   bool retval = true;
 
-  if (! m_instance)
+  if (! s_instance)
     {
-      m_instance = new env ();
+      s_instance = new env ();
       singleton_cleanup_list::add (cleanup_instance);
     }
 
@@ -103,109 +103,109 @@
 env::polite_directory_format (const std::string& name)
 {
   return (instance_ok ())
-         ? m_instance->do_polite_directory_format (name) : "";
+         ? s_instance->do_polite_directory_format (name) : "";
 }
 
 bool
 env::absolute_pathname (const std::string& s)
 {
   return (instance_ok ())
-         ? m_instance->do_absolute_pathname (s) : false;
+         ? s_instance->do_absolute_pathname (s) : false;
 }
 
 bool
 env::rooted_relative_pathname (const std::string& s)
 {
   return (instance_ok ())
-         ? m_instance->do_rooted_relative_pathname (s) : false;
+         ? s_instance->do_rooted_relative_pathname (s) : false;
 }
 
 std::string
 env::base_pathname (const std::string& s)
 {
   return (instance_ok ())
-         ? m_instance->do_base_pathname (s) : "";
+         ? s_instance->do_base_pathname (s) : "";
 }
 
 std::string
 env::make_absolute (const std::string& s, const std::string& dot_path)
 {
   return (instance_ok ())
-         ? m_instance->do_make_absolute (s, dot_path) : "";
+         ? s_instance->do_make_absolute (s, dot_path) : "";
 }
 
 std::string
 env::get_current_directory ()
 {
   return (instance_ok ())
-         ? m_instance->do_getcwd () : "";
+         ? s_instance->do_getcwd () : "";
 }
 
 std::string
 env::get_home_directory ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_home_directory () : "";
+         ? s_instance->do_get_home_directory () : "";
 }
 
 std::string
 env::get_temp_directory ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_temp_directory () : "";
+         ? s_instance->do_get_temp_directory () : "";
 }
 
 std::string
 env::get_user_config_directory ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_user_config_directory () : "";
+         ? s_instance->do_get_user_config_directory () : "";
 }
 
 std::string
 env::get_user_data_directory ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_user_data_directory () : "";
+         ? s_instance->do_get_user_data_directory () : "";
 }
 
 std::string
-env::get_program_name (void)
+env::get_program_name ()
 {
   return (instance_ok ())
-         ? m_instance->m_prog_name : "";
+         ? s_instance->m_prog_name : "";
 }
 
 std::string
-env::get_program_invocation_name (void)
+env::get_program_invocation_name ()
 {
   return (instance_ok ())
-         ? m_instance->m_prog_invocation_name : "";
+         ? s_instance->m_prog_invocation_name : "";
 }
 
 void
 env::set_program_name (const std::string& s)
 {
   if (instance_ok ())
-    m_instance->do_set_program_name (s);
+    s_instance->do_set_program_name (s);
 }
 
 std::string
-env::get_user_name (void)
+env::get_user_name ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_user_name () : "";
+         ? s_instance->do_get_user_name () : "";
 }
 
 std::string
-env::get_host_name (void)
+env::get_host_name ()
 {
   return (instance_ok ())
-         ? m_instance->do_get_host_name () : "";
+         ? s_instance->do_get_host_name () : "";
 }
 
 std::string
-env::do_get_temp_directory (void) const
+env::do_get_temp_directory () const
 {
   std::string tempd = do_getenv ("TMPDIR");
 
@@ -246,7 +246,7 @@
 }
 
 std::string
-env::do_get_user_config_directory (void)
+env::do_get_user_config_directory ()
 {
   std::string cfg_dir;
 
@@ -267,7 +267,7 @@
 }
 
 std::string
-env::do_get_user_data_directory (void)
+env::do_get_user_data_directory ()
 {
   std::string data_dir;
 
@@ -296,7 +296,7 @@
 env::getenv (const std::string& name)
 {
   return (instance_ok ())
-         ? m_instance->do_getenv (name) : "";
+         ? s_instance->do_getenv (name) : "";
 }
 
 void
@@ -306,7 +306,7 @@
 }
 
 bool
-env::have_x11_display (void)
+env::have_x11_display ()
 {
   std::string display = getenv ("DISPLAY");
 
@@ -317,7 +317,7 @@
 env::chdir (const std::string& newdir)
 {
   return (instance_ok ())
-         ? m_instance->do_chdir (newdir) : false;
+         ? s_instance->do_chdir (newdir) : false;
 }
 
 void
@@ -518,7 +518,7 @@
 // Return a string which is the current working directory.
 
 std::string
-env::do_getcwd (void)
+env::do_getcwd ()
 {
   if (! m_follow_symbolic_links)
     m_current_directory = "";
@@ -533,7 +533,7 @@
 // running.
 
 std::string
-env::do_get_home_directory (void)
+env::do_get_home_directory ()
 {
   std::string hd = do_getenv ("HOME");
 
@@ -560,7 +560,7 @@
 }
 
 std::string
-env::do_get_user_name (void)
+env::do_get_user_name ()
 {
   if (m_user_name.empty ())
     {
@@ -573,7 +573,7 @@
 }
 
 std::string
-env::do_get_host_name (void)
+env::do_get_host_name ()
 {
   if (m_host_name.empty ())
     {
--- a/liboctave/system/oct-env.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-env.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,15 +40,13 @@
 {
 protected:
 
-  env (void);
+  env ();
 
 public:
 
-  // No copying!
+  OCTAVE_DISABLE_COPY_MOVE (env)
 
-  env (const env&) = delete;
-
-  env& operator = (const env&) = delete;
+  ~env () = default;
 
   static std::string polite_directory_format (const std::string& name);
 
@@ -62,29 +60,29 @@
   make_absolute (const std::string& s,
                  const std::string& dot_path = get_current_directory ());
 
-  static std::string get_current_directory (void);
+  static std::string get_current_directory ();
 
-  static std::string get_home_directory (void);
+  static std::string get_home_directory ();
 
-  static std::string get_temp_directory (void);
+  static std::string get_temp_directory ();
 
-  static std::string get_user_config_directory (void);
+  static std::string get_user_config_directory ();
 
-  static std::string get_user_data_directory (void);
+  static std::string get_user_data_directory ();
 
-  static std::string get_program_name (void);
+  static std::string get_program_name ();
 
-  static std::string get_program_invocation_name (void);
+  static std::string get_program_invocation_name ();
 
-  static std::string get_user_name (void);
+  static std::string get_user_name ();
 
-  static std::string get_host_name (void);
+  static std::string get_host_name ();
 
   static std::string getenv (const std::string& name);
 
   static void putenv (const std::string& name, const std::string& value);
 
-  static bool have_x11_display (void);
+  static bool have_x11_display ();
 
   static bool chdir (const std::string& newdir);
 
@@ -92,7 +90,7 @@
 
 private:
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
   std::string do_polite_directory_format (const std::string& name);
 
@@ -105,19 +103,19 @@
   std::string do_make_absolute (const std::string& s,
                                 const std::string& dot_path) const;
 
-  std::string do_getcwd (void);
+  std::string do_getcwd ();
 
-  std::string do_get_home_directory (void);
+  std::string do_get_home_directory ();
 
-  std::string do_get_temp_directory (void) const;
+  std::string do_get_temp_directory () const;
 
-  std::string do_get_user_config_directory (void);
+  std::string do_get_user_config_directory ();
 
-  std::string do_get_user_data_directory (void);
+  std::string do_get_user_data_directory ();
 
-  std::string do_get_user_name (void);
+  std::string do_get_user_name ();
 
-  std::string do_get_host_name (void);
+  std::string do_get_host_name ();
 
   std::string do_getenv (const std::string& name) const;
 
@@ -134,10 +132,10 @@
   void error (const std::string&) const;
 
   // The real thing.
-  static env *m_instance;
+  static env *s_instance;
 
-  static void cleanup_instance (void)
-  { delete m_instance; m_instance = nullptr; }
+  static void cleanup_instance ()
+  { delete s_instance; s_instance = nullptr; }
 
   // TRUE means follow symbolic links that point to directories just
   // as if they are real directories.
--- a/liboctave/system/oct-group.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-group.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 
 OCTAVE_NORETURN static
 void
-err_invalid (void)
+err_invalid ()
 {
   (*current_liboctave_error_handler) ("invalid group object");
 }
@@ -52,7 +52,7 @@
 OCTAVE_BEGIN_NAMESPACE(sys)
 
 std::string
-group::name (void) const
+group::name () const
 {
   if (! ok ())
     err_invalid ();
@@ -61,7 +61,7 @@
 }
 
 std::string
-group::passwd (void) const
+group::passwd () const
 {
   if (! ok ())
     err_invalid ();
@@ -70,7 +70,7 @@
 }
 
 gid_t
-group::gid (void) const
+group::gid () const
 {
   if (! ok ())
     err_invalid ();
@@ -79,7 +79,7 @@
 }
 
 string_vector
-group::mem (void) const
+group::mem () const
 {
   if (! ok ())
     err_invalid ();
@@ -88,7 +88,7 @@
 }
 
 group
-group::getgrent (void)
+group::getgrent ()
 {
   std::string msg;
   return getgrent (msg);
@@ -149,7 +149,7 @@
 }
 
 int
-group::setgrent (void)
+group::setgrent ()
 {
   std::string msg;
   return setgrent (msg);
@@ -169,7 +169,7 @@
 }
 
 int
-group::endgrent (void)
+group::endgrent ()
 {
   std::string msg;
   return endgrent (msg);
--- a/liboctave/system/oct-group.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-group.h	Fri Jun 23 20:51:51 2023 +0200
@@ -44,42 +44,25 @@
 {
 public:
 
-  group (void)
+  group ()
     : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false)
   { }
 
-  group (const group& gr)
-    : m_name (gr.m_name), m_passwd (gr.m_passwd),
-      m_gid (gr.m_gid), m_mem (gr.m_mem), m_valid (gr.m_valid)
-  { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (group)
+
+  std::string name () const;
+
+  std::string passwd () const;
 
-  group& operator = (const group& gr)
-  {
-    if (this != &gr)
-      {
-        m_name = gr.m_name;
-        m_passwd = gr.m_passwd;
-        m_gid = gr.m_gid;
-        m_mem = gr.m_mem;
-        m_valid = gr.m_valid;
-      }
+  gid_t gid () const;
 
-    return *this;
-  }
-
-  std::string name (void) const;
+  string_vector mem () const;
 
-  std::string passwd (void) const;
-
-  gid_t gid (void) const;
-
-  string_vector mem (void) const;
-
-  bool ok (void) const { return m_valid; }
+  bool ok () const { return m_valid; }
 
   operator bool () const { return ok (); }
 
-  static group getgrent (void);
+  static group getgrent ();
   static group getgrent (std::string& msg);
 
   static group getgrgid (gid_t gid);
@@ -88,10 +71,10 @@
   static group getgrnam (const std::string& nm);
   static group getgrnam (const std::string& nm, std::string& msg);
 
-  static int setgrent (void);
+  static int setgrent ();
   static int setgrent (std::string& msg);
 
-  static int endgrent (void);
+  static int endgrent ();
   static int endgrent (std::string& msg);
 
 private:
--- a/liboctave/system/oct-password.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-password.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 
 OCTAVE_NORETURN static
 void
-err_invalid (void)
+err_invalid ()
 {
   (*current_liboctave_error_handler) ("invalid password object");
 }
@@ -51,7 +51,7 @@
 OCTAVE_BEGIN_NAMESPACE(sys)
 
 std::string
-password::name (void) const
+password::name () const
 {
   if (! ok ())
     err_invalid ();
@@ -60,7 +60,7 @@
 }
 
 std::string
-password::passwd (void) const
+password::passwd () const
 {
   if (! ok ())
     err_invalid ();
@@ -69,7 +69,7 @@
 }
 
 uid_t
-password::uid (void) const
+password::uid () const
 {
   if (! ok ())
     err_invalid ();
@@ -78,7 +78,7 @@
 }
 
 gid_t
-password::gid (void) const
+password::gid () const
 {
   if (! ok ())
     err_invalid ();
@@ -87,7 +87,7 @@
 }
 
 std::string
-password::gecos (void) const
+password::gecos () const
 {
   if (! ok ())
     err_invalid ();
@@ -96,7 +96,7 @@
 }
 
 std::string
-password::dir (void) const
+password::dir () const
 {
   if (! ok ())
     err_invalid ();
@@ -105,7 +105,7 @@
 }
 
 std::string
-password::shell (void) const
+password::shell () const
 {
   if (! ok ())
     err_invalid ();
@@ -114,7 +114,7 @@
 }
 
 password
-password::getpwent (void)
+password::getpwent ()
 {
   std::string msg;
   return getpwent (msg);
@@ -175,7 +175,7 @@
 }
 
 int
-password::setpwent (void)
+password::setpwent ()
 {
   std::string msg;
   return setpwent (msg);
@@ -195,7 +195,7 @@
 }
 
 int
-password::endpwent (void)
+password::endpwent ()
 {
   std::string msg;
   return endpwent (msg);
--- a/liboctave/system/oct-password.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-password.h	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 {
 public:
 
-  password (void)
+  password ()
     : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (),
       m_dir (), m_shell (), m_valid (false)
   { }
@@ -70,27 +70,27 @@
     return *this;
   }
 
-  ~password (void) = default;
+  ~password () = default;
 
-  std::string name (void) const;
+  std::string name () const;
 
-  std::string passwd (void) const;
+  std::string passwd () const;
 
-  uid_t uid (void) const;
+  uid_t uid () const;
 
-  gid_t gid (void) const;
+  gid_t gid () const;
 
-  std::string gecos (void) const;
+  std::string gecos () const;
 
-  std::string dir (void) const;
+  std::string dir () const;
 
-  std::string shell (void) const;
+  std::string shell () const;
 
-  bool ok (void) const { return m_valid; }
+  bool ok () const { return m_valid; }
 
   operator bool () const { return ok (); }
 
-  static password getpwent (void);
+  static password getpwent ();
   static password getpwent (std::string& msg);
 
   static password getpwuid (uid_t uid);
@@ -99,10 +99,10 @@
   static password getpwnam (const std::string& nm);
   static password getpwnam (const std::string& nm, std::string& msg);
 
-  static int setpwent (void);
+  static int setpwent ();
   static int setpwent (std::string& msg);
 
-  static int endpwent (void);
+  static int endpwent ();
   static int endpwent (std::string& msg);
 
 private:
--- a/liboctave/system/oct-syscalls.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-syscalls.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -146,37 +146,37 @@
 }
 
 pid_t
-getpid (void)
+getpid ()
 {
   return octave_getpid_wrapper ();
 }
 
 pid_t
-getppid (void)
+getppid ()
 {
   return octave_getppid_wrapper ();
 }
 
 gid_t
-getgid (void)
+getgid ()
 {
   return octave_getgid_wrapper ();
 }
 
 gid_t
-getegid (void)
+getegid ()
 {
   return octave_getegid_wrapper ();
 }
 
 uid_t
-getuid (void)
+getuid ()
 {
   return octave_getuid_wrapper ();
 }
 
 uid_t
-geteuid (void)
+geteuid ()
 {
   return octave_geteuid_wrapper ();
 }
@@ -226,7 +226,7 @@
 }
 
 int
-wcontinue (void)
+wcontinue ()
 {
   return octave_wcontinue_wrapper ();
 }
@@ -268,7 +268,7 @@
 }
 
 int
-wnohang (void)
+wnohang ()
 {
   return octave_wnohang_wrapper ();
 }
@@ -286,7 +286,7 @@
 }
 
 int
-wuntraced (void)
+wuntraced ()
 {
   return octave_wuntraced_wrapper ();
 }
--- a/liboctave/system/oct-syscalls.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-syscalls.h	Fri Jun 23 20:51:51 2023 +0200
@@ -51,17 +51,17 @@
 
 extern OCTAVE_API pid_t getpgrp (std::string&);
 
-extern OCTAVE_API pid_t getpid (void);
+extern OCTAVE_API pid_t getpid ();
 
-extern OCTAVE_API pid_t getppid (void);
+extern OCTAVE_API pid_t getppid ();
 
-extern OCTAVE_API gid_t getgid (void);
+extern OCTAVE_API gid_t getgid ();
 
-extern OCTAVE_API gid_t getegid (void);
+extern OCTAVE_API gid_t getegid ();
 
-extern OCTAVE_API uid_t getuid (void);
+extern OCTAVE_API uid_t getuid ();
 
-extern OCTAVE_API uid_t geteuid (void);
+extern OCTAVE_API uid_t geteuid ();
 
 extern OCTAVE_API int pipe (int *);
 extern OCTAVE_API int pipe (int *, std::string&);
@@ -69,7 +69,7 @@
 extern OCTAVE_API pid_t waitpid (pid_t, int *status, int);
 extern OCTAVE_API pid_t waitpid (pid_t, int *status, int, std::string&);
 
-extern OCTAVE_API int wcontinue (void);
+extern OCTAVE_API int wcontinue ();
 
 extern OCTAVE_API int wcoredump (int status);
 
@@ -83,13 +83,13 @@
 
 extern OCTAVE_API int wexitstatus (int status);
 
-extern OCTAVE_API int wnohang (void);
+extern OCTAVE_API int wnohang ();
 
 extern OCTAVE_API int wstopsig (int status);
 
 extern OCTAVE_API int wtermsig (int status);
 
-extern OCTAVE_API int wuntraced (void);
+extern OCTAVE_API int wuntraced ();
 
 extern OCTAVE_API int kill (pid_t, int);
 extern OCTAVE_API int kill (pid_t, int, std::string&);
--- a/liboctave/system/oct-time.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-time.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -36,6 +36,8 @@
 
 #if defined (OCTAVE_USE_WINDOWS_API)
 #  include <windows.h>
+#else
+#  include "file-stat.h"
 #endif
 
 #include "lo-error.h"
@@ -94,7 +96,7 @@
 }
 
 std::string
-time::ctime (void) const
+time::ctime () const
 {
   return localtime (*this).asctime ();
 }
@@ -111,7 +113,7 @@
 }
 
 void
-time::stamp (void)
+time::stamp ()
 {
   time_t ot_unix_time;
   octave_gettimeofday_wrapper (&ot_unix_time, &m_ot_usec);
@@ -346,7 +348,7 @@
 }
 
 void
-cpu_time::stamp (void)
+cpu_time::stamp ()
 {
   time_t usr_sec, sys_sec;
   octave_cpu_time (&usr_sec, &sys_sec, &m_usr_usec, &m_sys_usec);
@@ -355,7 +357,7 @@
 }
 
 void
-resource_usage::stamp (void)
+resource_usage::stamp ()
 {
   time_t usr_sec, sys_sec;
   long usr_usec, sys_usec;
@@ -370,5 +372,46 @@
   m_cpu = cpu_time (usr_sec, sys_sec, usr_usec, sys_usec);
 }
 
+file_time::file_time ()
+{
+#if defined (OCTAVE_USE_WINDOWS_API)
+  FILETIME curr_file_time;
+  GetSystemTimeAsFileTime (&curr_file_time);
+  m_time
+    = (static_cast<OCTAVE_TIME_T> (curr_file_time.dwHighDateTime)) >> 32
+      | curr_file_time.dwLowDateTime;
+#else
+  time_t ot_unix_time;
+  time_t ot_usec;
+  octave_gettimeofday_wrapper (&ot_unix_time, &ot_usec);
+  // Discard usec.  We are assuming a 1 second resolution anyway.
+  m_time = ot_unix_time;
+#endif
+}
+
+file_time::file_time (const std::string& filename)
+{
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::wstring wfull_name = sys::u8_to_wstring (filename);
+  WIN32_FILE_ATTRIBUTE_DATA file_attributes;
+
+  if (! GetFileAttributesExW (wfull_name.c_str (), GetFileExInfoStandard,
+                              &file_attributes))
+    {
+      m_time = 0;
+      return;
+    }
+
+  FILETIME last_write_time = file_attributes.ftLastWriteTime;
+
+  m_time
+    = (static_cast<OCTAVE_TIME_T> (last_write_time.dwHighDateTime)) >> 32
+      | last_write_time.dwLowDateTime;
+#else
+  file_stat fs = file_stat (filename);
+  m_time = fs.mtime ().unix_time ();
+#endif
+}
+
 OCTAVE_END_NAMESPACE(sys)
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/system/oct-time.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-time.h	Fri Jun 23 20:51:51 2023 +0200
@@ -31,6 +31,18 @@
 #include <iosfwd>
 #include <string>
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+// Some Windows headers must be included in a certain order.
+// Don't include "windows.h" here to avoid potential issues due to that.
+// Instead just define the one type we need for the interface of one function.
+struct OCTAVE_WIN_FILETIME
+{
+  uint32_t dwLowDateTime;
+  uint32_t dwHighDateTime;
+};
+#endif
+
+
 static inline double
 as_double (OCTAVE_TIME_T sec, long usec)
 {
@@ -52,7 +64,7 @@
 {
 public:
 
-  time (void)
+  time ()
     : m_ot_unix_time (0), m_ot_usec (0) { stamp (); }
 
   time (OCTAVE_TIME_T t)
@@ -98,20 +110,20 @@
     return *this;
   }
 
-  ~time (void) = default;
+  ~time () = default;
 
-  OCTAVE_API void stamp (void);
+  OCTAVE_API void stamp ();
 
-  double double_value (void) const
+  double double_value () const
   {
     return as_double (m_ot_unix_time, m_ot_usec);
   }
 
-  OCTAVE_TIME_T unix_time (void) const { return m_ot_unix_time; }
+  OCTAVE_TIME_T unix_time () const { return m_ot_unix_time; }
 
-  long usec (void) const { return m_ot_usec; }
+  long usec () const { return m_ot_usec; }
 
-  OCTAVE_API std::string ctime (void) const;
+  OCTAVE_API std::string ctime () const;
 
   friend OCTAVE_API std::ostream& operator << (std::ostream& os, const time& ot);
 
@@ -186,7 +198,7 @@
 {
 public:
 
-  base_tm (void)
+  base_tm ()
     : m_usec (0), m_sec (0), m_min (0), m_hour (0),
       m_mday (0), m_mon (0), m_year (0), m_wday (0),
       m_yday (0), m_isdst (0), m_gmtoff (0), m_zone ("unknown")
@@ -220,20 +232,20 @@
     return *this;
   }
 
-  virtual ~base_tm (void) = default;
+  virtual ~base_tm () = default;
 
-  int usec (void) const { return m_usec; }
-  int sec (void) const { return m_sec; }
-  int min (void) const { return m_min; }
-  int hour (void) const { return m_hour; }
-  int mday (void) const { return m_mday; }
-  int mon (void) const { return m_mon; }
-  int year (void) const { return m_year; }
-  int wday (void) const { return m_wday; }
-  int yday (void) const { return m_yday; }
-  int isdst (void) const { return m_isdst; }
-  long gmtoff (void) const { return m_gmtoff; }
-  std::string zone (void) const { return m_zone; }
+  int usec () const { return m_usec; }
+  int sec () const { return m_sec; }
+  int min () const { return m_min; }
+  int hour () const { return m_hour; }
+  int mday () const { return m_mday; }
+  int mon () const { return m_mon; }
+  int year () const { return m_year; }
+  int wday () const { return m_wday; }
+  int yday () const { return m_yday; }
+  int isdst () const { return m_isdst; }
+  long gmtoff () const { return m_gmtoff; }
+  std::string zone () const { return m_zone; }
 
   OCTAVE_API base_tm& usec (int v);
   OCTAVE_API base_tm& sec (int v);
@@ -250,7 +262,7 @@
 
   OCTAVE_API std::string strftime (const std::string& fmt) const;
 
-  std::string asctime (void) const
+  std::string asctime () const
   { return strftime ("%a %b %d %H:%M:%S %Y\n"); }
 
 protected:
@@ -299,7 +311,7 @@
 {
 public:
 
-  localtime (void)
+  localtime ()
     : base_tm () { init (time ()); }
 
   localtime (const time& ot)
@@ -314,7 +326,7 @@
     return *this;
   }
 
-  ~localtime (void) = default;
+  ~localtime () = default;
 
 private:
 
@@ -326,19 +338,13 @@
 {
 public:
 
-  gmtime (void)
+  gmtime ()
     : base_tm () { init (time ()); }
 
   gmtime (const time& ot)
     : base_tm () { init (ot); }
 
-  gmtime& operator = (const gmtime& t)
-  {
-    base_tm::operator = (t);
-    return *this;
-  }
-
-  ~gmtime (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (gmtime)
 
 private:
 
@@ -350,25 +356,17 @@
 {
 public:
 
+  strptime () = delete;
+
   strptime (const std::string& str, const std::string& fmt)
     : base_tm (), m_nchars (0)
   {
     init (str, fmt);
   }
 
-  strptime (const strptime& s)
-    : base_tm (s), m_nchars (s.m_nchars) { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (strptime)
 
-  strptime& operator = (const strptime& s)
-  {
-    base_tm::operator = (s);
-    m_nchars = s.m_nchars;
-    return *this;
-  }
-
-  int characters_converted (void) const { return m_nchars; }
-
-  ~strptime (void) = default;
+  int characters_converted () const { return m_nchars; }
 
 private:
 
@@ -384,47 +382,31 @@
 
   friend class resource_usage;
 
-  cpu_time (void)
+  cpu_time ()
     : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0)
   {
     stamp ();
   }
 
-  cpu_time (const cpu_time& tm)
-    : m_usr_sec (tm.m_usr_sec), m_sys_sec (tm.m_sys_sec),
-      m_usr_usec (tm.m_usr_usec), m_sys_usec (tm.m_sys_usec)
-  { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (cpu_time)
 
-  cpu_time& operator = (const cpu_time& tm)
-  {
-    if (&tm != this)
-      {
-        m_usr_sec = tm.m_usr_sec;
-        m_sys_sec = tm.m_sys_sec;
-        m_usr_usec = tm.m_usr_usec;
-        m_sys_usec = tm.m_sys_usec;
-      }
+  OCTAVE_API void stamp ();
 
-    return *this;
-  }
-
-  OCTAVE_API void stamp (void);
-
-  double user (void) const
+  double user () const
   {
     return as_double (m_usr_sec, m_usr_usec);
   }
 
-  double system (void) const
+  double system () const
   {
     return as_double (m_sys_sec, m_sys_usec);
   }
 
-  OCTAVE_TIME_T user_sec (void) const { return m_usr_sec; }
-  long user_usec (void) const { return m_usr_usec; }
+  OCTAVE_TIME_T user_sec () const { return m_usr_sec; }
+  long user_usec () const { return m_usr_usec; }
 
-  OCTAVE_TIME_T system_sec (void) const { return m_sys_sec; }
-  long system_usec (void) const { return m_sys_usec; }
+  OCTAVE_TIME_T system_sec () const { return m_sys_sec; }
+  long system_usec () const { return m_sys_usec; }
 
 private:
 
@@ -445,7 +427,7 @@
 {
 public:
 
-  resource_usage (void)
+  resource_usage ()
     : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0),
       m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0),
       m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0),
@@ -454,60 +436,26 @@
     stamp ();
   }
 
-  resource_usage (const resource_usage& ru)
-    : m_cpu (ru.m_cpu), m_maxrss (ru.m_maxrss),
-      m_ixrss (ru.m_ixrss), m_idrss (ru.m_idrss),
-      m_isrss (ru.m_isrss), m_minflt (ru.m_minflt),
-      m_majflt (ru.m_majflt), m_nswap (ru.m_nswap),
-      m_inblock (ru.m_inblock), m_oublock (ru.m_oublock),
-      m_msgsnd (ru.m_msgsnd), m_msgrcv (ru.m_msgrcv),
-      m_nsignals (ru.m_nsignals), m_nvcsw (ru.m_nvcsw),
-      m_nivcsw (ru.m_nivcsw)
-  { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (resource_usage)
 
-  resource_usage& operator = (const resource_usage& ru)
-  {
-    if (&ru != this)
-      {
-        m_cpu = ru.m_cpu;
+  OCTAVE_API void stamp ();
+
+  cpu_time cpu () const { return m_cpu; }
 
-        m_maxrss = ru.m_maxrss;
-        m_ixrss = ru.m_ixrss;
-        m_idrss = ru.m_idrss;
-        m_isrss = ru.m_isrss;
-        m_minflt = ru.m_minflt;
-        m_majflt = ru.m_majflt;
-        m_nswap = ru.m_nswap;
-        m_inblock = ru.m_inblock;
-        m_oublock = ru.m_oublock;
-        m_msgsnd = ru.m_msgsnd;
-        m_msgrcv = ru.m_msgrcv;
-        m_nsignals = ru.m_nsignals;
-        m_nvcsw = ru.m_nvcsw;
-        m_nivcsw = ru.m_nivcsw;
-      }
-
-    return *this;
-  }
-
-  OCTAVE_API void stamp (void);
-
-  cpu_time cpu (void) const { return m_cpu; }
-
-  long maxrss (void) const { return m_maxrss; }
-  long ixrss (void) const { return m_ixrss; }
-  long idrss (void) const { return m_idrss; }
-  long isrss (void) const { return m_isrss; }
-  long minflt (void) const { return m_minflt; }
-  long majflt (void) const { return m_majflt; }
-  long nswap (void) const { return m_nswap; }
-  long inblock (void) const { return m_inblock; }
-  long oublock (void) const { return m_oublock; }
-  long msgsnd (void) const { return m_msgsnd; }
-  long msgrcv (void) const { return m_msgrcv; }
-  long nsignals (void) const { return m_nsignals; }
-  long nvcsw (void) const { return m_nvcsw; }
-  long nivcsw (void) const { return m_nivcsw; }
+  long maxrss () const { return m_maxrss; }
+  long ixrss () const { return m_ixrss; }
+  long idrss () const { return m_idrss; }
+  long isrss () const { return m_isrss; }
+  long minflt () const { return m_minflt; }
+  long majflt () const { return m_majflt; }
+  long nswap () const { return m_nswap; }
+  long inblock () const { return m_inblock; }
+  long oublock () const { return m_oublock; }
+  long msgsnd () const { return m_msgsnd; }
+  long msgrcv () const { return m_msgrcv; }
+  long nsignals () const { return m_nsignals; }
+  long nvcsw () const { return m_nvcsw; }
+  long nivcsw () const { return m_nivcsw; }
 
 private:
 
@@ -529,6 +477,113 @@
   long m_nivcsw;
 };
 
+// class to handle file time efficiently on different platforms
+
+class OCTAVE_API file_time
+{
+public:
+
+  file_time ();
+
+  file_time (OCTAVE_TIME_T t)
+    : m_time (t)
+  { }
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+  file_time (OCTAVE_WIN_FILETIME& t)
+  {
+    m_time = (static_cast<OCTAVE_TIME_T> (t.dwHighDateTime)) >> 32
+             | t.dwLowDateTime;
+  }
+#endif
+
+  file_time (const std::string& filename);
+
+  file_time (const file_time& ot)
+  {
+    m_time = ot.time ();
+  }
+
+  file_time& operator = (const file_time& ot)
+  {
+    if (this != &ot)
+      m_time = ot.time ();
+
+    return *this;
+  }
+
+  ~file_time () = default;
+
+  inline static file_time time_resolution ()
+  {
+#if defined (OCTAVE_USE_WINDOWS_API)
+    // FAT file systems have 2 seconds resolution for the modification time.
+    static OCTAVE_TIME_T time_resolution = 20000;
+#else
+    // Assume 1 second (see file_stat)
+    static OCTAVE_TIME_T time_resolution = 1;
+#endif
+    return time_resolution;
+  }
+
+  inline bool
+  operator == (const file_time& t2) const
+  {
+    return time () == t2.time ();
+  }
+
+  inline bool
+  operator != (const file_time& t2) const
+  {
+    return ! (*this == t2);
+  }
+
+  inline bool
+  operator < (const file_time& t2) const
+  {
+    return time () < t2.time ();
+  }
+
+  inline bool
+  operator <= (const file_time& t2) const
+  {
+    return (*this < t2 || *this == t2);
+  }
+
+  inline bool
+  operator > (const file_time& t2) const
+  {
+    return time () > t2.time ();
+  }
+
+  inline bool
+  operator >= (const file_time& t2) const
+  {
+    return (*this > t2 || *this == t2);
+  }
+
+  inline file_time
+  operator + (const file_time& t2) const
+  {
+    return file_time (time () + t2.time ());
+  }
+
+  inline file_time
+  operator + (const OCTAVE_TIME_T t2) const
+  {
+    return file_time (time () + t2);
+  }
+
+  OCTAVE_TIME_T time () const { return m_time; }
+
+private:
+
+  // The native file time type differs per platform.
+  // On POSIX, this is the number of 1 second intervals since the epoch.
+  // On Windows, this is the number of 0.1 ms intervals since a different epoch.
+  OCTAVE_TIME_T m_time;
+};
+
 OCTAVE_END_NAMESPACE(sys)
 OCTAVE_END_NAMESPACE(octave)
 
--- a/liboctave/system/oct-uname.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-uname.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,7 @@
 OCTAVE_BEGIN_NAMESPACE(sys)
 
 void
-uname::init (void)
+uname::init ()
 {
   char *sysname, *nodename, *release, *version, *machine;
 
--- a/liboctave/system/oct-uname.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/system/oct-uname.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 public:
 
-  uname (void)
+  uname ()
     : m_sysname ("unknown"), m_nodename ("unknown"),
       m_release ("unknown"), m_version ("unknown"),
       m_machine ("unknown"),
@@ -71,16 +71,16 @@
     return *this;
   }
 
-  ~uname (void) = default;
+  ~uname () = default;
 
-  std::string sysname (void) const { return m_sysname; }
-  std::string nodename (void) const { return m_nodename; }
-  std::string release (void) const { return m_release; }
-  std::string version (void) const { return m_version; }
-  std::string machine (void) const { return m_machine; }
+  std::string sysname () const { return m_sysname; }
+  std::string nodename () const { return m_nodename; }
+  std::string release () const { return m_release; }
+  std::string version () const { return m_version; }
+  std::string machine () const { return m_machine; }
 
-  std::string message (void) const { return m_errmsg; }
-  int error (void) const { return m_errno; }
+  std::string message () const { return m_errmsg; }
+  int error () const { return m_errno; }
 
 private:
 
@@ -93,7 +93,7 @@
   std::string m_errmsg;
   int m_errno;
 
-  void init (void);
+  void init ();
 };
 
 OCTAVE_END_NAMESPACE(sys)
--- a/liboctave/util/action-container.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/action-container.h	Fri Jun 23 20:51:51 2023 +0200
@@ -28,6 +28,7 @@
 
 #include "octave-config.h"
 
+#include <atomic>
 #include <cstddef>
 #include <functional>
 
@@ -39,6 +40,22 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+OCTAVE_BEGIN_NAMESPACE(util)
+
+template <typename T>
+struct atomic_traits
+{
+  typedef T type;
+};
+
+template <typename T>
+struct atomic_traits<std::atomic<T>>
+{
+  typedef T type;
+};
+
+OCTAVE_END_NAMESPACE(util)
+
 class
 action_container
 {
@@ -52,20 +69,16 @@
 
     friend class action_container;
 
-    elem (void) { }
+    elem () { }
 
-    // No copying!
-
-    elem (const elem&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (elem)
 
-    elem& operator = (const elem&) = delete;
+    virtual ~elem () = default;
 
-    virtual ~elem (void) = default;
-
-    virtual void run (void) { }
+    virtual void run () { }
   };
 
-  // An element that merely runs a void (*)(void) function.
+  // An element that merely runs a void (*)() function.
 
   class fcn_elem : public elem
   {
@@ -79,11 +92,11 @@
       : m_fcn (std::bind (fcn, args...))
     { }
 
-    void run (void) { m_fcn (); }
+    void run () { m_fcn (); }
 
   private:
 
-    std::function<void (void)> m_fcn;
+    std::function<void ()> m_fcn;
   };
 
   // An element that stores arbitrary variable, and restores it.
@@ -96,17 +109,16 @@
     restore_var_elem (T& ref, const T& val)
       : m_ptr (&ref), m_val (val) { }
 
-    // No copying!
-
-    restore_var_elem (const restore_var_elem&) = delete;
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (restore_var_elem)
 
-    restore_var_elem& operator = (const restore_var_elem&) = delete;
+    ~restore_var_elem () = default;
 
-    void run (void) { *m_ptr = m_val; }
+    void run () { *m_ptr = m_val; }
 
   private:
 
-    T *m_ptr, m_val;
+    T *m_ptr;
+    typename util::atomic_traits<T>::type m_val;
   };
 
   // Deletes a class allocated using new.
@@ -119,28 +131,22 @@
     delete_ptr_elem (T *ptr)
       : m_ptr (ptr) { }
 
-    // No copying!
-
-    delete_ptr_elem (const delete_ptr_elem&) = delete;
+    OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (delete_ptr_elem)
 
-    delete_ptr_elem operator = (const delete_ptr_elem&) = delete;
+    ~delete_ptr_elem () = default;
 
-    void run (void) { delete m_ptr; }
+    void run () { delete m_ptr; }
 
   private:
 
     T *m_ptr;
   };
 
-  action_container (void) { }
-
-  // No copying!
+  action_container () { }
 
-  action_container (const action_container&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (action_container)
 
-  action_container& operator = (const action_container&) = delete;
-
-  virtual ~action_container (void) = default;
+  virtual ~action_container () = default;
 
   template <typename F, typename... Args>
   void add (F&& fcn, Args&& ... args)
@@ -193,15 +199,15 @@
     add_action (new restore_var_elem<T> (var, val));
   }
 
-  operator bool (void) const { return ! empty (); }
+  operator bool () const { return ! empty (); }
 
-  virtual void run_first (void) = 0;
+  virtual void run_first () = 0;
 
   OCTAVE_API void run (std::size_t num);
 
-  void run (void) { run (size ()); }
+  void run () { run (size ()); }
 
-  virtual void discard_first (void) = 0;
+  virtual void discard_first () = 0;
 
   void discard (std::size_t num)
   {
@@ -212,11 +218,11 @@
       discard_first ();
   }
 
-  void discard (void) { discard (size ()); }
+  void discard () { discard (size ()); }
 
-  virtual std::size_t size (void) const = 0;
+  virtual std::size_t size () const = 0;
 
-  bool empty (void) const { return size () == 0; }
+  bool empty () const { return size () == 0; }
 
 protected:
 
--- a/liboctave/util/base-list.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/base-list.h	Fri Jun 23 20:51:51 2023 +0200
@@ -47,10 +47,10 @@
   typedef typename std::list<elt_type>::const_reverse_iterator
     const_reverse_iterator;
 
-  bool empty (void) const { return m_lst.empty (); }
+  bool empty () const { return m_lst.empty (); }
 
-  std::size_t size (void) const { return m_lst.size (); }
-  std::size_t length (void) const { return size (); }
+  std::size_t size () const { return m_lst.size (); }
+  std::size_t length () const { return size (); }
 
   iterator erase (iterator pos) { return m_lst.erase (pos); }
 
@@ -60,38 +60,38 @@
     m_lst.remove_if (pred);
   }
 
-  void clear (void) { m_lst.clear (); }
+  void clear () { m_lst.clear (); }
 
-  iterator begin (void) { return iterator (m_lst.begin ()); }
-  const_iterator begin (void) const { return const_iterator (m_lst.begin ()); }
+  iterator begin () { return iterator (m_lst.begin ()); }
+  const_iterator begin () const { return const_iterator (m_lst.begin ()); }
 
-  iterator end (void) { return iterator (m_lst.end ()); }
-  const_iterator end (void) const { return const_iterator (m_lst.end ()); }
+  iterator end () { return iterator (m_lst.end ()); }
+  const_iterator end () const { return const_iterator (m_lst.end ()); }
 
-  reverse_iterator rbegin (void) { return reverse_iterator (m_lst.rbegin ()); }
-  const_reverse_iterator rbegin (void) const
+  reverse_iterator rbegin () { return reverse_iterator (m_lst.rbegin ()); }
+  const_reverse_iterator rbegin () const
   { return const_reverse_iterator (m_lst.rbegin ()); }
 
-  reverse_iterator rend (void) { return reverse_iterator (m_lst.rend ()); }
-  const_reverse_iterator rend (void) const
+  reverse_iterator rend () { return reverse_iterator (m_lst.rend ()); }
+  const_reverse_iterator rend () const
   { return const_reverse_iterator (m_lst.rend ()); }
 
-  elt_type& front (void) { return m_lst.front (); }
-  elt_type& back (void) { return m_lst.back (); }
+  elt_type& front () { return m_lst.front (); }
+  elt_type& back () { return m_lst.back (); }
 
-  const elt_type& front (void) const { return m_lst.front (); }
-  const elt_type& back (void) const { return m_lst.back (); }
+  const elt_type& front () const { return m_lst.front (); }
+  const elt_type& back () const { return m_lst.back (); }
 
   void push_front (const elt_type& s) { m_lst.push_front (s); }
   void push_back (const elt_type& s) { m_lst.push_back (s); }
 
-  void pop_front (void) { m_lst.pop_front (); }
-  void pop_back (void) { m_lst.pop_back (); }
+  void pop_front () { m_lst.pop_front (); }
+  void pop_back () { m_lst.pop_back (); }
 
   // For backward compatibility.
   void append (const elt_type& s) { m_lst.push_back (s); }
 
-  base_list (void) = default;
+  base_list () = default;
 
   base_list (const std::list<elt_type>& l) : m_lst (l) { }
 
@@ -99,7 +99,7 @@
 
   base_list& operator = (const base_list& bl) = default;
 
-  virtual ~base_list (void) = default;
+  virtual ~base_list () = default;
 
 protected:
 
--- a/liboctave/util/caseless-str.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/caseless-str.h	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,7 @@
   typedef std::string::iterator iterator;
   typedef std::string::const_iterator const_iterator;
 
-  caseless_str (void) = default;
+  caseless_str () = default;
 
   caseless_str (const std::string& s) : std::string (s) { }
   caseless_str (const char *s) : std::string (s) { }
@@ -47,7 +47,7 @@
 
   caseless_str& operator = (const caseless_str&) = default;
 
-  ~caseless_str (void) = default;
+  ~caseless_str () = default;
 
   bool operator < (const std::string& s) const
   {
--- a/liboctave/util/cmd-edit.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/cmd-edit.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,6 +37,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "lo-error.h"
+#include "lo-sysdep.h"
 #include "lo-utils.h"
 #include "oct-env.h"
 #include "oct-mutex.h"
@@ -58,11 +59,11 @@
 
 command_editor *command_editor::s_instance = nullptr;
 
-std::set<command_editor::startup_hook_fcn> command_editor::m_startup_hook_set;
+std::set<command_editor::startup_hook_fcn> command_editor::s_startup_hook_set;
 
-std::set<command_editor::pre_input_hook_fcn> command_editor::m_pre_input_hook_set;
+std::set<command_editor::pre_input_hook_fcn> command_editor::s_pre_input_hook_set;
 
-std::set<command_editor::event_hook_fcn> command_editor::m_event_hook_set;
+std::set<command_editor::event_hook_fcn> command_editor::s_event_hook_set;
 
 static mutex event_hook_lock;
 
@@ -81,9 +82,11 @@
 
   typedef command_editor::completion_fcn completion_fcn;
 
-  gnu_readline (void);
+  gnu_readline ();
 
-  ~gnu_readline (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (gnu_readline)
+
+  ~gnu_readline () = default;
 
   void do_set_name (const std::string& n);
 
@@ -91,27 +94,27 @@
 
   void do_set_input_stream (FILE *f);
 
-  FILE * do_get_input_stream (void);
+  FILE * do_get_input_stream ();
 
   void do_set_output_stream (FILE *f);
 
-  FILE * do_get_output_stream (void);
+  FILE * do_get_output_stream ();
 
-  void do_redisplay (void);
+  void do_redisplay ();
 
-  int do_terminal_rows (void);
+  int do_terminal_rows ();
 
-  int do_terminal_cols (void);
+  int do_terminal_cols ();
 
   void do_clear_screen (bool skip_redisplay);
 
-  void do_resize_terminal (void);
+  void do_resize_terminal ();
 
   void do_set_screen_size (int ht, int wd);
 
-  std::string newline_chars (void);
+  std::string newline_chars ();
 
-  void do_restore_terminal_state (void);
+  void do_restore_terminal_state ();
 
   void do_blink_matching_paren (bool flag);
 
@@ -139,56 +142,56 @@
 
   void do_set_user_accept_line_function (user_accept_line_fcn f);
 
-  completion_fcn do_get_completion_function (void) const;
+  completion_fcn do_get_completion_function () const;
 
-  quoting_fcn do_get_quoting_function (void) const;
+  quoting_fcn do_get_quoting_function () const;
 
-  dequoting_fcn do_get_dequoting_function (void) const;
+  dequoting_fcn do_get_dequoting_function () const;
 
-  char_is_quoted_fcn do_get_char_is_quoted_function (void) const;
+  char_is_quoted_fcn do_get_char_is_quoted_function () const;
 
-  user_accept_line_fcn do_get_user_accept_line_function (void) const;
+  user_accept_line_fcn do_get_user_accept_line_function () const;
 
   string_vector
   do_generate_filename_completions (const std::string& text);
 
-  std::string do_get_line_buffer (void) const;
+  std::string do_get_line_buffer () const;
 
-  std::string do_get_current_line (void) const;
+  std::string do_get_current_line () const;
 
   char do_get_prev_char (int) const;
 
   void do_replace_line (const std::string& text, bool clear_undo);
 
-  void do_kill_full_line (void);
+  void do_kill_full_line ();
 
   void do_insert_text (const std::string& text);
 
-  void do_newline (void);
+  void do_newline ();
 
-  void do_accept_line (void);
+  void do_accept_line ();
 
-  bool do_undo (void);
+  bool do_undo ();
 
-  void do_clear_undo_list (void);
+  void do_clear_undo_list ();
 
   void set_startup_hook (startup_hook_fcn f);
 
-  void restore_startup_hook (void);
+  void restore_startup_hook ();
 
   void set_pre_input_hook (pre_input_hook_fcn f);
 
-  void restore_pre_input_hook (void);
+  void restore_pre_input_hook ();
 
   void set_event_hook (event_hook_fcn f);
 
-  void restore_event_hook (void);
+  void restore_event_hook ();
 
-  void do_restore_event_hook (void);
+  void do_restore_event_hook ();
 
   void do_read_init_file (const std::string& file);
 
-  void do_re_read_init_file (void);
+  void do_re_read_init_file ();
 
   bool do_filename_completion_desired (bool);
 
@@ -198,7 +201,7 @@
 
   void do_interrupt (bool);
 
-  void do_handle_interrupt_signal (void);
+  void do_handle_interrupt_signal ();
 
   static int operate_and_get_next (int, int);
 
@@ -237,7 +240,7 @@
 
   char_is_quoted_fcn m_char_is_quoted_function;
 
-  user_accept_line_fcn user_accept_line_function;
+  user_accept_line_fcn m_user_accept_line_function;
 
   static std::string s_completer_quote_characters;
 };
@@ -249,7 +252,7 @@
     m_previous_pre_input_hook (nullptr),
     m_previous_event_hook (nullptr), m_completion_function (nullptr),
     m_quoting_function (nullptr), m_dequoting_function (nullptr),
-    m_char_is_quoted_function (nullptr), user_accept_line_function (nullptr)
+    m_char_is_quoted_function (nullptr), m_user_accept_line_function (nullptr)
 {
   // FIXME: need interface to rl_add_defun, rl_initialize, and
   // a function to set rl_terminal_name
@@ -305,7 +308,7 @@
 }
 
 FILE *
-gnu_readline::do_get_input_stream (void)
+gnu_readline::do_get_input_stream ()
 {
   return ::octave_rl_get_input_stream ();
 }
@@ -317,13 +320,13 @@
 }
 
 FILE *
-gnu_readline::do_get_output_stream (void)
+gnu_readline::do_get_output_stream ()
 {
   return ::octave_rl_get_output_stream ();
 }
 
 void
-gnu_readline::do_redisplay (void)
+gnu_readline::do_redisplay ()
 {
   ::octave_rl_redisplay ();
 }
@@ -335,7 +338,7 @@
 // us.
 
 int
-gnu_readline::do_terminal_rows (void)
+gnu_readline::do_terminal_rows ()
 {
   int sh = ::octave_rl_screen_height ();
 
@@ -343,7 +346,7 @@
 }
 
 int
-gnu_readline::do_terminal_cols (void)
+gnu_readline::do_terminal_cols ()
 {
   int sw = ::octave_rl_screen_width ();
 
@@ -357,7 +360,7 @@
 }
 
 void
-gnu_readline::do_resize_terminal (void)
+gnu_readline::do_resize_terminal ()
 {
   ::octave_rl_resize_terminal ();
 }
@@ -369,13 +372,13 @@
 }
 
 std::string
-gnu_readline::newline_chars (void)
+gnu_readline::newline_chars ()
 {
   return "\r\n";
 }
 
 void
-gnu_readline::do_restore_terminal_state (void)
+gnu_readline::do_restore_terminal_state ()
 {
   ::octave_rl_restore_terminal_state ();
 }
@@ -479,7 +482,7 @@
 void
 gnu_readline::do_set_user_accept_line_function (user_accept_line_fcn f)
 {
-  user_accept_line_function = f;
+  m_user_accept_line_function = f;
 
   if (f)
     octave_rl_add_defun ("accept-line", gnu_readline::command_accept_line,
@@ -490,33 +493,33 @@
 }
 
 gnu_readline::completion_fcn
-gnu_readline::do_get_completion_function (void) const
+gnu_readline::do_get_completion_function () const
 {
   return m_completion_function;
 }
 
 gnu_readline::quoting_fcn
-gnu_readline::do_get_quoting_function (void) const
+gnu_readline::do_get_quoting_function () const
 {
   return m_quoting_function;
 }
 
 gnu_readline::dequoting_fcn
-gnu_readline::do_get_dequoting_function (void) const
+gnu_readline::do_get_dequoting_function () const
 {
   return m_dequoting_function;
 }
 
 gnu_readline::char_is_quoted_fcn
-gnu_readline::do_get_char_is_quoted_function (void) const
+gnu_readline::do_get_char_is_quoted_function () const
 {
   return m_char_is_quoted_function;
 }
 
 gnu_readline::user_accept_line_fcn
-gnu_readline::do_get_user_accept_line_function (void) const
+gnu_readline::do_get_user_accept_line_function () const
 {
-  return user_accept_line_function;
+  return m_user_accept_line_function;
 }
 
 // True if the last "word" of the string line (delimited by delim) is
@@ -548,9 +551,7 @@
             candidate_filename
               = sys::file_ops::tilde_expand (candidate_filename);
 
-          sys::file_stat fs (candidate_filename);
-
-          retval = fs.is_dir ();
+          retval = sys::dir_exists (candidate_filename);
         }
     }
 
@@ -634,13 +635,13 @@
 }
 
 std::string
-gnu_readline::do_get_line_buffer (void) const
+gnu_readline::do_get_line_buffer () const
 {
   return ::octave_rl_line_buffer ();
 }
 
 std::string
-gnu_readline::do_get_current_line (void) const
+gnu_readline::do_get_current_line () const
 {
   std::string retval;
   char *buf = ::octave_rl_copy_line ();
@@ -667,7 +668,7 @@
 }
 
 void
-gnu_readline::do_kill_full_line (void)
+gnu_readline::do_kill_full_line ()
 {
   ::octave_rl_kill_full_line ();
 }
@@ -679,19 +680,19 @@
 }
 
 void
-gnu_readline::do_newline (void)
+gnu_readline::do_newline ()
 {
   ::octave_rl_newline (1, '\n');
 }
 
 void
-gnu_readline::do_accept_line (void)
+gnu_readline::do_accept_line ()
 {
   command_accept_line (1, '\n');
 }
 
 bool
-gnu_readline::do_undo (void)
+gnu_readline::do_undo ()
 {
   return ::octave_rl_do_undo ();
 }
@@ -712,7 +713,7 @@
 }
 
 void
-gnu_readline::restore_startup_hook (void)
+gnu_readline::restore_startup_hook ()
 {
   ::octave_rl_set_startup_hook (m_previous_startup_hook);
 }
@@ -727,7 +728,7 @@
 }
 
 void
-gnu_readline::restore_pre_input_hook (void)
+gnu_readline::restore_pre_input_hook ()
 {
   ::octave_rl_set_pre_input_hook (m_previous_pre_input_hook);
 }
@@ -741,7 +742,7 @@
 }
 
 void
-gnu_readline::restore_event_hook (void)
+gnu_readline::restore_event_hook ()
 {
   ::octave_rl_set_event_hook (m_previous_event_hook);
 }
@@ -753,7 +754,7 @@
 }
 
 void
-gnu_readline::do_re_read_init_file (void)
+gnu_readline::do_re_read_init_file ()
 {
   ::octave_rl_re_read_init_file ();
 }
@@ -783,9 +784,9 @@
 }
 
 void
-gnu_readline::do_handle_interrupt_signal (void)
+gnu_readline::do_handle_interrupt_signal ()
 {
-  octave_signal_caught = 0;
+  octave_signal_caught = false;
   octave_interrupt_state = 0;
 
   ::octave_rl_recover_from_interrupt ();
@@ -933,44 +934,40 @@
 {
 public:
 
-  default_command_editor (void)
+  default_command_editor ()
     : command_editor (), m_input_stream (stdin), m_output_stream (stdout) { }
 
-  // No copying!
-
-  default_command_editor (const default_command_editor&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (default_command_editor)
 
-  default_command_editor& operator = (const default_command_editor&) = delete;
-
-  ~default_command_editor (void) = default;
+  ~default_command_editor () = default;
 
   std::string do_readline (const std::string& prompt, bool& eof);
 
   void do_set_input_stream (FILE *f);
 
-  FILE * do_get_input_stream (void);
+  FILE * do_get_input_stream ();
 
   void do_set_output_stream (FILE *f);
 
-  FILE * do_get_output_stream (void);
+  FILE * do_get_output_stream ();
 
   string_vector do_generate_filename_completions (const std::string& text);
 
-  std::string do_get_line_buffer (void) const;
+  std::string do_get_line_buffer () const;
 
-  std::string do_get_current_line (void) const;
+  std::string do_get_current_line () const;
 
   char do_get_prev_char (int) const;
 
   void do_replace_line (const std::string& text, bool clear_undo);
 
-  void do_kill_full_line (void);
+  void do_kill_full_line ();
 
   void do_insert_text (const std::string& text);
 
-  void do_newline (void);
+  void do_newline ();
 
-  void do_accept_line (void);
+  void do_accept_line ();
 
 private:
 
@@ -995,7 +992,7 @@
 }
 
 FILE *
-default_command_editor::do_get_input_stream (void)
+default_command_editor::do_get_input_stream ()
 {
   return m_input_stream;
 }
@@ -1007,7 +1004,7 @@
 }
 
 FILE *
-default_command_editor::do_get_output_stream (void)
+default_command_editor::do_get_output_stream ()
 {
   return m_output_stream;
 }
@@ -1020,13 +1017,13 @@
 }
 
 std::string
-default_command_editor::do_get_line_buffer (void) const
+default_command_editor::do_get_line_buffer () const
 {
   return "";
 }
 
 std::string
-default_command_editor::do_get_current_line (void) const
+default_command_editor::do_get_current_line () const
 {
   // FIXME
   return "";
@@ -1045,7 +1042,7 @@
 }
 
 void
-default_command_editor::do_kill_full_line (void)
+default_command_editor::do_kill_full_line ()
 {
   // FIXME
 }
@@ -1057,19 +1054,19 @@
 }
 
 void
-default_command_editor::do_newline (void)
+default_command_editor::do_newline ()
 {
   // FIXME
 }
 
 void
-default_command_editor::do_accept_line (void)
+default_command_editor::do_accept_line ()
 {
   // FIXME
 }
 
 bool
-command_editor::instance_ok (void)
+command_editor::instance_ok ()
 {
   bool retval = true;
 
@@ -1093,7 +1090,7 @@
 }
 
 void
-command_editor::make_command_editor (void)
+command_editor::make_command_editor ()
 {
 #if defined (USE_READLINE)
   s_instance = new gnu_readline ();
@@ -1103,7 +1100,7 @@
 }
 
 void
-command_editor::force_default_editor (void)
+command_editor::force_default_editor ()
 {
   delete s_instance;
   s_instance = new default_command_editor ();
@@ -1117,18 +1114,18 @@
 }
 
 int
-command_editor::insert_initial_input (void)
+command_editor::insert_initial_input ()
 {
   return instance_ok () ? s_instance->do_insert_initial_input () : 0;
 }
 
 int
-command_editor::startup_handler (void)
+command_editor::startup_handler ()
 {
   // Iterate over a copy of the set to avoid problems if a hook
   // function attempts to remove itself from the startup_hook_set.
 
-  std::set<startup_hook_fcn> hook_set = m_startup_hook_set;
+  std::set<startup_hook_fcn> hook_set = s_startup_hook_set;
 
   for (startup_hook_fcn f : hook_set)
     {
@@ -1140,12 +1137,12 @@
 }
 
 int
-command_editor::pre_input_handler (void)
+command_editor::pre_input_handler ()
 {
   // Iterate over copy of the set to avoid problems if a hook function
   // attempts to remove itself from the pre_input_hook_set.
 
-  std::set<pre_input_hook_fcn> hook_set = m_pre_input_hook_set;
+  std::set<pre_input_hook_fcn> hook_set = s_pre_input_hook_set;
 
   for (pre_input_hook_fcn f : hook_set)
     {
@@ -1157,14 +1154,14 @@
 }
 
 int
-command_editor::event_handler (void)
+command_editor::event_handler ()
 {
   if (octave_interrupt_state)
     handle_interrupt_signal ();
 
   event_hook_lock.lock ();
 
-  std::set<event_hook_fcn> hook_set (m_event_hook_set);
+  std::set<event_hook_fcn> hook_set (s_event_hook_set);
 
   event_hook_lock.unlock ();
 
@@ -1216,7 +1213,7 @@
 }
 
 FILE *
-command_editor::get_input_stream (void)
+command_editor::get_input_stream ()
 {
   return instance_ok () ? s_instance->do_get_input_stream () : nullptr;
 }
@@ -1229,26 +1226,26 @@
 }
 
 FILE *
-command_editor::get_output_stream (void)
+command_editor::get_output_stream ()
 {
   return instance_ok () ? s_instance->do_get_output_stream () : nullptr;
 }
 
 void
-command_editor::redisplay (void)
+command_editor::redisplay ()
 {
   if (instance_ok ())
     s_instance->do_redisplay ();
 }
 
 int
-command_editor::terminal_rows (void)
+command_editor::terminal_rows ()
 {
   return instance_ok () ? s_instance->do_terminal_rows () : -1;
 }
 
 int
-command_editor::terminal_cols (void)
+command_editor::terminal_cols ()
 {
   return instance_ok () ? s_instance->do_terminal_cols () : -1;
 }
@@ -1261,7 +1258,7 @@
 }
 
 void
-command_editor::resize_terminal (void)
+command_editor::resize_terminal ()
 {
   if (instance_ok ())
     s_instance->do_resize_terminal ();
@@ -1281,7 +1278,7 @@
 }
 
 int
-command_editor::current_command_number (void)
+command_editor::current_command_number ()
 {
   return instance_ok () ? s_instance->m_command_number : 0;
 }
@@ -1294,14 +1291,14 @@
 }
 
 void
-command_editor::increment_current_command_number (void)
+command_editor::increment_current_command_number ()
 {
   if (instance_ok ())
     s_instance->m_command_number++;
 }
 
 void
-command_editor::restore_terminal_state (void)
+command_editor::restore_terminal_state ()
 {
   if (instance_ok ())
     s_instance->do_restore_terminal_state ();
@@ -1398,32 +1395,32 @@
 }
 
 command_editor::completion_fcn
-command_editor::get_completion_function (void)
+command_editor::get_completion_function ()
 {
   return instance_ok () ? s_instance->do_get_completion_function () : nullptr;
 }
 
 command_editor::quoting_fcn
-command_editor::get_quoting_function (void)
+command_editor::get_quoting_function ()
 {
   return instance_ok () ? s_instance->do_get_quoting_function () : nullptr;
 }
 
 command_editor::dequoting_fcn
-command_editor::get_dequoting_function (void)
+command_editor::get_dequoting_function ()
 {
   return instance_ok () ? s_instance->do_get_dequoting_function () : nullptr;
 }
 
 command_editor::char_is_quoted_fcn
-command_editor::get_char_is_quoted_function (void)
+command_editor::get_char_is_quoted_function ()
 {
   return (instance_ok ()
           ? s_instance->do_get_char_is_quoted_function () : nullptr);
 }
 
 command_editor::user_accept_line_fcn
-command_editor::get_user_accept_line_function (void)
+command_editor::get_user_accept_line_function ()
 {
   return (instance_ok ()
           ? s_instance->do_get_user_accept_line_function () : nullptr);
@@ -1438,13 +1435,13 @@
 }
 
 std::string
-command_editor::get_line_buffer (void)
+command_editor::get_line_buffer ()
 {
   return instance_ok () ? s_instance->do_get_line_buffer () : "";
 }
 
 std::string
-command_editor::get_current_line (void)
+command_editor::get_current_line ()
 {
   return instance_ok () ? s_instance->do_get_current_line () : "";
 }
@@ -1465,7 +1462,7 @@
 }
 
 void
-command_editor::kill_full_line (void)
+command_editor::kill_full_line ()
 {
   if (instance_ok ())
     s_instance->do_kill_full_line ();
@@ -1479,27 +1476,27 @@
 }
 
 void
-command_editor::newline (void)
+command_editor::newline ()
 {
   if (instance_ok ())
     s_instance->do_newline ();
 }
 
 void
-command_editor::accept_line (void)
+command_editor::accept_line ()
 {
   if (instance_ok ())
     s_instance->do_accept_line ();
 }
 
 bool
-command_editor::undo (void)
+command_editor::undo ()
 {
   return instance_ok () ? s_instance->do_undo () : false;
 }
 
 void
-command_editor::clear_undo_list (void)
+command_editor::clear_undo_list ()
 {
   if (instance_ok ())
     s_instance->do_clear_undo_list ();
@@ -1510,7 +1507,7 @@
 {
   if (instance_ok ())
     {
-      m_startup_hook_set.insert (f);
+      s_startup_hook_set.insert (f);
 
       s_instance->set_startup_hook (startup_handler);
     }
@@ -1521,12 +1518,12 @@
 {
   if (instance_ok ())
     {
-      auto p = m_startup_hook_set.find (f);
+      auto p = s_startup_hook_set.find (f);
 
-      if (p != m_startup_hook_set.end ())
-        m_startup_hook_set.erase (p);
+      if (p != s_startup_hook_set.end ())
+        s_startup_hook_set.erase (p);
 
-      if (m_startup_hook_set.empty ())
+      if (s_startup_hook_set.empty ())
         s_instance->restore_startup_hook ();
     }
 }
@@ -1536,7 +1533,7 @@
 {
   if (instance_ok ())
     {
-      m_pre_input_hook_set.insert (f);
+      s_pre_input_hook_set.insert (f);
 
       s_instance->set_pre_input_hook (pre_input_handler);
     }
@@ -1547,12 +1544,12 @@
 {
   if (instance_ok ())
     {
-      auto p = m_pre_input_hook_set.find (f);
+      auto p = s_pre_input_hook_set.find (f);
 
-      if (p != m_pre_input_hook_set.end ())
-        m_pre_input_hook_set.erase (p);
+      if (p != s_pre_input_hook_set.end ())
+        s_pre_input_hook_set.erase (p);
 
-      if (m_pre_input_hook_set.empty ())
+      if (s_pre_input_hook_set.empty ())
         s_instance->restore_pre_input_hook ();
     }
 }
@@ -1562,7 +1559,7 @@
 {
   autolock guard (event_hook_lock);
 
-  m_event_hook_set.insert (f);
+  s_event_hook_set.insert (f);
 }
 
 void
@@ -1570,15 +1567,15 @@
 {
   autolock guard (event_hook_lock);
 
-  auto p = m_event_hook_set.find (f);
+  auto p = s_event_hook_set.find (f);
 
-  if (p != m_event_hook_set.end ())
-    m_event_hook_set.erase (p);
+  if (p != s_event_hook_set.end ())
+    s_event_hook_set.erase (p);
 
 }
 
 void
-command_editor::run_event_hooks (void)
+command_editor::run_event_hooks ()
 {
   event_handler ();
 }
@@ -1595,7 +1592,7 @@
 }
 
 void
-command_editor::re_read_init_file (void)
+command_editor::re_read_init_file ()
 {
   if (instance_ok ())
     s_instance->do_re_read_init_file ();
@@ -1649,13 +1646,13 @@
 }
 
 bool
-command_editor::event_loop_interrupted (void)
+command_editor::event_loop_interrupted ()
 {
   return instance_ok () ? s_instance->do_event_loop_interrupted  () : false;
 }
 
 void
-command_editor::handle_interrupt_signal (void)
+command_editor::handle_interrupt_signal ()
 {
   if (instance_ok ())
     s_instance->do_handle_interrupt_signal ();
@@ -1915,7 +1912,7 @@
 }
 
 int
-command_editor::do_insert_initial_input (void)
+command_editor::do_insert_initial_input ()
 {
   std::string input = m_initial_input;
 
--- a/liboctave/util/cmd-edit.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/cmd-edit.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,18 +43,18 @@
 {
 protected:
 
-  command_editor (void)
+  command_editor ()
     : m_command_number (1), m_rows (24), m_cols (80), m_interrupted (false),
       m_interrupt_event_loop (false), m_initial_input ()
   { }
 
 public:
 
-  typedef int (*startup_hook_fcn) (void);
+  typedef int (*startup_hook_fcn) ();
 
-  typedef int (*pre_input_hook_fcn) (void);
+  typedef int (*pre_input_hook_fcn) ();
 
-  typedef int (*event_hook_fcn) (void);
+  typedef int (*event_hook_fcn) ();
 
   typedef std::string (*completion_fcn) (const std::string&, int);
 
@@ -68,13 +68,9 @@
 
   typedef void (*user_accept_line_fcn) (const std::string&);
 
-  // No copying!
-
-  command_editor (const command_editor&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (command_editor)
 
-  command_editor& operator = (const command_editor&) = delete;
-
-  virtual ~command_editor (void) = default;
+  virtual ~command_editor () = default;
 
   static void set_name (const std::string& n);
 
@@ -84,27 +80,27 @@
 
   static void set_input_stream (FILE *f);
 
-  static FILE * get_input_stream (void);
+  static FILE * get_input_stream ();
 
   static void set_output_stream (FILE *f);
 
-  static FILE * get_output_stream (void);
+  static FILE * get_output_stream ();
 
-  static void redisplay (void);
+  static void redisplay ();
 
-  static int terminal_rows (void);
+  static int terminal_rows ();
 
-  static int terminal_cols (void);
+  static int terminal_cols ();
 
   static void clear_screen (bool skip_redisplay = false);
 
-  static void resize_terminal (void);
+  static void resize_terminal ();
 
   static void set_screen_size (int ht, int wd);
 
   static std::string decode_prompt_string (const std::string& s);
 
-  static void restore_terminal_state (void);
+  static void restore_terminal_state ();
 
   static void blink_matching_paren (bool flag);
 
@@ -132,38 +128,38 @@
 
   static void set_user_accept_line_function (user_accept_line_fcn f);
 
-  static completion_fcn get_completion_function (void);
+  static completion_fcn get_completion_function ();
 
-  static quoting_fcn get_quoting_function (void);
+  static quoting_fcn get_quoting_function ();
 
-  static dequoting_fcn get_dequoting_function (void);
+  static dequoting_fcn get_dequoting_function ();
 
-  static char_is_quoted_fcn get_char_is_quoted_function (void);
+  static char_is_quoted_fcn get_char_is_quoted_function ();
 
-  static user_accept_line_fcn get_user_accept_line_function (void);
+  static user_accept_line_fcn get_user_accept_line_function ();
 
   static string_vector
   generate_filename_completions (const std::string& text);
 
-  static std::string get_line_buffer (void);
+  static std::string get_line_buffer ();
 
-  static std::string get_current_line (void);
+  static std::string get_current_line ();
 
   static char get_prev_char (int);
 
   static void replace_line (const std::string& text, bool clear_undo = true);
 
-  static void kill_full_line (void);
+  static void kill_full_line ();
 
   static void insert_text (const std::string& text);
 
-  static void newline (void);
+  static void newline ();
 
-  static void accept_line (void);
+  static void accept_line ();
 
-  static bool undo (void);
+  static bool undo ();
 
-  static void clear_undo_list (void);
+  static void clear_undo_list ();
 
   static void add_startup_hook (startup_hook_fcn f);
 
@@ -177,11 +173,11 @@
 
   static void remove_event_hook (event_hook_fcn f);
 
-  static void run_event_hooks (void);
+  static void run_event_hooks ();
 
   static void read_init_file (const std::string& file = "");
 
-  static void re_read_init_file (void);
+  static void re_read_init_file ();
 
   static bool filename_completion_desired (bool);
 
@@ -193,47 +189,47 @@
 
   static void interrupt_event_loop (bool flag = true);
 
-  static bool event_loop_interrupted (void);
+  static bool event_loop_interrupted ();
 
-  static int current_command_number (void);
+  static int current_command_number ();
 
   static void reset_current_command_number (int n);
 
-  static void increment_current_command_number (void);
+  static void increment_current_command_number ();
 
-  static void force_default_editor (void);
+  static void force_default_editor ();
 
   static void set_initial_input (const std::string& text);
 
-  static int insert_initial_input (void);
+  static int insert_initial_input ();
 
 private:
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
-  static void make_command_editor (void);
+  static void make_command_editor ();
 
-  static int startup_handler (void);
+  static int startup_handler ();
 
-  static int pre_input_handler (void);
+  static int pre_input_handler ();
 
-  static int event_handler (void);
+  static int event_handler ();
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   {
     delete s_instance;
     s_instance = nullptr;
   }
 
-  static void handle_interrupt_signal (void);
+  static void handle_interrupt_signal ();
 
   //--------
 
   static command_editor *s_instance;  // the real thing.
 
-  static std::set<startup_hook_fcn> m_startup_hook_set;
-  static std::set<pre_input_hook_fcn> m_pre_input_hook_set;
-  static std::set<event_hook_fcn> m_event_hook_set;
+  static std::set<startup_hook_fcn> s_startup_hook_set;
+  static std::set<pre_input_hook_fcn> s_pre_input_hook_set;
+  static std::set<event_hook_fcn> s_event_hook_set;
 
 protected:
 
@@ -254,21 +250,21 @@
 
   virtual void do_set_input_stream (FILE *) = 0;
 
-  virtual FILE * do_get_input_stream (void) = 0;
+  virtual FILE * do_get_input_stream () = 0;
 
   virtual void do_set_output_stream (FILE *) = 0;
 
-  virtual FILE * do_get_output_stream (void) = 0;
+  virtual FILE * do_get_output_stream () = 0;
 
-  virtual void do_redisplay (void) { }
+  virtual void do_redisplay () { }
 
-  virtual int do_terminal_rows (void) { return m_rows; }
+  virtual int do_terminal_rows () { return m_rows; }
 
-  virtual int do_terminal_cols (void) { return m_cols; }
+  virtual int do_terminal_cols () { return m_cols; }
 
   virtual void do_clear_screen (bool) { }
 
-  virtual void do_resize_terminal (void) { }
+  virtual void do_resize_terminal () { }
 
   virtual void do_set_screen_size (int ht, int wd)
   {
@@ -278,9 +274,9 @@
 
   virtual std::string do_decode_prompt_string (const std::string&);
 
-  virtual std::string newline_chars (void) { return "\n"; }
+  virtual std::string newline_chars () { return "\n"; }
 
-  virtual void do_restore_terminal_state (void) { }
+  virtual void do_restore_terminal_state () { }
 
   virtual void do_blink_matching_paren (bool) { }
 
@@ -310,60 +306,60 @@
 
   virtual void do_set_user_accept_line_function (user_accept_line_fcn) { }
 
-  virtual completion_fcn do_get_completion_function (void) const
+  virtual completion_fcn do_get_completion_function () const
   { return nullptr; }
 
-  virtual quoting_fcn do_get_quoting_function (void) const
+  virtual quoting_fcn do_get_quoting_function () const
   { return nullptr; }
 
-  virtual dequoting_fcn do_get_dequoting_function (void) const
+  virtual dequoting_fcn do_get_dequoting_function () const
   { return nullptr; }
 
-  virtual char_is_quoted_fcn do_get_char_is_quoted_function (void) const
+  virtual char_is_quoted_fcn do_get_char_is_quoted_function () const
   { return nullptr; }
 
-  virtual user_accept_line_fcn do_get_user_accept_line_function (void) const
+  virtual user_accept_line_fcn do_get_user_accept_line_function () const
   { return nullptr; }
 
   virtual string_vector
   do_generate_filename_completions (const std::string& text) = 0;
 
-  virtual std::string do_get_line_buffer (void) const = 0;
+  virtual std::string do_get_line_buffer () const = 0;
 
-  virtual std::string do_get_current_line (void) const = 0;
+  virtual std::string do_get_current_line () const = 0;
 
   virtual char do_get_prev_char (int) const = 0;
 
   virtual void
   do_replace_line (const std::string& text, bool clear_undo) = 0;
 
-  virtual void do_kill_full_line (void) = 0;
+  virtual void do_kill_full_line () = 0;
 
   virtual void do_insert_text (const std::string& text) = 0;
 
-  virtual void do_newline (void) = 0;
+  virtual void do_newline () = 0;
 
-  virtual void do_accept_line (void) = 0;
+  virtual void do_accept_line () = 0;
 
-  virtual bool do_undo (void) { return false; }
+  virtual bool do_undo () { return false; }
 
-  virtual void do_clear_undo_list (void) { }
+  virtual void do_clear_undo_list () { }
 
   virtual void set_startup_hook (startup_hook_fcn) { }
 
-  virtual void restore_startup_hook (void) { }
+  virtual void restore_startup_hook () { }
 
   virtual void set_pre_input_hook (pre_input_hook_fcn) { }
 
-  virtual void restore_pre_input_hook (void) { }
+  virtual void restore_pre_input_hook () { }
 
   virtual void set_event_hook (event_hook_fcn) { }
 
-  virtual void restore_event_hook (void) { }
+  virtual void restore_event_hook () { }
 
   virtual void do_read_init_file (const std::string&) { }
 
-  virtual void do_re_read_init_file (void) { }
+  virtual void do_re_read_init_file () { }
 
   virtual bool do_filename_completion_desired (bool) { return false; }
 
@@ -373,14 +369,14 @@
 
   virtual void do_interrupt (bool) { }
 
-  virtual void do_handle_interrupt_signal (void) { }
+  virtual void do_handle_interrupt_signal () { }
 
   void do_interrupt_event_loop (bool arg) { m_interrupt_event_loop = arg; }
 
-  bool do_event_loop_interrupted (void) const
+  bool do_event_loop_interrupted () const
   { return m_interrupt_event_loop; }
 
-  int do_insert_initial_input (void);
+  int do_insert_initial_input ();
 
   int read_octal (const std::string& s);
 
--- a/liboctave/util/cmd-hist.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/cmd-hist.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -61,40 +61,42 @@
 {
 public:
 
-  gnu_history (void)
-    : command_history (), mark (0) { }
+  gnu_history ()
+    : command_history (), m_mark (0) { }
 
-  ~gnu_history (void) = default;
+  OCTAVE_DISABLE_COPY_MOVE (gnu_history)
+
+  ~gnu_history () = default;
 
   void do_process_histcontrol (const std::string&);
 
-  std::string do_histcontrol (void) const;
+  std::string do_histcontrol () const;
 
   bool do_add (const std::string&);
 
   void do_remove (int);
 
-  void do_clear (void);
+  void do_clear ();
 
-  int do_where (void) const;
+  int do_where () const;
 
-  int do_length (void) const;
+  int do_length () const;
 
-  int do_max_input_history (void) const;
+  int do_max_input_history () const;
 
-  int do_base (void) const;
+  int do_base () const;
 
-  int do_current_number (void) const;
+  int do_current_number () const;
 
   void do_stifle (int);
 
-  int do_unstifle (void);
+  int do_unstifle ();
 
-  int do_is_stifled (void) const;
+  int do_is_stifled () const;
 
   void do_set_mark (int);
 
-  int do_goto_mark (void);
+  int do_goto_mark ();
 
   void do_read (const std::string&, bool);
 
@@ -116,7 +118,7 @@
 
 private:
 
-  int mark;
+  int m_mark;
 };
 
 void
@@ -160,7 +162,7 @@
 }
 
 std::string
-gnu_history::do_histcontrol (void) const
+gnu_history::do_histcontrol () const
 {
   // FIXME: instead of reconstructing this value, should we just save
   // the string we were given when constructing the command_history object?
@@ -217,37 +219,37 @@
 }
 
 void
-gnu_history::do_clear (void)
+gnu_history::do_clear ()
 {
   ::octave_clear_history ();
 }
 
 int
-gnu_history::do_where (void) const
+gnu_history::do_where () const
 {
   return ::octave_where_history ();
 }
 
 int
-gnu_history::do_length (void) const
+gnu_history::do_length () const
 {
   return ::octave_history_length ();
 }
 
 int
-gnu_history::do_max_input_history (void) const
+gnu_history::do_max_input_history () const
 {
   return ::octave_max_input_history ();
 }
 
 int
-gnu_history::do_base (void) const
+gnu_history::do_base () const
 {
   return ::octave_history_base ();
 }
 
 int
-gnu_history::do_current_number (void) const
+gnu_history::do_current_number () const
 {
   return m_size > 0 ? do_base () + do_where () : -1;
 }
@@ -259,13 +261,13 @@
 }
 
 int
-gnu_history::do_unstifle (void)
+gnu_history::do_unstifle ()
 {
   return ::octave_unstifle_history ();
 }
 
 int
-gnu_history::do_is_stifled (void) const
+gnu_history::do_is_stifled () const
 {
   return ::octave_history_is_stifled ();
 }
@@ -273,15 +275,15 @@
 void
 gnu_history::do_set_mark (int n)
 {
-  mark = n;
+  m_mark = n;
 }
 
 int
-gnu_history::do_goto_mark (void)
+gnu_history::do_goto_mark ()
 {
-  if (mark)
+  if (m_mark)
     {
-      char *line = ::octave_history_goto_mark (mark);
+      char *line = ::octave_history_goto_mark (m_mark);
 
       if (line)
         {
@@ -291,7 +293,7 @@
         }
     }
 
-  mark = 0;
+  m_mark = 0;
 
   // FIXME: for operate_and_get_next.
   command_editor::remove_startup_hook (command_history::goto_mark);
@@ -369,8 +371,7 @@
           std::string hist_dir = sys::file_ops::dirname (f);
           if (! hist_dir.empty ())
             {
-              sys::file_stat fs (hist_dir);
-              if (! fs.is_dir ()
+              if (! sys::dir_exists (hist_dir)
                   && (sys::recursive_mkdir (hist_dir, 0777) < 0))
                 (*current_liboctave_error_handler)
                   ("%s: Could not create directory \"%s\" for history",
@@ -409,9 +410,7 @@
 
               if (! f.empty ())
                 {
-                  sys::file_stat fs (f);
-
-                  if (! fs)
+                  if (! sys::file_exists (f))
                     {
                       std::ofstream tmp = sys::ofstream (f, std::ios::out);
                       tmp.close ();
@@ -512,7 +511,7 @@
 #endif
 
 bool
-command_history::instance_ok (void)
+command_history::instance_ok ()
 {
   bool retval = true;
 
@@ -532,7 +531,7 @@
 }
 
 void
-command_history::make_command_history (void)
+command_history::make_command_history ()
 {
 #if defined (USE_READLINE)
   s_instance = new gnu_history ();
@@ -551,7 +550,7 @@
 }
 
 bool
-command_history::is_initialized (void)
+command_history::is_initialized ()
 {
   // We just want to check the status of an existing instance, not
   // create one.
@@ -570,7 +569,7 @@
 }
 
 std::string
-command_history::file (void)
+command_history::file ()
 {
   return instance_ok () ? s_instance->do_file () : "";
 }
@@ -583,7 +582,7 @@
 }
 
 std::string
-command_history::histcontrol (void)
+command_history::histcontrol ()
 {
   return instance_ok () ? s_instance->do_histcontrol () : "";
 }
@@ -596,7 +595,7 @@
 }
 
 int
-command_history::size (void)
+command_history::size ()
 {
   return instance_ok () ? s_instance->do_size () : 0;
 }
@@ -609,7 +608,7 @@
 }
 
 bool
-command_history::ignoring_entries (void)
+command_history::ignoring_entries ()
 {
   return instance_ok () ? s_instance->do_ignoring_entries () : false;
 }
@@ -630,38 +629,38 @@
 }
 
 void
-command_history::clear (void)
+command_history::clear ()
 {
   if (instance_ok ())
     s_instance->do_clear ();
 }
 
 int
-command_history::where (void)
+command_history::where ()
 {
   return instance_ok () ? s_instance->do_where () : 0;
 }
 
 int
-command_history::length (void)
+command_history::length ()
 {
   return instance_ok () ? s_instance->do_length () : 0;
 }
 
 int
-command_history::max_input_history (void)
+command_history::max_input_history ()
 {
   return instance_ok () ? s_instance->do_max_input_history () : 0;
 }
 
 int
-command_history::base (void)
+command_history::base ()
 {
   return instance_ok () ? s_instance->do_base () : 0;
 }
 
 int
-command_history::current_number (void)
+command_history::current_number ()
 {
   return instance_ok () ? s_instance->do_current_number () : 0;
 }
@@ -674,13 +673,13 @@
 }
 
 int
-command_history::unstifle (void)
+command_history::unstifle ()
 {
   return instance_ok () ? s_instance->do_unstifle () : 0;
 }
 
 int
-command_history::is_stifled (void)
+command_history::is_stifled ()
 {
   return instance_ok () ? s_instance->do_is_stifled () : 0;
 }
@@ -693,7 +692,7 @@
 }
 
 int
-command_history::goto_mark (void)
+command_history::goto_mark ()
 {
   return instance_ok () ? s_instance->do_goto_mark () : 0;
 }
@@ -793,7 +792,7 @@
 }
 
 bool
-command_history::do_is_initialized (void) const
+command_history::do_is_initialized () const
 {
   return m_initialized;
 }
@@ -805,7 +804,7 @@
 }
 
 std::string
-command_history::do_file (void)
+command_history::do_file ()
 {
   return m_file;
 }
@@ -817,7 +816,7 @@
 }
 
 int
-command_history::do_size (void) const
+command_history::do_size () const
 {
   return m_size;
 }
@@ -829,7 +828,7 @@
 }
 
 bool
-command_history::do_ignoring_entries (void) const
+command_history::do_ignoring_entries () const
 {
   return m_ignoring_additions;
 }
@@ -845,35 +844,35 @@
 { }
 
 void
-command_history::do_clear (void)
+command_history::do_clear ()
 { }
 
 int
-command_history::do_where (void) const
+command_history::do_where () const
 {
   return 0;
 }
 
 int
-command_history::do_length (void) const
+command_history::do_length () const
 {
   return 0;
 }
 
 int
-command_history::do_max_input_history (void) const
+command_history::do_max_input_history () const
 {
   return 0;
 }
 
 int
-command_history::do_base (void) const
+command_history::do_base () const
 {
   return 0;
 }
 
 int
-command_history::do_current_number (void) const
+command_history::do_current_number () const
 {
   return m_size > 0 ? do_base () + do_where () : -1;
 }
@@ -883,13 +882,13 @@
 { }
 
 int
-command_history::do_unstifle (void)
+command_history::do_unstifle ()
 {
   return -1;
 }
 
 int
-command_history::do_is_stifled (void) const
+command_history::do_is_stifled () const
 {
   return 0;
 }
@@ -899,7 +898,7 @@
 { }
 
 int
-command_history::do_goto_mark (void)
+command_history::do_goto_mark ()
 {
   return 0;
 }
--- a/liboctave/util/cmd-hist.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/cmd-hist.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 protected:
 
-  command_history (void)
+  command_history ()
     : m_initialized (false), m_ignoring_additions (false),
       m_history_control (0), m_lines_in_file (0),
       m_lines_this_session (0), m_file (), m_size (-1)
@@ -48,62 +48,58 @@
 
 public:
 
-  // No copying!
-
-  command_history (const command_history&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (command_history)
 
-  command_history& operator = (const command_history&) = delete;
-
-  virtual ~command_history (void) = default;
+  virtual ~command_history () = default;
 
   static void initialize (bool, const std::string&, int, const std::string&);
 
-  static bool is_initialized (void);
+  static bool is_initialized ();
 
   static void set_file (const std::string&);
 
-  static std::string file (void);
+  static std::string file ();
 
   static void process_histcontrol (const std::string&);
 
-  static std::string histcontrol (void);
+  static std::string histcontrol ();
 
   static void set_size (int);
 
-  static int size (void);
+  static int size ();
 
   static void ignore_entries (bool = true);
 
-  static bool ignoring_entries (void);
+  static bool ignoring_entries ();
 
   static bool add (const std::string&);
 
   static void remove (int);
 
-  static void clear (void);
+  static void clear ();
 
-  static int where (void);
+  static int where ();
 
-  static int length (void);
+  static int length ();
 
-  static int max_input_history (void);
+  static int max_input_history ();
 
-  static int base (void);
+  static int base ();
 
-  static int current_number (void);
+  static int current_number ();
 
   static void stifle (int);
 
-  static int unstifle (void);
+  static int unstifle ();
 
-  static int is_stifled (void);
+  static int is_stifled ();
 
   static void set_mark (int n);
 
   // Gag.  This declaration has to match the Function typedef in
   // readline.h.
 
-  static int goto_mark (void);
+  static int goto_mark ();
 
   static void read (bool = true);
 
@@ -130,14 +126,14 @@
 
 private:
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
-  static void make_command_history (void);
+  static void make_command_history ();
 
   // The real thing.
   static command_history *s_instance;
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   {
     delete s_instance;
     s_instance = nullptr;
@@ -151,50 +147,50 @@
 
   virtual void do_set_file (const std::string&);
 
-  virtual std::string do_file (void);
+  virtual std::string do_file ();
 
   virtual void do_process_histcontrol (const std::string&);
 
-  virtual std::string do_histcontrol (void) const { return ""; }
+  virtual std::string do_histcontrol () const { return ""; }
 
   virtual void do_initialize (bool, const std::string&, int,
                               const std::string&);
 
-  virtual bool do_is_initialized (void) const;
+  virtual bool do_is_initialized () const;
 
   virtual void do_set_size (int);
 
-  virtual int do_size (void) const;
+  virtual int do_size () const;
 
   virtual void do_ignore_entries (bool);
 
-  virtual bool do_ignoring_entries (void) const;
+  virtual bool do_ignoring_entries () const;
 
   virtual bool do_add (const std::string&);
 
   virtual void do_remove (int);
 
-  virtual void do_clear (void);
+  virtual void do_clear ();
 
-  virtual int do_where (void) const;
+  virtual int do_where () const;
 
-  virtual int do_length (void) const;
+  virtual int do_length () const;
 
-  virtual int do_max_input_history (void) const;
+  virtual int do_max_input_history () const;
 
-  virtual int do_base (void) const;
+  virtual int do_base () const;
 
-  virtual int do_current_number (void) const;
+  virtual int do_current_number () const;
 
   virtual void do_stifle (int);
 
-  virtual int do_unstifle (void);
+  virtual int do_unstifle ();
 
-  virtual int do_is_stifled (void) const;
+  virtual int do_is_stifled () const;
 
   virtual void do_set_mark (int);
 
-  virtual int do_goto_mark (void);
+  virtual int do_goto_mark ();
 
   virtual void do_read (const std::string&, bool);
 
--- a/liboctave/util/data-conv.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/data-conv.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -616,7 +616,7 @@
 
 OCTAVE_NORETURN static
 void
-err_unrecognized_float_fmt (void)
+err_unrecognized_float_fmt ()
 {
   (*current_liboctave_error_handler)
     ("unrecognized floating point format requested");
--- a/liboctave/util/file-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/file-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,7 +41,7 @@
 {
 public:
 
-  file_info (void)
+  file_info ()
     : m_file_buf (), m_offsets (), m_timestamp (static_cast<OCTAVE_TIME_T> (0))
   { }
 
@@ -60,22 +60,22 @@
 
   file_info& operator = (const file_info&) = default;
 
-  ~file_info (void) = default;
+  ~file_info () = default;
 
   OCTAVE_API std::string get_line (std::size_t line) const;
 
   OCTAVE_API std::deque<std::string>
   get_lines (std::size_t line, std::size_t num_lines) const;
 
-  std::size_t num_lines (void) const { return m_offsets.size (); }
+  std::size_t num_lines () const { return m_offsets.size (); }
 
-  std::string text (void) const { return m_file_buf; }
+  std::string text () const { return m_file_buf; }
 
-  std::vector<std::size_t> line_offsets (void) const { return m_offsets; }
+  std::vector<std::size_t> line_offsets () const { return m_offsets; }
 
-  sys::time timestamp (void) const { return m_timestamp; }
+  sys::time timestamp () const { return m_timestamp; }
 
-  std::size_t size (void) const { return m_file_buf.length (); }
+  std::size_t size () const { return m_file_buf.length (); }
 
 private:
 
--- a/liboctave/util/glob-match.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/glob-match.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -38,7 +38,7 @@
 }
 
 string_vector
-glob_match::glob (void) const
+glob_match::glob () const
 {
   return octave::sys::glob (m_pat);
 }
--- a/liboctave/util/glob-match.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/glob-match.h	Fri Jun 23 20:51:51 2023 +0200
@@ -60,7 +60,7 @@
 
   glob_match& operator = (const glob_match& gm) = default;
 
-  ~glob_match (void) = default;
+  ~glob_match () = default;
 
   void set_pattern (const std::string& p) { m_pat = p; }
 
@@ -83,7 +83,7 @@
   // We forward to glob_internal here to avoid problems with gnulib's
   // glob.h defining glob to be rpl_glob.
 
-  string_vector glob (void) const;
+  string_vector glob () const;
 
 private:
 
--- a/liboctave/util/kpse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/kpse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -45,6 +45,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "kpse.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-password.h"
 #include "oct-time.h"
@@ -54,8 +55,6 @@
 #if defined (OCTAVE_USE_WINDOWS_API)
 #  define WIN32_LEAN_AND_MEAN 1
 #  include <windows.h>
-
-#  include "lo-sysdep.h"
 #endif
 
 // Define the characters which separate components of filenames and
@@ -92,7 +91,7 @@
 unsigned int kpse_debug = 0;
 
 void
-kpse_path_iterator::set_end (void)
+kpse_path_iterator::set_end ()
 {
   m_e = m_b + 1;
 
@@ -111,7 +110,7 @@
 }
 
 void
-kpse_path_iterator::next (void)
+kpse_path_iterator::next ()
 {
   m_b = m_e + 1;
 
@@ -1015,17 +1014,6 @@
   return c;
 }
 
-/* Return true if FN is a directory or a symlink to a directory,
-   false if not. */
-
-static bool
-dir_p (const std::string& fn)
-{
-  octave::sys::file_stat fs (fn);
-
-  return (fs && fs.is_dir ());
-}
-
 /* Given a path element ELT, return a the element with a trailing slash
    or an empty string if the element is not a directory.
 
@@ -1042,7 +1030,7 @@
   if (elt.empty ())
     return ret;
 
-  if (dir_p (elt))
+  if (octave::sys::dir_exists (elt))
     {
       ret = elt;
 
--- a/liboctave/util/kpse.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/kpse.h	Fri Jun 23 20:51:51 2023 +0200
@@ -38,19 +38,18 @@
 {
 public:
 
+  kpse_path_iterator () = delete;
+
   kpse_path_iterator (const std::string& p)
     : m_path (p), m_b (0), m_e (0), m_len (m_path.length ())
   {
     set_end ();
   }
 
-  kpse_path_iterator (const kpse_path_iterator&) = default;
-
-  // No assignment!
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (kpse_path_iterator)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (kpse_path_iterator)
 
-  kpse_path_iterator& operator = (const kpse_path_iterator&) = delete;
-
-  ~kpse_path_iterator (void) = default;
+  ~kpse_path_iterator () = default;
 
   kpse_path_iterator operator ++ (int)
   {
@@ -59,7 +58,7 @@
     return retval;
   }
 
-  std::string operator * (void) { return m_path.substr (m_b, m_e-m_b); }
+  std::string operator * () { return m_path.substr (m_b, m_e-m_b); }
 
   bool operator != (const std::size_t sz) { return m_b != sz; }
 
@@ -70,8 +69,8 @@
   std::size_t m_e;
   std::size_t m_len;
 
-  void set_end (void);
-  void next (void);
+  void set_end ();
+  void next ();
 };
 
 extern unsigned int kpse_debug;
--- a/liboctave/util/lo-array-errwarn.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-array-errwarn.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -54,14 +54,14 @@
 static const char *warning_id_singular_matrix = "Octave:singular-matrix";
 
 void
-err_nan_to_logical_conversion (void)
+err_nan_to_logical_conversion ()
 {
   (*current_liboctave_error_handler)
     ("invalid conversion from NaN to logical");
 }
 
 void
-err_nan_to_character_conversion (void)
+err_nan_to_character_conversion ()
 {
   (*current_liboctave_error_handler)
     ("invalid conversion from NaN to character");
@@ -124,7 +124,7 @@
 // offending one, e.g., (<error>), (<error>,_), or (_,<error>,...[x5]...)
 
 std::string
-index_exception::expression (void) const
+index_exception::expression () const
 {
   std::ostringstream buf;
 
@@ -179,7 +179,9 @@
     update_message ();
   }
 
-  void update_message (void)
+  OCTAVE_DEFAULT_COPY_MOVE (invalid_index)
+
+  void update_message ()
   {
     static std::string exp
       = std::to_string (std::numeric_limits<octave_idx_type>::digits);
@@ -190,10 +192,17 @@
   }
 
   // ID of error to throw
-  const char * err_id (void) const
+  const char * err_id () const
   {
     return error_id_invalid_index;
   }
+
+  index_exception * dup ()
+  {
+    invalid_index *retval = new invalid_index {*this};
+    retval->set_identifier (retval->err_id ());
+    return retval;
+  }
 };
 
 // Complain if an index is negative, fractional, or too big.
@@ -247,7 +256,9 @@
     update_message ();
   }
 
-  void update_message (void)
+  OCTAVE_DEFAULT_COPY_MOVE (out_of_range)
+
+  void update_message ()
   {
     set_message (expression () + ": out of bound "
                  + std::to_string (m_extent)
@@ -255,11 +266,18 @@
   }
 
   // ID of error to throw.
-  const char * err_id (void) const
+  const char * err_id () const
   {
     return error_id_index_out_of_bounds;
   }
 
+  index_exception * dup ()
+  {
+    out_of_range *retval = new out_of_range {*this};
+    retval->set_identifier (retval->err_id ());
+    return retval;
+  }
+
 private:
 
   // Dimension of object being accessed.
@@ -278,7 +296,7 @@
 }
 
 void
-err_invalid_resize (void)
+err_invalid_resize ()
 {
   (*current_liboctave_error_with_id_handler)
     ("Octave:invalid-resize",
--- a/liboctave/util/lo-array-errwarn.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-array-errwarn.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,6 +45,8 @@
 {
 public:
 
+  index_exception () = delete;
+
   index_exception (const std::string& index, octave_idx_type nd = 0,
                    octave_idx_type dim = -1, const char *var = "")
     : m_index (index), m_nd (nd), m_dim (dim), m_var (var)
@@ -52,13 +54,15 @@
     set_message (expression ());
   }
 
-  ~index_exception (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE (index_exception)
+
+  ~index_exception () = default;
 
   // ID of error to throw.
-  virtual const char * err_id (void) const = 0;
+  virtual const char * err_id () const = 0;
 
   // By default, update message to show the erroneous index expression.
-  virtual void update_message (void) { set_message (expression ()); }
+  virtual void update_message () { set_message (expression ()); }
 
   // Position of error: dimension in error, and number of dimensions.
   void set_pos (octave_idx_type nd_arg, octave_idx_type dim_arg)
@@ -88,6 +92,9 @@
     update_message ();
   }
 
+  // Return a newly allocated copy of the index_exception object.
+  virtual index_exception * dup () = 0;
+
 private:
 
   // Value of invalid index.
@@ -96,7 +103,7 @@
 protected:
 
   // Show what's wrong, e.g.,  A(-1,_), A(0+1i).
-  OCTAVE_API std::string expression (void) const;
+  OCTAVE_API std::string expression () const;
 
   // Number of dimensions of indexed object.
   octave_idx_type m_nd;
@@ -109,10 +116,10 @@
 };
 
 OCTAVE_NORETURN extern OCTAVE_API void
-err_nan_to_logical_conversion (void);
+err_nan_to_logical_conversion ();
 
 OCTAVE_NORETURN extern OCTAVE_API void
-err_nan_to_character_conversion (void);
+err_nan_to_character_conversion ();
 
 OCTAVE_NORETURN extern OCTAVE_API void
 err_nonconformant (const char *op, octave_idx_type op1_len,
@@ -151,7 +158,7 @@
                    const std::string& var = "");
 
 OCTAVE_NORETURN extern OCTAVE_API void
-err_invalid_resize (void);
+err_invalid_resize ();
 
 extern OCTAVE_API void
 warn_singular_matrix (double rcond = 0.0);
--- a/liboctave/util/lo-hash.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-hash.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -57,14 +57,14 @@
   return buf.str ();
 }
 
-int md2_digest_size (void) { return octave_md2_digest_size (); }
-int md4_digest_size (void) { return octave_md4_digest_size (); }
-int md5_digest_size (void) { return octave_md5_digest_size (); }
-int sha1_digest_size (void) { return octave_sha1_digest_size (); }
-int sha224_digest_size (void) { return octave_sha224_digest_size (); }
-int sha256_digest_size (void) { return octave_sha256_digest_size (); }
-int sha384_digest_size (void) { return octave_sha384_digest_size (); }
-int sha512_digest_size (void) { return octave_sha512_digest_size (); }
+int md2_digest_size () { return octave_md2_digest_size (); }
+int md4_digest_size () { return octave_md4_digest_size (); }
+int md5_digest_size () { return octave_md5_digest_size (); }
+int sha1_digest_size () { return octave_sha1_digest_size (); }
+int sha224_digest_size () { return octave_sha224_digest_size (); }
+int sha256_digest_size () { return octave_sha256_digest_size (); }
+int sha384_digest_size () { return octave_sha384_digest_size (); }
+int sha512_digest_size () { return octave_sha512_digest_size (); }
 
 std::string
 md2_hash (const std::string& str)
--- a/liboctave/util/lo-hash.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-hash.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,14 +39,14 @@
 OCTAVE_API std::string
 hash (hash_fptr hash_fcn, const std::string& str, int result_buf_len);
 
-OCTAVE_API int md2_digest_size (void);
-OCTAVE_API int md4_digest_size (void);
-OCTAVE_API int md5_digest_size (void);
-OCTAVE_API int sha1_digest_size (void);
-OCTAVE_API int sha224_digest_size (void);
-OCTAVE_API int sha256_digest_size (void);
-OCTAVE_API int sha384_digest_size (void);
-OCTAVE_API int sha512_digest_size (void);
+OCTAVE_API int md2_digest_size ();
+OCTAVE_API int md4_digest_size ();
+OCTAVE_API int md5_digest_size ();
+OCTAVE_API int sha1_digest_size ();
+OCTAVE_API int sha224_digest_size ();
+OCTAVE_API int sha256_digest_size ();
+OCTAVE_API int sha384_digest_size ();
+OCTAVE_API int sha512_digest_size ();
 
 OCTAVE_API std::string md2_hash (const std::string& str);
 OCTAVE_API std::string md4_hash (const std::string& str);
--- a/liboctave/util/lo-ieee.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-ieee.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -65,7 +65,7 @@
 }
 
 double
-lo_ieee_inf_value (void)
+lo_ieee_inf_value ()
 {
   octave_ieee_init ();
 
@@ -73,7 +73,7 @@
 }
 
 double
-lo_ieee_na_value (void)
+lo_ieee_na_value ()
 {
   octave_ieee_init ();
 
@@ -81,7 +81,7 @@
 }
 
 double
-lo_ieee_nan_value (void)
+lo_ieee_nan_value ()
 {
   octave_ieee_init ();
 
@@ -97,7 +97,7 @@
 }
 
 float
-lo_ieee_float_inf_value (void)
+lo_ieee_float_inf_value ()
 {
   octave_ieee_init ();
 
@@ -105,7 +105,7 @@
 }
 
 float
-lo_ieee_float_na_value (void)
+lo_ieee_float_na_value ()
 {
   octave_ieee_init ();
 
@@ -113,7 +113,7 @@
 }
 
 float
-lo_ieee_float_nan_value (void)
+lo_ieee_float_nan_value ()
 {
   octave_ieee_init ();
 
@@ -121,7 +121,7 @@
 }
 
 void
-octave_ieee_init (void)
+octave_ieee_init ()
 {
   static bool initialized = false;
 
--- a/liboctave/util/lo-ieee.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-ieee.h	Fri Jun 23 20:51:51 2023 +0200
@@ -129,44 +129,31 @@
 struct numeric_limits
 {
 public:
-  static T NA (void) { return static_cast<T> (0); }
-  static T NaN (void) { return static_cast<T> (0); }
-  static T Inf (void) { return static_cast<T> (0); }
+  static T NA () { return static_cast<T> (0); }
+  static T NaN () { return static_cast<T> (0); }
+  static T Inf () { return static_cast<T> (0); }
 };
 
 template <>
 struct numeric_limits<double>
 {
 public:
-  static double NA (void) { return octave_NA; }
-  static double NaN (void) { return octave_NaN; }
-  static double Inf (void) { return octave_Inf; }
+  static double NA () { return octave_NA; }
+  static double NaN () { return octave_NaN; }
+  static double Inf () { return octave_Inf; }
 };
 
 template <>
 struct numeric_limits<float>
 {
 public:
-  static float NA (void) { return octave_Float_NA; }
-  static float NaN (void) { return octave_Float_NaN; }
-  static float Inf (void) { return octave_Float_Inf; }
+  static float NA () { return octave_Float_NA; }
+  static float NaN () { return octave_Float_NaN; }
+  static float Inf () { return octave_Float_Inf; }
 };
 
 OCTAVE_END_NAMESPACE(octave)
 
 #endif
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-
-OCTAVE_DEPRECATED (7, "use '__lo_ieee_isfinite' instead")
-inline int __lo_ieee_finite (double x) { return __lo_ieee_isfinite (x); }
-
-OCTAVE_DEPRECATED (7, "use '__lo_ieee_float_isfinite' instead")
-inline int __lo_ieee_float_finite (float x)
-{ return __lo_ieee_float_isfinite (x); }
-
-#define lo_ieee_finite(x) lo_ieee_isfinite(x)
-
 #endif
-
-#endif
--- a/liboctave/util/lo-regexp.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-regexp.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -112,13 +112,13 @@
 //        the user doesn't want.
 
 void
-regexp::free (void)
+regexp::free ()
 {
   octave_pcre_code_free (static_cast<octave_pcre_code *> (m_code));
 }
 
 void
-regexp::compile_internal (void)
+regexp::compile_internal ()
 {
   // If we had a previously compiled pattern, release it.
   free ();
@@ -488,7 +488,9 @@
 
           string_vector tokens (pos_match);
           string_vector named_tokens (m_names);
+#if ! defined (HAVE_PCRE2)
           int pos_offset = 0;
+#endif
           pos_match = 0;
 
           for (int i = 1; i < matches; i++)
@@ -532,8 +534,10 @@
                       tokens(pos_match++) = std::string (*(listptr+i), len);
 #endif
                     }
+#if ! defined (HAVE_PCRE2)
                   else
                     pos_offset++;
+#endif
                 }
             }
 
--- a/liboctave/util/lo-regexp.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-regexp.h	Fri Jun 23 20:51:51 2023 +0200
@@ -61,7 +61,7 @@
 
   regexp& operator = (const regexp& rx) = default;
 
-  ~regexp (void) { free (); }
+  ~regexp () { free (); }
 
   void compile (const std::string& pat,
                 const regexp::opts& opt = regexp::opts ())
@@ -125,7 +125,7 @@
   {
   public:
 
-    opts (void)
+    opts ()
       : m_case_insensitive (false), m_dotexceptnewline (false),
         m_emptymatch (false), m_freespacing (false), m_lineanchors (false),
         m_once (false) { }
@@ -134,7 +134,7 @@
 
     opts& operator = (const opts&) = default;
 
-    ~opts (void) = default;
+    ~opts () = default;
 
     void case_insensitive (bool val) { m_case_insensitive = val; }
     void dotexceptnewline (bool val) { m_dotexceptnewline = val; }
@@ -143,12 +143,12 @@
     void lineanchors (bool val) { m_lineanchors = val; }
     void once (bool val) { m_once = val; }
 
-    bool case_insensitive (void) const { return m_case_insensitive; }
-    bool dotexceptnewline (void) const { return m_dotexceptnewline; }
-    bool emptymatch (void) const { return m_emptymatch; }
-    bool freespacing (void) const { return m_freespacing; }
-    bool lineanchors (void) const { return m_lineanchors; }
-    bool once (void) const { return m_once; }
+    bool case_insensitive () const { return m_case_insensitive; }
+    bool dotexceptnewline () const { return m_dotexceptnewline; }
+    bool emptymatch () const { return m_emptymatch; }
+    bool freespacing () const { return m_freespacing; }
+    bool lineanchors () const { return m_lineanchors; }
+    bool once () const { return m_once; }
 
   private:
 
@@ -164,6 +164,8 @@
   {
   public:
 
+    match_element () = delete;
+
     match_element (const string_vector& nt, const string_vector& t,
                    const std::string& ms, const Matrix& te,
                    double s, double e)
@@ -171,16 +173,14 @@
         m_token_extents (te), m_start (s), m_end (e)
     { }
 
-    match_element (const match_element&) = default;
-
-    match_element& operator = (const match_element&) = default;
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (match_element)
 
-    std::string match_string (void) const { return m_match_string; }
-    string_vector named_tokens (void) const { return m_named_tokens; }
-    string_vector tokens (void) const { return m_tokens; }
-    Matrix token_extents (void) const { return m_token_extents; }
-    double start (void) const { return m_start; }
-    double end (void) const { return m_end; }
+    std::string match_string () const { return m_match_string; }
+    string_vector named_tokens () const { return m_named_tokens; }
+    string_vector tokens () const { return m_tokens; }
+    Matrix token_extents () const { return m_token_extents; }
+    double start () const { return m_start; }
+    double end () const { return m_end; }
 
   private:
 
@@ -200,7 +200,7 @@
   {
   public:
 
-    match_data (void)
+    match_data ()
       : base_list<match_element> (), m_named_pats ()
     { }
 
@@ -208,13 +208,9 @@
       : base_list<match_element> (l), m_named_pats (np)
     { }
 
-    match_data (const match_data&) = default;
-
-    match_data& operator = (const match_data&) = default;
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (match_data)
 
-    ~match_data (void) = default;
-
-    string_vector named_patterns (void) const { return m_named_pats; }
+    string_vector named_patterns () const { return m_named_pats; }
 
   private:
 
@@ -236,9 +232,9 @@
   Array<int> m_named_idx;
   std::string m_who;
 
-  void free (void);
+  void free ();
 
-  void compile_internal (void);
+  void compile_internal ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/util/lo-utils.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-utils.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -215,7 +215,10 @@
           {
             char c2 = is.get ();
             if (c2 == 'f' || c2 == 'F')
-              val = std::numeric_limits<T>::infinity ();
+              {
+                val = std::numeric_limits<T>::infinity ();
+                is.peek ();  // Potentially set EOF bit
+              }
             else
               is.setstate (std::ios::failbit);
           }
@@ -231,7 +234,10 @@
           {
             char c2 = is.get ();
             if (c2 == 'n' || c2 == 'N')
-              val = std::numeric_limits<T>::quiet_NaN ();
+              {
+                val = std::numeric_limits<T>::quiet_NaN ();
+                is.peek ();  // Potentially set EOF bit
+              }
             else
               {
                 val = numeric_limits<T>::NA ();
@@ -263,16 +269,13 @@
   T val = 0.0;
 
   // FIXME: resetting stream position is likely to fail unless we are
-  // reading from a file.
+  //        reading from a file.
   std::streampos pos = is.tellg ();
 
-  char c1 = ' ';
-
-  while (isspace (c1))
-    c1 = is.get ();
+  is >> std::ws;  // skip through whitespace and advance stream pointer
 
   bool neg = false;
-
+  char c1 = is.get ();
   switch (c1)
     {
     case '-':
@@ -285,13 +288,15 @@
         c2 = is.get ();
         if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           val = read_inf_nan_na<T> (is, c2);
+        else if (isspace (c2))
+          is.setstate (std::ios::failbit);
         else
           {
             is.putback (c2);
             is >> val;
           }
 
-        if (neg && ! is.fail ())
+        if (neg && ! math::isnan (val) && ! is.fail ())
           val = -val;
       }
       break;
@@ -321,10 +326,11 @@
         }
       else
         {
-          // True error.  Reset stream to original position and pass status on.
+          // True error.
+          // Reset stream to original position, clear eof bit, pass status on.
           is.clear ();
           is.seekg (pos);
-          is.setstate (status);
+          is.setstate (status & ~std::ios_base::eofbit);
         }
     }
 
@@ -379,22 +385,22 @@
 
 template <> OCTAVE_API double read_value (std::istream& is)
 {
-                                          return read_fp_value<double> (is);
+  return read_fp_value<double> (is);
 }
 
 template <> OCTAVE_API Complex read_value (std::istream& is)
 {
-                                           return read_cx_fp_value<double> (is);
+  return read_cx_fp_value<double> (is);
 }
 
 template <> OCTAVE_API float read_value (std::istream& is)
 {
-                                         return read_fp_value<float> (is);
+  return read_fp_value<float> (is);
 }
 
 template <> OCTAVE_API FloatComplex read_value (std::istream& is)
 {
-                                                return read_cx_fp_value<float> (is);
+  return read_cx_fp_value<float> (is);
 }
 
 template <typename T>
@@ -477,43 +483,43 @@
 
 OCTAVE_BEGIN_NAMESPACE(math)
 
-bool int_multiply_overflow (int a, int b, int *r)
-{
-  return octave_i_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (int a, int b, int *r)
+  {
+    return octave_i_multiply_overflow_wrapper (a, b, r);
+  }
 
-bool int_multiply_overflow (long int a, long int b, long int *r)
-{
-  return octave_li_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (long int a, long int b, long int *r)
+  {
+    return octave_li_multiply_overflow_wrapper (a, b, r);
+  }
 
 #if defined (OCTAVE_HAVE_LONG_LONG_INT)
-bool int_multiply_overflow (long long int a, long long int b,
-                            long long int *r)
-{
-  return octave_lli_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (long long int a, long long int b,
+                              long long int *r)
+  {
+    return octave_lli_multiply_overflow_wrapper (a, b, r);
+  }
 #endif
 
-bool int_multiply_overflow (unsigned int a, unsigned int b,
-                            unsigned int *r)
-{
-  return octave_ui_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (unsigned int a, unsigned int b,
+                              unsigned int *r)
+  {
+    return octave_ui_multiply_overflow_wrapper (a, b, r);
+  }
 
-bool int_multiply_overflow (unsigned long int a, unsigned long int b,
-                            unsigned long int *r)
-{
-  return octave_uli_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (unsigned long int a, unsigned long int b,
+                              unsigned long int *r)
+  {
+    return octave_uli_multiply_overflow_wrapper (a, b, r);
+  }
 
 #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
-bool int_multiply_overflow (unsigned long long int a,
-                            unsigned long long int b,
-                            unsigned long long int *r)
-{
-  return octave_ulli_multiply_overflow_wrapper (a, b, r);
-}
+  bool int_multiply_overflow (unsigned long long int a,
+                              unsigned long long int b,
+                              unsigned long long int *r)
+  {
+    return octave_ulli_multiply_overflow_wrapper (a, b, r);
+  }
 #endif
 
 OCTAVE_END_NAMESPACE(math)
--- a/liboctave/util/lo-utils.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/lo-utils.h	Fri Jun 23 20:51:51 2023 +0200
@@ -137,146 +137,4 @@
 OCTAVE_END_NAMESPACE(math)
 OCTAVE_END_NAMESPACE(octave)
 
-#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)
-template <typename F, typename T, bool zero>
-OCTAVE_DEPRECATED (7, "use 'octave::any_all_test' instead")
-bool
-any_all_test (F fcn, const T *m, octave_idx_type len)
-{
-  return octave::any_all_test<F, T, zero> (fcn, m, len);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::is_int_or_inf_or_nan' instead")
-inline bool xis_int_or_inf_or_nan (double x)
-{
-  return octave::is_int_or_inf_or_nan (x);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (7, "use 'octave::is_one_or_zero' instead")
-bool
-xis_one_or_zero (const T& x)
-{
-  return octave::is_one_or_zero (x);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (7, "use 'octave::is_zero' instead")
-bool
-xis_zero (const T& x)
-{
-  return octave::is_zero (x);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::' instead")
-inline bool xtoo_large_for_float (double x)
-{
-  return octave::too_large_for_float (x);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::' instead")
-inline bool xtoo_large_for_float (const Complex&  x)
-{
-  return octave::too_large_for_float (x);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::' instead")
-inline bool xis_int_or_inf_or_nan (float x)
-{
-  return octave::is_int_or_inf_or_nan (x);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::' instead")
-inline bool xtoo_large_for_float (float x)
-{
-  return octave::too_large_for_float (x);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::strsave' instead")
-inline char * strsave (const char *s)
-{
-  return octave::strsave (s);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead")
-inline std::string octave_fgets (std::FILE *f)
-{
-  return octave::fgets (f);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead")
-inline std::string octave_fgetl (std::FILE *f)
-{
-  return octave::fgetl (f);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead")
-inline std::string octave_fgets (std::FILE *f, bool& eof)
-{
-  return octave::fgets (f, eof);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead")
-inline std::string octave_fgetl (std::FILE *f, bool& eof)
-{
-  return octave::fgetl (f, eof);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::read_value<T>' instead")
-inline double
-octave_read_double (std::istream& is)
-{
-  return octave::read_value<double> (is);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::read_value<T>' instead")
-inline Complex
-octave_read_complex (std::istream& is)
-{
-  return octave::read_value<Complex> (is);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::read_value<T>' instead")
-inline float
-octave_read_float (std::istream& is)
-{
-  return octave::read_value<float> (is);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::read_value<T>' instead")
-inline FloatComplex
-octave_read_float_complex (std::istream& is)
-{
-  return octave::read_value<FloatComplex> (is);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::write_value<T>' instead")
-inline void
-octave_write_double (std::ostream& os, double value)
-{
-  octave::write_value<double> (os, value);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::write_value<T>' instead")
-inline void
-octave_write_complex (std::ostream& os, const Complex& value)
-{
-  octave::write_value<Complex> (os, value);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::write_value<T>' instead")
-inline void
-octave_write_float (std::ostream& os, float value)
-{
-  octave::write_value<float> (os, value);
-}
-
-OCTAVE_DEPRECATED (7, "use 'octave::write_value<T>' instead")
-inline void
-octave_write_float_complex (std::ostream& os, const FloatComplex& value)
-{
-  octave::write_value<FloatComplex> (os, value);
-}
 #endif
-
-#endif
--- a/liboctave/util/oct-atomic.c	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-atomic.c	Fri Jun 23 20:51:51 2023 +0200
@@ -29,9 +29,23 @@
 
 #include "oct-atomic.h"
 
+#if defined (__GNUC__)
+
+octave_idx_type
+octave_atomic_increment (octave_idx_type *x)
+{
+  return __sync_add_and_fetch (x,  1);
+}
+
+octave_idx_type
+octave_atomic_decrement (octave_idx_type *x)
+{
+  return __sync_sub_and_fetch (x, 1);
+}
+
 /* Some versions of GCC can't compile stdatomic.h with -fopenmp.  */
 
-#if defined (OCTAVE_STDATOMIC_H_OK)
+#elif defined (OCTAVE_STDATOMIC_H_OK)
 #  include <stdatomic.h>
 
 octave_idx_type
@@ -52,20 +66,6 @@
   return *x;
 }
 
-#elif defined (__GNUC__)
-
-octave_idx_type
-octave_atomic_increment (octave_idx_type *x)
-{
-  return __sync_add_and_fetch (x,  1);
-}
-
-octave_idx_type
-octave_atomic_decrement (octave_idx_type *x)
-{
-  return __sync_sub_and_fetch (x, 1);
-}
-
 #elif defined (_MSC_VER)
 #  include <intrin.h>
 
--- a/liboctave/util/oct-glob.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-glob.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -35,14 +35,13 @@
 #include "oct-glob.h"
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "unwind-prot.h"
 
 #if defined (OCTAVE_USE_WINDOWS_API)
 #  include <windows.h>
 #  include <shlwapi.h>
 #  include <wchar.h>
-
-#  include "lo-sysdep.h"
 #endif
 
 // These functions are defined here and not in glob_match.cc so that we
@@ -53,14 +52,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-static bool
-single_match_exists (const std::string& file)
-{
-  sys::file_stat s (file);
-
-  return s.exists ();
-}
-
 OCTAVE_BEGIN_NAMESPACE(sys)
 
 bool
@@ -121,7 +112,7 @@
 
               if (n > 1
                   || (n == 1
-                      && single_match_exists (std::string (matches[0]))))
+                      && sys::file_exists (std::string (matches[0]))))
                 {
                   retval.resize (k+n);
 
@@ -371,7 +362,7 @@
 
               if (n > 1
                   || (n == 1
-                      && single_match_exists (std::string (matches[0]))))
+                      && sys::file_exists (std::string (matches[0]))))
                 {
                   retval.resize (k + n);
 
--- a/liboctave/util/oct-inttypes.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-inttypes.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -42,7 +42,7 @@
 #define DEFINE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME)              \
   template <>                                                   \
   OCTAVE_API const char *                                       \
-  octave_int<TYPE>::type_name (void) { return TYPENAME; }
+  octave_int<TYPE>::type_name () { return TYPENAME; }
 
 DEFINE_OCTAVE_INT_TYPENAME (int8_t, "int8")
 DEFINE_OCTAVE_INT_TYPENAME (int16_t, "int16")
--- a/liboctave/util/oct-inttypes.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-inttypes.h	Fri Jun 23 20:51:51 2023 +0200
@@ -109,8 +109,7 @@
 
 #undef OCTAVE_REGISTER_INT_TYPE
 
-// Handles non-homogeneous integer comparisons.  Avoids doing useless
-// tests.
+// Handles non-homogeneous integer comparisons.  Avoids doing useless tests.
 
 class octave_int_cmp_op
 {
@@ -124,22 +123,22 @@
   class prom
   {
     // Promote to int?
-    static const bool pint = (sizeof (T1) < sizeof (int)
+    static const bool s_pint = (sizeof (T1) < sizeof (int)
                               && sizeof (T2) < sizeof (int));
 
-    static const bool t1sig = std::numeric_limits<T1>::is_signed;
-    static const bool t2sig = std::numeric_limits<T2>::is_signed;
+    static const bool s_t1sig = std::numeric_limits<T1>::is_signed;
+    static const bool s_t2sig = std::numeric_limits<T2>::is_signed;
 
-    static const bool psig
-      = (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig);
+    static const bool s_psig
+      = (s_pint || (sizeof (T2) > sizeof (T1) && s_t2sig) || s_t1sig);
 
-    static const int psize
-      = (pint
+    static const int s_psize
+      = (s_pint
          ? sizeof (int)
          : (sizeof (T2) > sizeof (T1) ? sizeof (T2) : sizeof (T1)));
   public:
 
-    typedef typename query_integer_type<psize, psig>::type type;
+    typedef typename query_integer_type<s_psize, s_psig>::type type;
   };
 
   // Implements comparisons between two types of equal size but
@@ -346,8 +345,8 @@
 {
 public:
 
-  static T min_val (void) { return std::numeric_limits<T>::min (); }
-  static T max_val (void) { return std::numeric_limits<T>::max (); }
+  static T min_val () { return std::numeric_limits<T>::min (); }
+  static T max_val () { return std::numeric_limits<T>::max (); }
 
   // Convert integer value.
 
@@ -787,7 +786,7 @@
 
   typedef T val_type;
 
-  octave_int (void) : m_ival () { }
+  octave_int () : m_ival () { }
 
   octave_int (T i) : m_ival (i) { }
 
@@ -827,26 +826,26 @@
 
   octave_int& operator = (const octave_int<T>&) = default;
 
-  ~octave_int (void) = default;
+  ~octave_int () = default;
 
-  T value (void) const { return m_ival; }
+  T value () const { return m_ival; }
 
-  const unsigned char * iptr (void) const
+  const unsigned char * iptr () const
   {
     return reinterpret_cast<const unsigned char *> (& m_ival);
   }
 
-  bool operator ! (void) const { return ! m_ival; }
+  bool operator ! () const { return ! m_ival; }
 
-  bool bool_value (void) const { return static_cast<bool> (value ()); }
+  bool bool_value () const { return static_cast<bool> (value ()); }
 
-  char char_value (void) const { return static_cast<char> (value ()); }
+  char char_value () const { return static_cast<char> (value ()); }
 
-  double double_value (void) const { return static_cast<double> (value ()); }
+  double double_value () const { return static_cast<double> (value ()); }
 
-  float float_value (void) const { return static_cast<float> (value ()); }
+  float float_value () const { return static_cast<float> (value ()); }
 
-  operator T (void) const { return value (); }
+  operator T () const { return value (); }
 
   octave_int<T> operator + () const { return *this; }
 
@@ -864,7 +863,7 @@
 
 #undef OCTAVE_INT_UN_OP
 
-  octave_int<T> operator ~ (void) const
+  octave_int<T> operator ~ () const
   {
     T bitinv = ~ m_ival;
     return bitinv;
@@ -895,12 +894,12 @@
 
 #undef OCTAVE_INT_BIN_OP
 
-  static octave_int<T> min (void) { return std::numeric_limits<T>::min (); }
-  static octave_int<T> max (void) { return std::numeric_limits<T>::max (); }
+  static octave_int<T> min () { return std::numeric_limits<T>::min (); }
+  static octave_int<T> max () { return std::numeric_limits<T>::max (); }
 
-  static int nbits (void) { return std::numeric_limits<T>::digits; }
+  static int nbits () { return std::numeric_limits<T>::digits; }
 
-  static int byte_size (void) { return sizeof (T); }
+  static int byte_size () { return sizeof (T); }
 
   static const OCTAVE_API char * type_name ();
 
--- a/liboctave/util/oct-mutex.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-mutex.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -39,19 +39,19 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 void
-base_mutex::lock (void)
+base_mutex::lock ()
 {
   (*current_liboctave_error_handler) ("mutex not supported on this platform");
 }
 
 void
-base_mutex::unlock (void)
+base_mutex::unlock ()
 {
   (*current_liboctave_error_handler) ("mutex not supported on this platform");
 }
 
 bool
-base_mutex::try_lock (void)
+base_mutex::try_lock ()
 {
   (*current_liboctave_error_handler) ("mutex not supported on this platform");
 
@@ -64,28 +64,28 @@
 w32_mutex : public base_mutex
 {
 public:
-  w32_mutex (void)
+  w32_mutex ()
     : base_mutex ()
   {
     InitializeCriticalSection (&cs);
   }
 
-  ~w32_mutex (void)
+  ~w32_mutex ()
   {
     DeleteCriticalSection (&cs);
   }
 
-  void lock (void)
+  void lock ()
   {
     EnterCriticalSection (&cs);
   }
 
-  void unlock (void)
+  void unlock ()
   {
     LeaveCriticalSection (&cs);
   }
 
-  bool try_lock (void)
+  bool try_lock ()
   {
     return (TryEnterCriticalSection (&cs) != 0);
   }
@@ -97,13 +97,13 @@
 static DWORD thread_id = 0;
 
 void
-thread::init (void)
+thread::init ()
 {
   thread_id = GetCurrentThreadId ();
 }
 
 bool
-thread::is_thread (void)
+thread::is_thread ()
 {
   return (GetCurrentThreadId () == thread_id);
 }
@@ -114,7 +114,8 @@
 pthread_mutex : public base_mutex
 {
 public:
-  pthread_mutex (void)
+
+  pthread_mutex ()
     : base_mutex (), m_pm ()
   {
     pthread_mutexattr_t attr;
@@ -125,22 +126,24 @@
     pthread_mutexattr_destroy (&attr);
   }
 
-  ~pthread_mutex (void)
+  OCTAVE_DISABLE_COPY_MOVE (pthread_mutex)
+
+  ~pthread_mutex ()
   {
     pthread_mutex_destroy (&m_pm);
   }
 
-  void lock (void)
+  void lock ()
   {
     pthread_mutex_lock (&m_pm);
   }
 
-  void unlock (void)
+  void unlock ()
   {
     pthread_mutex_unlock (&m_pm);
   }
 
-  bool try_lock (void)
+  bool try_lock ()
   {
     return (pthread_mutex_trylock (&m_pm) == 0);
   }
@@ -152,13 +155,13 @@
 static pthread_t thread_id = 0;
 
 void
-thread::init (void)
+thread::init ()
 {
   thread_id = pthread_self ();
 }
 
 bool
-thread::is_thread (void)
+thread::is_thread ()
 {
   return (pthread_equal (thread_id, pthread_self ()) != 0);
 }
@@ -166,7 +169,7 @@
 #endif
 
 static base_mutex *
-init_rep (void)
+init_rep ()
 {
 #if defined (OCTAVE_USE_WINDOWS_API)
   return new w32_mutex ();
@@ -177,6 +180,6 @@
 #endif
 }
 
-mutex::mutex (void) : m_rep (init_rep ()) { }
+mutex::mutex () : m_rep (init_rep ()) { }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/util/oct-mutex.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-mutex.h	Fri Jun 23 20:51:51 2023 +0200
@@ -41,15 +41,15 @@
 public:
   friend class mutex;
 
-  base_mutex (void) = default;
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (base_mutex)
 
-  virtual ~base_mutex (void) = default;
+  virtual ~base_mutex () = default;
 
-  virtual void lock (void);
+  virtual void lock ();
 
-  virtual void unlock (void);
+  virtual void unlock ();
 
-  virtual bool try_lock (void);
+  virtual bool try_lock ();
 };
 
 class
@@ -57,25 +57,21 @@
 mutex
 {
 public:
-  mutex (void);
-
-  mutex (const mutex& m) = default;
+  mutex ();
 
-  ~mutex (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (mutex)
 
-  mutex& operator = (const mutex& m) = default;
-
-  void lock (void)
+  void lock ()
   {
     m_rep->lock ();
   }
 
-  void unlock (void)
+  void unlock ()
   {
     m_rep->unlock ();
   }
 
-  bool try_lock (void)
+  bool try_lock ()
   {
     return m_rep->try_lock ();
   }
@@ -101,21 +97,17 @@
       m_lock_result = m_mutex.try_lock ();
   }
 
-  // No copying.
-
-  autolock (const autolock&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (autolock)
 
-  autolock& operator = (const autolock&) = delete;
-
-  ~autolock (void)
+  ~autolock ()
   {
     if (m_lock_result)
       m_mutex.unlock ();
   }
 
-  bool ok (void) const { return m_lock_result; }
+  bool ok () const { return m_lock_result; }
 
-  operator bool (void) const { return ok (); }
+  operator bool () const { return ok (); }
 
 private:
 
@@ -131,9 +123,9 @@
 {
 public:
 
-  static void init (void);
+  static void init ();
 
-  static bool is_thread (void);
+  static bool is_thread ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/util/oct-refcount.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-refcount.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,14 +45,12 @@
     : m_count (initial_count)
   { }
 
-  refcount (const refcount&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (refcount)
 
-  refcount& operator = (const refcount&) = delete;
-
-  ~refcount (void) = default;
+  ~refcount () = default;
 
   // Increment/Decrement.  int is postfix.
-  count_type operator++ (void)
+  count_type operator++ ()
   {
     return ++m_count;
   }
@@ -62,7 +60,7 @@
     return m_count++;
   }
 
-  count_type operator-- (void)
+  count_type operator-- ()
   {
     return --m_count;
   }
@@ -72,12 +70,12 @@
     return m_count--;
   }
 
-  count_type value (void) const
+  count_type value () const
   {
     return m_count.load ();
   }
 
-  operator count_type (void) const
+  operator count_type () const
   {
     return value ();
   }
--- a/liboctave/util/oct-shlib.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-shlib.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -62,12 +62,12 @@
 
 std::list<dynamic_library> possibly_unreferenced_dynamic_libraries;
 
-void dynamic_library::delete_later (void)
+void dynamic_library::delete_later ()
 {
   possibly_unreferenced_dynamic_libraries.push_back (*this);
 }
 
-int release_unreferenced_dynamic_libraries (void)
+int release_unreferenced_dynamic_libraries ()
 {
   possibly_unreferenced_dynamic_libraries.clear ();
 
@@ -87,14 +87,14 @@
 }
 
 bool
-dynamic_library::dynlib_rep::is_out_of_date (void) const
+dynamic_library::dynlib_rep::is_out_of_date () const
 {
   sys::file_stat fs (m_file);
   return (fs && fs.is_newer (m_time_loaded));
 }
 
 void
-dynamic_library::dynlib_rep::fake_reload (void)
+dynamic_library::dynlib_rep::fake_reload ()
 {
   // We can't actually reload the library, but we'll pretend we did.
   sys::file_stat fs (m_file);
@@ -127,7 +127,7 @@
 }
 
 std::list<std::string>
-dynamic_library::dynlib_rep::function_names (void) const
+dynamic_library::dynlib_rep::function_names () const
 {
   std::list<std::string> retval;
 
@@ -178,13 +178,9 @@
 
   octave_dlopen_shlib (const std::string& f);
 
-  // No copying!
-
-  octave_dlopen_shlib (const octave_dlopen_shlib&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (octave_dlopen_shlib)
 
-  octave_dlopen_shlib& operator = (const octave_dlopen_shlib&) = delete;
-
-  ~octave_dlopen_shlib (void);
+  ~octave_dlopen_shlib ();
 
   void * search (const std::string& name,
                 const dynamic_library::name_mangler& mangler
@@ -194,7 +190,7 @@
   // normally throw an exception, avoiding the construction of an invalid
   // library.  Leave it here for possible future use.
 
-  bool is_open (void) const
+  bool is_open () const
   {
     return (m_search_all_loaded || m_library != nullptr);
   }
@@ -246,7 +242,7 @@
     }
 }
 
-octave_dlopen_shlib::~octave_dlopen_shlib (void)
+octave_dlopen_shlib::~octave_dlopen_shlib ()
 {
   if (m_library)
     dlclose (m_library);
@@ -284,13 +280,9 @@
 
   octave_w32_shlib (const std::string& f);
 
-  // No copying!
-
-  octave_w32_shlib (const octave_w32_shlib&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_w32_shlib)
 
-  octave_w32_shlib& operator = (const octave_w32_shlib&) = delete;
-
-  ~octave_w32_shlib (void);
+  ~octave_w32_shlib ();
 
   void * search (const std::string& name,
                 const dynamic_library::name_mangler& mangler
@@ -298,7 +290,7 @@
 
   void * global_search (const std::string& sym_name);
 
-  bool is_open (void) const
+  bool is_open () const
   {
     return (m_search_all_loaded || m_handle != nullptr);
   }
@@ -354,7 +346,7 @@
     }
 }
 
-octave_w32_shlib::~octave_w32_shlib (void)
+octave_w32_shlib::~octave_w32_shlib ()
 {
   if (m_handle)
     FreeLibrary (m_handle);
--- a/liboctave/util/oct-shlib.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-shlib.h	Fri Jun 23 20:51:51 2023 +0200
@@ -49,11 +49,13 @@
   {
   public:
 
-    dynlib_rep (void)
+    dynlib_rep ()
       : m_count (1), m_fcn_names (), m_file (), m_time_loaded (OCTAVE_TIME_T ()),
         m_search_all_loaded (false)
     { }
 
+    OCTAVE_DISABLE_COPY_MOVE (dynlib_rep)
+
   protected:
 
     OCTAVE_API
@@ -61,40 +63,40 @@
 
   public:
 
-    virtual ~dynlib_rep (void)
+    virtual ~dynlib_rep ()
     {
       s_instances.erase (m_file);
     }
 
-    virtual bool is_open (void) const
+    virtual bool is_open () const
     { return false; }
 
     virtual void * search (const std::string&,
                           const name_mangler& = name_mangler ())
     { return nullptr; }
 
-    OCTAVE_API bool is_out_of_date (void) const;
+    OCTAVE_API bool is_out_of_date () const;
 
     // This method will be overridden conditionally.
     static OCTAVE_API dynlib_rep * new_instance (const std::string& f);
 
     static OCTAVE_API dynlib_rep * get_instance (const std::string& f, bool fake);
 
-    sys::time time_loaded (void) const
+    sys::time time_loaded () const
     { return m_time_loaded; }
 
-    std::string file_name (void) const
+    std::string file_name () const
     { return m_file; }
 
-    std::size_t num_fcn_names (void) const { return m_fcn_names.size (); }
+    std::size_t num_fcn_names () const { return m_fcn_names.size (); }
 
-    OCTAVE_API std::list<std::string> function_names (void) const;
+    OCTAVE_API std::list<std::string> function_names () const;
 
     OCTAVE_API void add_fcn_name (const std::string&);
 
     OCTAVE_API bool remove_fcn_name (const std::string&);
 
-    void clear_fcn_names (void) { m_fcn_names.clear (); }
+    void clear_fcn_names () { m_fcn_names.clear (); }
 
   public:
 
@@ -102,7 +104,7 @@
 
   protected:
 
-    OCTAVE_API void fake_reload (void);
+    OCTAVE_API void fake_reload ();
 
     static OCTAVE_API std::map<std::string, dynlib_rep *> s_instances;
 
@@ -122,18 +124,18 @@
 
 public:
 
-  dynamic_library (void) : m_rep (&s_nil_rep) { m_rep->m_count++; }
+  dynamic_library () : m_rep (&s_nil_rep) { m_rep->m_count++; }
 
   dynamic_library (const std::string& f, bool fake = true)
     : m_rep (dynlib_rep::get_instance (f, fake)) { }
 
-  ~dynamic_library (void)
+  ~dynamic_library ()
   {
     if (--m_rep->m_count == 0 && m_rep != &s_nil_rep)
       delete m_rep;
   }
 
-  OCTAVE_API void delete_later (void);
+  OCTAVE_API void delete_later ();
 
   dynamic_library (const dynamic_library& sl)
     : m_rep (sl.m_rep)
@@ -163,7 +165,7 @@
   void open (const std::string& f)
   { *this = dynamic_library (f); }
 
-  std::list<std::string> close (void)
+  std::list<std::string> close ()
   {
     std::list<std::string> removed_fcns = m_rep->function_names ();
 
@@ -190,16 +192,16 @@
   bool remove (const std::string& name)
   { return m_rep->remove_fcn_name (name); }
 
-  std::size_t number_of_functions_loaded (void) const
+  std::size_t number_of_functions_loaded () const
   { return m_rep->num_fcn_names (); }
 
-  bool is_out_of_date (void) const
+  bool is_out_of_date () const
   { return m_rep->is_out_of_date (); }
 
-  std::string file_name (void) const
+  std::string file_name () const
   { return m_rep->file_name (); }
 
-  sys::time time_loaded (void) const
+  sys::time time_loaded () const
   { return m_rep->time_loaded (); }
 
 private:
@@ -210,7 +212,7 @@
 // FIXME: Currently must return int so that it may be used as an
 // event_hook function.
 
-OCTAVE_API int release_unreferenced_dynamic_libraries (void);
+OCTAVE_API int release_unreferenced_dynamic_libraries ();
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/liboctave/util/oct-sort.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-sort.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -119,7 +119,7 @@
 #include "oct-locbuf.h"
 
 template <typename T>
-octave_sort<T>::octave_sort (void) :
+octave_sort<T>::octave_sort () :
   m_compare (ascending_compare), m_ms (nullptr)
 { }
 
--- a/liboctave/util/oct-sort.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-sort.h	Fri Jun 23 20:51:51 2023 +0200
@@ -106,17 +106,13 @@
   typedef std::function<bool (typename ref_param<T>::type,
                               typename ref_param<T>::type)> compare_fcn_type;
 
-  octave_sort (void);
+  octave_sort ();
 
   octave_sort (const compare_fcn_type&);
 
-  // No copying!
-
-  octave_sort (const octave_sort&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (octave_sort)
 
-  octave_sort& operator = (const octave_sort&) = delete;
-
-  ~octave_sort (void);
+  ~octave_sort ();
 
   void set_compare (const compare_fcn_type& comp) { m_compare = comp; }
 
@@ -199,20 +195,16 @@
   {
   public:
 
-    MergeState (void)
+    MergeState ()
       : m_min_gallop (), m_a (nullptr), m_ia (nullptr), m_alloced (0), m_n (0)
     { reset (); }
 
-    // No copying!
-
-    MergeState (const MergeState&) = delete;
+    OCTAVE_DISABLE_COPY_MOVE (MergeState)
 
-    MergeState& operator = (const MergeState&) = delete;
-
-    ~MergeState (void)
+    ~MergeState ()
     { delete [] m_a; delete [] m_ia; }
 
-    void reset (void)
+    void reset ()
     { m_min_gallop = MIN_GALLOP; m_n = 0; }
 
     void getmem (octave_idx_type need);
--- a/liboctave/util/oct-sparse.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-sparse.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -37,7 +37,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 static inline void
-check_suitesparse_integer_size (void)
+check_suitesparse_integer_size ()
 {
   // FIXME: maybe it would be better to make this a configure check and
   // disable suitesparse if it fails?
--- a/liboctave/util/oct-string.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-string.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -34,8 +34,10 @@
 #include <cstring>
 #include <iomanip>
 #include <string>
+#include <unordered_set>
 
 #include "Array.h"
+#include "iconv-wrappers.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "uniconv-wrappers.h"
@@ -607,6 +609,174 @@
   return num_replacements;
 }
 
+std::string
+octave::string::u16_to_encoding (const std::string& who,
+                                 const std::u16string& u16_string,
+                                 const std::string& encoding)
+{
+  const uint16_t *src = reinterpret_cast<const uint16_t *>
+                        (u16_string.c_str ());
+  std::size_t srclen = u16_string.length ();
+
+  std::size_t length;
+  char *native_str = octave_u16_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-16 to codepage '%s' failed: %s",
+           who.c_str (), encoding.c_str (), std::strerror (errno));
+    }
+
+  octave::unwind_action free_native_str ([=] () { ::free (native_str); });
+
+  std::string retval = std::string (native_str, length);
+
+  return retval;
+}
+
+std::vector<std::string>
+octave::string::get_encoding_list ()
+{
+  static std::vector<std::string> encoding_list;
+
+  if (encoding_list.empty ())
+    {
+#if defined (HAVE_ICONVLIST)
+      // get number of supported encodings
+      std::size_t count = 0;
+      octave_iconvlist_wrapper (
+        [] (unsigned int num, const char * const *, void *data) -> int
+          {
+            std::size_t *count_ptr = static_cast<std::size_t *> (data);
+            *count_ptr = num;
+            return 0;
+          },
+        &count);
+
+      if (count == static_cast<size_t>(-1))
+        {
+          encoding_list.push_back ("UTF-8");
+          return encoding_list;
+        }
+
+#  if defined (HAVE_ICONV_CANONICALIZE)
+      // use unordered_set to skip canonicalized aliases
+      std::unordered_set<std::string> encoding_set;
+      encoding_set.reserve (count);
+
+      // populate vector with name of encodings
+      octave_iconvlist_wrapper (
+        [] (unsigned int num, const char * const *names, void *data) -> int
+          {
+            std::unordered_set<std::string> *encoding_set_ptr
+              = static_cast<std::unordered_set<std::string> *> (data);
+            for (std::size_t i = 0; i < num; i++)
+              {
+                const char *canonicalized_enc
+                  = octave_iconv_canonicalize_wrapper (names[i]);
+                encoding_set_ptr->insert (canonicalized_enc);
+              }
+            return 0;
+          },
+        &encoding_set);
+
+      encoding_list.assign (encoding_set.begin (), encoding_set.end ());
+#  endif
+
+#else
+      // Use hardcoded list of encodings as a fallback for platforms without
+      // iconvlist (or another way of programmatically querrying a list of
+      // supported encodings).
+      // This list is inspired by the encodings supported by Geany.
+      encoding_list
+        = {"ISO-8859-1",
+           "ISO-8859-2",
+           "ISO-8859-3",
+           "ISO-8859-4",
+           "ISO-8859-5",
+           "ISO-8859-6",
+           "ISO-8859-7",
+           "ISO-8859-8",
+           "ISO-8859-9",
+           "ISO-8859-10",
+           "ISO-8859-13",
+           "ISO-8859-14",
+           "ISO-8859-15",
+           "ISO-8859-16",
+
+           "UTF-7",
+           "UTF-8",
+           "UTF-16LE",
+           "UTF-16BE",
+           "UTF-32LE",
+           "UTF-32BE",
+           "UCS-2LE",
+           "UCS-2BE",
+
+           "ARMSCII-8",
+           "BIG5",
+           "BIG5-HKSCS",
+           "CP866",
+
+           "EUC-JP",
+           "EUC-KR",
+           "EUC-TW",
+
+           "GB18030",
+           "GB_2312-80",
+           "GBK",
+           "HZ",
+
+           "IBM850",
+           "IBM852",
+           "IBM855",
+           "IBM857",
+           "IBM862",
+           "IBM864",
+
+           "ISO-2022-JP",
+           "ISO-2022-KR",
+           "JOHAB",
+           "KOI8-R",
+           "KOI8-U",
+
+           "SHIFT_JIS",
+           "TCVN",
+           "TIS-620",
+           "UHC",
+           "VISCII",
+
+           "CP1250",
+           "CP1251",
+           "CP1252",
+           "CP1253",
+           "CP1254",
+           "CP1255",
+           "CP1256",
+           "CP1257",
+           "CP1258",
+
+           "CP932"
+           };
+
+      // FIXME: Should we check whether those are actually valid encoding
+      // identifiers?
+#endif
+
+      // sort list of encodings
+      std::sort (encoding_list.begin (), encoding_list.end ());
+    }
+
+  return encoding_list;
+}
+
 typedef octave::string::codecvt_u8::InternT InternT;
 typedef octave::string::codecvt_u8::ExternT ExternT;
 typedef octave::string::codecvt_u8::StateT StateT;
--- a/liboctave/util/oct-string.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/oct-string.h	Fri Jun 23 20:51:51 2023 +0200
@@ -29,6 +29,7 @@
 #include "octave-config.h"
 
 #include <locale>
+#include <vector>
 
 #include "oct-cmplx.h"
 
@@ -158,18 +159,24 @@
 u8_validate (const std::string& who, std::string& in_string,
              const u8_fallback_type type = U8_REPLACEMENT_CHAR);
 
+extern OCTAVE_API std::string
+u16_to_encoding (const std::string& who, const std::u16string& u16_string,
+                 const std::string& encoding);
+
+extern OCTAVE_API std::vector<std::string>
+get_encoding_list ();
 
 template<class Facet>
-struct
-  deletable_facet : Facet
+struct deletable_facet : Facet
 {
+  deletable_facet () = delete;
+
   template<class ...Args>
   deletable_facet (Args&& ...args)
     : Facet (std::forward<Args> (args)...)
   { }
 
-  // destructor needs to be public
-  ~deletable_facet () { }
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (deletable_facet)
 };
 
 class
@@ -178,16 +185,12 @@
 {
 public:
 
-  // No copying!
-
-  codecvt_u8 (codecvt_u8&) = delete;
-
-  codecvt_u8& operator = (codecvt_u8&) = delete;
-
   codecvt_u8 (const std::string& enc)
     : m_enc (enc)
   { }
 
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (codecvt_u8)
+
   virtual ~codecvt_u8 () { }
 
   typedef char InternT;
--- a/liboctave/util/octave-preserve-stream-state.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/octave-preserve-stream-state.h	Fri Jun 23 20:51:51 2023 +0200
@@ -37,12 +37,17 @@
 {
 public:
 
+  preserve_stream_state () = delete;
+
   preserve_stream_state (std::ios& s)
     : m_stream (s), m_oflags (s.flags ()), m_oprecision (s.precision ()),
       m_owidth (s.width ()), m_ofill (s.fill ())
   { }
 
-  ~preserve_stream_state (void)
+  OCTAVE_DEFAULT_COPY_MOVE_CTOR (preserve_stream_state)
+  OCTAVE_DISABLE_COPY_MOVE_ASGN (preserve_stream_state)
+
+  ~preserve_stream_state ()
   {
     m_stream.flags (m_oflags);
     m_stream.precision (m_oprecision);
--- a/liboctave/util/pathsearch.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/pathsearch.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -47,12 +47,12 @@
     init ();
 }
 
-std::list<std::string> directory_path::elements (void)
+std::list<std::string> directory_path::elements ()
 {
   return m_initialized ? m_path_elements : std::list<std::string> ();
 }
 
-std::list<std::string> directory_path::all_directories (void)
+std::list<std::string> directory_path::all_directories ()
 {
   std::list<std::string> retval;
 
@@ -97,7 +97,7 @@
           : std::list<std::string> ());
 }
 
-void directory_path::init (void)
+void directory_path::init ()
 {
   static bool octave_kpse_initialized = false;
 
@@ -119,12 +119,12 @@
   m_initialized = true;
 }
 
-char directory_path::path_sep_char (void)
+char directory_path::path_sep_char ()
 {
   return SEPCHAR;
 }
 
-std::string directory_path::path_sep_str (void)
+std::string directory_path::path_sep_str ()
 {
   return SEPCHAR_STR;
 }
--- a/liboctave/util/pathsearch.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/pathsearch.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,7 +45,7 @@
 
   directory_path& operator = (const directory_path&) = default;
 
-  ~directory_path (void) = default;
+  ~directory_path () = default;
 
   void set (const std::string& s)
   {
@@ -54,9 +54,9 @@
     init ();
   }
 
-  std::list<std::string> elements (void);
+  std::list<std::string> elements ();
 
-  std::list<std::string> all_directories (void);
+  std::list<std::string> all_directories ();
 
   std::string find_first (const std::string&);
 
@@ -69,17 +69,17 @@
   std::list<std::string>
   find_all_first_of (const std::list<std::string>& names);
 
-  void rehash (void)
+  void rehash ()
   {
     m_initialized = false;
     init ();
   }
 
-  static char path_sep_char (void);
+  static char path_sep_char ();
 
   // static void path_sep_char (char c);
 
-  static std::string path_sep_str (void);
+  static std::string path_sep_str ();
 
   static bool is_path_sep (char c) { return c == path_sep_char (); }
 
@@ -98,7 +98,7 @@
   // The elements of the list.
   std::list<std::string> m_path_elements;
 
-  void init (void);
+  void init ();
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/util/quit.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/quit.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include <atomic>
 #include <cstring>
 
 #include <ostream>
@@ -35,16 +36,16 @@
 
 #include "quit.h"
 
-sig_atomic_t octave_interrupt_state = 0;
+std::atomic<sig_atomic_t> octave_interrupt_state{0};
 
-volatile sig_atomic_t octave_signal_caught = 0;
+volatile std::atomic<bool> octave_signal_caught{false};
 
-void (*octave_signal_hook) (void) = nullptr;
-void (*octave_interrupt_hook) (void) = nullptr;
+void (*octave_signal_hook) () = nullptr;
+void (*octave_interrupt_hook) () = nullptr;
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-std::string execution_exception::stack_trace (void) const
+std::string execution_exception::stack_trace () const
 {
   std::size_t nframes = m_stack_info.size ();
 
@@ -95,18 +96,25 @@
     }
 }
 
+void octave_quit_c (void)
+{
+  octave_quit ();
+}
+
 OCTAVE_END_NAMESPACE(octave)
 
 void
-octave_handle_signal (void)
+octave_handle_signal ()
 {
   if (octave_signal_hook)
     octave_signal_hook ();
 
-  if (octave_interrupt_state > 0)
-    {
-      octave_interrupt_state = -1;
+  sig_atomic_t curr_interrupt_state = octave_interrupt_state.load ();
 
-      throw octave::interrupt_exception ();
-    }
+  while (curr_interrupt_state > 0 &&
+    ! octave_interrupt_state.compare_exchange_weak (curr_interrupt_state, -1))
+    ;
+
+  if (curr_interrupt_state > 0)
+    throw octave::interrupt_exception ();
 }
--- a/liboctave/util/quit.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/quit.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,12 +30,12 @@
 
 /* The signal header is just needed for the sig_atomic_t type.  */
 #if defined (__cplusplus)
+#  include <atomic>
 #  include <csignal>
 #  include <iosfwd>
 #  include <list>
 #  include <stdexcept>
 #  include <string>
-extern "C" {
 #else
 #  include <signal.h>
 #endif
@@ -167,11 +167,7 @@
       m_safe_to_return (safe_to_return)
   { }
 
-  exit_exception (const exit_exception&) = default;
-
-  exit_exception& operator = (exit_exception&) = default;
-
-  ~exit_exception (void) = default;
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (exit_exception)
 
   const char * what (void) const noexcept { return "exit exception"; }
 
@@ -203,6 +199,8 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
+extern "C" {
+
 #endif
 
 // The following enum values are deprecated and will eventually be
@@ -223,9 +221,14 @@
     0: no interrupt pending
   < 0: handling interrupt
 */
-extern OCTAVE_API sig_atomic_t octave_interrupt_state;
+
+#if defined (__cplusplus)
 
-extern OCTAVE_API volatile sig_atomic_t octave_signal_caught;
+extern OCTAVE_API std::atomic<int> octave_interrupt_state;
+
+extern OCTAVE_API volatile std::atomic<bool> octave_signal_caught;
+
+#endif
 
 extern OCTAVE_API void octave_handle_signal (void);
 
@@ -233,27 +236,19 @@
 
 inline void octave_quit (void)
 {
-  if (octave_signal_caught)
-    {
-      octave_signal_caught = 0;
-      octave_handle_signal ();
-    }
+  bool expected = true;
+
+  if (octave_signal_caught.compare_exchange_strong (expected, false))
+    octave_handle_signal ();
 }
 
 #define OCTAVE_QUIT octave_quit ()
 
 #else
 
-#define OCTAVE_QUIT                             \
-  do                                            \
-    {                                           \
-      if (octave_signal_caught)                 \
-        {                                       \
-          octave_signal_caught = 0;             \
-          octave_handle_signal ();              \
-        }                                       \
-    }                                           \
-  while (0)
+extern OCTAVE_API void octave_quit_c (void);
+#define OCTAVE_QUIT octave_quit_c ()
+
 #endif
 
 /* The following macros are obsolete.  Interrupting immediately by
--- a/liboctave/util/singleton-cleanup.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/singleton-cleanup.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 
 singleton_cleanup_list *singleton_cleanup_list::s_instance = nullptr;
 
-singleton_cleanup_list::~singleton_cleanup_list (void)
+singleton_cleanup_list::~singleton_cleanup_list ()
 {
   for (fptr fcn : m_fcn_list)
     {
@@ -41,7 +41,7 @@
 }
 
 bool
-singleton_cleanup_list::instance_ok (void)
+singleton_cleanup_list::instance_ok ()
 {
   bool retval = true;
 
--- a/liboctave/util/singleton-cleanup.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/singleton-cleanup.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,19 +36,15 @@
 {
 protected:
 
-  singleton_cleanup_list (void) : m_fcn_list () { }
+  singleton_cleanup_list () : m_fcn_list () { }
 
 public:
 
-  typedef void (*fptr) (void);
-
-  // No copying!
+  typedef void (*fptr) ();
 
-  singleton_cleanup_list (const singleton_cleanup_list&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (singleton_cleanup_list)
 
-  singleton_cleanup_list& operator = (const singleton_cleanup_list&) = delete;
-
-  ~singleton_cleanup_list (void);
+  ~singleton_cleanup_list ();
 
   static void add (fptr f)
   {
@@ -56,7 +52,7 @@
       s_instance->do_add (f);
   }
 
-  static void cleanup (void)
+  static void cleanup ()
   {
     delete s_instance;
     s_instance = nullptr;
@@ -66,9 +62,9 @@
 
   static singleton_cleanup_list *s_instance;
 
-  static bool instance_ok (void);
+  static bool instance_ok ();
 
-  static void cleanup_instance (void)
+  static void cleanup_instance ()
   {
     delete s_instance;
     s_instance = nullptr;
--- a/liboctave/util/str-vec.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/str-vec.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -86,7 +86,7 @@
   return *this;
 }
 string_vector&
-string_vector::uniq (void)
+string_vector::uniq ()
 {
   octave_idx_type len = numel ();
 
@@ -154,7 +154,7 @@
 }
 
 char **
-string_vector::c_str_vec (void) const
+string_vector::c_str_vec () const
 {
   octave_idx_type len = numel ();
 
@@ -169,7 +169,7 @@
 }
 
 std::list<std::string>
-string_vector::std_list (void) const
+string_vector::std_list () const
 {
   octave_idx_type len = numel ();
 
--- a/liboctave/util/str-vec.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/str-vec.h	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
 {
 public:
 
-  string_vector (void) = default;
+  string_vector () = default;
 
   explicit string_vector (octave_idx_type n) : m_data (dim_vector (n, 1)) { }
 
@@ -72,11 +72,11 @@
 
   string_vector& operator = (string_vector&&) = default;
 
-  ~string_vector (void) = default;
+  ~string_vector () = default;
 
-  bool empty (void) const { return numel () == 0; }
+  bool empty () const { return numel () == 0; }
 
-  octave_idx_type max_length (void) const
+  octave_idx_type max_length () const
   {
     octave_idx_type n = numel ();
     octave_idx_type longest = 0;
@@ -97,9 +97,9 @@
     m_data.resize (dim_vector (n, 1), rfv);
   }
 
-  octave_idx_type numel (void) const { return m_data.numel (); }
+  octave_idx_type numel () const { return m_data.numel (); }
 
-  bool isempty (void) const { return m_data.isempty (); }
+  bool isempty () const { return m_data.isempty (); }
 
   std::string& elem (octave_idx_type i) { return m_data.elem (i); }
 
@@ -119,7 +119,7 @@
 
   string_vector& sort (bool make_uniq = false);
 
-  string_vector& uniq (void);
+  string_vector& uniq ();
 
   string_vector& append (const std::string& s);
 
@@ -127,9 +127,9 @@
 
   std::string join (const std::string& sep = "") const;
 
-  char ** c_str_vec (void) const;
+  char ** c_str_vec () const;
 
-  std::list<std::string> std_list (void) const;
+  std::list<std::string> std_list () const;
 
   static void delete_c_str_vec (const char * const*);
 
--- a/liboctave/util/unwind-prot.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/unwind-prot.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -33,7 +33,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 void
-unwind_protect_safe::warn_unhandled_exception (void) const
+unwind_protect_safe::warn_unhandled_exception () const
 {
   (*current_liboctave_warning_handler)
     ("unhandled exception in unwind_protect_safe handler.  "
@@ -42,7 +42,7 @@
 }
 
 void
-unwind_action_safe::warn_unhandled_exception (void) const
+unwind_action_safe::warn_unhandled_exception () const
 {
   (*current_liboctave_warning_handler)
     ("unhandled exception in unwind_action_safe handler.  "
--- a/liboctave/util/unwind-prot.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/unwind-prot.h	Fri Jun 23 20:51:51 2023 +0200
@@ -43,23 +43,19 @@
 {
 public:
 
-  unwind_protect (void) : m_lifo () { }
-
-  // No copying!
+  unwind_protect () : m_lifo () { }
 
-  unwind_protect (const unwind_protect&) = delete;
-
-  unwind_protect& operator = (const unwind_protect&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (unwind_protect)
 
   // Destructor should not raise an exception, so all actions
   // registered should be exception-safe.  If you're not sure, see
   // unwind_protect_safe.
 
-  ~unwind_protect (void) { run (); }
+  ~unwind_protect () { run (); }
 
-  operator bool (void) const { return ! empty (); }
+  operator bool () const { return ! empty (); }
 
-  void run_first (void)
+  void run_first ()
   {
     if (! empty ())
       {
@@ -70,7 +66,7 @@
       }
   }
 
-  void discard_first (void)
+  void discard_first ()
   {
     if (! empty ())
       {
@@ -80,7 +76,7 @@
       }
   }
 
-  std::size_t size (void) const { return m_lifo.size (); }
+  std::size_t size () const { return m_lifo.size (); }
 
 protected:
 
@@ -102,19 +98,15 @@
 {
 private:
 
-  void warn_unhandled_exception (void) const;
+  void warn_unhandled_exception () const;
 
 public:
 
-  unwind_protect_safe (void) : unwind_protect () { }
-
-  // No copying!
+  unwind_protect_safe () : unwind_protect () { }
 
-  unwind_protect_safe (const unwind_protect_safe&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (unwind_protect_safe)
 
-  unwind_protect_safe& operator = (const unwind_protect_safe&) = delete;
-
-  ~unwind_protect_safe (void)
+  ~unwind_protect_safe ()
   {
     while (! empty ())
       {
@@ -150,7 +142,7 @@
 //     // flexibility in calling forms (function pointer or lambda):
 //
 //     unwind_action act1 (fcn, val);
-//     unwind_action act2 ([val] (void) { fcn (val); });
+//     unwind_action act2 ([val] () { fcn (val); });
 //   }
 //
 // NOTE: Don't forget to provide a name for the unwind_action
@@ -166,7 +158,7 @@
 {
 public:
 
-  unwind_action (void) : m_fcn () { }
+  unwind_action () : m_fcn () { }
 
   // FIXME: Do we need to apply std::forward to the arguments to
   // std::bind here?
@@ -176,13 +168,9 @@
     : m_fcn (std::bind (fcn, args...))
   { }
 
-  // No copying!
-
-  unwind_action (const unwind_action&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (unwind_action)
 
-  unwind_action& operator = (const unwind_action&) = delete;
-
-  ~unwind_action (void) { run (); }
+  ~unwind_action () { run (); }
 
   // FIXME: Do we need to apply std::forward to the arguments to
   // std::bind here?
@@ -193,12 +181,12 @@
     m_fcn = std::bind (fcn, args...);
   }
 
-  void set (void) { m_fcn = nullptr; }
+  void set () { m_fcn = nullptr; }
 
   // Alias for set() which is clearer about programmer intention.
-  void discard (void) { set (); }
+  void discard () { set (); }
 
-  void run (void)
+  void run ()
   {
     if (m_fcn)
       m_fcn ();
@@ -209,7 +197,7 @@
 
 private:
 
-  std::function<void (void)> m_fcn;
+  std::function<void ()> m_fcn;
 };
 
 // Like unwind_action, but this one will guard against the possibility
@@ -220,11 +208,11 @@
 {
 private:
 
-  void warn_unhandled_exception (void) const;
+  void warn_unhandled_exception () const;
 
 public:
 
-  unwind_action_safe (void) : m_fcn () { }
+  unwind_action_safe () : m_fcn () { }
 
   // FIXME: Do we need to apply std::forward to the arguments to
   // std::bind here?
@@ -234,13 +222,9 @@
     : m_fcn (std::bind (fcn, args...))
   { }
 
-  // No copying!
-
-  unwind_action_safe (const unwind_action_safe&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (unwind_action_safe)
 
-  unwind_action_safe& operator = (const unwind_action_safe&) = delete;
-
-  ~unwind_action_safe (void) { run (); }
+  ~unwind_action_safe () { run (); }
 
   // FIXME: Do we need to apply std::forward to the arguments to
   // std::bind here?
@@ -251,12 +235,12 @@
     m_fcn = std::bind (fcn, args...);
   }
 
-  void set (void) { m_fcn = nullptr; }
+  void set () { m_fcn = nullptr; }
 
   // Alias for set() which is clearer about programmer intention.
-  void discard (void) { set (); }
+  void discard () { set (); }
 
-  void run (void)
+  void run ()
   {
     try
       {
@@ -274,7 +258,7 @@
 
 private:
 
-  std::function<void (void)> m_fcn;
+  std::function<void ()> m_fcn;
 };
 
 // Reset a variable value at the end of the current scope when
@@ -333,13 +317,9 @@
     m_ref = new_val;
   }
 
-  // No copying!
-
-  unwind_protect_var (const unwind_protect_var&) = delete;
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (unwind_protect_var)
 
-  unwind_protect_var& operator = (const unwind_protect_var&) = delete;
-
-  ~unwind_protect_var (void)
+  ~unwind_protect_var ()
   {
     m_ref = m_val;
   }
--- a/liboctave/util/url-transfer.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/url-transfer.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,7 +48,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-base_url_transfer::base_url_transfer (void)
+base_url_transfer::base_url_transfer ()
   : m_host_or_url (), m_valid (false), m_ftp (false),
     m_ascii_mode (false), m_ok (true), m_errmsg (),
     m_curr_istream (&std::cin), m_curr_ostream (&std::cout)
@@ -75,9 +75,8 @@
                                    const std::string& target)
 {
   std::string sep = sys::file_ops::dir_sep_str ();
-  sys::file_stat fs (directory);
 
-  if (! fs || ! fs.is_dir ())
+  if (! sys::dir_exists (directory))
     {
       std::string msg;
       int status = sys::mkdir (directory, 0777, msg);
@@ -175,9 +174,7 @@
             std::string realfile
               = realdir + sys::file_ops::dir_sep_str () + file;
 
-            sys::file_stat fs (realfile);
-
-            if (! fs.exists ())
+            if (! sys::file_exists (realfile))
               {
                 m_ok = false;
                 m_errmsg = "__ftp__mput: file '" + realfile
@@ -185,7 +182,7 @@
                 break;
               }
 
-            if (fs.is_dir ())
+            if (sys::dir_exists (realfile))
               {
                 file_list.append (mput_directory (realdir, file));
 
@@ -289,7 +286,7 @@
 {
 public:
 
-  curl_transfer (void)
+  curl_transfer ()
     : base_url_transfer (), m_curl (curl_easy_init ()), m_errnum (), m_url (),
       m_userpwd ()
   {
@@ -352,19 +349,15 @@
     SETOPT (CURLOPT_HTTPGET, 1);
   }
 
-  // No copying!
-
-  curl_transfer (const curl_transfer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (curl_transfer);
 
-  curl_transfer& operator = (const curl_transfer&) = delete;
-
-  ~curl_transfer (void)
+  ~curl_transfer ()
   {
     if (m_curl)
       curl_easy_cleanup (m_curl);
   }
 
-  void perform (void)
+  void perform ()
   {
     m_errnum = curl_easy_perform (m_curl);
 
@@ -375,7 +368,7 @@
       }
   }
 
-  std::string lasterror (void) const
+  std::string lasterror () const
   {
     return std::string (curl_easy_strerror (m_errnum));
   }
@@ -396,13 +389,13 @@
     return retval;
   }
 
-  void ascii (void)
+  void ascii ()
   {
     m_ascii_mode = true;
     SETOPT (CURLOPT_TRANSFERTEXT, 1);
   }
 
-  void binary (void)
+  void binary ()
   {
     m_ascii_mode = false;
     SETOPT (CURLOPT_TRANSFERTEXT, 0);
@@ -483,7 +476,7 @@
     SETOPT (CURLOPT_URL, m_url.c_str ());
   }
 
-  void dir (void)
+  void dir ()
   {
     m_url = "ftp://" + m_host_or_url + '/';
     SETOPT (CURLOPT_URL, m_url.c_str ());
@@ -498,7 +491,7 @@
     SETOPT (CURLOPT_URL, m_url.c_str ());
   }
 
-  string_vector list (void)
+  string_vector list ()
   {
     string_vector retval;
 
@@ -582,7 +575,7 @@
     curl_easy_getinfo (m_curl, CURLINFO_FILETIME, &ft);
     filetime = ft;
     double fs;
-    curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs);
+    curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &fs);
     filesize = fs;
 
     SETOPT (CURLOPT_WRITEFUNCTION, write_data);
@@ -598,7 +591,7 @@
     cwd ('/' + path);
   }
 
-  std::string pwd (void)
+  std::string pwd ()
   {
     std::string retval;
 
@@ -717,12 +710,12 @@
   // path of the file as its value.
   void form_data_post (const Array<std::string>& param)
   {
-    struct curl_httppost *post = nullptr;
-    struct curl_httppost *last = nullptr;
+    curl_mime *mime = nullptr;
+    curl_mimepart *part = nullptr;
 
     SETOPT (CURLOPT_URL, m_host_or_url.c_str ());
 
-    unwind_action cleanup_httppost ([=] () { curl_formfree (post); });
+    unwind_action cleanup_mime ([=] () { curl_mime_free (mime); });
 
     if (param.numel () >= 2)
       {
@@ -731,15 +724,15 @@
             std::string name = param(i);
             std::string data = param(i+1);
 
+            part = curl_mime_addpart (mime);
+            curl_mime_name (part, name.c_str ());
             if (name == "file")
-              curl_formadd (&post, &last, CURLFORM_COPYNAME, name.c_str (),
-                            CURLFORM_FILE, data.c_str (), CURLFORM_END);
+              curl_mime_filedata (part, data.c_str ());
             else
-              curl_formadd(&post, &last, CURLFORM_COPYNAME, name.c_str (),
-                           CURLFORM_COPYCONTENTS, data.c_str (), CURLFORM_END);
+              curl_mime_data (part, data.c_str (), CURL_ZERO_TERMINATED);
           }
 
-        SETOPT (CURLOPT_HTTPPOST, post);
+        SETOPT (CURLOPT_MIMEPOST, mime);
       }
 
     perform ();
@@ -923,7 +916,7 @@
 #  define REP_CLASS base_url_transfer
 #endif
 
-url_transfer::url_transfer (void) : m_rep (new REP_CLASS ())
+url_transfer::url_transfer () : m_rep (new REP_CLASS ())
 { }
 
 url_transfer::url_transfer (const std::string& host, const std::string& user,
--- a/liboctave/util/url-transfer.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/util/url-transfer.h	Fri Jun 23 20:51:51 2023 +0200
@@ -59,7 +59,7 @@
 
   friend class url_transfer;
 
-  base_url_transfer (void);
+  base_url_transfer ();
 
   base_url_transfer (const std::string& host,
                      const std::string& /* user_arg */,
@@ -68,21 +68,17 @@
 
   base_url_transfer (const std::string& url, std::ostream& os);
 
-  // No copying!
-
-  base_url_transfer (const base_url_transfer&) = delete;
+  OCTAVE_DISABLE_COPY_MOVE (base_url_transfer)
 
-  base_url_transfer& operator = (const base_url_transfer&) = delete;
+  virtual ~base_url_transfer () = default;
 
-  virtual ~base_url_transfer (void) = default;
+  bool is_valid () const { return m_valid; }
 
-  bool is_valid (void) const { return m_valid; }
-
-  bool good (void) const { return m_valid && m_ok; }
+  bool good () const { return m_valid && m_ok; }
 
-  virtual void perform (void) { }
+  virtual void perform () { }
 
-  virtual std::string lasterror (void) const { return m_errmsg; }
+  virtual std::string lasterror () const { return m_errmsg; }
 
   virtual std::ostream& set_ostream (std::ostream& /* os */)
   {
@@ -94,13 +90,13 @@
     return *m_curr_istream;
   }
 
-  virtual void ascii (void) { }
+  virtual void ascii () { }
 
-  virtual void binary (void) { }
+  virtual void binary () { }
 
-  bool is_ascii (void) const { return m_ascii_mode; }
+  bool is_ascii () const { return m_ascii_mode; }
 
-  bool is_binary (void) const { return ! m_ascii_mode; }
+  bool is_binary () const { return ! m_ascii_mode; }
 
   virtual void cwd (const std::string& /* path */) { }
 
@@ -125,16 +121,16 @@
   string_vector mput_directory (const std::string& base,
                                 const std::string& directory);
 
-  virtual void dir (void) { }
+  virtual void dir () { }
 
-  virtual string_vector list (void) { return string_vector (); }
+  virtual string_vector list () { return string_vector (); }
 
   virtual void get_fileinfo (const std::string& /* filename */,
                              double& /* filesize */,
                              OCTAVE_TIME_T& /* filetime */,
                              bool& /* fileisdir */) { }
 
-  virtual std::string pwd (void) { return ""; }
+  virtual std::string pwd () { return ""; }
 
   virtual void http_get (const Array<std::string>& /* param */) { }
 
@@ -170,7 +166,7 @@
 {
 public:
 
-  url_transfer (void);
+  url_transfer ();
 
   url_transfer (const std::string& host, const std::string& user,
                 const std::string& passwd, std::ostream& os);
@@ -181,13 +177,13 @@
 
   url_transfer& operator = (const url_transfer&) = default;
 
-  ~url_transfer (void) = default;
+  ~url_transfer () = default;
 
-  bool is_valid (void) const { return m_rep->is_valid (); }
+  bool is_valid () const { return m_rep->is_valid (); }
 
-  bool good (void) const { return m_rep->good (); }
+  bool good () const { return m_rep->good (); }
 
-  std::string lasterror (void) const { return m_rep->lasterror (); }
+  std::string lasterror () const { return m_rep->lasterror (); }
 
   std::ostream& set_ostream (std::ostream& os)
   {
@@ -199,13 +195,13 @@
     return m_rep->set_istream (is);
   }
 
-  void ascii (void) { m_rep->ascii (); }
+  void ascii () { m_rep->ascii (); }
 
-  void binary (void) { m_rep->binary (); }
+  void binary () { m_rep->binary (); }
 
-  bool is_ascii (void) const { return m_rep->is_ascii (); }
+  bool is_ascii () const { return m_rep->is_ascii (); }
 
-  bool is_binary (void) const { return m_rep->is_binary (); }
+  bool is_binary () const { return m_rep->is_binary (); }
 
   void cwd (const std::string& path) { m_rep->cwd (path); }
 
@@ -242,9 +238,9 @@
     return m_rep->mput_directory (base, directory);
   }
 
-  void dir (void) { m_rep->dir (); }
+  void dir () { m_rep->dir (); }
 
-  string_vector list (void) { return m_rep->list (); }
+  string_vector list () { return m_rep->list (); }
 
   void get_fileinfo (const std::string& filename, double& filesize,
                      OCTAVE_TIME_T& filetime, bool& fileisdir)
@@ -252,7 +248,7 @@
     m_rep->get_fileinfo (filename, filesize, filetime, fileisdir);
   }
 
-  std::string pwd (void) { return m_rep->pwd (); }
+  std::string pwd () { return m_rep->pwd (); }
 
   void http_get (const Array<std::string>& param)
   {
--- a/liboctave/version.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/version.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -48,27 +48,26 @@
 std::string
 octave_www_statement (bool html)
 {
-  return "Additional information about Octave is available at "
-         + format_url (html, "https://www.octave.org") + ".";
+  return "Home page:            "
+         + format_url (html, "https://octave.org");
 }
 
 std::string
 octave_contrib_statement (bool html)
 {
-  return "Please contribute if you find this software useful.\n\
-For more information, visit "
-         + format_url (html, "https://www.octave.org/get-involved.html");
+  return "Improve Octave:       "
+         + format_url (html, "https://octave.org/get-involved");
 }
 
 std::string
 octave_bugs_statement (bool html)
 {
-  return "Read " + format_url (html, "https://www.octave.org/bugs.html")
-         + " to learn how to submit bug reports.";
+  return "Support resources:    "
+         + format_url (html, "https://octave.org/support");
 }
 
 std::string
-octave_name_version_and_copyright (void)
+octave_name_version_and_copyright ()
 {
   // The GNU coding standards say that on the first line printed by
   // --version, the version number should follow the last space on the
@@ -99,21 +98,15 @@
 octave_name_version_copyright_copying_warranty_and_bugs
   (bool html, const std::string& extra_info)
 {
-  std::string sep = (html ? "\n</p>\n<p>\n" : "\n\n");
-
-  std::string msg;
-
-  if (html)
-    msg = "<p>\n";
-
-  msg += octave_name_version_copyright_copying_and_warranty (html, extra_info)
-         + sep
-         + octave_www_statement (html)
-         + sep
-         + octave_contrib_statement (html)
-         + sep
-         + octave_bugs_statement (html)
-         + (html ? "\n</p>" : "");
+  std::string sep = (html ? "\n</p>\n<p>\n" : "\n");
+  std::string msg =
+        (html ? "<p>\n" : "")
+        + octave_name_version_copyright_copying_and_warranty (html, extra_info)
+        + (html ? "" : "\n")               + sep
+        + octave_www_statement (html)      + sep
+        + octave_bugs_statement (html)     + sep
+        + octave_contrib_statement (html)  + sep
+        + (html ? "\n</p>" : "");
 
   return msg;
 }
@@ -127,7 +120,7 @@
 
   msg += (html ? "<p>\n" : "\n");
 
-  msg += "For information about changes from previous versions, type 'news'.";
+  msg += "For changes from previous versions, type 'news'.";
 
   msg += (html ? "\n</p>" : "");
 
--- a/liboctave/version.in.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/version.in.h	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,7 @@
 
 extern OCTAVE_API std::string octave_bugs_statement (bool html = false);
 
-extern OCTAVE_API std::string octave_name_version_and_copyright (void);
+extern OCTAVE_API std::string octave_name_version_and_copyright ();
 
 extern OCTAVE_API std::string
 octave_name_version_copyright_copying_and_warranty
--- a/liboctave/wrappers/cxx-signal-helpers.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/cxx-signal-helpers.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -1,6 +1,6 @@
 ////////////////////////////////////////////////////////////////////////
 //
-// Copyright (C) 2016-2022 The Octave Project Developers
+// Copyright (C) 2016-2023 The Octave Project Developers
 //
 // See the file COPYRIGHT.md in the top-level directory of this
 // distribution or <https://octave.org/copyright/>.
@@ -45,7 +45,7 @@
 // The following pattern often used in C code to initialize a static
 // variable could possibly cause trouble in multi-threaded code:
 //
-//   TYPE * get_var (void) {
+//   TYPE * get_var () {
 //     static bool initialized = false;
 //     static TYPE *var;
 //     if (! initialized) {
@@ -57,14 +57,14 @@
 //
 // Changing this code to
 //
-//   static TYPE *var = init_var (void);
+//   static TYPE *var = init_var ();
 //
 // doesn't work in C because the static variable can't be initialized by
 // a function call.  So we have to do this job in C++.  To avoid calling
 // new, initialize sigset_t rather than a pointer to allocated storage.
 
 static const sigset_t
-init_async_signals (void)
+init_async_signals ()
 {
   sigset_t sigmask;
 
@@ -148,7 +148,7 @@
 #endif
 
 void
-octave_block_async_signals (void)
+octave_block_async_signals ()
 {
 #if ! defined (__WIN32__) || defined (__CYGWIN__)
   pthread_sigmask (SIG_BLOCK, &async_signals, 0);
@@ -156,7 +156,7 @@
 }
 
 void
-octave_unblock_async_signals (void)
+octave_unblock_async_signals ()
 {
 #if ! defined (__WIN32__) || defined (__CYGWIN__)
   pthread_sigmask (SIG_UNBLOCK, &async_signals, 0);
--- a/liboctave/wrappers/iconv-wrappers.c	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/iconv-wrappers.c	Fri Jun 23 20:51:51 2023 +0200
@@ -42,3 +42,29 @@
 {
   return iconv_close ((iconv_t) cd);
 }
+
+void
+octave_iconvlist_wrapper (int (*do_one) (unsigned int namescount,
+                                         const char * const *names,
+                                         void *data),
+                          void *data)
+{
+#if defined (HAVE_ICONVLIST)
+  iconvlist (do_one, data);
+#else
+  octave_unused_parameter (do_one);
+  octave_unused_parameter (data);
+#endif
+
+  return;
+}
+
+const char *
+octave_iconv_canonicalize_wrapper (const char *name)
+{
+#if defined (HAVE_ICONV_CANONICALIZE)
+  return iconv_canonicalize (name);
+#else
+  return name;
+#endif
+}
--- a/liboctave/wrappers/iconv-wrappers.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/iconv-wrappers.h	Fri Jun 23 20:51:51 2023 +0200
@@ -35,6 +35,15 @@
 
 extern OCTAVE_API int octave_iconv_close_wrapper (void *cd);
 
+extern OCTAVE_API void
+octave_iconvlist_wrapper (int (*do_one) (unsigned int namescount,
+                                         const char * const *names,
+                                         void *data),
+                          void *data);
+
+extern OCTAVE_API const char *
+octave_iconv_canonicalize_wrapper (const char *name);
+
 #if defined __cplusplus
 }
 #endif
--- a/liboctave/wrappers/time-wrappers.c	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/time-wrappers.c	Fri Jun 23 20:51:51 2023 +0200
@@ -43,7 +43,7 @@
 {
   struct timeval tv;
 
-  int status = gettimeofday (&tv, 0);
+  int status = gettimeofday (&tv, NULL);
 
   if (status < 0)
     {
@@ -155,3 +155,12 @@
 {
   return mktime (tp);
 }
+
+// Avoid the risk of gnulib overriding anything above by placing this underneath the above fns
+#include "gethrxtime.h"
+
+long long
+octave_gettime_ns_wrapper ()
+{
+  return gethrxtime ();
+}
--- a/liboctave/wrappers/time-wrappers.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/time-wrappers.h	Fri Jun 23 20:51:51 2023 +0200
@@ -36,6 +36,9 @@
 extern "C" {
 #endif
 
+extern OCTAVE_API long long
+octave_gettime_ns_wrapper (void);
+
 extern OCTAVE_API int octave_gettimeofday_wrapper (time_t *sec, long *usec);
 
 extern OCTAVE_API int
--- a/liboctave/wrappers/uniconv-wrappers.c	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.c	Fri Jun 23 20:51:51 2023 +0200
@@ -110,6 +110,38 @@
                                             src, srclen, NULL, lengthp);
 }
 
+uint16_t *
+octave_u16_conv_from_encoding (const char *fromcode, const char *src,
+                               size_t srclen, size_t *lengthp)
+{
+  return u16_conv_from_encoding (fromcode, iconveh_question_mark,
+                                 src, srclen, NULL, NULL, lengthp);
+}
+
+uint16_t *
+octave_u16_conv_from_encoding_strict (const char *fromcode, const char *src,
+                                      size_t srclen, size_t *lengthp)
+{
+  return u16_conv_from_encoding (fromcode, iconveh_error,
+                                 src, srclen, NULL, NULL, lengthp);
+}
+
+char *
+octave_u16_conv_to_encoding (const char *tocode, const uint16_t *src,
+                             size_t srclen, size_t *lengthp)
+{
+  return u16_conv_to_encoding (tocode, iconveh_question_mark,
+                               src, srclen, NULL, NULL, lengthp);
+}
+
+char *
+octave_u16_conv_to_encoding_strict (const char *tocode, const uint16_t *src,
+                                    size_t srclen, size_t *lengthp)
+{
+  return u16_conv_to_encoding (tocode, iconveh_error,
+                               src, srclen, NULL, NULL, lengthp);
+}
+
 char *
 octave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,
                                     size_t srclen, size_t *lengthp)
--- a/liboctave/wrappers/uniconv-wrappers.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.h	Fri Jun 23 20:51:51 2023 +0200
@@ -53,6 +53,22 @@
 octave_u8_conv_to_encoding_strict (const char *tocode, const uint8_t *src,
                                    size_t srclen, size_t *lengthp);
 
+extern OCTAVE_API uint16_t *
+octave_u16_conv_from_encoding (const char *fromcode, const char *src,
+                               size_t srclen, size_t *lengthp);
+
+extern OCTAVE_API uint16_t *
+octave_u16_conv_from_encoding_strict (const char *fromcode, const char *src,
+                                      size_t srclen, size_t *lengthp);
+
+extern OCTAVE_API char *
+octave_u16_conv_to_encoding (const char *tocode, const uint16_t *src,
+                             size_t srclen, size_t *lengthp);
+
+extern OCTAVE_API char *
+octave_u16_conv_to_encoding_strict (const char *tocode, const uint16_t *src,
+                                    size_t srclen, size_t *lengthp);
+
 extern OCTAVE_API char *
 octave_u32_conv_to_encoding_strict (const char *tocode, const uint32_t *src,
                                     size_t srclen, size_t *lengthp);
--- a/liboctave/wrappers/unistd-wrappers.c	Fri Jun 23 20:51:15 2023 +0200
+++ b/liboctave/wrappers/unistd-wrappers.c	Fri Jun 23 20:51:51 2023 +0200
@@ -148,20 +148,6 @@
 
   int status = _wspawnv (P_WAIT, wfile, wargv+1);
 
-#    if 0
-  // Code snippet from gnulib execute.c
-
-  // Executing arbitrary files as shell scripts is unsecure.
-  if (status == -1 && errno == ENOEXEC)
-    {
-      // prog is not a native executable.  Try to execute it as a
-      // shell script.  Note that prepare_spawn() has already prepended
-      // a hidden element "sh.exe" to argv.
-      argv[1] = prog_path;
-      status = _wspawnv (P_WAIT, wargv[0], wargv);
-    }
-#    endif
-
   // This happens when the spawned child process terminates.
 
   free (wfile);
--- a/m4/acinclude.m4	Fri Jun 23 20:51:15 2023 +0200
+++ b/m4/acinclude.m4	Fri Jun 23 20:51:51 2023 +0200
@@ -167,93 +167,6 @@
   fi
 ])
 dnl
-dnl Check for broken stl_algo.h header file in gcc versions 4.8.0, 4.8.1, 4.8.2
-dnl which leads to failures in nth_element.
-dnl
-AC_DEFUN([OCTAVE_CHECK_BROKEN_STL_ALGO_H], [
-  AC_CACHE_CHECK([whether stl_algo.h is broken],
-    [octave_cv_broken_stl_algo_h],
-    [AC_LANG_PUSH(C++)
-    AC_RUN_IFELSE([AC_LANG_PROGRAM([[
-// Based on code from a GCC test program.
-
-// Copyright (C) 2013 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3. If not see
-// <https://www.gnu.org/licenses/>.
-
-// 25.3.2 [lib.alg.nth.element]
-
-// { dg-options "-std=gnu++11" }
-
-#include <algorithm>
-#include <vector>
-      ]], [[
-std::vector<int> v (7);
-
-v[0] = 207089;
-v[1] = 202585;
-v[2] = 180067;
-v[3] = 157549;
-v[4] = 211592;
-v[5] = 216096;
-v[6] = 207089;
-
-std::nth_element (v.begin (), v.begin () + 3, v.end ());
-
-return v[3] == 207089 ? 0 : 1;
-    ]])],
-    octave_cv_broken_stl_algo_h=no,
-    octave_cv_broken_stl_algo_h=yes,
-    [case "$GXX_VERSION" in
-       *4.8.2*)
-         octave_cv_broken_stl_algo_h=yes
-       ;;
-       *)
-         octave_cv_broken_stl_algo_h=no
-       ;;
-     esac
-    ])
-    AC_LANG_POP(C++)
-  ])
-  if test "$GXX" = yes; then
-    if test $octave_cv_broken_stl_algo_h = yes; then
-      case "$GXX_VERSION" in
-        4.8.[[012]])
-        ;;
-        *)
-          octave_cv_broken_stl_algo_h=no
-          warn_stl_algo_h="UNEXPECTED: found nth_element broken in g++ $GXX_VERSION.  Refusing to fix except for g++ 4.8.0, 4.8.1, or 4.8.2.  You appear to have g++ $GXX_VERSION."
-          OCTAVE_CONFIGURE_WARNING([warn_stl_algo_h])
-        ;;
-      esac
-    else
-      case "$GXX_VERSION" in
-        4.8.2)
-          warn_stl_algo_h="UNEXPECTED: found nth_element working in g++ 4.8.2.  Has it been patched on your system?"
-          OCTAVE_CONFIGURE_WARNING([warn_stl_algo_h])
-        ;;
-      esac
-    fi
-  else
-    octave_cv_broken_stl_algo_h=no
-    warn_stl_algo_h="UNEXPECTED: nth_element test failed.  Refusing to fix except for g++ 4.8.2."
-    OCTAVE_CONFIGURE_WARNING([warn_stl_algo_h])
-  fi
-])
-dnl
 dnl Check for LLVM or Apple libc++ library.
 dnl
 AC_DEFUN([OCTAVE_LLVM_LIBCXX], [
@@ -518,6 +431,8 @@
 dnl Check whether the Qt class QList has a constructor that accepts
 dnl a pair of iterators.  This constructor was introduced in Qt 5.14.
 dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.
+dnl
 AC_DEFUN([OCTAVE_CHECK_FUNC_QFONTMETRICS_HORIZONTAL_ADVANCE], [
   AC_CACHE_CHECK([for QFontMetrics::horizontalAdvance function],
     [octave_cv_func_qfontmetrics_horizontal_advance],
@@ -548,38 +463,10 @@
   fi
 ])
 dnl
-dnl Check whether the Qt QGuiApplication class has the setDesktopFileName
-dnl static member function.  This function was introduced in Qt 5.7.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 5.6 or older.
+dnl Check whether the Qt class QHelpEngine has the documentsForIdentifier
+dnl function.  This member function was introduced in Qt 5.15.
 dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QGUIAPPLICATION_SETDESKTOPFILENAME], [
-  AC_CACHE_CHECK([for QGuiApplication::setDesktopFileName],
-    [octave_cv_func_qguiapplication_setdesktopfilename],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QGuiApplication>
-        ]], [[
-        QGuiApplication::setDesktopFileName ("com.example.Example.desktop");
-        ]])],
-      octave_cv_func_qguiapplication_setdesktopfilename=yes,
-      octave_cv_func_qguiapplication_setdesktopfilename=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qguiapplication_setdesktopfilename = yes; then
-    AC_DEFINE(HAVE_QGUIAPPLICATION_SETDESKTOPFILENAME, 1,
-      [Define to 1 if you have the `QGuiApplication::setDesktopFileName' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QHelpEngine has the documentsForIdentifier
-dnl function.  dnl This member function was introduced in Qt 5.15.
+dnl FIXME: Delete this entirely when we drop support for Qt 5.14 or older.
 dnl
 AC_DEFUN([OCTAVE_CHECK_FUNC_QHELPENGINE_DOCUMENTSFORIDENTIFIER], [
   AC_CACHE_CHECK([for QHelpEngine::documentsForIdentifier in <QHelpEngine>],
@@ -648,6 +535,8 @@
 dnl Check whether the Qt class QList has a constructor that accepts
 dnl a pair of iterators.  This constructor was introduced in Qt 5.14.
 dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.
+dnl
 AC_DEFUN([OCTAVE_CHECK_FUNC_QLIST_ITERATOR_CONSTRUCTOR], [
   AC_CACHE_CHECK([for QList<T>::QList (iterator, iterator) constructor],
     [octave_cv_func_qlist_iterator_constructor],
@@ -674,136 +563,11 @@
   fi
 ])
 dnl
-dnl Check whether the Qt class QMainWindow has the resizeDocks member function.
-dnl This member function was introduced in Qt 5.6.
-dnl
-dnl FIXME: remove this test when we drop support for Qt older than 5.6
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QMAINWINDOW_RESIZEDOCKS], [
-  AC_CACHE_CHECK([for QMainWindow::resizeDocks in <QMainWindow>],
-    [octave_cv_func_mainwindow_resizedocks],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QMainWindow>
-        #include <QDockWidget>
-        ]], [[
-        QMainWindow *mw = new QMainWindow ();
-        QDockWidget *dw = new QDockWidget (mw);
-        mw->addDockWidget (Qt::LeftDockWidgetArea, dw);
-        mw->resizeDocks ({dw},{20},Qt::Horizontal);
-        ]])],
-      octave_cv_func_mainwindow_resizedocks=yes,
-      octave_cv_func_mainwindow_resizedocks=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_mainwindow_resizedocks = yes; then
-    AC_DEFINE(HAVE_QMAINWINDOW_RESIZEDOCKS, 1,
-      [Define to 1 if you have the 'QMainWindow::resizeDocks' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QPrinter has the setPageSize member function.
-dnl This member function was introduced in Qt 5.3.
-dnl
-dnl FIXME: remove this test when we drop support for Qt older than 5.3.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QPRINTER_SETPAGESIZE], [
-  AC_CACHE_CHECK([for QPrinter::setPageSize in <QPrinter>],
-    [octave_cv_func_qprinter_setpagesize],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QPrinter>
-        ]], [[
-        QPrinter printer;
-        printer.setPageSize (QPageSize (QSizeF (8.5, 11.0), QPageSize::Inch));
-        ]])],
-      octave_cv_func_qprinter_setpagesize=yes,
-      octave_cv_func_qprinter_setpagesize=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qprinter_setpagesize = yes; then
-    AC_DEFINE(HAVE_QPRINTER_SETPAGESIZE, 1,
-      [Define to 1 if you have the 'QPrinter::setPageSize' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QScreen has the devicePixelRatio member function.
-dnl This member function was introduced in Qt 5.5.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QSCREEN_DEVICEPIXELRATIO], [
-  AC_CACHE_CHECK([for QScreen::devicePixelRatio in <QScreen>],
-    [octave_cv_func_qscreen_devicepixelratio],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QApplication>
-        #include <QScreen>
-        ]], [[
-        QScreen *screen = QApplication::primaryScreen ();
-        qreal ratio = screen->devicePixelRatio ();
-        ]])],
-      octave_cv_func_qscreen_devicepixelratio=yes,
-      octave_cv_func_qscreen_devicepixelratio=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qscreen_devicepixelratio = yes; then
-    AC_DEFINE(HAVE_QSCREEN_DEVICEPIXELRATIO, 1,
-      [Define to 1 if you have the `QScreen::devicePixelRatio' member function.])
-  fi
-])
-dnl
-dnl Check whether the Qt class QWheelEvent has the angleDelta member function.
-dnl This member function was introduced in Qt 5.
-dnl
-dnl FIXME: Delete this entirely when we drop support for Qt 4.
-dnl
-AC_DEFUN([OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA], [
-  AC_CACHE_CHECK([for QWheelEvent::angleDelta in <QWheelEvent>],
-    [octave_cv_func_qwheelevent_angledelta],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QWheelEvent>
-        void foo (const QWheelEvent& ev)
-        {
-          ev.angleDelta ();
-        };
-        ]])],
-      octave_cv_func_qwheelevent_angledelta=yes,
-      octave_cv_func_qwheelevent_angledelta=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_func_qwheelevent_angledelta = yes; then
-    AC_DEFINE(HAVE_QWHEELEVENT_ANGLEDELTA, 1,
-      [Define to 1 if you have the `QWheelEvent::angleDelta' member function.])
-  fi
-])
-dnl
 dnl Check whether the Qt class QWheelEvent has the position member function.
 dnl This member function was introduced in Qt 5.14.
 dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.
+dnl
 AC_DEFUN([OCTAVE_CHECK_FUNC_QWHEELEVENT_POSITION], [
   AC_CACHE_CHECK([for QWheelEvent::position in <QWheelEvent>],
     [octave_cv_func_qwheelevent_position],
@@ -832,7 +596,10 @@
 ])
 dnl
 dnl Check whether the Qt method QPainter::setRenderHint accepts the
-dnl QPainter::LosslessImageRendering flag.  This flag was introduced in Qt 5.13.
+dnl QPainter::LosslessImageRendering flag.  This flag was introduced in
+dnl Qt 5.13.
+dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.12 or older.
 dnl
 AC_DEFUN([OCTAVE_CHECK_FUNC_QPAINTER_SETRENDERHINT_LOSSLESS], [
   AC_CACHE_CHECK([for QPainter::LosslessImageRendering flag],
@@ -860,6 +627,102 @@
   fi
 ])
 dnl
+dnl Check whether the Qt methods QColor::getRgbF and QColor::getHslF
+dnl use float types as their arguments.  The type of the arguments
+dnl changed from qreal to float in Qt6.
+dnl
+dnl FIXME: Delete this check when we drop support for any version of Qt5.
+dnl
+AC_DEFUN([OCTAVE_CHECK_FUNC_QCOLOR_FLOAT_TYPE], [
+  AC_CACHE_CHECK([for QColor::getRgbF and QColor::getHslF with float arguments],
+    [octave_cv_func_qcolor_float_type],
+    [AC_LANG_PUSH(C++)
+    ac_octave_save_CPPFLAGS="$CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #include <QColor>
+        ]], [[
+        QColor color;
+        float r, g, b, h, s, l, a;
+        color.getRgbF (&r, &g, &b);
+        color.getHslF (&h, &s, &l, &a);
+        ]])],
+      octave_cv_func_qcolor_float_type=yes,
+      octave_cv_func_qcolor_float_type=no)
+    CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_func_qcolor_float_type = yes; then
+    AC_DEFINE(HAVE_QCOLOR_FLOAT_TYPE, 1,
+      [Define to 1 if QColor::getRgbF and QColor::getHslF use float type arguments.])
+  fi
+])
+dnl
+dnl Check whether Qt provides a QStringView class.  This class was first
+dnl introduced in Qt 5.10 and finally replaced QStringRef in Qt6.
+dnl
+dnl FIXME: Delete this check when we drop support for Qt 5.9 or older.
+dnl
+AC_DEFUN([OCTAVE_CHECK_CLASS_QSTRINGVIEW], [
+  AC_CACHE_CHECK([for class QStringView],
+    [octave_cv_class_qstringview],
+    [AC_LANG_PUSH(C++)
+    ac_octave_save_CPPFLAGS="$CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #include <QStringView>
+        ]], [[
+        QStringView qstrv {};
+        ]])],
+      octave_cv_class_qstringview=yes,
+      octave_cv_class_qstringview=no)
+    CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_class_qstringview = yes; then
+    AC_DEFINE(HAVE_QSTRINGVIEW, 1,
+      [Define to 1 if Qt provides the class QStringView.])
+  fi
+])
+dnl
+dnl Check whether the Qt class QTextStream has the setEncoding function.
+dnl This function was introduced replacing QTextStream::setCodec in Qt6.
+dnl
+dnl FIXME: Delete this check when we drop support for any version of Qt5.
+dnl
+AC_DEFUN([OCTAVE_CHECK_FUNC_QTEXTSTREAM_SETENCODING], [
+  AC_CACHE_CHECK([for QTextStream::setEncoding],
+    [octave_cv_func_qtextstream_setencoding],
+    [AC_LANG_PUSH(C++)
+    ac_octave_save_CPPFLAGS="$CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #include <QStringConverter>
+        #include <QTextStream>
+        ]], [[
+        QTextStream textstream;
+        textstream.setEncoding (QStringConverter::Utf8);
+        ]])],
+      octave_cv_func_qtextstream_setencoding=yes,
+      octave_cv_func_qtextstream_setencoding=no)
+    CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_func_qtextstream_setencoding = yes; then
+    AC_DEFINE(HAVE_QTEXTSTREAM_SETENCODING, 1,
+      [Define to 1 if you have the `QTextStream::setEncoding' member function.])
+  fi
+])
+dnl
 dnl Check whether HDF5 library has version 1.6 API functions.
 dnl
 AC_DEFUN([OCTAVE_CHECK_HDF5_HAS_VER_16_API], [
@@ -1393,6 +1256,68 @@
   fi
 ])
 dnl
+dnl Check whether iconv provides the function iconvlist.
+dnl
+AC_DEFUN([OCTAVE_CHECK_ICONVLIST], [
+  AC_CACHE_CHECK([whether the function iconvlist is available],
+    [octave_cv_iconvlist],
+    [ac_octave_save_LIBS="$LIBS"
+    LIBS="$LIBICONV $LIBS"
+    AC_LANG_PUSH(C++)
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+        #if HAVE_ICONV
+        extern "C"
+        {
+        #  include <iconv.h>
+        }
+        #endif
+        ]], [[
+        iconvlist (
+           [] (unsigned int, const char * const *, void *) -> int
+             {
+               return 0;
+             },
+           nullptr);
+        ]])],
+      octave_cv_iconvlist=yes,
+      octave_cv_iconvlist=no)
+    AC_LANG_POP(C++)
+    LIBS="$ac_octave_save_LIBS"
+  ])
+  if test $octave_cv_iconvlist = yes; then
+    AC_DEFINE(HAVE_ICONVLIST, 1, [Define to 1 if iconvlist is available.])
+  fi
+])
+dnl
+dnl Check whether iconv provides the function iconv_canonicalize.
+dnl
+AC_DEFUN([OCTAVE_CHECK_ICONV_CANONICALIZE], [
+  AC_CACHE_CHECK([whether the function iconv_canonicalize is available],
+    [octave_cv_iconv_canonicalize],
+    [ac_octave_save_LIBS="$LIBS"
+    LIBS="$LIBICONV $LIBS"
+    AC_LANG_PUSH(C++)
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+        #if HAVE_ICONV
+        extern "C"
+        {
+        #  include <iconv.h>
+        }
+        #endif
+        ]], [[
+        iconv_canonicalize ("UTF-8");
+        ]])],
+      octave_cv_iconv_canonicalize=yes,
+      octave_cv_iconv_canonicalize=no)
+    AC_LANG_POP(C++)
+    LIBS="$ac_octave_save_LIBS"
+  ])
+  if test $octave_cv_iconv_canonicalize = yes; then
+    AC_DEFINE(HAVE_ICONV_CANONICALIZE, 1,
+      [Define to 1 if iconv_canonicalize is available.])
+  fi
+])
+dnl
 dnl Check whether using HDF5 DLL under Windows.  This is done by
 dnl testing for a data symbol in the HDF5 library, which would
 dnl require the definition of _HDF5USEDL_ under MSVC compiler.
@@ -1723,42 +1648,11 @@
   fi
 ])
 dnl
-dnl Check whether Qt has the QOverload template introduced in Qt 5.7.
-dnl
-AC_DEFUN([OCTAVE_CHECK_QOVERLOAD_TEMPLATE], [
-  AC_CACHE_CHECK([for QOverload template],
-    [octave_cv_qoverload_template],
-    [AC_LANG_PUSH(C++)
-    ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    ac_octave_save_CXXFLAGS="$CXXFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <QtGlobal>
-        ]], [[
-        struct Foo
-        {
-            void overloadedFunction (int) const;
-            void overloadedFunction (int, const QString &) const;
-        };
-        QOverload<int>::of (&Foo::overloadedFunction);
-        QOverload<int, const QString &>::of (&Foo::overloadedFunction);
-        ]])],
-      octave_cv_qoverload_template=yes,
-      octave_cv_qoverload_template=no)
-    CPPFLAGS="$ac_octave_save_CPPFLAGS"
-    CXXFLAGS="$ac_octave_save_CXXFLAGS"
-    AC_LANG_POP(C++)
-  ])
-  if test $octave_cv_qoverload_template = yes; then
-    AC_DEFINE(HAVE_QOVERLOAD_TEMPLATE, 1,
-      [Define to 1 if you have the `QOverload' template.])
-  fi
-])
-dnl
 dnl Check whether the Qt class QRegion has the iterators and related
 dnl functions introduced in Qt 5.8.
 dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.7 or older.
+dnl
 AC_DEFUN([OCTAVE_CHECK_QREGION_ITERATORS], [
   AC_CACHE_CHECK([for QRegion iterators and related functions],
     [octave_cv_qregion_iterators],
@@ -1806,6 +1700,9 @@
     5)
       octave_qscintilla_libnames="qscintilla2-qt5 qscintilla2_qt5 qt5scintilla2"
     ;;
+    6)
+      octave_qscintilla_libnames="qscintilla2-qt6 qscintilla2_qt6 qt6scintilla2"
+    ;;
     *)
       AC_MSG_ERROR([Unrecognized Qt version $qt_version])
     ;;
@@ -1905,7 +1802,6 @@
   octave_qt_versions="$1"
 
   build_qt_gui=no
-  build_qt_graphics=no
   use_qscintilla=no
   win32_terminal=no
 
@@ -1918,7 +1814,7 @@
       ## If some modules were found for $ver, then warn about possible
       ## incomplete or broken Qt installation instead of checking for
       ## next version in the list.  Don't attempt a similar check for
-      ## tools here because Qt4 and Qt5 tools may be installed with
+      ## tools here because Qt5 and Qt6 tools may be installed with
       ## the same name so determining whether there is a mix of versions
       ## will require more work than just looking which tools are installed.
       warn_qt_modules="Your installation of Qt version $ver appears incomplete or broken in some way.  Fix that or use --with-qt=VER to use another version."
@@ -1931,6 +1827,9 @@
     if test x"$have_qt_version" = x5; then
       AC_DEFINE(HAVE_QT5, 1, [Define to 1 if using Qt version 5.])
     fi
+    if test x"$have_qt_version" = x6; then
+      AC_DEFINE(HAVE_QT6, 1, [Define to 1 if using Qt version 6.])
+    fi
   else
     if test -n "$QT_MODULES_MISSING" || test -n "$QT_TOOLS_MISSING"; then
       qt_missing=`echo $QT_MODULES_MISSING$QT_TOOLS_MISSING | sed 's/  *$//'`
@@ -1968,126 +1867,10 @@
   fi
 
   AM_CONDITIONAL([AMCOND_BUILD_QT_GUI], [test $build_qt_gui = yes])
-  AM_CONDITIONAL([AMCOND_BUILD_QT_GRAPHICS], [test $build_qt_graphics = yes])
   AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test $use_qscintilla = yes])
   AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])
 ])
 dnl
-dnl Check whether QOffscreenSurface is present.
-dnl
-AC_DEFUN([OCTAVE_CHECK_QT_OPENGL_OFFSCREEN_OK], [
-  dnl Normally the language and compiler flags would be set and restored
-  dnl inside of the AC_CACHE_CHECK body.  Because we also need to check for
-  dnl Qt header files associated with the compilation test, set and restore
-  dnl these values outside of the AC_CACHE_CHECK for this macro only.
-  AC_LANG_PUSH(C++)
-  ac_octave_save_CPPFLAGS="$CPPFLAGS"
-  ac_octave_save_CXXFLAGS="$CXXFLAGS"
-  CPPFLAGS="$QT_OPENGL_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-  CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-  AC_CHECK_HEADERS([QOffscreenSurface])
-  AC_CACHE_CHECK([whether Qt supports full offscreen OpenGL rendering],
-    [octave_cv_qt_opengl_os_ok],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-         #if HAVE_WINDOWS_H
-         #  include <windows.h>
-         #endif
-         #if defined (HAVE_GL_GL_H)
-         #  include <GL/gl.h>
-         #elif defined (HAVE_OPENGL_GL_H)
-         #  include <OpenGL/gl.h>
-         #endif
-         #if defined (HAVE_GL_GLU_H)
-         #  include <GL/glu.h>
-         #elif defined HAVE_OPENGL_GLU_H || defined HAVE_FRAMEWORK_OPENGL
-         #  include <OpenGL/glu.h>
-         #endif
-         #if defined (HAVE_QOPENGLWIDGET)
-         #  include <QOpenGLWidget>
-         #  include <QOpenGLContext>
-         #endif
-         #if defined (HAVE_QOFFSCREENSURFACE)
-         #  include <QOffscreenSurface>
-         #endif
-         QOpenGLContext ctx;
-         QOffscreenSurface surf;
-       ]])],
-       octave_cv_qt_opengl_os_ok=yes,
-       octave_cv_qt_opengl_os_ok=no)
-  ])
-  CPPFLAGS="$ac_octave_save_CPPFLAGS"
-  CXXFLAGS="$ac_octave_save_CXXFLAGS"
-  AC_LANG_POP(C++)
-  if test $octave_cv_qt_opengl_os_ok = yes; then
-    $1
-    :
-  else
-    $2
-    :
-  fi
-])
-dnl
-dnl Check whether Qt works with full OpenGL support
-dnl
-AC_DEFUN([OCTAVE_CHECK_QT_OPENGL_OK], [
-  dnl Normally the language and compiler flags would be set and restored
-  dnl inside of the AC_CACHE_CHECK body.  Because we also need to check for
-  dnl Qt header files associated with the compilation test, set and restore
-  dnl these values outside of the AC_CACHE_CHECK for this macro only.
-  AC_LANG_PUSH(C++)
-  ac_octave_save_CPPFLAGS="$CPPFLAGS"
-  ac_octave_save_CXXFLAGS="$CXXFLAGS"
-  CPPFLAGS="$QT_OPENGL_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
-  CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
-  AC_CHECK_HEADERS([QOpenGLWidget QGLWidget QGLFunctions_1_1])
-  AC_CACHE_CHECK([whether Qt works with OpenGL and GLU],
-    [octave_cv_qt_opengl_ok],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-         #if HAVE_WINDOWS_H
-         #  include <windows.h>
-         #endif
-         #if defined (HAVE_GL_GL_H)
-         #  include <GL/gl.h>
-         #elif defined (HAVE_OPENGL_GL_H)
-         #  include <OpenGL/gl.h>
-         #endif
-         #if defined (HAVE_GL_GLU_H)
-         #  include <GL/glu.h>
-         #elif defined HAVE_OPENGL_GLU_H || defined HAVE_FRAMEWORK_OPENGL
-         #  include <OpenGL/glu.h>
-         #endif
-         #if defined (HAVE_QOPENGLWIDGET)
-         #  include <QOpenGLWidget>
-         #  define OCTAVE_QT_OPENGL_WIDGET QOpenGLWidget
-         #elif defined (HAVE_QGLWIDGET)
-         #  include <QGLWidget>
-         #  define OCTAVE_QT_OPENGL_WIDGET QGLWidget
-         #endif
-         class gl_widget : public OCTAVE_QT_OPENGL_WIDGET
-         {
-         public:
-           gl_widget (QWidget *parent = 0)
-             : OCTAVE_QT_OPENGL_WIDGET (parent) { }
-           ~gl_widget () {}
-         };
-         ]], [[
-         gl_widget widget;
-       ]])],
-       octave_cv_qt_opengl_ok=yes,
-       octave_cv_qt_opengl_ok=no)
-  ])
-  CPPFLAGS="$ac_octave_save_CPPFLAGS"
-  CXXFLAGS="$ac_octave_save_CXXFLAGS"
-  AC_LANG_POP(C++)
-  if test $octave_cv_qt_opengl_ok = yes; then
-    $1
-    :
-  else
-    $2
-    :
-  fi
-])
-dnl
 dnl Check whether the Qt::ImCursorRectangle enum value exists.
 dnl It replaces the Qt::ImMicroFocus enum value that was deprecated
 dnl in Qt 5.14.
@@ -2121,6 +1904,8 @@
 dnl Qt::KeepEmptyParts and Qt::SkipEmptyParts members.  This enum
 dnl was introduced or modified in Qt 5.14.
 dnl
+dnl FIXME: Delete this entirely when we drop support for Qt 5.13 or older.
+dnl
 AC_DEFUN([OCTAVE_CHECK_QT_SPLITBEHAVIOR_ENUM], [
   AC_CACHE_CHECK([for Qt::SplitBehavior enum],
     [octave_cv_qt_splitbehavior_enum],
@@ -2167,8 +1952,8 @@
   fi
 ])
 dnl
-dnl Check whether Qt VERSION is present, supports QtOpenGL and
-dnl QScintilla, and will work for Octave.
+dnl Check whether Qt VERSION is present, supports QScintilla,
+dnl and will work for Octave.
 dnl
 dnl OCTAVE_CHECK_QT_VERSION(VERSION)
 dnl
@@ -2180,8 +1965,6 @@
   qt_version="$1";
 
   build_qt_gui=yes
-  build_qt_graphics=no
-  have_qt_opengl_offscreen=no
   win32_terminal=no
 
   warn_qt_libraries=""
@@ -2195,8 +1978,22 @@
   ## Check for Qt libraries
   case "$qt_version" in
     5)
-      QT_OPENGL_MODULE="Qt5OpenGL"
-      QT_MODULES="Qt5Core Qt5Gui Qt5Help Qt5Network Qt5PrintSupport Qt5Xml"
+      QT_MODULES="Qt5Core Qt5Gui Qt5Help Qt5Network Qt5OpenGL Qt5PrintSupport Qt5Xml"
+    ;;
+    6)
+      QT_MODULES="Qt6Core Qt6Gui Qt6Help Qt6Network Qt6OpenGL Qt6OpenGLWidgets Qt6PrintSupport Qt6Xml"
+      case $host_os in
+        mingw* | msdosmsvc*)
+        ;;
+        *)
+          # FIXME: Remove Qt6Core5Compat when we no longer rely on classes that
+          #        have been removed in Qt6:
+          #        https://www.qt.io/blog/porting-from-qt-5-to-qt-6-using-qt5compat-library
+          #        It is still needed for the terminal implementation in
+          #        libgui/qterminal/libqterminal/unix
+          QT_MODULES="$QT_MODULES Qt6Core5Compat"
+        ;;
+      esac
     ;;
     *)
       AC_MSG_ERROR([Unrecognized Qt version $qt_version])
@@ -2226,9 +2023,6 @@
     QT_CPPFLAGS="$($PKG_CONFIG --cflags-only-I $QT_MODULES | $SED -e 's/^ *$//')"
     QT_LDFLAGS="$($PKG_CONFIG --libs-only-L $QT_MODULES | $SED -e 's/^ *$//')"
     QT_LIBS="$($PKG_CONFIG --libs-only-l $QT_MODULES | $SED -e 's/^ *$//')"
-    QT_OPENGL_CPPFLAGS="$($PKG_CONFIG --cflags-only-I $QT_OPENGL_MODULE | $SED -e 's/^ *$//')"
-    QT_OPENGL_LDFLAGS="$($PKG_CONFIG --libs-only-L $QT_OPENGL_MODULE | $SED -e 's/^ *$//')"
-    QT_OPENGL_LIBS="$($PKG_CONFIG --libs-only-l $QT_OPENGL_MODULE | $SED -e 's/^ *$//')"
 
     case $host_os in
       *darwin*)
@@ -2236,8 +2030,6 @@
         if test -z "$QT_LIBS"; then
           QT_LDFLAGS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -e '-F' | uniq | tr '\n' ' '`"
           QT_LIBS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -v -e '-F' | uniq | tr '\n' ' '`"
-          QT_OPENGL_LDFLAGS="`$PKG_CONFIG --libs-only-other $QT_OPENGL_MODULE | tr ' ' '\n' | $GREP -e '-F' | uniq | tr '\n' ' '`"
-          QT_OPENGL_LIBS="`$PKG_CONFIG --libs-only-other $QT_OPENGL_MODULE | tr ' ' '\n' | $GREP -v -e '-F' | uniq | tr '\n' ' '`"
           ## Enabling link_all_deps works around libtool's imperfect handling
           ## of the -F flag
           if test -n "$QT_LDFLAGS"; then
@@ -2329,36 +2121,20 @@
     ## version that we are testing now will be the one used.
 
     OCTAVE_CHECK_FUNC_QFONTMETRICS_HORIZONTAL_ADVANCE
-    OCTAVE_CHECK_FUNC_QGUIAPPLICATION_SETDESKTOPFILENAME
     OCTAVE_CHECK_FUNC_QHELPSEARCHQUERYWIDGET_SEARCHINPUT
     OCTAVE_CHECK_NEW_QHELPINDEXWIDGET_API
     OCTAVE_CHECK_FUNC_QLIST_ITERATOR_CONSTRUCTOR
-    OCTAVE_CHECK_FUNC_QMAINWINDOW_RESIZEDOCKS
-    OCTAVE_CHECK_FUNC_QPRINTER_SETPAGESIZE
-    OCTAVE_CHECK_FUNC_QSCREEN_DEVICEPIXELRATIO
     OCTAVE_CHECK_FUNC_QHELPENGINE_DOCUMENTSFORIDENTIFIER
-    OCTAVE_CHECK_FUNC_QWHEELEVENT_ANGLEDELTA
     OCTAVE_CHECK_FUNC_QWHEELEVENT_POSITION
     OCTAVE_CHECK_FUNC_QPAINTER_SETRENDERHINT_LOSSLESS
+    OCTAVE_CHECK_FUNC_QCOLOR_FLOAT_TYPE
+    OCTAVE_CHECK_CLASS_QSTRINGVIEW
+    OCTAVE_CHECK_FUNC_QTEXTSTREAM_SETENCODING
 
-    OCTAVE_CHECK_QOVERLOAD_TEMPLATE
     OCTAVE_CHECK_QREGION_ITERATORS
     OCTAVE_CHECK_QT_IMCURSORRECTANGLE_ENUM_VALUE
     OCTAVE_CHECK_QT_SPLITBEHAVIOR_ENUM
 
-    if test -n "$OPENGL_LIBS"; then
-      OCTAVE_CHECK_QT_OPENGL_OK([build_qt_graphics=yes],
-        [warn_qt_opengl="Qt does not work with the OpenGL libs (GL and GLU); disabling OpenGL graphics with Qt GUI"])
-
-      if test $build_qt_graphics = yes; then
-        AC_DEFINE(HAVE_QT_GRAPHICS, 1, [Define to 1 if Qt works with OpenGL libs (GL and GLU)])
-        OCTAVE_CHECK_QT_OPENGL_OFFSCREEN_OK([have_qt_opengl_offscreen=yes])
-        if test $have_qt_opengl_offscreen = yes; then
-          AC_DEFINE(HAVE_QT_OFFSCREEN, 1, [Define to 1 if Qt handles offscreen OpenGL rendering])
-        fi
-      fi
-    fi
-
     OCTAVE_CHECK_QSCINTILLA([$qt_version])
 
   fi
@@ -2371,9 +2147,6 @@
   AC_SUBST(QT_CPPFLAGS)
   AC_SUBST(QT_LDFLAGS)
   AC_SUBST(QT_LIBS)
-  AC_SUBST(QT_OPENGL_CPPFLAGS)
-  AC_SUBST(QT_OPENGL_LDFLAGS)
-  AC_SUBST(QT_OPENGL_LIBS)
 ])
 dnl
 dnl Check if the default Fortran INTEGER is 64 bits wide.
@@ -2662,7 +2435,7 @@
   ])
   if test $octave_cv_cxx_complex_reference_accessors = yes; then
     AC_DEFINE(HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS, 1,
-      [Define to 1 if C++ complex class has T& real (void) and T& imag (void) methods.])
+      [Define to 1 if C++ complex class has T& real () and T& imag () methods.])
   fi
 ])
 dnl
--- a/oct-conf-post-public.in.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/oct-conf-post-public.in.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,7 +39,7 @@
    OCTAVE_ATTRIBUTE_NAME in place of vendor specific attribute
    mechanisms.  As compilers evolve, the underlying implementation can
    be changed with the macro definitions below.  FIXME: Update macros
-   to use C++ standard attribute syntax when Octave moves to C++ 2011
+   to use C++ standard attribute syntax when Octave moves to C++ 2014
    standard.  */
 
 #if defined (__GNUC__)
@@ -66,6 +66,16 @@
 /* #  undef HAVE_OCTAVE_UNUSED_ATTR */
 #endif
 
+/* Branch hint macros for use in if condititions.
+   Returns logical value of x. */
+#if defined (__GNUC__)
+#  define OCTAVE_LIKELY(x) __builtin_expect (!!(x), 1)
+#  define OCTAVE_UNLIKELY(x) __builtin_expect (!!(x), 0)
+#else
+#  define OCTAVE_LIKELY(x) !!(x)
+#  define OCTAVE_UNLIKELY(x) !!(x)
+#endif
+
 #if defined (__MINGW32__)
   /* MinGW requires special handling due to different format specifiers
    * on different platforms.  The macro __MINGW_PRINTF_FORMAT maps to
@@ -320,6 +330,83 @@
 #  define OCTAVE_THREAD_LOCAL
 #endif
 
+#if defined (__cplusplus)
+#  define OCTAVE_DISABLE_COPY(X)                \
+  X (const X&) = delete;                        \
+  X& operator = (const X&) = delete;
+
+#  define OCTAVE_DISABLE_MOVE(X)                \
+  X (X&&) = delete;                             \
+  X (const X&&) = delete;                       \
+  X& operator = (X&&) = delete;                 \
+  X& operator = (const X&&) = delete;
+
+#  define OCTAVE_DISABLE_COPY_MOVE(X)           \
+  OCTAVE_DISABLE_COPY (X)                       \
+  OCTAVE_DISABLE_MOVE (X)
+
+#  define OCTAVE_DISABLE_COPY_MOVE_ASGN(X)      \
+  X& operator = (const X&) = delete;            \
+  X& operator = (X&&) = delete;                 \
+  X& operator = (const X&&) = delete;
+
+#  define OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE(X) \
+  X () = delete;                                \
+  OCTAVE_DISABLE_COPY (X)                       \
+  OCTAVE_DISABLE_MOVE (X)
+
+#  define OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE(X)  \
+  X () = delete;                                        \
+  OCTAVE_DISABLE_COPY (X)                               \
+  OCTAVE_DISABLE_MOVE (X)                               \
+  ~X () = delete;
+
+#  define OCTAVE_DEFAULT_COPY(X)                \
+  X (const X&) = default;                       \
+  X& operator = (const X&) = default;
+
+#  define OCTAVE_DEFAULT_MOVE(X)                \
+  X (X&&) = default;                            \
+  X& operator = (X&&) = default;
+
+#  define OCTAVE_DEFAULT_COPY_MOVE(X)           \
+  OCTAVE_DEFAULT_COPY (X)                       \
+  OCTAVE_DEFAULT_MOVE (X)
+
+#  define OCTAVE_DEFAULT_COPY_MOVE_CTOR(X)      \
+  X (const X&) = default;                       \
+  X (X&&) = default;
+
+#  define OCTAVE_DEFAULT_CONSTRUCT_COPY(X)      \
+  X () = default;                               \
+  OCTAVE_DEFAULT_COPY (X)
+
+#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE(X) \
+  X () = default;                               \
+  OCTAVE_DEFAULT_COPY_MOVE (X)
+
+#  define OCTAVE_DEFAULT_COPY_DELETE(X)         \
+  OCTAVE_DEFAULT_COPY (X)                       \
+  ~X () = default;
+
+#  define OCTAVE_DEFAULT_COPY_MOVE_DELETE(X)    \
+  OCTAVE_DEFAULT_COPY_MOVE (X)                  \
+  ~X () = default;
+
+#  define OCTAVE_DEFAULT_CONSTRUCT_DELETE(X)    \
+  X () = default;                               \
+  ~X () = default;
+
+#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_DELETE(X)       \
+  OCTAVE_DEFAULT_CONSTRUCT_DELETE (X)                   \
+  OCTAVE_DEFAULT_COPY (X)                               \
+
+#  define OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE(X)  \
+  OCTAVE_DEFAULT_CONSTRUCT_DELETE (X)                   \
+  OCTAVE_DEFAULT_COPY_MOVE (X)
+
+#endif
+
 typedef OCTAVE_IDX_TYPE octave_idx_type;
 typedef OCTAVE_F77_INT_TYPE octave_f77_int_type;
 
--- a/scripts/+containers/Map.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/+containers/Map.m	Fri Jun 23 20:51:51 2023 +0200
@@ -217,7 +217,7 @@
         this.map = cell2struct (vals, keys);
       elseif (nargin == 4)
         for i = [1, 3]
-          switch (tolower (varargin{i}))
+          switch (lower (varargin{i}))
             case "keytype"
               this.KeyType = varargin{i+1};
             case "valuetype"
--- a/scripts/deprecated/disable_diagonal_matrix.m	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2021-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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{val} =} disable_diagonal_matrix ()
-## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val})
-## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val}, "local")
-##
-## @code{disable_diagonal_matrix} is deprecated and will be removed in Octave
-## version 9.  Use @code{optimize_diagonal_matrix} instead.
-##
-## Query or set whether storing diagonal matrices in a special space-efficient
-## format is disabled.
-##
-## The default value is false.  If this option is set to true, Octave will
-## store ranges as full matrices.
-##
-## When called from inside a function with the @qcode{"local"} option, the
-## setting is changed locally for the function and any subroutines it calls.
-## The original setting is restored when exiting the function.
-## @seealso{disable_diagonal_matrix, disable_permutation_matrix}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 9.
-
-function retval = disable_diagonal_matrix (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "disable_diagonal_matrix is obsolete and will be removed from a future version of Octave, please use optimize_diagonal_matrix instead\n");
-  endif
-
-  if (nargin == 0)
-    retval = ! optimize_diagonal_matrix ();
-  elseif (nargout == 0)
-    optimize_diagonal_matrix (! varargin{1}, varargin{2:end});
-  else
-    retval = ! optimize_diagonal_matrix (! varargin{1}, varargin{2:end});
-  endif
-
-endfunction
--- a/scripts/deprecated/disable_permutation_matrix.m	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2021-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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{val} =} disable_permutation_matrix ()
-## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val})
-## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val}, "local")
-##
-## @code{disable_permutation_matrix} is deprecated and will be removed in
-## Octave version 9.  Use @code{optimize_permutation_matrix} instead.
-##
-## Query or set whether storing permutation matrices in a special
-## space-efficient format is disabled.
-##
-## The default value is false.  If this option is set to true, Octave will
-## store ranges as full matrices.
-##
-## When called from inside a function with the @qcode{"local"} option, the
-## setting is changed locally for the function and any subroutines it calls.
-## The original setting is restored when exiting the function.
-## @seealso{disable_diagonal_matrix, disable_permutation_matrix}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 9.
-
-function retval = disable_permutation_matrix (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "disable_permutation_matrix is obsolete and will be removed from a future version of Octave, please use optimize_permutation_matrix instead\n");
-  endif
-
-  if (nargin == 0)
-    retval = ! optimize_permutation_matrix ();
-  elseif (nargout == 0)
-    optimize_permutation_matrix (! varargin{1}, varargin{2:end});
-  else
-    retval = ! optimize_permutation_matrix (! varargin{1}, varargin{2:end});
-  endif
-
-endfunction
--- a/scripts/deprecated/disable_range.m	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2021-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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{val} =} disable_range ()
-## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val})
-## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val}, "local")
-##
-## @code{disable_range} is deprecated and will be removed in Octave version 9.
-## Use @code{optimize_range} instead.
-##
-## Query or set whether storing ranges in a special space-efficient format is
-## disabled.
-##
-## The default value is false.  If this option is set to true, Octave will
-## store ranges as full matrices.
-##
-## When called from inside a function with the @qcode{"local"} option, the
-## setting is changed locally for the function and any subroutines it calls.
-## The original setting is restored when exiting the function.
-## @seealso{disable_diagonal_matrix, disable_permutation_matrix}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 9.
-
-function retval = disable_range (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "disable_range is obsolete and will be removed from a future version of Octave, please use optimize_range instead\n");
-  endif
-
-  if (nargin == 0)
-    retval = ! optimize_range ();
-  elseif (nargout == 0)
-    optimize_range (! varargin{1}, varargin{2:end});
-  else
-    retval = ! optimize_range (! varargin{1}, varargin{2:end});
-  endif
-
-endfunction
--- a/scripts/deprecated/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/deprecated/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -2,9 +2,6 @@
 
 %canon_reldir%_FCN_FILES = \
   %reldir%/.oct-config \
-  %reldir%/disable_diagonal_matrix.m \
-  %reldir%/disable_permutation_matrix.m \
-  %reldir%/disable_range.m \
   %reldir%/shift.m \
   %reldir%/sparse_auto_mutate.m
 
--- a/scripts/general/idivide.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/idivide.m	Fri Jun 23 20:51:51 2023 +0200
@@ -81,7 +81,7 @@
   if (nargin == 2)
     op = "fix";
   else
-    op = tolower (op);
+    op = lower (op);
   endif
 
   if (! isinteger (A) && ! isinteger (B))
--- a/scripts/general/integral.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/integral.m	Fri Jun 23 20:51:51 2023 +0200
@@ -171,7 +171,7 @@
         error ("integral: property PROP must be a string");
       endif
 
-      switch (tolower (prop))
+      switch (lower (prop))
         case "reltol"
           reltol = varargin{idx++};
         case "abstol"
--- a/scripts/general/integral2.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/integral2.m	Fri Jun 23 20:51:51 2023 +0200
@@ -168,7 +168,7 @@
       error ("integral2: property PROP must be a string");
     endif
 
-    switch (tolower (prop))
+    switch (lower (prop))
       case "abstol"
         abstol = varargin{idx++};
         if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))
@@ -182,7 +182,7 @@
         endif
 
       case "method"
-        method = tolower (varargin{idx++});
+        method = lower (varargin{idx++});
         if (! any (strcmp (method, {"auto", "iterated", "tiled"})))
           error ("integral2 : unrecognized method '%s'", method);
         endif
--- a/scripts/general/integral3.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/integral3.m	Fri Jun 23 20:51:51 2023 +0200
@@ -179,7 +179,7 @@
       error ("integral3: property PROP must be a string");
     endif
 
-    switch (tolower (prop))
+    switch (lower (prop))
       case "abstol"
         abstol = varargin{idx++};
         if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))
@@ -193,7 +193,7 @@
         endif
 
       case "method"
-        method = tolower (varargin{idx++});
+        method = lower (varargin{idx++});
         if (! any (strcmp (method, {"auto", "iterated", "tiled"})))
           error ("integral3 : unrecognized method '%s'", method);
         endif
--- a/scripts/general/interp1.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/interp1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -133,7 +133,7 @@
     for i_arg = 1:length (varargin)
       arg = varargin{i_arg};
       if (ischar (arg))
-        arg = tolower (arg);
+        arg = lower (arg);
         switch (arg)
           case "extrap"
             extrap = "extrap";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/isuniform.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,129 @@
+########################################################################
+##
+## Copyright (C) 2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## 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{tf} =} isuniform (@var{v})
+## @deftypefnx {} {[@var{tf}, @var{delta}] =} isuniform (@var{v})
+## Return true if the real vector @var{v} is uniformly spaced and false
+## otherwise.
+##
+## A vector is uniform if the mean difference (@var{delta}) between all
+## elements is the same to within a tolerance of
+## @w{@code{4 * eps (max (abs (@var{v})))}}.
+##
+## The optional output @var{delta} is the uniform difference between elements.
+## If the vector is not uniform then @var{delta} is @code{NaN}.  @var{delta}
+## is of the same class as @var{v} for floating point inputs and of class
+## double for integer, logical, and character inputs.
+##
+## Programming Notes: The output is always false for the special cases of an
+## empty input or a scalar input.  If any element is @code{NaN} then the output
+## is false.  If @var{delta} is smaller than the calculated relative tolerance
+## then an absolute tolerance of @code{eps} is used.
+##
+## @seealso{linspace, colon}
+## @end deftypefn
+
+function [tf, delta] = isuniform (v)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (! (isreal (v) && (isvector (v) || isempty (v))))
+    error ("isuniform: V must be a real vector");
+  endif
+
+  if (! isfloat (v))
+    v = double (v);  # char, logical, integer inputs converted to double
+  endif
+
+  ## Handle special corner cases
+  if (isempty (v) || isscalar (v))
+    tf = false;
+    delta = NaN (class (v));
+    return;
+  endif
+
+  ## Compare mean delta to individual deltas with a tolerance
+  d = diff (v, 1);
+  delta = mean (d);
+  if (isnan (delta))
+    tf = false;
+  else
+    tol = 4 * eps (max (abs (v)));
+    if (delta < tol)
+      ## Switch to absolute tolerance for very small delta
+      tol = eps (class (v));
+    endif
+    tf = ! any (abs (d - delta) > tol);
+    if (! tf)
+      delta = NaN (class (v));
+    endif
+  endif
+
+endfunction
+
+
+%!assert (isuniform ([]), false)                  # empty input
+%!assert (isuniform (zeros (1,2,0,4)), false)     # empty input
+%!assert (isuniform (1), false)                   # scalar input
+%!assert (isuniform (1:5), true)
+%!assert (isuniform (int8 (1:3:10)), true)
+%!assert (isuniform ([false false false]), true)
+%!assert (isuniform (['A', 'C', 'E']), true)
+
+## Test return class of step
+%!test
+%! [tf, delta] = isuniform (single (10:-1.5:1));
+%! assert (tf, true);
+%! assert (delta, single (-1.5));
+%! [tf, delta] = isuniform (single ([1 2 5 6]));
+%! assert (tf, false);
+%! assert (delta, single (NaN));
+
+%!test
+%! [tf, delta] = isuniform (int8 (1:3:15));
+%! assert (tf, true);
+%! assert (delta, double (3));
+%! [tf, delta] = isuniform (int8 ([1 2 5 6]));
+%! assert (tf, false);
+%! assert (delta, double (NaN));
+
+## Test for small delta smaller than tolerance
+%!test
+%! v = 1:eps:(1+8*eps);
+%! [tf, delta] = isuniform (v);
+%! assert (tf, true);
+%! assert (delta, eps);
+%! v(3) -= 2*eps;
+%! [tf, delta] = isuniform (v);
+%! assert (tf, false);
+%! assert (delta, NaN);
+
+## test input validation
+%!error <Invalid call> isuniform ()
+%!error <V must be a real vector> isuniform (magic (3))
+%!error <V must be a real vector> isuniform ({1, 2, 3})
--- a/scripts/general/logspace.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/logspace.m	Fri Jun 23 20:51:51 2023 +0200
@@ -130,15 +130,13 @@
 %!testif HAVE_LLVM_LIBCXX  <55538>
 %! assert (logspace (-Inf + 1i, Inf + 1i, 3),
 %!         [0, NaN + NaN * 1i, complex(-Inf, Inf)])
-%!assert (logspace (0, Inf, 3), [1, Inf, Inf])
-%!assert (logspace (0, -Inf, 3), [1, 0, 0])
+## Octave prefers to return NaN which indicates failure of algorithm.
+## Tests can be re-instated if full Matlab-compatibility is coded.
+%!#assert (logspace (0, Inf, 3), [1, Inf, Inf])
+%!#assert (logspace (0, -Inf, 3), [1, 0, 0])
 %!assert (logspace (Inf, -Inf, 3), [Inf, 1, 0])
-
-## FIXME: These are bizarre corner cases for Matlab compatibility.  See
-## bug #56933.  This is marked as "Won't Fix", but if linspace is updated at
-## some point then these tests can be re-instated.
-%!#assert (logspace (-Inf, 0, 3), [0, NaN, 1])
-%!#assert (logspace (Inf, 0, 3), [Inf, NaN, 1])
+%!assert (logspace (-Inf, 0, 3), [0, NaN, 1])
+%!assert (logspace (Inf, 0, 3), [Inf, NaN, 1])
 
 ## Test input validation
 %!error <Invalid call> logspace ()
--- a/scripts/general/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -44,6 +44,7 @@
   %reldir%/interpn.m \
   %reldir%/isequal.m \
   %reldir%/isequaln.m \
+  %reldir%/isuniform.m \
   %reldir%/logspace.m \
   %reldir%/nextpow2.m \
   %reldir%/num2str.m \
--- a/scripts/general/quad2d.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/quad2d.m	Fri Jun 23 20:51:51 2023 +0200
@@ -180,7 +180,7 @@
       error ("quad2d: property PROP must be a string");
     endif
 
-    switch (tolower (prop))
+    switch (lower (prop))
       case "abstol"
         abstol = varargin{idx++};
         if (! (isnumeric (abstol) && isscalar (abstol) && abstol >= 0))
--- a/scripts/general/quadgk.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/quadgk.m	Fri Jun 23 20:51:51 2023 +0200
@@ -203,7 +203,7 @@
           error ("quadgk: property PROP must be a string");
         endif
         prop = varargin{idx++};
-        switch (tolower (prop))
+        switch (lower (prop))
           case "reltol"
             reltol = varargin{idx++};
           case "abstol"
--- a/scripts/general/randi.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/randi.m	Fri Jun 23 20:51:51 2023 +0200
@@ -111,13 +111,13 @@
   ## Rejection Algorithm to guarantee unbiased results.  See bug #54619.
   rng = (imax - imin) + 1;              # requested range
   N = prod ([varargin{:}]);             # number of requested elements
-  K = floor ((flintmax () + 1) / rng);  # number of primary integers ...
+  K = floor (flintmax () / rng);        # number of primary integers ...
                                         # mapped to single output
-  p = (K*rng) / (flintmax () + 1);      # expected proportion of used primaries
+  p = (K*rng) / flintmax ();            # expected proportion of used primaries
 
   do
     M = ceil (N/p + 10*sqrt (N/p - N)); # number of requested primary integers
-    r_prim = floor (rand (M,1) * (flintmax () + 1));
+    r_prim = floor (rand (M,1) * flintmax ());
     r_prim = r_prim(r_prim < K*rng);
   until (numel (r_prim) >= N)           # should practically always be true
 
--- a/scripts/general/rng.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/general/rng.m	Fri Jun 23 20:51:51 2023 +0200
@@ -173,7 +173,7 @@
     error ("rng: GENERATOR must be a string");
   endif
 
-  gen = tolower (char (val));
+  gen = lower (char (val));
   if (any (strcmp (gen, {"simdtwister", "combrecursive", "philox", "threefry", "multfibonacci", "v4"})))
     error ('rng: random number generator "%s" is not available in Octave', gen);
   elseif (! any (strcmp (gen, {"twister", "v5uniform", "v5normal"})))
--- a/scripts/geometry/griddata.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/geometry/griddata.m	Fri Jun 23 20:51:51 2023 +0200
@@ -131,7 +131,7 @@
       elseif (! ischar (method))
         error ("griddata: METHOD must be a string");
       else
-        method = tolower (method);
+        method = lower (method);
       endif
 
       if (any (strcmp (method, {"linear", "nearest", "v4"})))
--- a/scripts/geometry/griddatan.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/geometry/griddatan.m	Fri Jun 23 20:51:51 2023 +0200
@@ -106,7 +106,7 @@
     elseif (! ischar (method))
       error ("griddatan: METHOD must be a string");
     else
-      method = tolower (method);
+      method = lower (method);
     endif
 
     if (strcmp (method, "linear") || strcmp (method, "nearest"))
--- a/scripts/geometry/tsearchn.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/geometry/tsearchn.m	Fri Jun 23 20:51:51 2023 +0200
@@ -26,15 +26,17 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{idx} =} tsearchn (@var{x}, @var{t}, @var{xi})
 ## @deftypefnx {} {[@var{idx}, @var{p}] =} tsearchn (@var{x}, @var{t}, @var{xi})
-## Search for the enclosing Delaunay convex hull.
+## Find the simplexes enclosing the given points.
 ##
-## For @code{@var{t} = delaunayn (@var{x})}, finds the index in @var{t}
-## containing the points @var{xi}.  For points outside the convex hull,
-## @var{idx} is NaN.
+## @code{tsearchn} is typically used with @code{delaunayn}:
+## @code{@var{t} = delaunayn (@var{x})} returns a set of simplexes @code{t},
+## then @code{tsearchn} returns the row index of @var{t} containing each point
+## of @var{xi}.  For points outside the convex hull, @var{idx} is NaN.
 ##
-## If requested @code{tsearchn} also returns the Barycentric coordinates
-## @var{p} of the enclosing triangles.
-## @seealso{delaunay, delaunayn}
+## If requested, @code{tsearchn} also returns the barycentric coordinates
+## @var{p} of the enclosing simplexes.
+##
+## @seealso{delaunay, delaunayn, tsearch}
 ## @end deftypefn
 
 function [idx, p] = tsearchn (x, t, xi)
@@ -43,57 +45,53 @@
     print_usage ();
   endif
 
+  if (columns (x) != columns (xi))
+    error ("tsearchn: number of columns of X and XI must match");
+  endif
+
+  if (max (t(:)) > rows (x))
+    error ("tsearchn: triangulation T must not access points outside X");
+  endif
+
+  if (nargout <= 1 && columns (x) == 2)  # pass to the faster tsearch.cc
+    idx = tsearch (x(:,1), x(:,2), t, xi(:,1), xi(:,2));
+    return;
+  endif
+
   nt = rows (t);
   [m, n] = size (x);
   mi = rows (xi);
   idx = NaN (mi, 1);
   p = NaN (mi, n + 1);
-
   ni = [1:mi].';
-  for i = 1 : nt
-    ## Only calculate the Barycentric coordinates for points that have not
-    ## already been found in a triangle.
-    b = cart2bary (x (t (i, :), :), xi(ni,:));
 
-    ## Our points xi are in the current triangle if
-    ## (all (b >= 0) && all (b <= 1)).  However as we impose that
-    ## sum (b,2) == 1 we only need to test all(b>=0).  Note need to add
-    ## a small margin for rounding errors
-    intri = all (b >= -1e-12, 2);
-    idx(ni(intri)) = i;
-    p(ni(intri),:) = b(intri, :);
-    ni(intri) = [];
-  endfor
+  for i = 1 : nt  # each simplex in turn
 
-endfunction
-
-function Beta = cart2bary (T, P)
+    T = x(t(i, :), :);  # T is the current simplex
+    P = xi(ni, :);      # P is the set of points left to calculate
 
-  ## Conversion of Cartesian to Barycentric coordinates.
-  ## Given a reference simplex in N dimensions represented by an
-  ## N+1-by-N matrix, an arbitrary point P in Cartesian coordinates,
-  ## represented by an N-by-1 column vector can be written as
-  ##
-  ## P = Beta * T
-  ##
-  ## Where Beta is an N+1 vector of the barycentric coordinates.  A criteria
-  ## on Beta is that
-  ##
-  ## sum (Beta) == 1
-  ##
-  ## and therefore we can write the above as
-  ##
-  ## P - T(end, :) = Beta(1:end-1) * (T(1:end-1,:) - ones (N,1) * T(end,:))
-  ##
-  ## and then we can solve for Beta as
-  ##
-  ## Beta(1:end-1) = (P - T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:))
-  ## Beta(end) = sum (Beta)
-  ##
-  ## Note code below is generalized for multiple values of P, one per row.
-  [M, N] = size (P);
-  Beta = (P - ones (M,1) * T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:));
-  Beta (:,end+1) = 1 - sum (Beta, 2);
+    ## Convert to barycentric coords: these are used to express a point P
+    ## as    P = Beta * T
+    ## where T is a simplex.
+    ##
+    ## If 0 <= Beta <= 1, then the linear combination is also convex,
+    ## and the point P is inside the simplex T, otherwise it is outside.
+    ## Since the equation system is underdetermined, we apply the constraint
+    ## sum (Beta) == 1  to make it unique up to scaling.
+    ##
+    ## Note that the code below is vectorized over P, one point per row.
+
+    b = (P - T(end,:)) / (T(1:end-1,:) - T(end,:));
+    b(:, end+1) = 1 - sum (b, 2);
+
+    ## The points xi are inside the current simplex if
+    ## (all (b >= 0) && all (b <= 1)).  As sum (b,2) == 1, we only need to
+    ## test all(b>=0).
+    inside = all (b >= -1e-12, 2);  # -1e-12 instead of 0 for rounding errors
+    idx(ni(inside)) = i;
+    p(ni(inside), :) = b(inside, :);
+    ni = ni(! inside);
+  endfor
 
 endfunction
 
@@ -121,3 +119,10 @@
 %! [idx, p] = tsearchn (x,tri,[1,1]);
 %! assert (idx, NaN);
 %! assert (p, [NaN, NaN, NaN]);
+
+## Test input validation
+%!error <Invalid call> tsearchn ()
+%!error <Invalid call> tsearchn (1)
+%!error <Invalid call> tsearchn (1, 2)
+%!error <number of columns of X and XI must match> tsearchn ([1,2], 3, 4)
+%!error <T must not access points outside X> tsearchn (1, 2, 3)
--- a/scripts/gui/listdlg.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/gui/listdlg.m	Fri Jun 23 20:51:51 2023 +0200
@@ -115,7 +115,7 @@
     if (strcmpi (varargin{i}, "ListString"))
       listcell = varargin{i+1};
     elseif (strcmpi (varargin{i}, "SelectionMode"))
-      selmode = tolower (varargin{i+1});
+      selmode = lower (varargin{i+1});
     elseif (strcmpi (varargin{i}, "ListSize"))
       listsize = varargin{i+1};
     elseif (strcmpi (varargin{i}, "InitialValue"))
--- a/scripts/gui/movegui.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/gui/movegui.m	Fri Jun 23 20:51:51 2023 +0200
@@ -159,7 +159,7 @@
     fpos(1) = ifelse (pos(1) >= 0, pos(1), pos(1) + x(3));
     fpos(2) = ifelse (pos(2) >= 0, pos(2), pos(2) + y(3));
   elseif (ischar (pos))
-    switch (tolower (pos))
+    switch (lower (pos))
       case "north"
         fpos(1:2) = [x(2), y(3)];
       case "south"
--- a/scripts/gui/private/__file_filter__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/gui/private/__file_filter__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -94,7 +94,7 @@
   if (isempty (name))
     extlist = ostrsplit (filterext, ";");
     extlist = strrep (extlist, "*.", "");
-    extlist = toupper (extlist);
+    extlist = upper (extlist);
     extlist(end+1, :) = repmat ({","}, 1, length (extlist));
     extlist = strcat (extlist{:});
     extlist = extlist(1:end-1);
--- a/scripts/gui/uigetfile.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/gui/uigetfile.m	Fri Jun 23 20:51:51 2023 +0200
@@ -173,7 +173,7 @@
         if (! ischar (val))
           error ('uigetfile: MultiSelect value must be a string ("on"/"off")');
         endif
-        outargs{4} = tolower (val);
+        outargs{4} = lower (val);
       else
         error ("uigetfile: unknown argument '%s'", prop);
       endif
--- a/scripts/gui/uisetfont.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/gui/uisetfont.m	Fri Jun 23 20:51:51 2023 +0200
@@ -110,7 +110,7 @@
   ## Populate fontstruct
   persistent defstruct = [];
   if (isempty (defstruct))
-    factory_fields = strcat ("factorytext", tolower (fontfields));
+    factory_fields = strcat ("factorytext", lower (fontfields));
     values = get (0, factory_fields);
     defstruct = struct ([fontfields; values]{:});
   endif
--- a/scripts/help/__unimplemented__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/help/__unimplemented__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -548,7 +548,7 @@
                  fcn, name);
 
   [~, status] = pkg ("describe", name);
-  switch (tolower (status{1}))
+  switch (lower (status{1}))
     case "loaded",
       for i = 1:length (classes)
         cls = classes{i};
--- a/scripts/help/type.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/help/type.m	Fri Jun 23 20:51:51 2023 +0200
@@ -97,8 +97,9 @@
       if (quiet)
         txt = contents;
       else
-        txt = sprintf ("%s is the user-defined function defined from: %s\n\n%s",
-                        name, file, contents);
+        tmp = __which__ (name);
+        txt = sprintf ("%s is the %s defined from: %s\n\n%s",
+                        name, tmp.type, file, contents);
       endif
     elseif (e == 3)
       txt = sprintf ("%s is a dynamically-linked function", name);
@@ -144,7 +145,7 @@
 %!test
 %! txt = type ("ls");
 %! typestr = txt{1}(1:31);
-%! assert (typestr, "ls is the user-defined function");
+%! assert (typestr, "ls is the function defined from");
 
 %!test
 %! txt = type ("ls", "-q");
--- a/scripts/help/warning_ids.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/help/warning_ids.m	Fri Jun 23 20:51:51 2023 +0200
@@ -410,6 +410,12 @@
 ## string constant.
 ## By default, the @code{Octave:single-quote-string} warning is disabled.
 ##
+## @item Octave:sparse:double-conversion
+## If the @code{Octave:sparse:double-conversion} warning is enabled, a warning
+## is printed when an implicit conversion from a full, single array occurs
+## during the creation of a sparse array.
+## By default, the @code{Octave:sparse:double-conversion} warning is enabled.
+##
 ## @item Octave:sqrtm:SingularMatrix
 ## If the @code{Octave:sqrtm:SingularMatrix} warning is enabled, a warning is
 ## printed if the matrix square root function @code{sqrtm} is called with an
@@ -459,5 +465,5 @@
 endfunction
 
 
-## Mark file as tested.  No test needed for a documentation m-file.
+## Mark file as tested.  No tests needed for a documentation m-file.
 %!assert (1)
--- a/scripts/image/colormap.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/colormap.m	Fri Jun 23 20:51:51 2023 +0200
@@ -106,7 +106,7 @@
   if (nargin == 1)
     map = varargin{1};
     if (ischar (map))
-      map = tolower (map);
+      map = lower (map);
       if (strcmp (map, "default"))
         map = viridis (64);
       else
--- a/scripts/image/getframe.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/getframe.m	Fri Jun 23 20:51:51 2023 +0200
@@ -167,8 +167,9 @@
 %! image (frame.cdata);
 %! title ("Lower left hand corner");
 
-%!testif HAVE_QT_OFFSCREEN; have_window_system () && strcmp ("qt", graphics_toolkit ())
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", graphics_toolkit ()))
 %! hf = figure ("visible", "off");
+%! graphics_toolkit (hf, "qt");
 %! unwind_protect
 %!   pos = get (hf, "position");
 %!   assert (size (getframe (hf).cdata)(1:2), pos(4:-1:3));
@@ -176,8 +177,9 @@
 %!   close (hf);
 %! end_unwind_protect
 
-%!testif HAVE_QT_OFFSCREEN; have_window_system () && strcmp ("qt", graphics_toolkit ())
+%!testif HAVE_OPENGL, HAVE_QT; have_window_system () && any (strcmp ("qt", graphics_toolkit ()))
 %! hf = figure ("visible", "off");
+%! graphics_toolkit (hf, "qt");
 %! unwind_protect
 %!   hax = axes ("visible", "off", "position", [0 0 1 1]);
 %!   verts = [0 0; .5 0; 1 0; ...
--- a/scripts/image/imformats.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/imformats.m	Fri Jun 23 20:51:51 2023 +0200
@@ -89,7 +89,7 @@
       formats = arg1;
 
     elseif (ischar (arg1))
-      switch (tolower (arg1))
+      switch (lower (arg1))
         case "add",
           if (! isstruct (arg2))
             error ("imformats: FORMAT to %s must be a structure", arg1);
--- a/scripts/image/imshow.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/imshow.m	Fri Jun 23 20:51:51 2023 +0200
@@ -134,7 +134,7 @@
         error ("imshow: argument number %d is invalid", narg);
       endif
     elseif (ischar (arg))
-      switch (tolower (arg))
+      switch (lower (arg))
         case "border"
           warning ("imshow: border argument is not implemented");
           narg += 1;
--- a/scripts/image/private/__imread__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/private/__imread__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -91,7 +91,7 @@
   options.region = {1:1:info.rows, 1:1:info.columns};
 
   for idx = offset:2:(numel (varargin) - offset + 1)
-    switch (tolower (varargin{idx}))
+    switch (lower (varargin{idx}))
 
       case {"frames", "index"}
         ## Do nothing.  This option was already processed before the loop.
--- a/scripts/image/private/__imwrite__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/private/__imwrite__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -57,7 +57,7 @@
 
   for idx = 1:2:numel (param_list)
 
-    switch (tolower (param_list{idx}))
+    switch (lower (param_list{idx}))
 
       case "alpha"
         options.alpha = param_list{idx+1};
@@ -80,7 +80,7 @@
           error ("imwrite: value for %s option must be a string",
                  param_list{idx});
         endif
-        options.compression = tolower (options.compression);
+        options.compression = lower (options.compression);
         if (! any (strcmp (options.compression, {"none", "bzip", "fax3", ...
                                                  "fax4", "jpeg", "lzw", ...
                                                  "rle", "deflate"})))
@@ -115,7 +115,7 @@
         elseif (! iscell (options.disposalmethod))
           options.disposalmethod = {options.disposalmethod};
         endif
-        options.disposalmethod = tolower (options.disposalmethod);
+        options.disposalmethod = lower (options.disposalmethod);
         matches = ismember (options.disposalmethod,
                             {"donotspecify", "leaveinplace", ...
                              "restorebg", "restoreprevious"});
@@ -172,7 +172,7 @@
           error ('imwrite: value for %s option must be "append" or "overwrite"',
                  param_list{idx});
         endif
-        options.writemode = tolower (options.writemode);
+        options.writemode = lower (options.writemode);
 
       otherwise
         error ("imwrite: invalid PARAMETER '%s'", param_list{idx});
--- a/scripts/image/rgbplot.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/image/rgbplot.m	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,7 @@
     error ("rgbplot: STYLE must be a string");
   endif
 
-  switch (tolower (style))
+  switch (lower (style))
     case "profile"
       x = 1:rows (cmap);
       htmp = plot (x,cmap(:,1),"r", x,cmap(:,2),"g", x,cmap(:,3),"b");
--- a/scripts/io/fileread.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/io/fileread.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,12 +24,23 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{str} =} fileread (@var{filename})
+## @deftypefn  {} {@var{str} =} fileread (@var{filename})
+## @deftypefnx {} {@var{str} =} fileread (@var{filename}, @var{param}, @var{value}, @dots{})
 ## Read the contents of @var{filename} and return it as a string.
-## @seealso{fread, fscanf, importdata, textscan, type}
+##
+## @var{param}, @var{value} are optional pairs of parameters and values.  Valid
+## options are:
+##
+## @table @asis
+## @item @qcode{"Encoding"}
+## Specify encoding used when reading from the file.  This is a character
+## string of a valid encoding identifier.  The default is @qcode{"utf-8"}.
+## @end table
+##
+## @seealso{fopen, fread, fscanf, importdata, textscan, type}
 ## @end deftypefn
 
-function str = fileread (filename)
+function str = fileread (filename, varargin)
 
   if (nargin < 1)
     print_usage ();
@@ -39,7 +50,32 @@
     error ("fileread: FILENAME argument must be a string");
   endif
 
-  fid = fopen (filename, "r");
+  encoding = "utf-8";
+
+  if (nargin > 1)
+
+    ## Check for parameter/value arguments
+    for i_arg = 1:2:numel (varargin)
+
+      if (! ischar (varargin{i_arg}))
+        error ("fileread: parameter %d must be a string", i_arg);
+      endif
+      parameter = varargin{i_arg};
+      if (i_arg+1 > numel (varargin))
+        error ('fileread: parameter "%s" missing value', parameter);
+      endif
+
+      switch (lower (parameter))
+        case "encoding"
+          encoding = varargin{i_arg+1};
+        otherwise
+          error ('fileread: Unknown option "%s"', parameter);
+      endswitch
+
+    endfor
+  endif
+
+  fid = fopen (filename, "r", "n", encoding);
   if (fid < 0)
     error ("fileread: cannot open file");
   endif
@@ -66,3 +102,11 @@
 ## Test input validation
 %!error <Invalid call> fileread ()
 %!error <FILENAME argument must be a string> fileread (1)
+%!error <parameter "Encoding" missing value> fileread ("filename", "Encoding")
+%!error <Unknown option "UnknownParam">
+%! fileread ("filename", "UnknownParam", "UnknownValue")
+## FIXME: The following test should be skipped if
+##        OCTAVE_HAVE_STRICT_ENCODING_FACET is defined.
+%!testif ; ! __have_feature__ ("LLVM_LIBCXX")
+%! fail ('fileread ("filename", "Encoding", "UnknownValue")', ...
+%!       "conversion from codepage 'unknownvalue' not supported");
--- a/scripts/java/javaclasspath.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/java/javaclasspath.m	Fri Jun 23 20:51:51 2023 +0200
@@ -81,7 +81,7 @@
     if (! nargin)
       what = "-all";
     endif
-    switch (tolower (what))
+    switch (lower (what))
       case "-dynamic", disp_path_list ("DYNAMIC", dynamic_path_list);
       case "-static",  disp_path_list ("STATIC", static_path_list);
       case "-all"
@@ -100,7 +100,7 @@
       path1 = cellstr (dynamic_path_list);
       path2 = cellstr (static_path_list);
     else
-      switch (tolower (what))
+      switch (lower (what))
         case "-all",     path1 = cellstr ([static_path_list,dynamic_path_list]);
         case "-dynamic", path1 = cellstr (dynamic_path_list);
         case "-static",  path1 = cellstr (static_path_list);
--- a/scripts/legacy/genvarname.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/legacy/genvarname.m	Fri Jun 23 20:51:51 2023 +0200
@@ -149,7 +149,7 @@
     str{i}(! (isalnum (str{i}) | str{i} == "_")) = "_";
     ## do not use keywords
     if (iskeyword (str{i}))
-      firstcharacter = toupper (str{i}(1));
+      firstcharacter = upper (str{i}(1));
       str{i} = ["x", firstcharacter, str{i}(2:end)];
     endif
     ## The variable cannot be empty
--- a/scripts/linear-algebra/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/linear-algebra/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -35,6 +35,7 @@
   %reldir%/rref.m \
   %reldir%/subspace.m \
   %reldir%/trace.m \
+  %reldir%/tensorprod.m \
   %reldir%/vech.m \
   %reldir%/vecnorm.m
 
--- a/scripts/linear-algebra/ordeig.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/linear-algebra/ordeig.m	Fri Jun 23 20:51:51 2023 +0200
@@ -127,11 +127,11 @@
 %!test
 %! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);
 %! B = toeplitz ([0, 0, 0, 1], [0, -1, 0, 2]);
-%! [AA, BB] = qz (A, B);
+%! [AA, BB] = qz (A, B, 'real');
 %! assert (isreal (AA) && isreal (BB));
 %! lambda = ordeig (AA, BB);
 %! assert (lambda, [0.5+0.86603i; 0.5-0.86603i; i; -i], 1e-4);
-%! [AA, BB] = qz (complex (A), complex (B));
+%! [AA, BB] = qz (A, B, 'complex');
 %! assert (iscomplex (AA) && iscomplex (BB));
 %! lambda = ordeig (AA, BB);
 %! assert (lambda, diag (AA) ./ diag (BB));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/tensorprod.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,441 @@
+########################################################################
+##
+## Copyright (C) 2022-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## 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{C} =} tensorprod (@var{A}, @var{B}, @var{dimA}, @var{dimB})
+## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dim})
+## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B})
+## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, "all")
+## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @dots{}, "NumDimensionsA", @var{value})
+## Compute the tensor product between numeric tensors @var{A} and @var{B}.
+##
+## The dimensions of @var{A} and @var{B} that are contracted are defined by
+## @var{dimA} and @var{dimB}, respectively.  @var{dimA} and @var{dimB} are
+## scalars or equal length vectors that define the dimensions to match up.
+## The matched dimensions of @var{A} and @var{B} must have the same number of
+## elements.
+##
+## When only @var{dim} is used, it is equivalent to
+## @code{@var{dimA} = @var{dimB} = @var{dim}}.
+##
+## When no dimensions are specified, @code{@var{dimA} = @var{dimB} = []}.  This
+## computes the outer product between @var{A} and @var{B}.
+##
+## Using the @qcode{"all"} option results in the inner product between @var{A}
+## and @var{B}.  This requires @code{size (@var{A}) == size (@var{B})}.
+##
+## Use the property-value pair with the property name @qcode{"NumDimensionsA"}
+## when @var{A} has trailing singleton dimensions that should be transferred to
+## @var{C}.  The specified @var{value} should be the total number of dimensions
+## of @var{A}.
+##
+## Matlab Compatibility: Octave does not currently support the
+## @qcode{"@var{property_name}=@var{value}"} syntax for the
+## @qcode{"NumDimensionsA"} parameter.
+##
+## @seealso{kron, dot, mtimes}
+## @end deftypefn
+
+function C = tensorprod (A, B, varargin)
+
+  ## FIXME: shortcut code paths could be added for trivial cases, such as if
+  ##        either A or B are a scalars, null, identity tensors, etc.
+
+  if (nargin < 2 || nargin > 6)
+    print_usage ();
+  endif
+
+  ## Check that A and B are single or double
+  if (! isfloat (A))
+    error ("tensorprod: A must be a single or double precision array");
+  endif
+
+  if (! isfloat (B))
+    error ("tensorprod: B must be a single or double precision array");
+  endif
+
+  ## Check for misplaced NumDimensionsA property
+  NumDimensionsA = 0;
+  if (nargin > 2)
+    if (strcmpi (varargin{end}, "NumDimensionsA"))
+      error (["tensorprod: a value for the NumDimensionsA property must ", ...
+              "be provided"]);
+    elseif (strncmpi (arg = inputname (nargin, false), "NumDimensionsA", 13))
+      error ("tensorprod: NumDimensionsA=VALUE syntax is unsupported.  Use syntax 'NumDimensionsA', VALUE");
+    endif
+  endif
+  ## Check for NumDimensionsA property
+  if (nargin > 3)
+    if (strcmpi (varargin{end-1}, "NumDimensionsA"))
+      if (! (isnumeric (varargin{end}) && isscalar (varargin{end})))
+        error (["tensorprod: value for NumDimensionsA must be a ", ...
+                "numeric scalar"]);
+      elseif (! isindex (varargin{end}))
+        error (["tensorprod: value for NumDimensionsA must be a ", ...
+                "positive integer"]);
+      endif
+      NumDimensionsA = varargin{end};
+      nargin = nargin - 2;
+    endif
+  endif
+
+  ndimargs = nargin - 2;
+
+  ## Set dimA and dimB
+  if (ndimargs == 0)
+    ## Calling without dimension arguments
+    dimA = [];
+    dimB = [];
+  elseif (ndimargs == 1)
+    ## Calling with dim or "all" option
+    if (isnumeric (varargin{1}))
+      if (! (isvector (varargin{1}) || isnull (varargin{1})))
+        error ("tensorprod: dim must be a numeric vector of integers or []");
+      endif
+      ## Calling with dim
+      dimA = varargin{1}(:).';  # Reshape to row vector
+    elseif (ischar (varargin{1}))
+      if (strcmpi (varargin{1}, "all"))
+        if (! size_equal (A, B))
+          error (["tensorprod: size of A and B must be identical when ", ...
+                  "using the 'all' option"]);
+        endif
+      else
+        error ("tensorprod: unknown option '%s'", varargin{1});
+      endif
+      ## Calling with "all" option
+      dimA = 1:ndims(A);
+    else
+      error (["tensorprod: third argument must be a numeric vector of ", ...
+              "integers, [], or 'all'"]);
+    endif
+    dimB = dimA;
+  elseif (ndimargs == 2)
+    ## Calling with dimA and dimB
+    if (! (isnumeric (varargin{1}) && (isvector (varargin{1}) || ...
+        isnull (varargin{1}))))
+      error("tensorprod: dimA must be a numeric vector of integers or []");
+    endif
+
+    if (! (isnumeric (varargin{2}) && (isvector (varargin{2}) || ...
+        isnull (varargin{2}))))
+      error ("tensorprod: dimB must be a numeric vector of integers or []");
+    endif
+
+    if (numel (varargin{1}) != numel (varargin{2}))
+      error (["tensorprod: an equal number of dimensions must be ", ...
+              "matched for A and B"]);
+    endif
+    dimA = varargin{1}(:).';  # Reshape to row vector
+    dimB = varargin{2}(:).';
+  else
+    ## Something is wrong - try to find the error
+    for i = 1:ndimargs
+      if (ischar (varargin{i}))
+        if (strcmpi (varargin{i}, "NumDimensionsA"))
+          error ("tensorprod: misplaced 'NumDimensionsA' option");
+        elseif (strcmpi (varargin{i}, "all"))
+          error ("tensorprod: misplaced 'all' option");
+        else
+          error ("tensorprod: unknown option '%s'", varargin{i});
+        endif
+      elseif (! isnumeric (varargin{i}))
+        error (["tensorprod: optional arguments must be numeric vectors ", ...
+                "of integers, [], 'all', or 'NumDimensionsA'"]);
+      endif
+    endfor
+    error ("tensorprod: too many dimension inputs given");
+  endif
+
+  ## Check that dimensions are positive integers ([] will also pass)
+  if (! isindex (dimA) || ! isindex (dimB))
+    error ("tensorprod: dimensions must be positive integers");
+  endif
+
+  ## Check that the length of matched dimensions are equal
+  if (any (size (A, dimA) != size (B, dimB)))
+    error (["tensorprod: matched dimensions of A and B must have the ", ...
+            "same lengths"]);
+  endif
+
+  ## Find size and ndims of A and B
+  ndimsA = max ([ndims(A), max(dimA)]);
+  sizeA = size (A, 1:ndimsA);
+  ndimsB = max ([ndims(B), max(dimB)]);
+  sizeB = size (B, 1:ndimsB);
+
+  ## Take NumDimensionsA property into account
+  if (NumDimensionsA)
+    if (NumDimensionsA < ndimsA)
+      if (ndimargs == 1)
+        error (["tensorprod: highest dimension of dim must be less than ", ...
+                "or equal to NumDimensionsA"]);
+      elseif (ndimargs == 2)
+        error (["tensorprod: highest dimension of dimA must be less ", ...
+                "than or equal to NumDimensionsA"]);
+      else
+        error (["tensorprod: NumDimensionsA cannot be smaller than the ", ...
+                "number of dimensions of A"]);
+      endif
+    elseif (NumDimensionsA > ndimsA)
+      sizeA = [sizeA, ones(1, NumDimensionsA - ndimsA)];
+      ndimsA = NumDimensionsA;
+    endif
+  endif
+
+  ## Interchange the dimension to sum over the end of A and the front of B
+  ## Prepare for A
+  remainDimA = [1:ndimsA];
+  remainDimA(dimA) = [];   # Dimensions of A to keep
+  newDimOrderA = [remainDimA, dimA]; # New dim order [to_keep, to_contract]
+  newSizeA = [prod(sizeA(remainDimA)), prod(sizeA(dimA))]; # Temp. 2D size for A
+
+  ## Prepare for B (See comments for A.  Note that in principle,
+  ## prod (sizeB (dimB)) should always be equal to prod (sizeA (dimA)).  May
+  ## be able to optimize further here.
+  remainDimB = [1:ndimsB];
+  remainDimB(dimB) = [];   # Dimensions of B to keep
+  newDimOrderB = [remainDimB, dimB];
+  newSizeB = [prod(sizeB(remainDimB)), prod(sizeB(dimB))];
+
+  ## Do reshaping into 2D array
+  newA = reshape (permute (A, newDimOrderA), newSizeA);
+  newB = reshape (permute (B, newDimOrderB), newSizeB);
+
+  ## Compute
+  C = newA * newB.';
+
+  ## If not an inner product, reshape back to tensor
+  if (! isscalar (C))
+    ## Contribution to size of C from remaining A dims
+    remainSizeA = sizeA(remainDimA);
+    remainSizeB = sizeB(remainDimB);
+    C = reshape (C, [remainSizeA, remainSizeB]);
+  endif
+
+endfunction
+
+
+%!assert (tensorprod (2, 3), 6)
+%!assert (tensorprod (2, 3, 1), 6)
+%!assert (tensorprod (2, 3, 2), 6)
+%!assert (tensorprod (2, 3, 10), 6)
+%!assert (tensorprod (2, 3, [1 2]), 6)
+%!assert (tensorprod (2, 3, [1 10]), 6)
+%!assert (tensorprod (2, 3, []), 6)
+%!assert (tensorprod (2, 3, 2, 1), 6)
+%!assert (tensorprod (2, 3, [], []), 6)
+
+%!shared v1, v2, M1, M2, T
+%! v1 = [1, 2];
+%! M1 = [1, 2; 3, 4];
+%! M2 = [1, 2; 3, 4; 5, 6];
+%! T = cat (3, M2, M2);
+
+%!assert (tensorprod (3, v1), reshape ([3, 6], [1, 1, 1, 2]))
+%!assert (tensorprod (v1, 3), [3, 6])
+%!assert (tensorprod (v1, v1, "all"), 5)
+%!assert (tensorprod (v1, v1), reshape ([1, 2, 2, 4], [1, 2, 1, 2]))
+%!assert (tensorprod (v1, v1, 1), [1, 2; 2, 4])
+%!assert (tensorprod (v1, v1, 2), 5)
+%!assert (tensorprod (v1, v1, 3), reshape ([1, 2, 2, 4], [1, 2, 1, 2]))
+%!assert (tensorprod (v1, v1, 5), reshape ([1, 2, 2, 4], [1, 2, 1, 1, 1, 2]))
+
+%!assert (tensorprod (M1, v1), cat (4, [1,2;3,4], [2,4;6,8]))
+%!assert (tensorprod (M1, v1'), cat (3, [1,2;3,4], [2,4;6,8]))
+%!assert (tensorprod (v1, M1), reshape ([1 2 3 6 2 4 4 8], [1,2,2,2]))
+%!assert (tensorprod (v1', M1), reshape ([1 2 3 6 2 4 4 8], [2,1,2,2]))
+%!assert (tensorprod (M1, v1', 2, 1), [5; 11])
+%!assert (tensorprod (M1, v1', 4, 4), cat(4, M1, 2*M1))
+%!assert (tensorprod (M1, v1', [1, 3]), [7; 10])
+%!assert (tensorprod (M1, v1', [1, 3], [1, 3]), [7; 10])
+%!assert (tensorprod (M1, v1', [2, 3], [1, 3]), [5; 11])
+%!assert (tensorprod (M1, v1', [2; 3], [1; 3]), [5; 11])
+%!assert (tensorprod (M1, v1', [2; 3], [1, 3]), [5; 11])
+%!assert (tensorprod (M1, v1', [2, 3], [1; 3]), [5; 11])
+%!assert (tensorprod (M1, v1', [], []), cat (3, M1, 2*M1))
+%!assert (tensorprod (M1, M1, "all"), 30)
+%!assert (tensorprod (M1, M1, 1), [10, 14; 14, 20])
+%!assert (tensorprod (M1, M1, 2), [5, 11; 11, 25])
+%!assert (tensorprod (M1, M2, 2), [5, 11, 17; 11, 25, 39])
+%!assert (tensorprod (M1, M2, 1, 2), [7, 15, 23; 10, 22, 34])
+%!assert (tensorprod (M1, M2), reshape ([1,3,2,4,3,9,6,12,5,15,10,20,2,6,4, ...
+%!                                      8,4,12,8,16,6,18,12,24], [2,2,3,2]))
+
+%!assert (tensorprod (T, M1),
+%!        reshape([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,2, ...
+%!                6,10,4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24],
+%!                [3,2,2,2,2]))
+%!assert (tensorprod (T, M1, 2),
+%!        cat (3, [5, 5; 11 11; 17, 17], [11, 11; 25, 25; 39, 39]))
+%!assert (tensorprod (T, M2, 1), cat (3, [35, 35; 44, 44], [44, 44; 56, 56]))
+%!assert (tensorprod (T, M2, 2), cat (3, [5, 5; 11, 11; 17, 17],
+%!                     [11,11;25,25;39,39], [17, 17; 39, 39; 61, 61]))
+%!assert (tensorprod (T, T, "all"), 182)
+%!assert (tensorprod (T, T, 1),
+%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],
+%!                 [2,2,2,2]))
+%!assert (tensorprod (T, T, 2),
+%!        reshape ([5,11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61,5, ...
+%!                 11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61],
+%!                 [3,2,3,2]))
+%!assert (tensorprod (T, T, 3),
+%!        reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ...
+%!                 20,8,16,24,8,24,40,16,32,48,12,36,60,24,48,72], [3,2,3,2]));
+%!assert (tensorprod (T, T, 10),
+%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ...
+%!                 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ...
+%!                 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ...
+%!                 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ...
+%!                 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ...
+%!                 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ...
+%!                 18,30,12,24,36,6,18,30,12,24,36],
+%!                 [3,2,2,1,1,1,1,1,1,3,2,2]))
+%!assert (tensorprod (T, T, []),
+%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ...
+%!                 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ...
+%!                 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ...
+%!                 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ...
+%!                 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ...
+%!                 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ...
+%!                 18,30,12,24,36,6,18,30,12,24,36],
+%!                 [3,2,2,3,2,2]))
+%!assert (tensorprod (T, T, 2, 3),
+%!        reshape ([3,7,11,3,7,11,9,21,33,9,21,33,15,35,55,15,35,55,6,14, ...
+%!                 22,6,14,22,12,28,44,12,28,44,18,42,66,18,42,66],
+%!                 [3,2,3,2]))
+%!assert (tensorprod (T, T(1:2, 1:2, :), [2, 3],[1, 3]),
+%!        [14, 20; 30, 44; 46, 68])
+%!assert (tensorprod (T, T(1:2, 1:2, :), [3, 2],[1, 3]),
+%!        [12, 18; 28, 42; 44, 66])
+%!assert (tensorprod (T, reshape (T, [2, 2, 3]), 2, 1),
+%!        reshape ([7,15,23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56,7,15, ...
+%!                 23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56],
+%!                 [3,2,2,3]))
+%!assert (tensorprod (T, T, [1, 3]), [70, 88; 88, 112])
+%!assert (tensorprod (T, T, [1, 3]), tensorprod (T, T, [3, 1]))
+%!assert (tensorprod (T, reshape (T, [2, 2, 3]), [2, 3], [1, 2]),
+%!        [16, 23, 25; 38, 51, 59; 60, 79, 93])
+
+## NumDimensionsA tests
+%!assert (tensorprod (v1, v1, "NumDimensionsA", 2),
+%!        reshape ([1, 2, 2, 4], [1, 2, 1, 2]));
+%!assert (tensorprod (v1, v1, "numdimensionsa", 2),
+%!        tensorprod (v1, v1, "NumDimensionsA", 2));
+%!assert (tensorprod (v1, v1, "NumDimensionsA", 3),
+%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));
+%!assert (tensorprod (v1, v1, [], "NumDimensionsA", 3),
+%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));
+%!assert (tensorprod (v1, v1, [], [], "NumDimensionsA", 3),
+%!        reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2]));
+%!assert (tensorprod (v1, v1, "all", "NumDimensionsA", 3), 5);
+%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 2), [5; 11]);
+%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 5), [5; 11]);
+%!assert (tensorprod (M1, v1, [2, 3], "NumDimensionsA", 5), [5; 11]);
+%!assert (tensorprod (M1, M2, "NumDimensionsA", 2), reshape ([1,3,2,4,3,9,6, ...
+%!        12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,3,2]))
+%!assert (tensorprod (M1, M2, "NumDimensionsA", 3), reshape ([1,3,2,4,3,9,6, ...
+%!        12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,1,3,2]))
+%!assert (tensorprod (T, T, 1, "NumDimensionsA", 3),
+%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],
+%!                 [2,2,2,2]))
+%!assert (tensorprod (T, T, 3, "NumDimensionsA", 3),
+%!        reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ...
+%!                20,8,16,24, 8,24,40,16,32,48,12,36,60,24,48,72],
+%!                [3,2,3,2]))
+%!assert (tensorprod (T, T, 1, "NumDimensionsA", 4),
+%!        reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56],
+%!                [2,2,1,2,2]))
+%!assert (tensorprod (T, T, 4, "NumDimensionsA", 4),
+%!        reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,5, ...
+%!                15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10,4,8, ...
+%!                12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36,6,18, ...
+%!                30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15, ...
+%!                6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2, ...
+%!                6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24, ...
+%!                36,6,18,30,12,24,36],
+%!                [3,2,2,3,2,2]))
+
+## Test empty inputs
+%!assert (tensorprod ([], []), zeros (0, 0, 0, 0))
+%!assert (tensorprod ([], 1), [])
+%!assert (tensorprod (1, []), zeros (1, 1, 0, 0))
+%!assert (tensorprod (zeros (0, 0, 0), zeros (0, 0, 0)), zeros (0, 0, 0, 0, 0, 0))
+%!assert (tensorprod ([], [], []), zeros (0, 0, 0, 0))
+%!assert (tensorprod ([], [], 1), [])
+%!assert (tensorprod ([], [], 2), [])
+%!assert (tensorprod ([], [], 3), zeros (0, 0, 0, 0))
+%!assert (tensorprod ([], [], 4), zeros (0, 0, 1, 0, 0))
+%!assert (tensorprod ([], [], 5), zeros (0, 0, 1, 1, 0, 0))
+%!assert (tensorprod ([], [], 3, "NumDimensionsA", 4), zeros (0, 0, 1, 0, 0))
+%!assert (tensorprod ([], [], 3, 4, "NumDimensionsA", 5), zeros (0, 0, 1, 1, 0, 0))
+
+## Test input validation
+%!error <Invalid call> tensorprod ()
+%!error <Invalid call> tensorprod (1)
+%!error <Invalid call> tensorprod (1,2,3,4,5,6,7)
+%!error <A must be a single or double precision array> tensorprod ("foo", 1)
+%!error <B must be a single or double precision array> tensorprod (1, "bar")
+%!error <A must be a single or double precision array> tensorprod (int32(1), 1)
+%!error <B must be a single or double precision array> tensorprod (1, int32(1))
+%!error <value for the NumDimensionsA property must be provided> tensorprod (1, 1, "NumDimensionsA")
+%!error <NumDimensionsA=VALUE syntax is unsupported> tensorprod (1, 1, NumDimensionsA=1)
+%!error <value for NumDimensionsA must be a numeric scalar> tensorprod (1, 1, 2, 1, "NumDimensionsA", "foo")
+%!error <value for NumDimensionsA must be a numeric scalar> tensorprod (1, 1, 2, 1, "NumDimensionsA", [1 2])
+%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, "NumDimensionsA", -1)
+%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, "NumDimensionsA", 0)
+%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, "NumDimensionsA", 1.5)
+%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, "NumDimensionsA", NaN)
+%!error <value for NumDimensionsA must be a positive integer> tensorprod (1, 1, 2, 1, "NumDimensionsA", Inf)
+%!error <dim must be a numeric vector of integers or \[\]> tensorprod (1, 1, ones (2,2))
+%!error <dim must be a numeric vector of integers or \[\]> tensorprod (1, 1, zeros (0,0,0))
+%!error <size of A and B must be identical when using the 'all' option> tensorprod (ones (3, 4), ones (4, 3), "all")
+%!error <unknown option 'foo'> tensorprod (1, 1, "foo")
+%!error <third argument must be a numeric vector of integers, \[\], or 'all'> tensorprod (1, 1, {})
+%!error <dimA must be a numeric vector of integers or \[\]> tensorprod (1, 1, "foo", 1)
+%!error <dimA must be a numeric vector of integers or \[\]> tensorprod (1, 1, ones (2,2), 1)
+%!error <dimA must be a numeric vector of integers or \[\]> tensorprod (1, 1, zeros (0,0,0), 1)
+%!error <dimB must be a numeric vector of integers or \[\]> tensorprod (1, 1, 1, "bar")
+%!error <dimB must be a numeric vector of integers or \[\]> tensorprod (1, 1, 1, ones (2,2))
+%!error <dimB must be a numeric vector of integers or \[\]> tensorprod (1, 1, 1, zeros (0,0,0))
+%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), 1, [1, 2])
+%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), 1, [])
+%!error <an equal number of dimensions must be matched for A and B> tensorprod (ones (3, 4), ones (4, 3), [], [1, 2])
+%!error <misplaced 'NumDimensionsA' option> tensorprod (1, 1, "NumDimensionsA", 1, 1)
+%!error <misplaced 'all' option> tensorprod (1, 1, 1, "all", 1)
+%!error <unknown option 'foo'> tensorprod (1, 1, 1, "foo", 1)
+%!error <optional arguments must be numeric vectors of integers, \[\], 'all', or 'NumDimensionsA'> tensorprod (1, 1, 1, {}, 1)
+%!error <too many dimension inputs given> tensorprod (1, 1, 2, 1, 1)
+%!error <too many dimension inputs given> tensorprod (1, 1, 2, 1, 1, 1)
+%!error <dimensions must be positive integers> tensorprod (1, 1, 0)
+%!error <dimensions must be positive integers> tensorprod (1, 1, -1)
+%!error <dimensions must be positive integers> tensorprod (1, 1, 1.5)
+%!error <dimensions must be positive integers> tensorprod (1, 1, NaN)
+%!error <dimensions must be positive integers> tensorprod (1, 1, Inf)
+%!error <matched dimensions of A and B must have the same lengths> tensorprod (ones (3, 4), ones (4, 3), 1)
+%!error <matched dimensions of A and B must have the same lengths> tensorprod (ones (3, 4), ones (4, 3), 1, 1)
+%!error <highest dimension of dim must be less than or equal to NumDimensionsA> tensorprod (1, 1, 5, "NumDimensionsA", 4)
+%!error <highest dimension of dimA must be less than or equal to NumDimensionsA> tensorprod (1, 1, 5, 2, "NumDimensionsA", 4)
+%!error <NumDimensionsA cannot be smaller than the number of dimensions of A> tensorprod (ones (2, 2, 2), 1, "NumDimensionsA", 2)
--- a/scripts/miscellaneous/edit.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/edit.m	Fri Jun 23 20:51:51 2023 +0200
@@ -168,7 +168,7 @@
     ## so first check for the various states
     statevar = varargin{1};
     stateval = varargin{2};
-    switch (toupper (statevar))
+    switch (upper (statevar))
       case "EDITOR"
         error ("Octave:deprecated-function",
                "The EDITOR option of edit has been removed.  Use EDITOR() directly.");
@@ -204,8 +204,8 @@
         FUNCTION.EDITINPLACE = stateval;
         return;
       case "GET"
-        if (isfield (FUNCTION, toupper (stateval)))
-          retval = FUNCTION.(toupper (stateval));
+        if (isfield (FUNCTION, upper (stateval)))
+          retval = FUNCTION.(upper (stateval));
         else
           retval = FUNCTION;
         endif
@@ -419,7 +419,7 @@
     author = ["Author: " FUNCTION.AUTHOR " " FUNCTION.EMAIL];
 
     ## Fill in the header.
-    uclicense = toupper (FUNCTION.LICENSE);
+    uclicense = upper (FUNCTION.LICENSE);
     switch (uclicense)
       case "GPL"
         head = cstrcat (copyright, "\n\n", "\
--- a/scripts/miscellaneous/inputParser.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/inputParser.m	Fri Jun 23 20:51:51 2023 +0200
@@ -43,51 +43,60 @@
   ## @end enumerate
   ##
   ## After defining the function API with these methods, the supplied arguments
-  ## can be parsed with the @code{parse} method and the parsing results
-  ## accessed with the @code{Results} accessor.
+  ## can be parsed with the @code{parse} method and the results accessed with
+  ## the @code{Results} accessor.
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.Parameters
-  ## Return list of parameter names already defined.
+  ## Return the list of parameter names already defined.  (read-only)
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.Results
-  ## Return structure with argument names as fieldnames and corresponding
-  ## values.
+  ## Return a structure with argument names as fieldnames and corresponding
+  ## values.  (read-only)
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.Unmatched
-  ## Return structure similar to @code{Results}, but for unmatched parameters.
+  ## Return a structure similar to @code{Results}, but for unmatched
+  ## parameters.  (read-only)
   ## See the @code{KeepUnmatched} property.
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.UsingDefaults
   ## Return cell array with the names of arguments that are using default
-  ## values.
-  ## @end deftypefn
-  ##
-  ## @deftypefn {} {} inputParser.CaseSensitive = @var{boolean}
-  ## Set whether matching of argument names should be case sensitive.  Defaults
-  ## to false.
+  ## values.  (read-only)
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.FunctionName = @var{name}
   ## Set function name to be used in error messages; Defaults to empty string.
   ## @end deftypefn
   ##
+  ## @deftypefn {} {} inputParser.CaseSensitive = @var{boolean}
+  ## Set whether matching of argument names should be case sensitive; Defaults
+  ## to false.
+  ## @end deftypefn
+  ##
   ## @deftypefn {} {} inputParser.KeepUnmatched = @var{boolean}
-  ## Set whether an error should be given for non-defined arguments.  Defaults
-  ## to false.  If set to true, the extra arguments can be accessed through
-  ## @code{Unmatched} after the @code{parse} method.  Note that since
-  ## @code{Switch} and @code{Parameter} arguments can be mixed, it is
-  ## not possible to know the unmatched type.  If argument is found unmatched
-  ## it is assumed to be of the @code{Parameter} type and it is expected to
-  ## be followed by a value.
+  ## Set whether string arguments which do not match any Parameter are parsed
+  ## and stored in the @code{Unmatched} property; Defaults to false.  If false,
+  ## an error will be emitted at the first unrecognized argument and parsing
+  ## will stop.  Note that since @code{Switch} and @code{Parameter} arguments
+  ## can be mixed, it is not possible to know the type of the unmatched
+  ## argument.  Octave assumes that all unmatched arguments are of the
+  ## @code{Parameter} type and therefore must be followed by a value.
+  ## @end deftypefn
+  ##
+  ## @deftypefn {} {} inputParser.PartialMatching = @var{boolean}
+  ## Set whether argument names for @code{Parameter} and @code{Switch} options
+  ## may be given in shortened form as long as the name uniquely identifies
+  ## an option; Defaults to true.  For example, the argument @qcode{'opt'} will
+  ## match a parameter @qcode{'opt_color'}, but will fail if there is also a
+  ## parameter @qcode{'opt_case'}.
   ## @end deftypefn
   ##
   ## @deftypefn {} {} inputParser.StructExpand = @var{boolean}
-  ## Set whether a structure can be passed to the function instead of
-  ## parameter/value pairs.  Defaults to true.
+  ## Set whether a structure passed to the function is expanded into
+  ## parameter/value pairs (parameter = fieldname); Defaults to true.
   ##
   ## The following example shows how to use this class:
   ##
@@ -99,23 +108,23 @@
   ##   p.addRequired ("pack", @@ischar);         # mandatory argument
   ##   p.addOptional ("path", pwd(), @@ischar);  # optional argument
   ##
-  ##   ## create a function handle to anonymous functions for validators
-  ##   val_mat = @@(x) isvector (x) && all (x <= 1) && all (x >= 0);
-  ##   p.addOptional ("mat", [0 0], val_mat);
+  ##   ## Create anonymous function handle for validators
+  ##   valid_vec = @@(x) isvector (x) && all (x >= 0) && all (x <= 1);
+  ##   p.addOptional ("vec", [0 0], valid_vec);
   ##
-  ##   ## create two arguments of type "Parameter"
-  ##   val_type = @@(x) any (strcmp (x, @{"linear", "quadratic"@}));
-  ##   p.addParameter ("type", "linear", val_type);
-  ##   val_verb = @@(x) any (strcmp (x, @{"low", "medium", "high"@}));
-  ##   p.addParameter ("tolerance", "low", val_verb);
+  ##   ## Create two arguments of type "Parameter"
+  ##   vld_type = @@(x) any (strcmp (x, @{"linear", "quadratic"@}));
+  ##   p.addParameter ("type", "linear", vld_type);
+  ##   vld_tol = @@(x) any (strcmp (x, @{"low", "medium", "high"@}));
+  ##   p.addParameter ("tolerance", "low", vld_tol);
   ##
-  ##   ## create a switch type of argument
+  ##   ## Create a switch type of argument
   ##   p.addSwitch ("verbose");
   ##
   ##   p.parse (varargin@{:@});  # Run created parser on inputs
   ##
-  ##   ## the rest of the function can access inputs by using p.Results.
-  ##   ## for example, get the tolerance input with p.Results.tolerance
+  ##   ## The rest of the function can access inputs by using p.Results.
+  ##   ## For example, get the tolerance input with p.Results.tolerance
   ## endfunction
   ## @end example
   ##
@@ -129,13 +138,13 @@
   ## check ("mech", "~/dev", [0 1 0 0], "type", "linear");  # valid
   ##
   ## ## following is also valid.  Note how the Switch argument type can
-  ## ## be mixed into or before the Parameter argument type (but it
-  ## ## must still appear after any Optional argument).
+  ## ## be mixed in with or before the Parameter argument type (but it
+  ## ## must still appear after any Optional arguments).
   ## check ("mech", "~/dev", [0 1 0 0], "verbose", "tolerance", "high");
   ##
-  ## ## following returns an error since not all optional arguments,
-  ## ## 'path' and 'mat', were given before the named argument 'type'.
-  ## check ("mech", "~/dev", "type", "linear");
+  ## ## following returns an error since an Optional argument, 'path',
+  ## ## was given after the Parameter argument 'type'.
+  ## check ("mech", "type", "linear", "~/dev");
   ## @end group
   ## @end example
   ##
@@ -143,7 +152,7 @@
   ## they must appear in a specific order.  @code{Required} arguments must be
   ## first and can be followed by any @code{Optional} arguments.  Only
   ## the @code{Parameter} and @code{Switch} arguments may be mixed
-  ## together and they must appear at the end.
+  ## together and they must appear following the first two types.
   ##
   ## @emph{Note 2}: If both @code{Optional} and @code{Parameter} arguments
   ## are mixed in a function API then once a string Optional argument fails to
@@ -156,10 +165,10 @@
 
   properties
     ## FIXME: set input checking for these properties
-    CaseSensitive = false;
-    FunctionName  = "";
-    KeepUnmatched = false;
-    PartialMatching = false; # FIXME: unimplemented (and default should be true)
+    CaseSensitive   = false;
+    FunctionName    = "";
+    KeepUnmatched   = false;
+    PartialMatching = true;
     StructExpand    = true;
   endproperties
 
@@ -175,19 +184,19 @@
     ## structs with the fields "name", "def" (default), and "val" (validator).
     Required = cell ();
     Optional = cell ();
-    ## Parameter and Switch are unordered so we have a struct whose fieldnames
-    ## are the argname, and values are a struct with fields "def" and "val"
-    Parameter = struct ();
-    Switch    = struct ();
+    ## Parameter and Switch are unordered so we use a struct array with
+    ## fields "name", "def" (default", and "val" (validator).
+    Parameter = struct ([]);  # create 0x0 struct array, not scalar struct
+    Switch    = struct ([]);
 
-    ## List of Parameter and Switch names to ease searches
+    ## List of Parameter and Switch names to simplify searches
     ParameterNames = cell ();
     SwitchNames    = cell ();
 
-    ## When checking for fieldnames in a Case Insensitive way, this variable
-    ## holds the correct identifier for the last searched named using the
-    ## is_argname method.
+    ## Simplify searches by cacheing the last name and last index of a
+    ## match from is_argname() into the Parameter or Switch struct arrays.
     last_name = "";
+    last_idx = 1;
   endproperties
 
   properties (Access = protected, Constant = true)
@@ -197,12 +206,6 @@
 
   methods
 
-    function set.PartialMatching (this, val)
-      if (val)
-        error ("inputParser: PartialMatching is not yet implemented");
-      endif
-    endfunction
-
     function addRequired (this, name, val = inputParser.def_val)
 
       ## -*- texinfo -*-
@@ -210,27 +213,27 @@
       ## @deftypefnx {} {} addRequired (@var{argname}, @var{validator})
       ## Add new mandatory argument to the object @var{parser} of inputParser
       ## class.  This method belongs to the inputParser class and implements
-      ## an ordered arguments type of API.
+      ## an ordered-argument type of API.
       ##
       ## @var{argname} must be a string with the name of the new argument.  The
-      ## order in which new arguments are added with @code{addrequired},
+      ## order in which new arguments are added with @code{addRequired}
       ## represents the expected order of arguments.
       ##
-      ## @var{validator} is an optional function handle to validate the given
-      ## values for the argument with name @var{argname}.  Alternatively, a
-      ## function name can be used.
+      ## The optional argument @var{validator} is a function (handle or name)
+      ## that will return false or throw an error if the input @var{argname}
+      ## is invalid.
       ##
       ## See @code{help inputParser} for examples.
       ##
-      ## @emph{Note}: this can be used together with the other type of
-      ## arguments but it must be the first (see @code{@@inputParser}).
+      ## @emph{Note}: A Required argument can be used together with other
+      ## types of arguments but it must be the first (see @code{@@inputParser}).
       ##
       ## @end deftypefn
 
       if (nargin < 2)
         print_usage ();
-      elseif (numel (this.Optional) || numfields (this.Parameter)
-              || numfields (this.Switch))
+      elseif (numel (this.Optional)
+              || numel (this.Parameter) || numel (this.Switch))
         error (["inputParser.addRequired: can't have a Required argument " ...
                 "after Optional, Parameter, or Switch"]);
       endif
@@ -245,33 +248,36 @@
       ## @deftypefn  {} {} addOptional (@var{argname}, @var{default})
       ## @deftypefnx {} {} addOptional (@var{argname}, @var{default}, @var{validator})
       ## Add new optional argument to the object @var{parser} of the class
-      ## inputParser to implement an ordered arguments type of API
+      ## inputParser to implement an ordered-argument type of API
       ##
       ## @var{argname} must be a string with the name of the new argument.  The
-      ## order in which new arguments are added with @code{addOptional},
+      ## order in which new arguments are added with @code{addOptional}
       ## represents the expected order of arguments.
       ##
       ## @var{default} will be the value used when the argument is not
       ## specified.
       ##
-      ## @var{validator} is an optional anonymous function to validate the
-      ## given values for the argument with name @var{argname}.  Alternatively,
-      ## a function name can be used.
+      ## The optional argument @var{validator} is a function (handle or name)
+      ## that will return false or throw an error if the input @var{argname}
+      ## is invalid.
       ##
       ## See @code{help inputParser} for examples.
       ##
-      ## @emph{Note}: if a string argument does not validate, it will be
-      ## considered a ParamValue key.  If an optional argument is not given a
-      ## validator, anything will be valid, and so any string will be
-      ## considered will be the value of the optional argument (in @sc{matlab},
-      ## if no validator is given and argument is a string it will also be
-      ## considered a ParamValue key).
+      ## @emph{Note1}: If an optional argument is not given a
+      ## validator then anything will be valid, and therefore a string in the
+      ## correct position (after Required arguments) will be assigned to the
+      ## value of the Optional argument @emph{even} if the string is the name
+      ## of a Parameter key.  @sc{matlab} adds a default validator
+      ## @code{@@(x) ~ischar (x)} if none is specified which emits an error
+      ## in this instance.
       ##
+      ## @emph{Note2}: if a string argument fails validation, it will be
+      ## considered as a possible Parameter.
       ## @end deftypefn
 
       if (nargin < 3)
         print_usage ();
-      elseif (numfields (this.Parameter) || numfields (this.Switch))
+      elseif (numel (this.Parameter) || numel (this.Switch))
         error (["inputParser.Optional: can't have Optional arguments " ...
                 "after Parameter or Switch"]);
       endif
@@ -288,11 +294,14 @@
       ## -*- texinfo -*-
       ## @deftypefn  {} {} addParamValue (@var{argname}, @var{default})
       ## @deftypefnx {} {} addParamValue (@var{argname}, @var{default}, @var{validator})
+      ## This function is deprecated.  Use @code{addParameter} in all new code.
+      ##
       ## Add new parameter to the object @var{parser} of the class inputParser
       ## to implement a name/value pair type of API.
       ##
       ## This is an alias for @code{addParameter} method without the
-      ## @qcode{"PartialMatchPriority"} option.  See it for the help text.
+      ## @qcode{"PartialMatchPriority"} option.  See @code{addParameter} for
+      ## the help text.
       ##
       ## @end deftypefn
 
@@ -308,17 +317,16 @@
       ## -*- texinfo -*-
       ## @deftypefn  {} {} addParameter (@var{argname}, @var{default})
       ## @deftypefnx {} {} addParameter (@var{argname}, @var{default}, @var{validator})
-      ## Add new parameter to the object @var{parser} of the class inputParser
-      ## to implement a name/value pair type of API.
+      ## Add new parameter argument to the object @var{parser} of the class
+      ## inputParser to implement a name/value pair type of API.
       ##
       ## @var{argname} must be a string with the name of the new parameter.
       ##
       ## @var{default} will be the value used when the parameter is not
       ## specified.
       ##
-      ## @var{validator} is an optional function handle to validate the given
-      ## values for the parameter with name @var{argname}.  Alternatively, a
-      ## function name can be used.
+      ## The optional argument @var{validator} is a function handle that will
+      ## return false or throw an error if the input @var{argname} is invalid.
       ##
       ## See @code{help inputParser} for examples.
       ##
@@ -328,17 +336,23 @@
         print_usage ();
       endif
 
+      this.validate_name ("Parameter", name);
+
       n_opt = numel (varargin);
 
       if (n_opt == 0 || n_opt == 2)
         val = inputParser.def_val;
-      else # n_opt is 1 or 3
+      else  # n_opt is 1 or 3
         val = varargin{1};
+        if (! is_function_handle (val))
+          error ("inputParser.addParameter: VALIDATOR must be a function handle");
+        endif
       endif
 
+      ## FIXME: PartialMatchPriority is parsed, but not implemented
       if (n_opt == 0 || n_opt == 1)
         match_priority = 1;
-      else # n_opt is 2 or 3
+      else  # n_opt is 2 or 3
         if (! strcmpi (varargin{end-1}, "PartialMatchPriority"))
           error ("inputParser.addParameter: unrecognized option");
         endif
@@ -348,9 +362,12 @@
                             "PartialMatchPriority");
       endif
 
-      this.validate_name ("Parameter", name);
-      this.Parameter.(name).def = def;
-      this.Parameter.(name).val = val;
+      if (iscell (def))
+        ## Accept cell default values (bug #64305).
+        this.Parameter(end+1) = struct ("name", name, "def", {def}, "val", val);
+      else
+        this.Parameter(end+1) = struct ("name", name, "def", def, "val", val);
+      endif
 
     endfunction
 
@@ -358,28 +375,31 @@
 
       ## -*- texinfo -*-
       ## @deftypefn {} {} addSwitch (@var{argname})
-      ## Add new switch type of argument to the object @var{parser} of
-      ## inputParser class.
-      ##
-      ## This method belongs to the inputParser class and implements a switch
-      ## arguments type of API.
+      ## Add new switch argument to the object @var{parser} of the class
+      ## inputParser to implement a name/boolean type of API.
       ##
       ## @var{argname} must be a string with the name of the new argument.
-      ## Arguments of this type can be specified at the end, after
-      ## @code{Required} and @code{Optional}, and mixed between the
-      ## @code{Parameter}.  They default to false.  If one of the arguments
-      ## supplied is a string like @var{argname}, then after parsing the value
-      ## of @var{parse}.Results.@var{argname} will be true.
+      ##
+      ## Arguments of this type must be specified after @code{Required} and
+      ## @code{Optional} arguments, but can be mixed with any @code{Parameter}
+      ## definitions.  The default for switch arguments is false.  During
+      ## parsing, if one of the arguments supplied is a string such as
+      ## @var{argname} that matches a defined switch such as
+      ## @w{@code{addSwitch (@var{argname})}}, then after parsing the value
+      ## of @code{parse.Results.@var{argname}} will be true.
       ##
       ## See @code{help inputParser} for examples.
       ##
+      ## Compatibility Note: @code{addSwitch} is an Octave extension not
+      ## present in @sc{matlab}.
+      ##
       ## @end deftypefn
 
       if (nargin != 2)
         print_usage ();
       endif
       this.validate_name ("Switch", name);
-      this.Switch.(name).def = false;
+      this.Switch(end+1) = struct ("name", name, "def", false);
 
     endfunction
 
@@ -387,8 +407,8 @@
 
       ## -*- texinfo -*-
       ## @deftypefn {} {} parse (@var{varargin})
-      ## Parses and validates list of arguments according to object
-      ## @var{parser} of the class inputParser.
+      ## Parse and validate list of arguments according to object @var{parser}
+      ## of the class inputParser.
       ##
       ## After parsing, the results can be accessed with the @code{Results}
       ## accessor.  See @code{help inputParser} for a more complete
@@ -407,9 +427,14 @@
         endif
       endif
       pnargin = numel (varargin);
-
-      this.ParameterNames = fieldnames (this.Parameter);
-      this.SwitchNames    = fieldnames (this.Switch);
+      this.ParameterNames = {};
+      if (numel (this.Parameter))
+        this.ParameterNames = {this.Parameter.name};
+      endif
+      this.SwitchNames = {};
+      if (numel (this.Switch))
+        this.SwitchNames = {this.Switch.name};
+      endif
 
       ## Evaluate the Required arguments first
       nReq = numel (this.Required);
@@ -428,34 +453,30 @@
         in  = varargin{++vidx};
         if ((this.is_argname ("Parameter", in) && vidx < pnargin)
             || this.is_argname ("Switch", in))
-          ## This looks like an optional parameter/value pair or a
-          ## switch, not an positional option.  This does mean that
-          ## positional options cannot be strings named like parameter
-          ## keys.  See bug #50752.
+          ## The string value looks like an optional parameter/value pair or a
+          ## switch.  The Optional positional argument which could apply here
+          ## is specifically not used (this is Matlab compatible).
+          ## See bug #50752.
           idx -= 1;
           vidx -= 1;
           break;
         endif
-        try
-          valid_option = opt.val (in);
-        catch
-          valid_option = false;
-        end_try_catch
+        valid_option = this.validate_arg ("", opt.val, in);
         if (! valid_option)
-          ## If it does not match there's two options:
-          ##    1) input is actually wrong and we should error;
-          ##    2) it's a Parameter or Switch name and we should use
+          ## If it does not match there are two options:
+          ##   1a) it's a Parameter or Switch name and we should use
           ##       the default for the rest;
-          ##    3) it's a struct with the Parameter pairs.
-          if (ischar (in) || (this.StructExpand && isstruct (in)
-                              && isscalar (in)))
+          ##   1b) it's a struct with the Parameter pairs.
+          ##   2) input is actually wrong and we should error;
+          if (ischar (in)
+              || (this.StructExpand && isstruct (in) && isscalar (in)))
             idx -= 1;
             vidx -= 1;
             break;
           else
-            this.error (sprintf (["failed validation of %s\n", ...
+            this.error (sprintf (["failed validation of '%s'\n", ...
                                   "Validation function: %s"],
-                                 toupper (opt.name), disp (opt.val)));
+                                 opt.name, disp (opt.val)));
           endif
         endif
         this.Results.(opt.name) = in;
@@ -477,7 +498,7 @@
           if (isempty (expanded_options))
             continue;  # empty, continue to next argument
           endif
-          n_new_args = numel (expanded_options) -1;
+          n_new_args = numel (expanded_options) - 1;
           pnargin += n_new_args;
           varargin(vidx+n_new_args+1:pnargin) = varargin(vidx+1:end);
           varargin(vidx:vidx+n_new_args) = expanded_options;
@@ -485,16 +506,15 @@
         endif
 
         if (! ischar (name))
-          this.error ("non-string for Parameter name or Switch");
+          this.error ("Parameter or Switch name must be a string");
         endif
 
         if (this.is_argname ("Parameter", name))
-          if (vidx++ > pnargin)
-            this.error (sprintf ("no matching value for option '%s'",
-                                 toupper (name)));
+          if (++vidx > pnargin)
+            this.error (sprintf ("no value for parameter '%s'", name));
           endif
           this.validate_arg (this.last_name,
-                             this.Parameter.(this.last_name).val,
+                             this.Parameter(this.last_idx).val,
                              varargin{vidx});
         elseif (this.is_argname ("Switch", name))
           this.Results.(this.last_name) = true;
@@ -502,8 +522,7 @@
           if (vidx++ < pnargin && this.KeepUnmatched)
             this.Unmatched.(name) = varargin{vidx};
           else
-            this.error (sprintf ("argument '%s' is not a valid parameter",
-                                 toupper (name)));
+            this.error (sprintf ("argument '%s' is not a declared parameter or switch", name));
           endif
         endif
       endwhile
@@ -511,6 +530,9 @@
       this.add_missing ("Parameter");
       this.add_missing ("Switch");
 
+      ## Sort fields for Matlab compatibility (bug #64003)
+      this.Results = orderfields (this.Results);
+
     endfunction
 
     function disp (this)
@@ -520,10 +542,12 @@
       endif
       printf ("inputParser object with properties:\n\n");
       b2s = @(x) ifelse (any (x), "true", "false");
-      printf (["   CaseSensitive   : %s\n   FunctionName    : %s\n" ...
-               "   KeepUnmatched   : %s\n   PartialMatching : %s\n" ...
+      printf (["   FunctionName    : \"%s\"\n" ...
+               "   CaseSensitive   : %s\n" ...
+               "   KeepUnmatched   : %s\n" ...
+               "   PartialMatching : %s\n" ...
                "   StructExpand    : %s\n\n"],
-               b2s (this.CaseSensitive), b2s (this.FunctionName),
+               this.FunctionName, b2s (this.CaseSensitive),
                b2s (this.KeepUnmatched), b2s (this.PartialMatching),
                b2s (this.StructExpand));
       printf ("Defined parameters:\n\n   {%s}\n",
@@ -540,42 +564,41 @@
       if (! isvarname (name))
         error ("inputParser.add%s: NAME is an invalid identifier", method);
       elseif (any (strcmpi (this.Parameters, name)))
-        ## Even if CaseSensitive is "on", we still shouldn't allow
+        ## Even if CaseSensitive is true, we still shouldn't allow
         ## two args with the same name.
-        error ("inputParser.add%s: argname '%s' has already been specified",
+        error ("inputParser.add%s: argname '%s' has already been declared",
                type, name);
       endif
       this.Parameters{end+1} = name;
+      ## Sort Parameters for Matlab compatibility (bug #64003)
+      this.Parameters = sort (this.Parameters);
 
     endfunction
 
-    function validate_arg (this, name, val, in)
+    function r = validate_arg (this, name, val, in)
 
-      ## Checking "nargout (val)" doesn't work for builtin functions.
-      ## So, we need to use this nested try-catch construct.
-      err = sprintf ('Checked with "%s"', func2str (val));
+      ## Validation function can either produce a true/false result or have
+      ## no outputs but throw an error when failing.  Tricky code here
+      ## relies on side effect, but calls validation function only once
+      ## which is a performance win and may also be necessary if validation
+      ## function maintains state.  See bug #49793.
+      ans = true;
       try
-        ok = val (in);
-      catch exception
-        if (strcmp (exception.identifier, "Octave:invalid-fun-call"))
-          ## check if function also fails when called without output argument
-          try
-            val (in);
-            ok = true;
-          catch exception
-            ok = false;
-            err = exception.message;
-          end_try_catch
-        else
-          ok = false;
-          err = exception.message;
+        val (in);  # call function with no arguments in case nargout == 0
+        ok = ans;  # use side effect of assignment to 'ans' when nargout == 1
+      catch
+        ok = false;
+      end_try_catch
+
+      if (nargout > 0)
+        r = ok;
+      else
+        if (! ok)
+          err = sprintf ('Checked with "%s"', func2str (val));
+          this.error (sprintf ("failed validation of '%s'.  %s", name, err));
         endif
-      end_try_catch
-      if (! ok)
-        this.error (sprintf ("failed validation of %s. %s",
-                             toupper (name), err));
+        this.Results.(name) = in;
       endif
-      this.Results.(name) = in;
 
     endfunction
 
@@ -583,31 +606,80 @@
 
       r = ischar (name) && isrow (name);
       if (r)
-        if (this.CaseSensitive)
-          r = isfield (this.(type), name);
-          if (r)
-            this.last_name = name;
+        fnames = this.([type "Names"]);
+        if (this.PartialMatching)
+          if (this.CaseSensitive)
+            idx = strncmp (name, fnames, numel (name));
+            r = sum (idx);
+            if (r > 1)
+              ## Check for exact match and prefer it over a partial match
+              idx2 = strcmp (name, {fnames{idx}});
+              if (any (idx2))
+                idx = (find (idx))(idx2);
+                r = 1;
+              else
+                matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
+                matches(end) = '.';
+                this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              endif
+            endif
+            r = logical (r);
+          else  # not CaseSensitive
+            idx = strncmpi (name, fnames, numel (name));
+            r = sum (idx);
+            if (r > 1)
+              idx2 = strcmpi (name, {fnames{idx}});
+              if (any (idx2))
+                idx = (find (idx))(idx2);
+                r = 1;
+              else
+                matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
+                matches(end) = '.';
+                this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              endif
+            endif
+            r = logical (r);
           endif
-        else
-          fnames = this.([type "Names"]);
-          l = strcmpi (name, fnames);
-          r = any (l(:));
-          if (r)
-            this.last_name = fnames{l};
+        else  # no PartialMatching
+          if (this.CaseSensitive)
+            idx = strcmp (name, fnames);
+            r = any (idx(:));
+          else
+            idx = strcmpi (name, fnames);
+            r = any (idx(:));
           endif
         endif
       endif
 
+      if (r)
+        ## Cache values to simplify and speed up later code.
+        this.last_name = fnames{idx};
+        this.last_idx = find (idx);
+      endif
+
     endfunction
 
     function add_missing (this, type)
 
-      unmatched = setdiff (fieldnames (this.(type)), fieldnames (this.Results));
-      for namec = unmatched(:)'
-        name = namec{1};
-        this.UsingDefaults{end+1} = name;
-        this.Results.(name) = this.(type).(name).def;
-      endfor
+      if (isempty (this.(type)))
+        return;
+      endif
+
+      ## Implement setdiff() without calling out to function for performance.
+      typenames = {this.(type).name}(:);
+      Resultnames = fieldnames (this.Results);
+      [sorted, sidx] = sort ([typenames; Resultnames]);
+      dups = strcmp (sorted(1:end-1), sorted(2:end));
+      idx = true (size (typenames));
+      idx(sidx(dups)) = false;
+      if (any (idx))
+        unmatched_names = typenames(idx);
+        unmatched_def = {this.(type)(idx).def}(:);
+        this.Results = ...
+          cell2struct (vertcat (struct2cell (this.Results), unmatched_def),
+                       [Resultnames; unmatched_names]);
+        this.UsingDefaults = [this.UsingDefaults, unmatched_names.'];
+      endif
 
     endfunction
 
@@ -629,6 +701,7 @@
 %!function p = create_p ()
 %!  p = inputParser ();
 %!  p.CaseSensitive = true;
+%!  p.PartialMatching = false;
 %!  p.addRequired ("req1", @(x) ischar (x));
 %!  p.addOptional ("op1", "val", @(x) any (strcmp (x, {"val", "foo"})));
 %!  p.addOptional ("op2", 78, @(x) x > 50);
@@ -662,15 +735,33 @@
 %! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
 %!         {"file", "val", 78,    false,     "circle"});
 
-## check case insensitivity
+## check CaseSensitive (default false state)
 %!test
 %! p = create_p ();
-%!  p.CaseSensitive = false;
+%! p.CaseSensitive = false;
 %! p.parse ("file", "foo", 80, "LiNE", "circle", "vERbOSe");
 %! r = p.Results;
 %! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
 %!         {"file", "foo", 80,    true,      "circle"});
 
+## check PartialMatching (default true state)
+%!test
+%! p = create_p ();
+%! p.PartialMatching = true;
+%! p.parse ("file", "foo", 80, "l", "circle", "verb");
+%! r = p.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!         {"file", "foo", 80,    true,      "circle"});
+
+## Check PartialMatching selects an exact match if it exists
+%!test
+%! p = inputParser ();
+%! p.addParameter ('Mass', []);
+%! p.addParameter ('MassSingular', []);
+%! p.parse ("Mass", pi);
+%! r = p.Results;
+%! assert ({r.Mass, r.MassSingular}, {pi, []});
+
 ## check KeepUnmatched
 %!test
 %! p = create_p ();
@@ -683,21 +774,38 @@
 %! p = create_p ();
 %! p.parse ();
 
-## check error when given required does not validate
+## check error when required arg does not validate
 %!error <failed validation of >
 %! p = create_p ();
 %! p.parse (50);
 
-## check error when given optional does not validate
-%!error <is not a valid parameter>
+## check error when optional arg does not validate
+%!error <is not a declared parameter or switch>
 %! p = create_p ();
 %! p.parse ("file", "no-val");
 
-## check error when given Parameter does not validate
+## check error when Parameter arg does not validate
 %!error <failed validation of >
 %! p = create_p ();
 %! p.parse ("file", "foo", 51, "line", "round");
 
+## check PartialMatching errors
+%!error <'arg' matches more than one Parameter: 'arg123', 'arg456'>
+%! p = inputParser ();
+%! p.addParameter ('arg123', 123);
+%! p.addParameter ('arg456', 456);
+%! p.addSwitch ('arg789');
+%! p.addSwitch ('arg790');
+%! p.parse ('arg', 'bad');
+
+%!error <'arg7' matches more than one Switch: 'arg789', 'arg790'>
+%! p = inputParser ();
+%! p.addParameter ('arg123', 123);
+%! p.addParameter ('arg456', 456);
+%! p.addSwitch ('arg789');
+%! p.addSwitch ('arg790');
+%! p.parse ('arg7', 'bad');
+
 ## check alternative method (obj, ...) API
 %!function p2 = create_p2 ();
 %!  p2 = inputParser ();
@@ -725,7 +833,7 @@
 %! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
 %!         {"file", "foo", 80,    true,      "circle"});
 
-## We must not perform validation of default values
+## Octave must not perform validation of default values
 %!test <*45837>
 %! p = inputParser ();
 %! p.addParameter ("Dir", [], @ischar);
@@ -759,7 +867,7 @@
 %!  addParameter (p3, "style", "tt", @(x) any (strcmp (x, {"tt", "f", "i"})));
 %!endfunction
 
-## Test StructExpand
+## check StructExpand
 %!test
 %! p3 = create_p3 ();
 %! p3.parse (struct ("line", "circle", "color", "green"));
@@ -767,7 +875,7 @@
 %!                             "line", "circle", "color", "green",
 %!                             "style", "tt"))
 
-%!test
+%!test  # check last param/value pair overrides previous
 %! p3 = create_p3 ();
 %! p3.parse (struct ("line", "circle", "color", "green"), "line", "tree");
 %! assert (p3.Results.line, "tree");
@@ -790,27 +898,26 @@
 %! assert (p3.Results.color, "green");
 %! assert (p3.Results.verbose, false);
 
-
 ## Some simple tests for addParamValue since all the other ones use add
 ## addParameter but they use the same codepath.
 %!test
 %! p = inputParser ();
-%! addParameter (p, "line", "tree", @(x) any (strcmp (x, {"tree", "circle"})));
-%! addParameter (p, "color", "red", @(x) any (strcmp (x, {"red", "green"})));
+%! addParamValue (p, "line", "tree", @(x) any (strcmp (x, {"tree", "circle"})));
+%! addParamValue (p, "color", "red", @(x) any (strcmp (x, {"red", "green"})));
 %! p.parse ("line", "circle");
 %! assert ({p.Results.line, p.Results.color}, {"circle", "red"});
 
 %!test
 %! p = inputParser ();
-%! p.addParameter ("foo", "bar", @ischar);
+%! p.addParamValue ("foo", "bar", @ischar);
 %! p.parse ();
 %! assert (p.Results, struct ("foo", "bar"));
 %! p.parse ("foo", "qux");
 %! assert (p.Results, struct ("foo", "qux"));
 
-## This behaviour means that a positional option can never be a string
-## that is the name of a parameter key.  This is required for Matlab
-## compatibility.
+## An Optional argument which has a string value that is the name of a
+## Parameter will be parsed as a Parameter/Value pair.
+## This is required for Matlab compatibility.
 %!test <*50752>
 %! p = inputParser ();
 %! p.addOptional ("op1", "val");
@@ -843,13 +950,13 @@
 %! p.addOptional ("op1", "val1", @ischar);
 %! p.addOptional ("op2", "val2", @isnumeric);
 %! p.addParameter ("line", "circle", @ischar);
-%! fail ('p.parse ("line", 89)', "failed validation of LINE")
+%! fail ('p.parse ("line", 89)', "failed validation of 'line'")
 %!
 %! p = inputParser ();
 %! p.addOptional ("op1", "val1");
 %! p.addParamValue ("line", "circle", @ischar);
 %! fail ('p.parse ("line", "line", 89)',
-%!       "non-string for Parameter name or Switch")
+%!       "Parameter or Switch name must be a string")
 
 %!test <*50752>
 %! ## This fails in Matlab but works in Octave.  It is a bug there
@@ -887,7 +994,7 @@
 %! assert (p.Unmatched, struct ());
 
 ## Test for patch #9241
-%!error <failed validation of A.*ischar>
+%!error <failed validation of 'a'.*ischar>
 %! p = inputParser ();
 %! p.addParameter ("a", [], @ischar);
 %! p.parse ("a", 1);
@@ -920,3 +1027,39 @@
 %! p.parse ("x");
 %! r = p.Results;
 %! assert (r.opt, "x");
+
+%!test <*64003>
+%! p = inputParser ();
+%! p.addOptional ('c',3);
+%! p.addOptional ('z',4);
+%! p.addParameter ('b',2);
+%! p.addParameter ('a',1);
+%! p.parse (30, 'b', 20, 'a',10);
+%! assert (fieldnames (p.Results), {'a'; 'b'; 'c'; 'z'});
+
+%!test <*64305>
+%! p = inputParser ();
+%! p.addParameter ('a',{});
+%! p.parse ('a', 20);
+%! assert (fieldnames (p.Results), {'a'});
+%! assert (p.Results.a, 20);
+
+%!test <*49793>
+%! p = inputParser ();
+%! p.addRequired ("name", @(x) validateattributes (x, {'char'}, {'nonempty'}));
+%! p.addOptional ("year", 0001, @(x) validateattributes (x, {'numeric'}, ...
+%!                                     {'nonempty','integer','positive'}));
+%! p.addParameter ("color", '-', @(x) validateattributes (x, {'char'}, ...
+%!                                                           {'nonempty'}));
+%! p.parse ('Jim', 1980, 'color', 'black');
+%! assert (p.Results.name, 'Jim');
+%! assert (p.Results.year, 1980);
+%! assert (p.Results.color, 'black');
+
+%!test <*64318>
+%! p = inputParser;
+%! p.addOptional ('p_opt', []);
+%! p.addParameter ('p1', 'p1_default');
+%! p.addParameter ('p2', 'p2_default');
+%! p.parse ();
+%! assert (size (p.UsingDefaults), [1, 3]);
--- a/scripts/miscellaneous/license.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/license.m	Fri Jun 23 20:51:51 2023 +0200
@@ -77,7 +77,7 @@
 
   [features, loaded] = get_all_features ();
 
-  switch (tolower (cmd))
+  switch (lower (cmd))
     case "inuse"
       features = features(loaded);
 
@@ -99,7 +99,7 @@
         ## We ignore the toggle argument because... what's the point?  We
         ## don't need a license management system on Octave.  This function
         ## will return true, even if anyone tries to disable a license.
-        switch (tolower (toggle))
+        switch (lower (toggle))
           case "enable"   # do nothing
           case "disable"  # do nothing
           otherwise       error ("license: TOGGLE must be enable or disable");
--- a/scripts/miscellaneous/methods.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/methods.m	Fri Jun 23 20:51:51 2023 +0200
@@ -65,8 +65,8 @@
   elseif (ischar (obj))
     ## Could be a classname for an Octave class or Java class.
     ## Try Octave class first.
-    mtds_list = __methods__ (obj);
-    if (isempty (mtds_list))
+    [mtds_list, valid] = __methods__ (obj);
+    if (! valid)
       mtds_str = javaMethod ("getMethods", "org.octave.ClassHelper", obj);
       mtds_list = ostrsplit (mtds_str, ';');
       mtds_list = mtds_list(:);  # return a column vector for compatibility
@@ -115,10 +115,23 @@
 endfunction
 
 
+## test classdef object
+%!test
+%! ip = inputParser ();
+%! assert (methods (ip),
+%!         {"addOptional"; "addParamValue"; "addParameter"; "addRequired";
+%!          "addSwitch"; "delete"; "disp"; "parse"; });
+
+## test classdef classname
+%!assert (methods ("inputParser"),
+%!        {"addOptional"; "addParamValue"; "addParameter"; "addRequired";
+%!         "addSwitch"; "delete"; "disp"; "parse"; });
+
 ## test old-style @classname
 %!test
 %! mtds = methods ("ftp");
 %! assert (mtds{1}, "ascii");
+%! assert (numel (mtds), 15);
 
 ## test Java classname
 %!testif HAVE_JAVA; usejava ("jvm")
@@ -132,20 +145,17 @@
 %! search = strfind (mtds, "java.lang.Double valueOf");
 %! assert (! isempty ([search{:}]));
 
-## test that methods does the right thing when passed a String object
-%!testif HAVE_JAVA; usejava ("jvm") <*48758>
-%! object = javaObject ("java.lang.String", "java.lang.Integer");
-%! assert (methods (object), methods ("java.lang.String"));
+## test Java object
+%!testif HAVE_JAVA; usejava ("jvm")
+%! jobject = javaObject ("java.lang.Double", pi);
+%! assert (methods (jobject), methods ("java.lang.Double"));
 
-## test classdef classname
-%!assert (methods ("inputParser"),
-%!        {"addOptional"; "addParamValue"; "addParameter";
-%!         "addRequired"; "addSwitch"; "add_missing"; "delete";
-%!         "disp"; "error"; "is_argname"; "parse"; "validate_arg";
-%!         "validate_name"});
+## test exceptional case of Java String object
+%!testif HAVE_JAVA; usejava ("jvm") <*48758>
+%! jobject = javaObject ("java.lang.String", "java.lang.Integer");
+%! assert (methods (jobject), methods ("java.lang.String"));
 
 ## Test input validation
 %!error <Invalid call> methods ()
-%!error methods ("a", "b", "c")
 %!error <invalid option> methods ("ftp", "option1")
 %!error <invalid input argument> methods (1)
--- a/scripts/miscellaneous/open.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/open.m	Fri Jun 23 20:51:51 2023 +0200
@@ -91,9 +91,9 @@
   [~, fname, ext] = fileparts (file);
 
   if (! isempty (ext)
-      && any (exist (["open" tolower(ext(2:end))]) == [2 3 5 103]))
+      && any (exist (["open" lower(ext(2:end))]) == [2 3 5 103]))
     try
-      openfcn = ["open" tolower(ext(2:end))];
+      openfcn = ["open" lower(ext(2:end))];
       if (nargout > 0)
         output = feval (openfcn, file);
       else
--- a/scripts/miscellaneous/parseparams.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/parseparams.m	Fri Jun 23 20:51:51 2023 +0200
@@ -85,7 +85,7 @@
     if (! size_equal (names, defaults))
       error ("parseparams: needs odd number of arguments");
     endif
-    [names, sidx] = sort (toupper (names));
+    [names, sidx] = sort (upper (names));
 
     varargout = defaults;
     if (i)
@@ -95,7 +95,7 @@
       if (! size_equal (pnames, values) || ! all (strs(i:2:end)))
         error_as_caller ("options must be given as name-value pairs");
       endif
-      idx = lookup (names, toupper (pnames), "m");
+      idx = lookup (names, upper (pnames), "m");
       if (! all (idx))
         error_as_caller ("unrecognized option: %s", pnames{find (idx == 0, 1)});
       else
--- a/scripts/miscellaneous/unpack.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/unpack.m	Fri Jun 23 20:51:51 2023 +0200
@@ -241,7 +241,7 @@
     error ("unpack: %s: not a directory", dir);
   endif
 
-  if (isfield (commandlist, tolower (nodotext)))
+  if (isfield (commandlist, lower (nodotext)))
     [commandv, commandq, parsefcn, move] = deal (commandlist.(nodotext){:});
     origdir = pwd ();
     if (move)
--- a/scripts/miscellaneous/validateattributes.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/miscellaneous/validateattributes.m	Fri Jun 23 20:51:51 2023 +0200
@@ -259,7 +259,7 @@
     ## FIXME: once we use this in Octave core, it might be worthy to find
     ## which attributes are checked more often, and place them in that
     ## order inside the switch block.
-    switch (tolower (attr{idx++}))
+    switch (lower (attr{idx++}))
       case "2d",
         problem = ndims (A) != 2;
         err_id = "Octave:expected-2d";
--- a/scripts/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -94,7 +94,7 @@
   $(GEN_FCN_FILES) \
   $(PKG_ADD_FILES)
 
-FCN_FILES_WITH_TESTS = $(shell $(SHELL) $(srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(FCN_FILES) $(GEN_FCN_FILES_IN))
+FCN_FILES_WITH_TESTS = $(shell $(SHELL) build-aux/find-files-with-tests.sh "$(srcdir)" $(FCN_FILES) $(GEN_FCN_FILES_IN))
 
 define PKG_ADD_FILE_TEMPLATE
 $(1)/PKG_ADD: $$($(2)_FCN_FILES) $$($(2)_GEN_FCN_FILES) $(1)/$(octave_dirstamp) %reldir%/mk-pkg-add.sh
--- a/scripts/ode/odeset.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/ode/odeset.m	Fri Jun 23 20:51:51 2023 +0200
@@ -154,8 +154,6 @@
   persistent p;
 
   if (isempty (p))
-    ## FIXME: Add an inexact match option once it is available in inputParser.
-    ## See bug #49364.
     p = inputParser ();
     p.addParameter ("AbsTol", []);
     p.addParameter ("BDF", []);
@@ -281,13 +279,10 @@
 %! odeopt = odeset ("NewtonTol", 3);
 %! assert (odeopt.NewtonTol, 3);
 
-## FIXME: Add an inexact match option once it is available in inputParser.
-## See bug #49364.
-## %!warning <no exact match for 'Rel'.  Assuming 'RelTol'> odeset ("Rel", 1);
-## %!error <Possible fields found: InitialSlope, InitialStep> odeset ("Initial", 1)
-
 ## Test input validation
-%!error <argument 'OPT1' is not a valid parameter> odeset ("opt1")
+%!error <argument 'opt1' is not a declared parameter> odeset ("opt1")
 %!error odeset (1, 1)
-%!error <argument 'OPT1' is not a valid parameter> odeset (odeset (), "opt1")
+%!error <argument 'opt1' is not a declared parameter> odeset (odeset (), "opt1")
 %!error odeset (odeset (), 1, 1)
+%!error <'Re' matches more than one Parameter: 'Refine', 'RelTol'>
+%! odeset ('Re', 1);
--- a/scripts/optimization/__all_opts__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/optimization/__all_opts__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -63,7 +63,7 @@
       end_try_catch
     endfor
     names = unique (names);
-    [lnames, idx] = unique (tolower (names));
+    [lnames, idx] = unique (lower (names));
     if (length (lnames) < length (names))
       ## This is bad.
       error ("__all_opts__: duplicate options with inconsistent case");
--- a/scripts/optimization/sqp.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/optimization/sqp.m	Fri Jun 23 20:51:51 2023 +0200
@@ -121,8 +121,7 @@
 ## inequality constraints @var{g} and @var{h}.  If the arguments are vectors
 ## then @var{x}(i) is bound by @var{lb}(i) and @var{ub}(i).  A bound can also
 ## be a scalar in which case all elements of @var{x} will share the same
-## bound.  If only one bound (lb, ub) is specified then the other will
-## default to (-@var{realmax}, +@var{realmax}).
+## bound.
 ##
 ## The seventh argument @var{maxiter} specifies the maximum number of
 ## iterations.  The default value is 100.
@@ -288,37 +287,43 @@
       ## constraint inequality function with bounds present
       lb_idx = ub_idx = true (size (x0));
       ub_grad = - (lb_grad = eye (rows (x0)));
+
+      ## if unspecified set ub and lb to +/-Inf, preserving single type
+      if (isempty (lb))
+        if (isa (x0, "single"))
+          lb = - inf (size (x0), "single");
+        else
+          lb = - inf (size (x0));
+        endif
+      endif
+
       if (isvector (lb))
-        globals.lb = tmp_lb = lb(:);
-        lb_idx(:) = tmp_idx = (lb != -Inf);
-        globals.lb = globals.lb(tmp_idx, 1);
+        lb = lb(:);
+        lb_idx(:) = (lb != -Inf);
+        globals.lb = lb(lb_idx, 1);
         lb_grad = lb_grad(lb_idx, :);
-      elseif (isempty (lb))
-        if (isa (x0, "single"))
-          globals.lb = tmp_lb = -realmax ("single");
-        else
-          globals.lb = tmp_lb = -realmax ();
-        endif
       else
         error ("sqp: invalid lower bound");
       endif
 
+      if (isempty (ub))
+        if (isa (x0, "single"))
+          ub = inf (size (x0), "single");
+        else
+          ub = inf (size (x0));
+        endif
+      endif
+
       if (isvector (ub))
-        globals.ub = tmp_ub = ub(:);
-        ub_idx(:) = tmp_idx = (ub != Inf);
-        globals.ub = globals.ub(tmp_idx, 1);
+        ub = ub(:);
+        ub_idx(:) = (ub != Inf);
+        globals.ub = ub(ub_idx, 1);
         ub_grad = ub_grad(ub_idx, :);
-      elseif (isempty (ub))
-        if (isa (x0, "single"))
-          globals.ub = tmp_ub = realmax ("single");
-        else
-          globals.ub = tmp_ub = realmax ();
-        endif
       else
         error ("sqp: invalid upper bound");
       endif
 
-      if (any (tmp_lb > tmp_ub))
+      if (any (globals.lb > globals.ub))
         error ("sqp: upper bound smaller than lower bound");
       endif
       bounds_grad = [lb_grad; ub_grad];
@@ -705,15 +710,32 @@
 
 
 function res = cf_ub_lb (x, lbidx, ubidx, globals)
+  ## function returning constraint evaluated at x, and distance between ub/lb
+  ## and x, when they are specified (otherwise return empty)
 
-  ## combine constraint function with ub and lb
-  if (isempty (globals.cifcn))
-    res = [x(lbidx,1)-globals.lb; globals.ub-x(ubidx,1)];
+  ## inequality constraints
+  if (! isempty (globals.cifcn))
+    ci = feval (globals.cifcn, x);
+  else
+    ci = [];
+  endif
+
+  ## lower bounds
+  if (! isempty (globals.lb))
+    lb = x(lbidx, 1) - globals.lb;
   else
-    res = [feval(globals.cifcn,x); x(lbidx,1)-globals.lb;
-           globals.ub-x(ubidx,1)];
+    lb = [];
   endif
 
+  ## upper bounds
+  if (! isempty (globals.ub))
+    ub = globals.ub - x(ubidx, 1);
+  else
+    ub = [];
+  end
+
+  res = [ci; lb; ub];
+
 endfunction
 
 
--- a/scripts/pkg/private/get_description.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/pkg/private/get_description.m	Fri Jun 23 20:51:51 2023 +0200
@@ -54,7 +54,7 @@
         warning ("pkg: skipping invalid line in DESCRIPTION file");
       else
         colon = colon(1);
-        keyword = tolower (strtrim (line(1:colon-1)));
+        keyword = lower (strtrim (line(1:colon-1)));
         value = strtrim (line (colon+1:end));
         if (length (value) == 0)
             fclose (fid);
@@ -91,7 +91,7 @@
   else
     desc.depends = "";
   endif
-  desc.name = tolower (desc.name);
+  desc.name = lower (desc.name);
 
 endfunction
 
@@ -101,7 +101,7 @@
 ##   package, version, operator
 function deps_cell = fix_depends (depends)
 
-  deps = strtrim (ostrsplit (tolower (depends), ","));
+  deps = strtrim (ostrsplit (lower (depends), ","));
   deps_cell = cell (1, length (deps));
   dep_pat = ...
   '\s*(?<name>[-\w]+)\s*(\(\s*(?<op>[<>=]+)\s*(?<ver>\d+\.\d+(\.\d+)*)\s*\))*\s*';
@@ -113,7 +113,7 @@
     ## Is the dependency specified
     ## in the correct format?
     if (! isempty (start))
-      package = tolower (strtrim (nm.name));
+      package = lower (strtrim (nm.name));
       ## Does the dependency specify a version
       ## Example: package(>= version).
       if (! isempty (nm.ver))
@@ -128,7 +128,7 @@
         ## If no version is specified for the dependency
         ## we say that the version should be greater than
         ## or equal to "0.0.0".
-        package = tolower (strtrim (dep));
+        package = lower (strtrim (dep));
         operator = ">=";
         nm.ver  = "0.0.0";
       endif
--- a/scripts/pkg/private/get_forge_pkg.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/pkg/private/get_forge_pkg.m	Fri Jun 23 20:51:51 2023 +0200
@@ -40,7 +40,7 @@
     error ("get_forge_pkg: invalid package NAME: %s", name);
   endif
 
-  name = tolower (name);
+  name = lower (name);
 
   ## Try to download package's index page.
   [html, succ] = urlread (sprintf ("https://packages.octave.org/%s/index.html", ...
@@ -81,10 +81,10 @@
       len1 = length (name);
       len2 = length (x);
       if (len1 <= len2)
-        d = sum (abs (tolower (name(1:len1)) - tolower (x(1:len1)))) ...
+        d = sum (abs (lower (name(1:len1)) - lower (x(1:len1)))) ...
             + (len2 - len1)*23;
       else
-        d = sum (abs (tolower (name(1:len2)) - tolower (x(1:len2)))) ...
+        d = sum (abs (lower (name(1:len2)) - lower (x(1:len2)))) ...
             + (len1 - len2)*23;
       endif
 
--- a/scripts/pkg/private/install.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/pkg/private/install.m	Fri Jun 23 20:51:51 2023 +0200
@@ -329,11 +329,7 @@
 
 function pkg = extract_pkg (nm, pat)
 
-  mfile_encoding = __mfile_encoding__ ();
-  if (strcmp (mfile_encoding, "system"))
-    mfile_encoding = __locale_charset__ ();
-  endif
-  fid = fopen (nm, "rt", "n", mfile_encoding);
+  fid = fopen (nm, "rt", "n", mfile_encoding ());
   pkg = "";
   if (fid >= 0)
     while (! feof (fid))
--- a/scripts/plot/appearance/camorbit.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/camorbit.m	Fri Jun 23 20:51:51 2023 +0200
@@ -138,7 +138,7 @@
   endif
 
   if (ischar (dir))
-    switch (tolower (dir))
+    switch (lower (dir))
       case "x"
         dir = [1 0 0];
       case "y"
--- a/scripts/plot/appearance/daspect.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/daspect.m	Fri Jun 23 20:51:51 2023 +0200
@@ -82,7 +82,7 @@
         error ("daspect: DATA_ASPECT_RATIO must be a 2 or 3 element vector");
       endif
     elseif (ischar (arg))
-      arg = tolower (arg);
+      arg = lower (arg);
       switch (arg)
         case "auto"
           set (hax, "dataaspectratiomode", "auto");
--- a/scripts/plot/appearance/datetick.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/datetick.m	Fri Jun 23 20:51:51 2023 +0200
@@ -133,7 +133,7 @@
   if (nargin != 0)
     arg = varargin{1};
     if (ischar (arg) && any (strcmpi (arg, {"x", "y", "z"})))
-      ax = tolower (arg);
+      ax = lower (arg);
       if (nargin > 1)
         form = varargin{2};
         varargin(1:2) = [];
--- a/scripts/plot/appearance/pbaspect.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/pbaspect.m	Fri Jun 23 20:51:51 2023 +0200
@@ -83,7 +83,7 @@
         error ("pbaspect: PLOT_BOX_ASPECT_RATIO must be a 2 or 3 element vector");
       endif
     elseif (ischar (arg))
-      arg = tolower (arg);
+      arg = lower (arg);
       switch (arg)
         case "auto"
           set (hax, "plotboxaspectratiomode", "auto");
--- a/scripts/plot/appearance/private/__axis_limits__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/private/__axis_limits__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -26,9 +26,13 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{limits} =} __axis_limits__ (@var{fcn})
 ## @deftypefnx {} {@var{xmode} =} __axis_limits__ (@var{fcn}, "mode")
+## @deftypefnx {} {@var{xmethod} =} __axis_limits__ (@var{fcn}, "method")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, [@var{x_lo} @var{x_hi}])
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "auto")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "manual")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "tickaligned")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "tight")
+## @deftypefnx {} {} __axis_limits__ (@var{fcn}, "padded")
 ## @deftypefnx {} {} __axis_limits__ (@var{fcn}, @var{hax}, @dots{})
 ## @deftypefn {} {@var{old_limits} =} __axis_limits__ (@var{fcn}, @dots{})
 ## Internal function that implements common code to query or set the axis
@@ -48,13 +52,18 @@
     retval = get (hax, fcn);
   else
     retval = [];
-    fcnmode = [fcn "mode"];
     arg = varargin{1};
     if (ischar (arg))
       if (strcmpi (arg, "mode"))
-        retval = get (hax, fcnmode);
+        retval = get (hax, [fcn "mode"]);
+      elseif (strcmpi (arg, "method"))
+        retval = get (hax, [fcn "itmethod"]);
       elseif (any (strcmpi (arg, {"auto", "manual"})))
-        set (hax, fcnmode, arg);
+        set (hax, [fcn "mode"], arg);
+      elseif (any (strcmpi (arg, {"tickaligned", "tight", "padded"})))
+        set (hax, [fcn "itmethod"], arg);
+      else
+        error ('%s: unrecognized argument "%s"', fcn, arg);
       endif
     else
       if (! isnumeric (arg) || any (size (arg(:)) != [2, 1]))
--- a/scripts/plot/appearance/private/__tickangle__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/private/__tickangle__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -31,7 +31,7 @@
 
 function retval = __tickangle__ (caller, hax, angle)
 
-  ax = tolower (caller(1));
+  ax = lower (caller(1));
   switch (nargin)
     case 1
       retval = get (gca (), [ax, "ticklabelrotation"]);
--- a/scripts/plot/appearance/rticks.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/rticks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -92,7 +92,7 @@
     error ("rticks: MODE is not yet implemented for the rtick property");
 
     ## FIXME: Enable mode args if/when they are available in polar/polarplot
-    ## arg = tolower (arg);
+    ## arg = lower (arg);
     ## switch (arg)
     ##   case "mode"
     ##     tickval = get (hax, "rtickmode");
--- a/scripts/plot/appearance/thetaticks.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/thetaticks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -96,7 +96,7 @@
     error ("thetaticks: MODE is not yet implemented for the ttick property");
 
     ## FIXME: Enable mode args if/when they are available in polar/polarplot
-    ##    arg = tolower (arg);
+    ##    arg = lower (arg);
     ## switch (arg)
     ##   case "mode"
     ##     tickval = get (hax, "ttickmode");
--- a/scripts/plot/appearance/xlim.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/xlim.m	Fri Jun 23 20:51:51 2023 +0200
@@ -26,9 +26,10 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{xlimits} =} xlim ()
 ## @deftypefnx {} {@var{xmode} =} xlim ("mode")
+## @deftypefnx {} {@var{xmethod} =} xlim ("method")
 ## @deftypefnx {} {} xlim ([@var{x_lo} @var{x_hi}])
-## @deftypefnx {} {} xlim ("auto")
-## @deftypefnx {} {} xlim ("manual")
+## @deftypefnx {} {} xlim ("mode")
+## @deftypefnx {} {} xlim ("method")
 ## @deftypefnx {} {} xlim (@var{hax}, @dots{})
 ## Query or set the limits of the x-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current x-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current x-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{x_lo} @var{x_hi}], the limits of the
 ## x-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+##
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+##
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{xlim} function operates by modifying the
-## @qcode{"xlim"} and @qcode{"xlimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"xlim"}, @qcode{"xlimmode"}, and @qcode{"xlimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{ylim, zlim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -97,6 +126,8 @@
 %!   xlim ([0, 1.1]);
 %!   assert (get (gca, "xlim"), [0, 1.1], eps);
 %!   assert (xlim ("mode"), "manual");
+%!   xlim ('padded');
+%!   assert (get (gca, "xlimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -107,6 +138,7 @@
 %!   h = plot3 ([0,1.1], [0,1], [0, 1]);
 %!   assert (get (gca, "xlim"), [0, 1.4], eps);
 %!   assert (xlim ("mode"), "auto");
+%!   assert (xlim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -116,6 +148,7 @@
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   h = plot3 ([0,1.1], [0,1], [0, 1]);
+%!   fail ("xlim ('foobar')", 'unrecognized argument "foobar"');
 %!   fail ("xlim ({1, 2})", "LIMITS must be a 2-element vector");
 %!   fail ("xlim ([1, 2, 3])", "LIMITS must be a 2-element vector");
 %!   fail ("xlim ([2, 1])", "axis limits must be increasing");
--- a/scripts/plot/appearance/xticklabels.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/xticklabels.m	Fri Jun 23 20:51:51 2023 +0200
@@ -88,6 +88,14 @@
     hax = gca ();
   endif
 
+  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))
+    print_usage ();
+  endif
+
+  if (isempty (arg))
+    arg = {};  # Either '' or [] are converted empty cell array
+  endif
+
   if (iscell (arg) || isnumeric (arg))
     if (nargout > 0)
       error ("xticklabels: too many output arguments requested");
@@ -99,7 +107,6 @@
       ## This implementation allows for a numeric array, which is handled in
       ## the same order as Matlab handles a cell array
       arg = num2cell (arg(:));
-
     endif
 
     ## Convert any numeric elements to characters, make it a 1-D cell array.
@@ -114,8 +121,7 @@
               "xtickmode", "manual");
 
   elseif (ischar (arg))
-    arg = tolower (arg);
-    switch (arg)
+    switch (lower (arg))
       case "mode"
         labels = get (hax, "xticklabelmode");
 
@@ -131,8 +137,6 @@
 
     endswitch
 
-  else
-    print_usage ();
   endif
 
 endfunction
--- a/scripts/plot/appearance/xticks.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/xticks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -94,7 +94,7 @@
     set (hax, "xtick", arg);
 
   elseif (ischar (arg))
-    arg = tolower (arg);
+    arg = lower (arg);
     switch (arg)
       case "mode"
         tickval = get (hax, "xtickmode");
--- a/scripts/plot/appearance/ylim.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/ylim.m	Fri Jun 23 20:51:51 2023 +0200
@@ -25,10 +25,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{ylimits} =} ylim ()
-## @deftypefnx {} {@var{xmode} =} ylim ("mode")
+## @deftypefnx {} {@var{ymode} =} ylim ("mode")
+## @deftypefnx {} {@var{ymethod} =} ylim ("method")
 ## @deftypefnx {} {} ylim ([@var{y_lo} @var{y_hi}])
-## @deftypefnx {} {} ylim ("auto")
-## @deftypefnx {} {} ylim ("manual")
+## @deftypefnx {} {} ylim ("mode")
+## @deftypefnx {} {} ylim ("method")
 ## @deftypefnx {} {} ylim (@var{hax}, @dots{})
 ## Query or set the limits of the y-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current y-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current y-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{y_lo} @var{y_hi}], the limits of the
 ## y-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+##
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+##
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{ylim} function operates by modifying the
-## @qcode{"ylim"} and @qcode{"ylimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"ylim"}, @qcode{"ylimmode"}, and @qcode{"ylimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{xlim, zlim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -98,6 +127,8 @@
 %!   ylim (limy);
 %!   assert (get (gca, "ylim"), limy, eps);
 %!   assert (ylim ("mode"), "manual");
+%!   ylim ('padded');
+%!   assert (get (gca, "ylimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -108,6 +139,7 @@
 %!   plot3 ([0,1], [0,1.1], [0, 1]);
 %!   assert (get (gca, "ylim"), [0, 1.4], eps);
 %!   assert (ylim ("mode"), "auto");
+%!   assert (ylim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/plot/appearance/yticklabels.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/yticklabels.m	Fri Jun 23 20:51:51 2023 +0200
@@ -88,6 +88,14 @@
     hax = gca ();
   endif
 
+  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))
+    print_usage ();
+  endif
+
+  if (isempty (arg))
+    arg = {};  # Either '' or [] are converted empty cell array
+  endif
+
   if (iscell (arg) || isnumeric (arg))
     if (nargout > 0)
       error ("yticklabels: too many output arguments requested");
@@ -99,7 +107,6 @@
       ## This implementation allows for a numeric array, which is handled in
       ## the same order as Matlab handles a cell array
       arg = num2cell (arg(:));
-
     endif
 
     ## Convert any numeric elements to characters, make it a 1-D cell array.
@@ -113,9 +120,8 @@
               "yticklabelmode", "manual",
               "ytickmode", "manual");
 
-  elseif (ischar (arg))
-    arg = tolower (arg);
-    switch (arg)
+  else
+    switch (lower (arg))
       case "mode"
         labels = get (hax, "yticklabelmode");
 
@@ -131,8 +137,6 @@
 
     endswitch
 
-  else
-    print_usage ();
   endif
 
 endfunction
--- a/scripts/plot/appearance/yticks.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/yticks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -96,7 +96,7 @@
     endif
 
   elseif (ischar (arg))
-    arg = tolower (arg);
+    arg = lower (arg);
     switch (arg)
       case "mode"
         tickval = get (hax, "ytickmode");
--- a/scripts/plot/appearance/zlim.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/zlim.m	Fri Jun 23 20:51:51 2023 +0200
@@ -25,10 +25,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{zlimits} =} zlim ()
-## @deftypefnx {} {@var{xmode} =} zlim ("mode")
+## @deftypefnx {} {@var{zmode} =} zlim ("mode")
+## @deftypefnx {} {@var{zmethod} =} zlim ("method")
 ## @deftypefnx {} {} zlim ([@var{z_lo} @var{z_hi}])
-## @deftypefnx {} {} zlim ("auto")
-## @deftypefnx {} {} zlim ("manual")
+## @deftypefnx {} {} zlim ("mode")
+## @deftypefnx {} {} zlim ("method")
 ## @deftypefnx {} {} zlim (@var{hax}, @dots{})
 ## Query or set the limits of the z-axis for the current plot.
 ##
@@ -38,20 +39,48 @@
 ## With the input query @qcode{"mode"}, return the current z-limit calculation
 ## mode which is either @qcode{"auto"} or @qcode{"manual"}.
 ##
+## With the input query @qcode{"method"}, return the current z-limit
+## calculation method which is either @qcode{"tickaligned"}, @qcode{"tight"},
+## or @qcode{"padded"}.
+##
 ## If passed a 2-element vector [@var{z_lo} @var{z_hi}], the limits of the
 ## z-axis are set to these values and the mode is set to @qcode{"manual"}.
 ## The special values -Inf and Inf can be used to indicate that either
 ## the lower axis limit or upper axis limit should be automatically calculated.
 ##
-## The current plotting mode can be changed by using either @qcode{"auto"}
-## or @qcode{"manual"} as the argument.
+## The current limit calculation "mode" may be one of
+##
+## @table @asis
+## @item @qcode{"auto"} (default)
+## Automatically calculate limits based on the plot data and the currently
+## specified limit calculation method.
+##
+## @item @qcode{"manual"}
+## Fix axis limits at current values.
+## @end table
+##
+## The current limit calculation method may be one of
+##
+## @table @asis
+## @item @qcode{"tickaligned"} (default)
+## Calculate limits that encompass all of the data and extend outwards to the
+## nearest tick mark.
+##
+## @item @qcode{"tight"}
+## Calculate limits that exactly fit the data range.
+##
+## @item @qcode{"padded"}
+## Calculate limits that leave a margin around the data of approximately 7% of
+## the data range.
+## @end table
 ##
 ## If the first argument @var{hax} is an axes handle, then operate on
 ## this axes rather than the current axes returned by @code{gca}.
 ##
 ## Programming Note: The @code{zlim} function operates by modifying the
-## @qcode{"zlim"} and @qcode{"zlimmode"} properties of an axes object.  These
-## properties can be directly inspected and altered with @code{get}/@code{set}.
+## @qcode{"zlim"}, @qcode{"zlimmode"}, and @qcode{"zlimitmethod"} properties of
+## an axes object.  These properties can be directly inspected and altered with
+## @code{get}/@code{set}.
 ## @seealso{xlim, ylim, axis, set, get, gca}
 ## @end deftypefn
 
@@ -98,6 +127,8 @@
 %!   zlim (limz);
 %!   assert (get (gca, "zlim"), limz, eps);
 %!   assert (zlim ("mode"), "manual");
+%!   zlim ('padded');
+%!   assert (get (gca, "zlimitmethod"), 'padded');
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
@@ -108,6 +139,7 @@
 %!   plot3 ([0,1], [0,1], [0, 1.1]);
 %!   assert (get (gca, "zlim"), [0, 1.4], eps);
 %!   assert (zlim ("mode"), "auto");
+%!   assert (zlim ("method"), "tickaligned");
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/plot/appearance/zticklabels.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/zticklabels.m	Fri Jun 23 20:51:51 2023 +0200
@@ -88,6 +88,14 @@
     hax = gca ();
   endif
 
+  if (! (iscell (arg) || isnumeric (arg) || ischar (arg)))
+    print_usage ();
+  endif
+
+  if (isempty (arg))
+    arg = {};  # Either '' or [] are converted empty cell array
+  endif
+
   if (iscell (arg) || isnumeric (arg))
     if (nargout > 0)
       error ("zticklabels: too many output arguments requested");
@@ -99,7 +107,6 @@
       ## This implementation allows for a numeric array, which is handled in
       ## the same order as Matlab handles a cell array
       arg = num2cell (arg(:));
-
     endif
 
     ## Convert any numeric elements to characters, make it a 1-D cell array.
@@ -114,8 +121,7 @@
               "ztickmode", "manual");
 
   elseif (ischar (arg))
-    arg = tolower (arg);
-    switch (arg)
+    switch (lower (arg))
       case "mode"
         labels = get (hax, "zticklabelmode");
 
@@ -131,8 +137,6 @@
 
     endswitch
 
-  else
-    print_usage ();
   endif
 
 endfunction
--- a/scripts/plot/appearance/zticks.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/appearance/zticks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -94,7 +94,7 @@
     set (hax, "ztick", arg);
 
   elseif (ischar (arg))
-    arg = tolower (arg);
+    arg = lower (arg);
     switch (arg)
       case "mode"
         tickval = get (hax, "ztickmode");
--- a/scripts/plot/draw/camlight.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/camlight.m	Fri Jun 23 20:51:51 2023 +0200
@@ -168,7 +168,7 @@
   endif
 
   if (! isempty (where))
-    switch (tolower (where))
+    switch (lower (where))
       case "left"
         az = -30;
         el = 30;
--- a/scripts/plot/draw/colorbar.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/colorbar.m	Fri Jun 23 20:51:51 2023 +0200
@@ -117,19 +117,19 @@
       error ("colorbar: expected string argument at position %d", i-1);
     endif
 
-    switch (tolower (arg))
+    switch (lower (arg))
       case {"north", "south", "east", "west", ...
             "northoutside", "southoutside", "eastoutside", "westoutside"}
         if (i <= nargin)
           error ("colorbar: LOC specification must occur as final argument");
         endif
-        loc = tolower (arg);
+        loc = lower (arg);
 
       case "location"
         if (i > nargin)
           error ('colorbar: missing value after "location"');
         endif
-        loc = tolower (varargin{i++});
+        loc = lower (varargin{i++});
 
       case {"delete", "hide", "off"}
         delete_cbar = true;
--- a/scripts/plot/draw/isocaps.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/isocaps.m	Fri Jun 23 20:51:51 2023 +0200
@@ -124,7 +124,7 @@
   ## select type of cap (above or below iso value)
   data_min = min ([v(:); isoval]);
   data_max = max ([v(:); isoval]);
-  switch (tolower (which_caps))
+  switch (lower (which_caps))
     case {"a", "above"}
       pad_val = data_min - 1;
 
--- a/scripts/plot/draw/isosurface.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/isosurface.m	Fri Jun 23 20:51:51 2023 +0200
@@ -245,7 +245,7 @@
     if (! ischar (varargin{i_arg}) || i_arg < 1)
       break;  # no string arguments at end, exit checking
     endif
-    switch (tolower (varargin{i_arg}))
+    switch (lower (varargin{i_arg}))
       case {"v", "verbose"}
         verbose = true;
         num_string_inputs++;
--- a/scripts/plot/draw/pcolor.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/pcolor.m	Fri Jun 23 20:51:51 2023 +0200
@@ -91,44 +91,9 @@
     set (htmp, "facecolor", "flat");
     if (! ishold ())
       set (hax, "view", [0, 90], "box", "on");
-      ## FIXME: Maybe this should be in the general axis limit setting routine?
-      ##        When values are integers (such as from meshgrid), we want to
-      ##        use tight limits for pcolor, mesh, surf, etc.  Situation is
-      ##        complicated immensely by vector or matrix input and meshgrid()
-      ##        or ndgrid() format.
-      meshgrid_fmt = true;
-      if (isvector (x))
-        xrng = x(isfinite (x));
-      else
-        xrng = x(1, isfinite (x(1,:)));    # meshgrid format (default)
-        if (all (xrng == xrng(1)))
-          xrng = x(isfinite (x(:,1)), 1);  # ndgrid format
-          meshgrid_fmt = false;
-        endif
-      endif
-      if (isvector (y))
-        yrng = y(isfinite (y));
-      else
-        if (meshgrid_fmt)
-          yrng = y(isfinite (y(:,1)), 1);
-        else
-          yrng = y(1, isfinite (y(1,:)));
-        endif
-      endif
-      if (all (xrng == fix (xrng)))
-        xmin = min (xrng);
-        xmax = max (xrng);
-        if (xmin < xmax)
-          xlim ([xmin, xmax]);
-        endif
-      endif
-      if (all (yrng == fix (yrng)))
-        ymin = min (yrng);
-        ymax = max (yrng);
-        if (ymin < ymax)
-          ylim ([ymin, ymax]);
-        endif
-      endif
+      set (hax, "xlimmode", "auto", "ylimmode", "auto", "zlimmode", "auto",
+                "xlimitmethod", "tight", "ylimitmethod", "tight",
+                "zlimitmethod", "tight");
     endif
 
   unwind_protect_cleanup
--- a/scripts/plot/draw/private/__add_datasource__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/private/__add_datasource__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
     arg = varargin{++i};
     if (i != numel (varargin) && ischar (arg)
         && length (arg) > 9 && strcmpi (arg(end-9:end), "datasource"))
-      arg = tolower (arg);
+      arg = lower (arg);
       val = varargin{++i};
       if (ischar (val))
         set (h, arg, val);
--- a/scripts/plot/draw/private/__patch__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/private/__patch__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -162,7 +162,7 @@
     elseif (iscolorspec (c))
       ## Color specification is a string
       args{7} = "facecolor";
-      args{8} = tolower (c);
+      args{8} = lower (c);
       args{9} = "cdata";
       args{10} = [];
     elseif (! isempty (c))
--- a/scripts/plot/draw/private/__quiver__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/private/__quiver__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -28,8 +28,7 @@
 ## Undocumented internal function.
 ## @end deftypefn
 
-function hg = __quiver__ (varargin)
-
+function [hax, hg]= __quiver__ (varargin)
   hax = varargin{1};
   is3d = varargin{2};
 
@@ -40,74 +39,120 @@
   ## in order to get equivalent visual results while keeping equivalent
   ## property values.
   arrowsize = 0.20;
-
-  firstnonnumeric = find (! cellfun ("isnumeric", varargin(3:nargin)), 1);
-  if (isempty (firstnonnumeric))
-    firstnonnumeric = Inf;
-  else
-    firstnonnumeric += 2;
-  endif
+  lastnumeric = find (cellfun ("ischar", varargin(3:nargin)), 1) - 1;
 
-  ioff = 3;
-  if (nargin < (6 + is3d) || firstnonnumeric < (6 + is3d))
-    if (is3d)
-      z = varargin{ioff++};
-    endif
-    u = varargin{ioff++};
-    v = varargin{ioff++};
-    if (is3d)
-      w = varargin{ioff++};
-    endif
-    if (is3d)
-      if (! size_equal (z, u, v, w))
-        error ("quiver3: Z, U, V, and W must be the same size");
-      endif
-    else
-      if (! size_equal (u, v))
-        error ("quiver: U and V must be the same size");
-      endif
-    endif
-    [x, y] = meshgrid (1:columns (u), 1:rows (u));
+  if (isempty (lastnumeric))
+    lastnumeric = nargin;
+    ## Recast non-float inputs as doubles to avoid erroneous plots.
+    varargin(3:end) = cellfun ('double', varargin(3:end), ...
+                                  "UniformOutput", false);
+  else
 
-    if (nargin >= ioff && isnumeric (varargin{ioff})
-        && isscalar (varargin{ioff}))
-      autoscale = varargin{ioff++};
-    endif
-  else
-    x = varargin{ioff++};
-    y = varargin{ioff++};
-    if (is3d)
-      z = varargin{ioff++};
-    endif
-    u = varargin{ioff++};
-    v = varargin{ioff++};
-    if (is3d)
-      w = varargin{ioff++};
-      if (isvector (x) && isvector (y) && isvector (z)
-          && (! isvector (u) || ! isvector (v) || ! isvector (w)))
-        [x, y, z] = meshgrid (x, y, z);
-      endif
-    else
-      if (isvector (x) && isvector (y) && (! isvector (u) || ! isvector (v)))
-        [x, y] = meshgrid (x, y);
-      endif
-    endif
-    if (is3d)
-      if (! size_equal (x, y, z, u, v, w))
-        error ("quiver3: X, Y, Z, U, V, and W must be the same size");
-      endif
-    else
-      if (! size_equal (x, y, u, v))
-        error ("quiver: X, Y, U, and V must be the same size");
-      endif
-    endif
+    lastnumeric += 2;
+    ## Recast non-float inputs as doubles to avoid erroneous plots.
+    varargin(3:lastnumeric) = cellfun ('double',
+                    varargin(3:lastnumeric), "UniformOutput", false);
 
-    if (nargin >= ioff && isnumeric (varargin{ioff})
-        && isscalar (varargin{ioff}))
-      autoscale = varargin{ioff++};
+    ## Check for scaling factor "off" and set it to 0.
+    if ((nargin > lastnumeric) && strcmpi (varargin{lastnumeric+1}, "off"))
+      varargin(++lastnumeric) = 0;
     endif
   endif
 
+  if (is3d)
+    ## quiver3 3D input validation.
+    switch (lastnumeric)
+      case {6,7}
+        [z, u, v, w] = deal (varargin{3:6});
+        if (isvector (z) && ! isvector (u))
+          if (! size_equal (u, v, w))
+            error ("quiver3: U, V, and W must be the same size");
+          elseif (numel(z) != size (u, 3))
+            error (["quiver3: Z vector length must equal size of ", ...
+                        "U, V, and W in dim 3"]);
+          endif
+          [x, y, z] = meshgrid (1 : columns (u), 1 : rows (u), z);
+        else
+          if (! size_equal (z, u, v, w))
+            error ("quiver3: Z, U, V, and W must be the same size");
+          endif
+          [x, y] = meshgrid (1 : columns (u), 1 : rows (u), 1:size (u, 3));
+        endif
+
+      case {8,9}
+        [x, y, z, u, v, w] = deal (varargin{3:8});
+        if (isvector (x) && isvector (y) && isvector (z) && ! isvector (u))
+          if (! size_equal (u, v, w))
+            error ("quiver3: U, V, and W must be the same size");
+          elseif (numel(x) != columns (u))
+            error (["quiver3: X vector length must equal number of ", ...
+                        "columns in U, V, and W"]);
+          elseif (numel(y) != rows (u))
+            error (["quiver3: Y vector length must equal number of ", ...
+                        "rows in U, V, and W"]);
+          elseif (numel(z) != size (u, 3))
+            error (["quiver3: Z vector length must equal size of ", ...
+                        "U, V, and W in dim 3"]);
+          endif
+          [x, y, z] = meshgrid (x, y, z);
+
+        elseif (! size_equal (x, y, z, u, v, w))
+          error ("quiver3: X, Y, Z, U, V, and W must be the same size");
+        endif
+      otherwise
+        ## too few or too many numeric inputs before first style input
+        print_usage ("quiver3");
+    endswitch
+
+  else
+    ## quiver 2D input validation.
+    switch (lastnumeric)
+      case {4,5}
+        [u, v] = deal (varargin{3:4});
+        if (! size_equal (u, v))
+          error ("quiver: U and V must be the same size");
+        endif
+        [x, y] = meshgrid (1:columns (u), 1:rows (u));
+
+      case {6,7} #
+        [x, y, u, v] = deal (varargin{3:6});
+
+        if (isvector (x) && isvector (y) && ...
+                (! isvector (u) || ! isvector (v) ))
+           if (! size_equal (u, v))
+              error ("quiver: U and V must be the same size");
+           elseif (numel (x) != columns (u))
+              error (["quiver: X vector length must equal number of ", ...
+                        "columns in U and V"]);
+           elseif (numel (y) != rows (u))
+              error (["quiver: Y vector length must equal number of ", ...
+                        "rows in U and V"]);
+           endif
+          [x, y] = meshgrid (x, y);
+        elseif (! size_equal (x, y, u, v))
+          error ("quiver: X, Y, U, and V must be the same size");
+        endif
+      otherwise
+        ## too few or too many numeric inputs before first style input
+        print_usage ("quiver");
+    endswitch
+  endif
+
+  if (rem (lastnumeric, 2))
+    autoscale = varargin{lastnumeric}; # Last odd input is scale factor.
+
+    if (autoscale < 0 || ! isscalar (autoscale))
+      if (is3d)
+        error (["quiver3: scaling factor must be a non-negative scalar ", ...
+                 "or 'off'"]);
+      else
+        error (["quiver: scaling factor must be a non-negative scalar ", ...
+                 "or 'off'"]);
+      endif
+    endif
+  endif
+
+  ioff = lastnumeric + 1;
   have_filled = false;
   have_line_spec = false;
   args = {};
@@ -149,7 +194,7 @@
   else
     len = max (sqrt (u(:).^2 + v(:).^2));
   endif
-  if (len > 0 && autoscale && numel (u) > 1)
+  if (len > 0 && autoscale && numel (u) >= 1)
     if (isvector (x))
       nx = ny = sqrt (length (x));
     else
@@ -175,6 +220,7 @@
     endif
   endif
 
+  hax = newplot (hax);
   hstate = get (hax, "nextplot");
   unwind_protect
     if (have_line_spec)
@@ -333,7 +379,12 @@
 
     if (! isempty (args))
       set (hg, args{:});
+      if (have_line_spec && ! isempty (linespec.marker) && ...
+            ! strcmp (linespec.marker, "none"))
+        set (h2, "linestyle", "none");
+      endif
     endif
+
   unwind_protect_cleanup
     set (hax, "nextplot", hstate);
   end_unwind_protect
@@ -450,7 +501,8 @@
   set (kids([3 2]), {"color", "linestyle", "linewidth"},
             get (h, {"color", "linestyle", "linewidth"}));
   set (kids(2), "visible", get (h, "showarrowhead"));
-  set (kids(1), {"color", "marker", "markerfacecolor", "markersize"},
-        get (h, {"color", "marker", "markerfacecolor", "markersize"}));
+  set (kids(1), {"color", "marker", "markerfacecolor", "markersize", ...
+            "linewidth"}, get (h, {"color", "marker", "markerfacecolor", ...
+            "markersize", "linewidth"}));
 
 endfunction
--- a/scripts/plot/draw/private/__scatter__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/private/__scatter__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -87,7 +87,7 @@
       c = c(:);
     endif
   elseif (firstnonnumeric == istart && ischar (varargin{istart})
-          && any (tolower (varargin{istart}(1)) == "ymcrgbwk"))
+          && any (lower (varargin{istart}(1)) == "ymcrgbwk"))
     [linespec, valid] = __pltopt__ (fcn, varargin{istart}, false);
     if (valid)
       c = varargin{istart};
--- a/scripts/plot/draw/quiver.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/quiver.m	Fri Jun 23 20:51:51 2023 +0200
@@ -36,8 +36,8 @@
 ##
 ## Plot the (@var{u}, @var{v}) components of a vector field at the grid points
 ## defined by (@var{x}, @var{y}).  If the grid is uniform then @var{x} and
-## @var{y} can be specified as vectors and @code{meshgrid} is used to create
-## the 2-D grid.
+## @var{y} can be specified as grid vectors and @code{meshgrid} is used to
+## create the 2-D grid.
 ##
 ## If @var{x} and @var{y} are not given they are assumed to be
 ## @code{(1:@var{m}, 1:@var{n})} where
@@ -46,14 +46,15 @@
 ## The optional input @var{s} is a scalar defining a scaling factor to use for
 ## the arrows of the field relative to the mesh spacing.  A value of 1.0 will
 ## result in the longest vector exactly filling one grid square.  A value of 0
-## disables all scaling.  The default value is 0.9.
+## or "off" disables all scaling.  The default value is 0.9.
 ##
-## The style to use for the plot can be defined with a line style @var{style}
+## The style to use for the plot can be defined with a line style, @var{style},
 ## of the same format as the @code{plot} command.  If a marker is specified
 ## then the markers are drawn at the origin of the vectors (which are the grid
 ## points defined by @var{x} and @var{y}).  When a marker is specified, the
 ## arrowhead is not drawn.  If the argument @qcode{"filled"} is given then the
-## markers are filled.
+## markers are filled.  If name-value plot style properties are used, they must
+## appear in pairs and follow any other plot style arguments.
 ##
 ## If the first argument @var{hax} is an axes handle, then plot into this axes,
 ## rather than the current axes returned by @code{gca}.
@@ -88,8 +89,7 @@
     oldfig = get (0, "currentfigure");
   endif
   unwind_protect
-    hax = newplot (hax);
-    htmp = __quiver__ (hax, false, varargin{:});
+    [hax, htmp] = __quiver__ (hax, false, varargin{:});
 
     ## FIXME: This should be moved into __quiver__ when problem with
     ##        re-initialization of title object is fixed.
@@ -138,3 +138,480 @@
 %! axis equal tight;
 %! hold on; plot (x,y,"r"); hold off;
 %! title ("quiver() with scaled arrows");
+
+## Check standard inputs, single arrow.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 1, 2);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!
+%!   h = quiver (hax, 1, 2, 0.5);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*0.5, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.5, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!
+%!   h = quiver (hax, 0, 1, 2, 3);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 0, eps);
+%!   assert (childxdata{stemchild}(2), 0 + 2*0.9, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 0 + 2*0.9, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!
+%!   h = quiver (hax, 0, 1, 2, 3, 0.5);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 0, eps);
+%!   assert (childxdata{stemchild}(2), 0 + 2*0.5, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 0 + 2*0.5, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check arrowhead size
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 0, 0, 0, 1, 1); # up
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [1/9 0 -1/9 NaN], eps);
+%!   assert (childydata{arrowheadchild}, [2/3 1 2/3 NaN], eps);
+%!
+%!   h = quiver (hax, 0, 0, 0, -1, 1); # down
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [-1/9 0 1/9 NaN], eps);
+%!   assert (childydata{arrowheadchild}, [-2/3 -1 -2/3 NaN], eps);
+%!
+%!   h = quiver (hax, 0, 0, -1, 0, 1); # left
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [-2/3 -1 -2/3 NaN], eps);
+%!   assert (childydata{arrowheadchild}, [1/9 0 -1/9 NaN], eps);
+%!
+%!   h = quiver (hax, 0, 0, 1, 0, 1); # right
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [2/3 1 2/3 NaN], eps);
+%!   assert (childydata{arrowheadchild}, [-1/9 0 1/9 NaN], eps);
+%!
+%!   h = quiver (hax, 0, 0, 1, 1, 1); # 45 deg - symmetric
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [7/9 1 5/9 NaN], eps);
+%!   assert (childydata{arrowheadchild}, [5/9 1 7/9 NaN], eps);
+%!
+%!   h = quiver (hax, 0, 0, sqrt(3), 1, 1); # 30 deg
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{arrowheadchild}, [(6*sqrt(3)+1)/9, sqrt(3), (6*sqrt(3)-1)/9, NaN], eps);
+%!   assert (childydata{arrowheadchild}, [(6-sqrt(3))/9, 1, (6+sqrt(3))/9, NaN], eps);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check standard inputs, multiple arrows.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   [x,y] = meshgrid (0:1);
+%!   u = [0 1; 1 -2];
+%!   v = [1 0; 1 -2];
+%!   numpts = 4;
+%!   h = quiver (hax, u, v, 1);  # assumes [x,y] = meshgrid (1:2)
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   basechild = find (cellfun (@numel, childxdata) == 1*numpts);
+%!   stemchild = find (cellfun (@numel, childxdata) == 3*numpts);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4*numpts);
+%!   assert (childxdata{basechild}, [1 1 2 2]);
+%!   assert (childxdata{stemchild}, [1,1,NaN,1,1.25,NaN,2,2.25,NaN,2,1.5,NaN], eps);
+%!   assert (childxdata{arrowheadchild}([2, 6, 10, 14]), [1, 1.25, 2.25, 1.5], eps);
+%!   assert (childxdata{arrowheadchild}([4, 8, 12, 16]), NaN(1,4), eps);
+%!
+%!   h = quiver (hax, x, y, u, v, 1);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   basechild = find (cellfun (@numel, childxdata) == 1*numpts);
+%!   stemchild = find (cellfun (@numel, childxdata) == 3*numpts);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4*numpts);
+%!   assert (childxdata{basechild}, [0 0 1 1]);
+%!   assert (childxdata{stemchild}, [0,0,NaN,0,0.25,NaN,1,1.25,NaN,1,0.5,NaN], eps);
+%!   assert (childxdata{arrowheadchild}([2, 6, 10, 14]), [0, 0.25, 1.25, 0.5], eps);
+%!   assert (childxdata{arrowheadchild}([4, 8, 12, 16]), NaN(1,4), eps);
+%!
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check multiple arrows, vector inputs identical to array inputs.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   [x,y] = meshgrid (0:1);
+%!   u = [0 1; 1 -2];
+%!   v = [1 0; 1 -2];
+%!   h = quiver (hax, x, y, u, v, 1);  # arrayinput
+%!   haxarray = get(hax);
+%!   haxarray.children = [];
+%!   haxarray.xlabel = [];
+%!   haxarray.ylabel = [];
+%!   haxarray.zlabel = [];
+%!   haxarray.title = [];
+%!   parentarray = get(h);
+%!   parentarray.children = [];
+%!   childrenarray = get (get (h, "children"));
+%!   [childrenarray.parent] = deal ([]);
+%!   h = quiver (hax, [0:1], [0:1], u, v, 1);
+%!   haxvect1 = get(hax);
+%!   haxvect1.children = [];
+%!   haxvect1.xlabel= [];
+%!   haxvect1.ylabel= [];
+%!   haxvect1.zlabel= [];
+%!   haxvect1.title= [];
+%!   parentvect1 = get(h);
+%!   parentvect1.children = [];
+%!   childrenvect1 = get (get (h, "children"));
+%!   [childrenvect1.parent] = deal ([]);
+%!   assert (isequaln (haxarray, haxvect1));
+%!   assert (isequaln (parentarray, parentvect1));
+%!   assert (isequaln (childrenarray, childrenvect1));
+%!   h = quiver (hax, [0:1], [0:1]', u, v, 1);
+%!   haxvect2 = get(hax);
+%!   haxvect2.children = [];
+%!   haxvect2.xlabel= [];
+%!   haxvect2.ylabel= [];
+%!   haxvect2.zlabel= [];
+%!   haxvect2.title= [];
+%!   parentvect2 = get(h);
+%!   parentvect2.children = [];
+%!   childrenvect2 = get (get (h, "children"));
+%!   [childrenvect2.parent] = deal ([]);
+%!   assert (isequaln (haxvect1, haxvect2));
+%!   assert (isequaln (parentvect1, parentvect2));
+%!   assert (isequaln (childrenvect1, childrenvect2));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check scale factor "off" is identical to scale factor = 0.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 1, 2, 0);
+%!   haxzero = get(hax);
+%!   haxzero.children = [];
+%!   haxzero.xlabel = [];
+%!   haxzero.ylabel = [];
+%!   haxzero.zlabel = [];
+%!   haxzero.title = [];
+%!   parentzero = get(h);
+%!   parentzero.children = [];
+%!   childrenzero = get (get (h, "children"));
+%!   [childrenzero.parent] = deal ([]);
+%!   h = quiver (hax, 1, 2, "off");
+%!   haxoff = get(hax);
+%!   haxoff.children = [];
+%!   haxoff.xlabel= [];
+%!   haxoff.ylabel= [];
+%!   haxoff.zlabel= [];
+%!   haxoff.title= [];
+%!   parentoff = get(h);
+%!   parentoff.children = [];
+%!   childrenoff = get (get (h, "children"));
+%!   [childrenoff.parent] = deal ([]);
+%!   assert (isequaln (haxzero, haxoff));
+%!   assert (isequaln (parentzero, parentoff));
+%!   assert (isequaln (childrenzero, childrenoff));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check input styles.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 0, 1, 2, 3, "-o"); # Linestyle
+%!   parent = get (h);
+%!   assert (parent.marker, "o");
+%!   assert (parent.markerfacecolor, "none");
+%!   childdata = get (parent.children);
+%!   basechild = find (cellfun (@numel, {childdata.xdata}) == 1);
+%!   arrowheadchild = find (cellfun (@numel, {childdata.xdata}) == 4);
+%!   assert (childdata(basechild).marker, "o");
+%!   assert (childdata(basechild).markerfacecolor, "none");
+%!   assert (childdata(basechild).linestyle, "none");
+%!   assert (childdata(arrowheadchild).marker, "none");
+%!   assert (childdata(arrowheadchild).markerfacecolor, "none");
+%!   assert (childdata(arrowheadchild).linestyle, "none");
+%!
+%!   h = quiver (hax, 0, 1, 2, 3, "-o", "filled");  # Linestyle + filled.
+%!   parent = get (h);
+%!   assert (parent.marker, "o");
+%!   assert (numel (parent.markerfacecolor), 3);
+%!   childdata = get (parent.children);
+%!   basechild = find (cellfun (@numel, {childdata.xdata}) == 1);
+%!   arrowheadchild = find (cellfun (@numel, {childdata.xdata}) == 4);
+%!   assert (childdata(basechild).marker, "o");
+%!   assert (numel (childdata(basechild).markerfacecolor), 3);
+%!   assert (childdata(basechild).linestyle, "none");
+%!   assert (childdata(arrowheadchild).marker, "none");
+%!   assert (childdata(arrowheadchild).markerfacecolor, "none");
+%!   assert (childdata(arrowheadchild).linestyle, "none");
+%!
+%!   h = quiver (hax, 0, 1, 2, 3, "linewidth", 10); # Name/value pair.
+%!   parent = get (h);
+%!   assert (parent.marker, "none");
+%!   assert (parent.markerfacecolor, "none");
+%!   assert (parent.linestyle, "-");
+%!   assert (parent.linewidth, 10);
+%!   childdata = get (parent.children);
+%!   basechild = find (cellfun (@numel, {childdata.xdata}) == 1);
+%!   stemchild = find (cellfun (@numel, {childdata.xdata}) == 3);
+%!   arrowheadchild = find (cellfun (@numel, {childdata.xdata}) == 4);
+%!   assert (childdata(basechild).marker, "none");
+%!   assert (childdata(basechild).markerfacecolor, "none");
+%!   assert (childdata(basechild).linestyle, "none");
+%!   assert (childdata(stemchild).marker, "none");
+%!   assert (childdata(stemchild).markerfacecolor, "none");
+%!   assert (childdata(stemchild).linestyle, "-");
+%!   assert (childdata(stemchild).linewidth, 10);
+%!   assert (childdata(arrowheadchild).marker, "none");
+%!   assert (childdata(arrowheadchild).markerfacecolor, "none");
+%!   assert (childdata(arrowheadchild).linestyle, "-");
+%!   assert (childdata(arrowheadchild).linewidth, 10);
+%!
+%!  unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test both Linestyle with marker + name/value pair suppress arrowhead
+%!test <*64143>
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 0, 1, 2, 3, "-o", "linewidth", 10);
+%!   parent = get (h);
+%!   assert (parent.marker, "o");
+%!   assert (parent.markerfacecolor, "none");
+%!   assert (parent.linestyle, "-");
+%!   assert (parent.linewidth, 10);
+%!   childdata = get (parent.children);
+%!   basechild = find (cellfun (@numel, {childdata.xdata}) == 1);
+%!   stemchild = find (cellfun (@numel, {childdata.xdata}) == 3);
+%!   arrowheadchild = find (cellfun (@numel, {childdata.xdata}) == 4);
+%!   assert (childdata(basechild).marker, "o");
+%!   assert (childdata(basechild).markerfacecolor, "none");
+%!   assert (childdata(basechild).linestyle, "none");
+%!   assert (childdata(stemchild).marker, "none");
+%!   assert (childdata(stemchild).markerfacecolor, "none");
+%!   assert (childdata(stemchild).linestyle, "-");
+%!   assert (childdata(stemchild).linewidth, 10);
+%!   assert (childdata(arrowheadchild).marker, "none");
+%!   assert (childdata(arrowheadchild).markerfacecolor, "none");
+%!   assert (childdata(arrowheadchild).linestyle, "none");
+%!   assert (childdata(arrowheadchild).linewidth, 10);
+%!
+%!  unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test that linewidth and color but not linestyle are passed to base marker
+%!test <*64143>
+%! hf = figure ("visible", "off");
+%! hax = gca();
+%! unwind_protect
+%!   h = quiver (hax, 0, 1, 2, 3, "--o", "linewidth", 10, "color", [1 0 0]);
+%!   parent = get (h);
+%!   assert (parent.marker, "o");
+%!   assert (parent.markerfacecolor, "none");
+%!   assert (parent.linestyle, "--");
+%!   assert (parent.linewidth, 10);
+%!   childdata = get (parent.children);
+%!   basechild = find (cellfun (@numel, {childdata.xdata}) == 1);
+%!   stemchild = find (cellfun (@numel, {childdata.xdata}) == 3);
+%!   arrowheadchild = find (cellfun (@numel, {childdata.xdata}) == 4);
+%!   assert (childdata(basechild).marker, "o");
+%!   assert (childdata(basechild).markerfacecolor, "none");
+%!   assert (childdata(basechild).linestyle, "none");
+%!   assert (childdata(basechild).color, [1 0 0]);
+%!   assert (childdata(basechild).linewidth, 10);
+%!   assert (childdata(stemchild).marker, "none");
+%!   assert (childdata(stemchild).markerfacecolor, "none");
+%!   assert (childdata(stemchild).linestyle, "--");
+%!   assert (childdata(stemchild).linewidth, 10);
+%!   assert (childdata(stemchild).color, [1 0 0]);
+%!   assert (childdata(arrowheadchild).marker, "none");
+%!   assert (childdata(arrowheadchild).markerfacecolor, "none");
+%!   assert (childdata(arrowheadchild).linestyle, "none");
+%!   assert (childdata(arrowheadchild).linewidth, 10);
+%!   assert (childdata(arrowheadchild).color, [1 0 0]);
+%!
+%!  unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check arrow length, scale factor adjustment, one arrow.
+%!test <*39552>
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   [x,y] = meshgrid (1:2);
+%!   u = [0 1; 2 3];
+%!   v = [1 2; 3 4];
+%!   numpts = numel (x);
+%!   sf = 0.5;
+%!
+%!   ## Check single arrow.
+%!   h = quiver (hax, x(4), y(4), u(4), v(4), 1);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   xendpoint = childxdata{stemchild}(2);
+%!   assert (xendpoint, x(4) + u(4), eps);
+%!
+%!   h = quiver (hax, x(4), y(4), u(4), v(4), sf);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   xendpoint = childxdata{stemchild}(2);
+%!   assert (xendpoint, x(4) + sf*u(4), eps);
+%!
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check arrow length, scale factor adjustment, multiple arrows.
+%!test <*39552>
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   [x,y] = meshgrid (1:2);
+%!   u = [0 1; 2 3];
+%!   v = [1 2; 3 4];
+%!   numpts = numel (x);
+%!   sf = 0.5;
+%!
+%!   ## Check multiple arrows.
+%!   h = quiver (hax, x, y, u, v, 1);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3*numpts);
+%!   xendpoint1 = childxdata{stemchild}(5);
+%!   xendpoint2 = childxdata{stemchild}(11);
+%!   assert (xendpoint1, x(2) + (sqrt(2)/10)*u(2), eps);
+%!   assert (xendpoint2, x(4) + (sqrt(2)/10)*u(4), eps);
+%!
+%!   h = quiver (hax, x, y, u, v, sf);
+%!   childxdata = get (get (h, "children"), "xdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3*numpts);
+%!   xendpoint1 = childxdata{stemchild}(5);
+%!   xendpoint2 = childxdata{stemchild}(11);
+%!   assert (xendpoint1, x(2) + sf*(sqrt(2)/10)*u(2), eps);
+%!   assert (xendpoint2, x(4) + sf*(sqrt(2)/10)*u(4), eps);
+%!
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check for proper plotting with non-float inputs.
+%!test <*59695>
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   h = quiver (int32(1), int32(1), int32(1), int32(1), double(0.5));
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childxdata, 'UniformOutput', false), "double")));
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childydata, 'UniformOutput', false), "double")));
+%!   assert (childxdata{2}(2) , 1.5, eps);
+%!   assert (childxdata{3}(2) , 1.5, eps);
+%!   assert (childydata{2}(2) , 1.5, eps);
+%!   assert (childydata{3}(2) , 1.5, eps);
+%!
+%!   h = quiver (0.5, 0.5, 0.5, 0.5, int32(1));
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childxdata, 'UniformOutput', false), "double")));
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childydata, 'UniformOutput', false), "double")));
+%!   assert (childxdata{2}(2) , 1, eps);
+%!   assert (childxdata{3}(2) , 1, eps);
+%!   assert (childydata{2}(2) , 1, eps);
+%!   assert (childydata{3}(2) , 1, eps);
+%!
+%!   h = quiver (false, true, false, true, true);
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childxdata, 'UniformOutput', false), "double")));
+%!   assert (all (strcmp (cellfun (...
+%!                 'class', childydata, 'UniformOutput', false), "double")));
+%!   assert (childxdata{2}(2) , 0, eps);
+%!   assert (childxdata{3}(2) , 0, eps);
+%!   assert (childydata{2}(2) , 2, eps);
+%!   assert (childydata{3}(2) , 2, eps);
+%!
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error <Invalid call> quiver()
+%!error <Invalid call> quiver(1.1)
+%!error <Invalid call> quiver(1.1, "foo")
+%!error <Invalid call> quiver(1.1, 2, 3, 4, 5, 6, "foo")
+%!error <U and V must be the same size> quiver ([1, 2], 3)
+%!error <U and V must be the same size> quiver (1.1, [2, 3])
+%!error <U and V must be the same size> quiver (1.1, 2, eye(2), 4)
+%!error <U and V must be the same size> quiver (1.1, 2, 3, eye(2))
+%!error <X vector length must equal> quiver (1.1, [2 3], eye(2), eye(2))
+%!error <Y vector length must equal> quiver ([1, 2], 3, eye(2), eye(2))
+%!error <X, Y, U, and V must be the same size> quiver (eye(3), eye(2), eye(2), eye(2))
+%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(3), eye(2), eye(2))
+%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(2), eye(3), eye(2))
+%!error <X, Y, U, and V must be the same size> quiver (eye(2), eye(2), eye(2), eye(3))
+%!error <scaling factor must be> quiver (10, 20, -5)
+%!error <scaling factor must be> quiver (10, 20, [1 2])
+%!error <scaling factor must be> quiver (10, 20, 30, 40, -5)
+%!error <scaling factor must be> quiver (10, 20, 30, 40, [1 2])
+
--- a/scripts/plot/draw/quiver3.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/quiver3.m	Fri Jun 23 20:51:51 2023 +0200
@@ -36,7 +36,7 @@
 ##
 ## Plot the (@var{u}, @var{v}, @var{w}) components of a vector field at the
 ## grid points defined by (@var{x}, @var{y}, @var{z}).  If the grid is uniform
-## then @var{x}, @var{y}, and @var{z} can be specified as vectors and
+## then @var{x}, @var{y}, and @var{z} can be specified as grid vectors and
 ## @code{meshgrid} is used to create the 3-D grid.
 ##
 ## If @var{x} and @var{y} are not given they are assumed to be
@@ -46,14 +46,15 @@
 ## The optional input @var{s} is a scalar defining a scaling factor to use for
 ## the arrows of the field relative to the mesh spacing.  A value of 1.0 will
 ## result in the longest vector exactly filling one grid cube.  A value of 0
-## disables all scaling.  The default value is 0.9.
+## or "off" disables all scaling.  The default value is 0.9.
 ##
 ## The style to use for the plot can be defined with a line style @var{style}
 ## of the same format as the @code{plot} command.  If a marker is specified
 ## then the markers are drawn at the origin of the vectors (which are the grid
 ## points defined by @var{x}, @var{y}, @var{z}).  When a marker is specified,
 ## the arrowhead is not drawn.  If the argument @qcode{"filled"} is given then
-## the markers are filled.
+## the markers are filled.  If name-value plot style properties are used, they
+## must appear in pairs and follow any other plot style arguments.
 ##
 ## If the first argument @var{hax} is an axes handle, then plot into this axes,
 ## rather than the current axes returned by @code{gca}.
@@ -80,7 +81,7 @@
 
   [hax, varargin, nargin] = __plt_get_axis_arg__ ("quiver3", varargin{:});
 
-  if (nargin < 2)
+  if (nargin < 4)
     print_usage ();
   endif
 
@@ -89,8 +90,7 @@
     oldfig = get (0, "currentfigure");
   endif
   unwind_protect
-    hax = newplot (hax);
-    htmp = __quiver__ (hax, true, varargin{:});
+    [hax, htmp] = __quiver__ (hax, true, varargin{:});
 
     if (! ishold ())
       set (hax, "view", [-37.5, 30],
@@ -108,7 +108,6 @@
 
 endfunction
 
-
 %!demo
 %! clf;
 %! colormap ("default");
@@ -134,3 +133,239 @@
 %! shading interp;
 %! title ({"quiver3() of surface normals to peaks() function"; ...
 %!         'shading "interp"'});
+
+## Check standard inputs, single arrow.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!
+%!   h = quiver3 (hax, 0, 1, 2, 3);
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   childzdata = get (children, "zdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!   assert (childydata{stemchild}(1), 1, eps);
+%!   assert (childydata{stemchild}(2), 1 + 2*0.9, eps);
+%!   assert (isnan (childydata{stemchild}(3)));
+%!   assert (childydata{arrowheadchild}(2), 1 + 2*0.9, eps);
+%!   assert (isnan (childydata{arrowheadchild}(4)));
+%!   assert (childzdata{stemchild}(1), 0, eps);
+%!   assert (childzdata{stemchild}(2), 0 + 3*0.9, eps);
+%!   assert (isnan (childzdata{stemchild}(3)));
+%!   assert (childzdata{arrowheadchild}(2), 0 + 3*0.9, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(4)));
+%!
+%!   h = quiver3 (hax, 1, 1, 0, 1, 2, 3);
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   childzdata = get (children, "zdata");
+%!   stemchild = find (cellfun (@numel, childxdata) == 3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == 4);
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*0.9, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!   assert (childydata{stemchild}(1), 1, eps);
+%!   assert (childydata{stemchild}(2), 1 + 2*0.9, eps);
+%!   assert (isnan (childydata{stemchild}(3)));
+%!   assert (childydata{arrowheadchild}(2), 1 + 2*0.9, eps);
+%!   assert (isnan (childydata{arrowheadchild}(4)));
+%!   assert (childzdata{stemchild}(1), 0, eps);
+%!   assert (childzdata{stemchild}(2), 0 + 3*0.9, eps);
+%!   assert (isnan (childzdata{stemchild}(3)));
+%!   assert (childzdata{arrowheadchild}(2), 0 + 3*0.9, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(4)));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Check standard inputs, multiple arrows.
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!
+%!   a = reshape(1:12,2,3,2);
+%!   x = 1:3; y = 1:2; z = 1:2;
+%!   [xx,yy,zz] = meshgrid (x,y,z);
+%!   numpts = 12;
+%!   sf= sqrt(sumsq([1/3 1/2 11/6])/432); # Actual internal scale factor, z=a.
+%!   sf2= sqrt(sumsq([1/3 1/2 1/6])/432); # z vector internal scale factor.
+%!
+%!   h = quiver3 (hax, a, a, a, a, 1); # No x,y input.
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   childzdata = get (children, "zdata");
+%!   basechild = find (cellfun (@numel, childxdata) == numpts);
+%!   stemchild = find (cellfun (@numel, childxdata) == numpts*3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == numpts*4);
+%!   ## Check all bases.
+%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);
+%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);
+%!   assert (childzdata{basechild}, [1:12]);
+%!   ## Check first arrow.
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!   assert (childydata{stemchild}(1), 1, eps);
+%!   assert (childydata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childydata{stemchild}(3)));
+%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childydata{arrowheadchild}(4)));
+%!   assert (childzdata{stemchild}(1), 1, eps);
+%!   assert (childzdata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childzdata{stemchild}(3)));
+%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(4)));
+%!   ## Check last arrow.
+%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);
+%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf, eps);
+%!   assert (isnan (childxdata{stemchild}(end)));
+%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(end)));
+%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);
+%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf, eps);
+%!   assert (isnan (childydata{stemchild}(end)));
+%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf, eps);
+%!   assert (isnan (childydata{arrowheadchild}(end)));
+%!   assert (childzdata{stemchild}(numpts*3-2), 12, eps);
+%!   assert (childzdata{stemchild}(numpts*3-1), 12 + 12*sf, eps);
+%!   assert (isnan (childzdata{stemchild}(end)));
+%!   assert (childzdata{arrowheadchild}(numpts*4-2), 12 + 12*sf, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(end)));
+%!
+%!   h = quiver3 (hax, xx, yy, a, a, a, a, 1); # x,y input as matrices.
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   childzdata = get (children, "zdata");
+%!   basechild = find (cellfun (@numel, childxdata) == numpts);
+%!   stemchild = find (cellfun (@numel, childxdata) == numpts*3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == numpts*4);
+%!   ## Check all bases.
+%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);
+%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);
+%!   assert (childzdata{basechild}, [1:12]);
+%!   ## Check first arrow.
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!   assert (childydata{stemchild}(1), 1, eps);
+%!   assert (childydata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childydata{stemchild}(3)));
+%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childydata{arrowheadchild}(4)));
+%!   assert (childzdata{stemchild}(1), 1, eps);
+%!   assert (childzdata{stemchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childzdata{stemchild}(3)));
+%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(4)));
+%!   ## Check last arrow.
+%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);
+%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf, eps);
+%!   assert (isnan (childxdata{stemchild}(end)));
+%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(end)));
+%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);
+%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf, eps);
+%!   assert (isnan (childydata{stemchild}(end)));
+%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf, eps);
+%!   assert (isnan (childydata{arrowheadchild}(end)));
+%!   assert (childzdata{stemchild}(numpts*3-2), 12, eps);
+%!   assert (childzdata{stemchild}(numpts*3-1), 12 + 12*sf, eps);
+%!   assert (isnan (childzdata{stemchild}(end)));
+%!   assert (childzdata{arrowheadchild}(numpts*4-2), 12 + 12*sf, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(end)));
+%!
+%!   h = quiver3 (hax, x, y, z, a, a, a, 1); # x,y z input as vectors.
+%!   children = get (h, "children");
+%!   childxdata = get (children, "xdata");
+%!   childydata = get (children, "ydata");
+%!   childzdata = get (children, "zdata");
+%!   basechild = find (cellfun (@numel, childxdata) == numpts);
+%!   stemchild = find (cellfun (@numel, childxdata) == numpts*3);
+%!   arrowheadchild = find (cellfun (@numel, childxdata) == numpts*4);
+%!   ## Check all bases.
+%!   assert (childxdata{basechild}, [1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3]);
+%!   assert (childydata{basechild}, [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]);
+%!   assert (childzdata{basechild}, [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2]);
+%!   ## Check first arrow.
+%!   assert (childxdata{stemchild}(1), 1, eps);
+%!   assert (childxdata{stemchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childxdata{stemchild}(3)));
+%!   assert (childxdata{arrowheadchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(4)));
+%!   assert (childydata{stemchild}(1), 1, eps);
+%!   assert (childydata{stemchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childydata{stemchild}(3)));
+%!   assert (childydata{arrowheadchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childydata{arrowheadchild}(4)));
+%!   assert (childzdata{stemchild}(1), 1, eps);
+%!   assert (childzdata{stemchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childzdata{stemchild}(3)));
+%!   assert (childzdata{arrowheadchild}(2), 1 + 1*sf2, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(4)));
+%!   ## Check last arrow.
+%!   assert (childxdata{stemchild}(numpts*3-2), 3, eps);
+%!   assert (childxdata{stemchild}(numpts*3-1), 3 + 12*sf2, eps);
+%!   assert (isnan (childxdata{stemchild}(end)));
+%!   assert (childxdata{arrowheadchild}(numpts*4-2), 3 + 12*sf2, eps);
+%!   assert (isnan (childxdata{arrowheadchild}(end)));
+%!   assert (childydata{stemchild}(numpts*3-2), 2, eps);
+%!   assert (childydata{stemchild}(numpts*3-1), 2 + 12*sf2, eps);
+%!   assert (isnan (childydata{stemchild}(end)));
+%!   assert (childydata{arrowheadchild}(numpts*4-2), 2 + 12*sf2, eps);
+%!   assert (isnan (childydata{arrowheadchild}(end)));
+%!   assert (childzdata{stemchild}(numpts*3-2), 2, eps);
+%!   assert (childzdata{stemchild}(numpts*3-1), 2 + 12*sf2, eps);
+%!   assert (isnan (childzdata{stemchild}(end)));
+%!   assert (childzdata{arrowheadchild}(numpts*4-2), 2 + 12*sf2, eps);
+%!   assert (isnan (childzdata{arrowheadchild}(end)));
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+##Test input validation
+%!error <Invalid call> quiver3 ()
+%!error <Invalid call> quiver3 (1.1)
+%!error <Invalid call> quiver3 (1.1, 2)
+%!error <Invalid call> quiver3 (1.1, 2, 3)
+%!error <Invalid call> quiver3 (1.1, 2, 3, "foo")
+%!error <Invalid call> quiver3 (1.1, 2, 3, 4, 5, 6, 7, 8, "foo")
+%!error <U, V, and W must be the same> quiver3 (30, [40 50], 60, 70)
+%!error <Z vector length must equal size of> quiver3 ([30 40], eye(3), eye(3), eye(3))
+%!error <Z, U, V, and W must be the same> quiver3 ([30 40], 50, 60, 70)
+%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(3), eye(2), eye(2))
+%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(2), eye(3), eye(2))
+%!error <Z, U, V, and W must be the same> quiver3 (eye(2), eye(2), eye(2), eye(3))
+%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(3), eye(2), eye(2))
+%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(2), eye(3), eye(2))
+%!error <U, V, and W must be the same size> quiver3 ([1:2], [1:2], 1, eye(2), eye(2), eye(3))
+%!error <X vector length must equal number of> quiver3 ([1:3], [1:2], 1, eye(2), eye(2), eye(2))
+%!error <Y vector length must equal number of> quiver3 ([1:2], [1:3], 1, eye(2), eye(2), eye(2))
+%!error <Z vector length must equal size of> quiver3 ([1:2], [1:2], [1:2], eye(2), eye(2), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(3), eye(2), eye(2), eye(2), eye(2), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(3), eye(2), eye(2), eye(2), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(3), eye(2), eye(2), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(3), eye(2), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(2), eye(3), eye(2))
+%!error <X, Y, Z, U, V, and W must be the same size> quiver3 (eye(2), eye(2), eye(2), eye(2), eye(2), eye(3))
+%!error <scaling factor must be> quiver3 (10, 20, 30, 40, -5)
+%!error <scaling factor must be> quiver3 (10, 20, 30, 40, [1 2])
+%!error <scaling factor must be> quiver3 (10, 20, 30, 40, 50, 60, -5)
+%!error <scaling factor must be> quiver3 (10, 20, 30, 40, 50, 60, [1 2])
--- a/scripts/plot/draw/reducepatch.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/reducepatch.m	Fri Jun 23 20:51:51 2023 +0200
@@ -155,7 +155,7 @@
     if (! ischar (arg{1}))
       break;  # no string arguments at end, exit checking
     endif
-    switch (tolower (arg{1}))
+    switch (lower (arg{1}))
       case {"f", "fast"}
         fast = true;
         num_string_inputs += 1;
--- a/scripts/plot/draw/smooth3.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/smooth3.m	Fri Jun 23 20:51:51 2023 +0200
@@ -117,7 +117,7 @@
             "of positive odd integers"]);
   endif
 
-  switch (tolower (method))
+  switch (lower (method))
     case {"b", "box"}
       conv_kernel = ones (sz) / prod (sz);
 
--- a/scripts/plot/draw/surfl.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/draw/surfl.m	Fri Jun 23 20:51:51 2023 +0200
@@ -97,7 +97,7 @@
   ## Check for lighting type.
   use_cdata = true;
   if (ischar (varargin{end}))
-    switch (tolower (varargin{end}))
+    switch (lower (varargin{end}))
       case "light"
         use_cdata = false;
       case "cdata"
--- a/scripts/plot/util/__check_rendering_capability__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/__check_rendering_capability__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -35,21 +35,12 @@
   endif
 
   toolkit = get (fig, "__graphics_toolkit__");
-  display = getenv ("DISPLAY");
 
-  if (! strcmp (toolkit, "qt"))
-    error ("%s: rendering with %s toolkit requires visible figure (DISPLAY='%s')",
-           who, toolkit, display);
-  endif
-
-  gl_window = get (fig, "__gl_window__");
-  qt_offscreen = __have_feature__ ("QT_OFFSCREEN");
-
-  if (strcmp (gl_window, "on") || qt_offscreen)
+  if (strcmp (toolkit, "qt"))
     return;
   endif
 
-  error ("%s: offscreen rendering with %s toolkit requires __gl_window__='on' or QT_OFFSCREEN feature (__gl_window__='%s'; QT_OFFSCREEN=%d, DISPLAY='%s')",
-         who, toolkit, gl_window, qt_offscreen, display);
+  error ("%s: rendering with %s toolkit requires visible figure (DISPLAY='%s')",
+         who, toolkit, getenv ("DISPLAY"));
 
 endfunction
--- a/scripts/plot/util/__pltopt__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/__pltopt__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -158,12 +158,6 @@
     topt = opt(1);
     n = 1;
 
-    if (any (topt == "0":"6"))
-      warning ("Octave:deprecated-option", ...
-               ["%s: using numbers to select line colors is deprecated.  ", ...
-                "Use the corresponding color identifier instead."], caller);
-    endif
-
     ## LineStyles
     if (strncmp (opt, "--", 2) || strncmp (opt, "-.", 2))
       options.linestyle = opt(1:2);
@@ -195,20 +189,19 @@
         topt = "+";
       endif
       options.marker = topt;
-    ## Numeric color specs are for backward compatibility.  Don't document.
-    elseif (topt == "k" || topt == "0")
+    elseif (topt == "k")
       options.color = [0, 0, 0];
-    elseif (topt == "r" || topt == "1")
+    elseif (topt == "r")
       if (strncmp (opt, "red", 3))
         n = 3;
       endif
       options.color = [1, 0, 0];
-    elseif (topt == "g" || topt == "2")
+    elseif (topt == "g")
       if (strncmp (opt, "green", 5))
         n = 5;
       endif
       options.color = [0, 1, 0];
-    elseif (topt == "b" || topt == "3")
+    elseif (topt == "b")
       if (strncmp (opt, "black", 5))
         options.color = [0, 0, 0];
         n = 5;
@@ -223,17 +216,17 @@
         n = 6;
       endif
       options.color = [1, 1, 0];
-    elseif (topt == "m" || topt == "4")
+    elseif (topt == "m")
       if (strncmp (opt, "magenta", 7))
         n = 7;
       endif
       options.color = [1, 0, 1];
-    elseif (topt == "c" || topt == "5")
+    elseif (topt == "c")
       if (strncmp (opt, "cyan", 4))
         n = 4;
       endif
       options.color = [0, 1, 1];
-    elseif (topt == "w" || topt == "6")
+    elseif (topt == "w")
       if (strncmp (opt, "white", 5))
         n = 5;
       endif
--- a/scripts/plot/util/copyobj.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/copyobj.m	Fri Jun 23 20:51:51 2023 +0200
@@ -203,7 +203,7 @@
 %! set (hnew, "position", [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);
 %! drawnow ();
 
-%!testif HAVE_MAGICK; (have_window_system () && __have_feature__ ("QT_OFFSCREEN") && any (strcmp ("qt", available_graphics_toolkits ())));
+%!testif HAVE_MAGICK; (have_window_system () && any (strcmp ("qt", available_graphics_toolkits ())));
 %! toolkit = graphics_toolkit ();
 %! graphics_toolkit ("qt");
 %! unwind_protect
--- a/scripts/plot/util/hgload.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/hgload.m	Fri Jun 23 20:51:51 2023 +0200
@@ -88,7 +88,7 @@
     for i = 1:numel (hg)
       fn_old = fieldnames (hg(i).properties);
       for j = 1:numel (fn_new)
-        idx = ismember (tolower (fn_old), tolower (fn_new{j}));
+        idx = ismember (lower (fn_old), lower (fn_new{j}));
         if (any (idx))
           if (calc_old_prop)
             old_prop{i}.(fn_new{j}) = hg(i).properties.(fn_old{idx});
--- a/scripts/plot/util/hgsave.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/hgsave.m	Fri Jun 23 20:51:51 2023 +0200
@@ -90,7 +90,7 @@
 endfunction
 
 
-%!testif HAVE_MAGICK; (have_window_system () && __have_feature__ ("QT_OFFSCREEN") && any (strcmp ("qt", available_graphics_toolkits ())));
+%!testif HAVE_MAGICK; (have_window_system () && any (strcmp ("qt", available_graphics_toolkits ())));
 %! toolkit = graphics_toolkit ();
 %! graphics_toolkit ("qt");
 %! h1 = figure ("visible", "off", "paperposition", [0.25, 2.5, 8.0, 6.0]);
--- a/scripts/plot/util/hold.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/hold.m	Fri Jun 23 20:51:51 2023 +0200
@@ -58,7 +58,9 @@
 
 function hold (varargin)
 
+  have_axes_arg = false;
   if (nargin > 0 && isscalar (varargin{1}) && isaxes (varargin{1}))
+    have_axes_arg = true;
     hax = varargin{1};
     varargin(1) = [];
     nargs = numel (varargin);
@@ -74,8 +76,11 @@
   hold_all = false;
   if (nargs == 0)
     turn_hold_off = ishold (hax);
+    state_str = ifelse (turn_hold_off, "off", "on");
+    axes_str = ifelse (have_axes_arg, "specified", "current");
+    printf ("hold is now %s for %s axes\n", state_str, axes_str);
   elseif (nargs == 1)
-    state = tolower (varargin{1});
+    state = lower (varargin{1});
     switch (state)
       case "off"
         turn_hold_off = true;
--- a/scripts/plot/util/ishold.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/ishold.m	Fri Jun 23 20:51:51 2023 +0200
@@ -77,7 +77,7 @@
 %!   assert (! ishold (gca));
 %!   assert (get (gca, "NextPlot"), "replace");
 %!   assert (get (hf, "NextPlot"), "add");
-%!   hold;
+%!   hold on;
 %!   assert (ishold);
 %!   assert (ishold (gca));
 %!   assert (get (gca, "NextPlot"), "add");
--- a/scripts/plot/util/openfig.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/openfig.m	Fri Jun 23 20:51:51 2023 +0200
@@ -85,7 +85,7 @@
     if (! ischar (varargin{i}))
       error ("openfig: input argument %d must be a string", i+1);
     endif
-    switch (tolower (varargin{i}))
+    switch (lower (varargin{i}))
       case "reuse"
         copies = false;
       case "new"
--- a/scripts/plot/util/private/__add_default_menu__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/private/__add_default_menu__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -227,7 +227,7 @@
             "*.tiff", "TIFF Image"};
   ## Reorder filters to have current first
   [~, ~, ext] = fileparts (def);
-  idx = strcmp (filter(:,1), ["*" tolower(ext)]);
+  idx = strcmp (filter(:,1), ["*" lower(ext)]);
   filter = [filter(idx,:); filter(! idx,:)];
 
   [filename, filedir, filteridx] = uiputfile (filter, "Save Figure", def);
--- a/scripts/plot/util/private/__print_parse_opts__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -155,7 +155,7 @@
           arg_st.debug_file = arg(8:end);
         endif
       elseif (length (arg) > 2 && arg(1:2) == "-d")
-        arg_st.devopt = tolower (arg(3:end));
+        arg_st.devopt = lower (arg(3:end));
       elseif (length (arg) > 2 && arg(1:2) == "-P")
         arg_st.printer = arg;
       elseif (strncmp (arg, "-EPSTOOL:", 9))
@@ -236,7 +236,7 @@
     elseif (dot == 0)
       arg_st.devopt = "psc";
     else
-      arg_st.devopt = tolower (arg_st.name(dot+1:end));
+      arg_st.devopt = lower (arg_st.name(dot+1:end));
     endif
   endif
 
@@ -246,7 +246,7 @@
 
   if (any (strcmp (unsupported, arg_st.devopt)))
     warning ('Octave:print:deprecated-format',
-             'print: "%s" format is no more officially supported', ...
+             'print: "%s" format is no longer officially supported',
              arg_st.devopt);
   endif
 
--- a/scripts/plot/util/refreshdata.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/refreshdata.m	Fri Jun 23 20:51:51 2023 +0200
@@ -79,7 +79,7 @@
           || ! any (strcmpi (workspace, {"base", "caller"})))
         error ('refreshdata: WORKSPACE must be "base" or "caller"');
       endif
-      workspace = tolower (workspace);
+      workspace = lower (workspace);
     endif
   endif
 
--- a/scripts/plot/util/saveas.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/saveas.m	Fri Jun 23 20:51:51 2023 +0200
@@ -127,7 +127,7 @@
     endif
   endif
 
-  fmt = tolower (fmt);
+  fmt = lower (fmt);
 
   if (any (strcmp (fmt, {"ofig", "fig"})))
     savefig (fig, filename);
--- a/scripts/plot/util/struct2hdl.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/plot/util/struct2hdl.m	Fri Jun 23 20:51:51 2023 +0200
@@ -106,7 +106,7 @@
 
   ## Use lowercase for all properties
   s.properties = cell2struct (struct2cell (s.properties), ...
-                              tolower (fieldnames (s.properties)));
+                              lower (fieldnames (s.properties)));
 
   ## Place the "*mode" properties at the end to avoid having the updaters
   ## change the mode to "manual" when the value is "auto".
--- a/scripts/signal/movfun.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/signal/movfun.m	Fri Jun 23 20:51:51 2023 +0200
@@ -197,20 +197,20 @@
   clear parser
   ## End parse input arguments
 
+  if (isempty (x))
+    ## Nothing to do.  Return immediately with empty output same shape as input.
+    ## Technically, it would be best to return the correct class, rather than
+    ## always "double", but this seems like a lot of work for little gain.
+    y = zeros (size (x));
+    return;
+  endif
+
   ## If dim was not provided find the first non-singleton dimension.
   szx = size (x);
   if (isempty (dim))
     (dim = find (szx > 1, 1)) || (dim = 1);
   endif
-
   N = szx(dim);
-  if (N == 0)
-    ## Nothing to do.  Return immediately with empty output same shape as input.
-    ## Technically, it would be best to return the correct class, rather than
-    ## always "double", but this seems like a lot of work for little gain.
-    y = zeros (szx);
-    return;
-  endif
 
   ## Calculate slicing indices.  This call also validates WLEN input.
   [slc, C, Cpre, Cpos, win] = movslice (N, wlen);
@@ -237,7 +237,7 @@
     bcfcn = @replaceval_bc;
     bcfcn (true, bc);  # initialize replaceval function with value
   else
-    switch (tolower (bc))
+    switch (lower (bc))
       case "shrink"
         bcfcn = @shrink_bc;
 
@@ -305,7 +305,23 @@
   y = zeros (N, odim, yclass);
 
   ## Process center of data
-  y(C,:) = fcn (x(slcidx));
+  try
+    y(C,:) = fcn (x(slcidx));
+  catch err
+    ## Operation failed, likely because of out-of-memory error for "x(slcidx)".
+    if (! strcmp (err.identifier, "Octave:bad-alloc"))
+      rethrow (err);
+    endif
+
+    ## Try divide and conquer approach with smaller slices of data.
+    ## For loops are slow, so don't try too hard with this approach.
+    N_SLICES = 8;  # configurable
+    idx1 = fix (linspace (1, numel (C), N_SLICES));
+    idx2 = fix (linspace (1, columns (slcidx), N_SLICES));
+    for i = 1 : N_SLICES-1
+      y(C(idx1(i):idx1(i+1)),:) = fcn (x(slcidx(:, idx2(i):idx2(i+1))));
+    endfor
+  end_try_catch
 
   ## Process boundaries
   if (! isempty (Cpre))
@@ -617,7 +633,7 @@
 ## outdim > dim
 %!error movfun (@(x) [min(x), max(x)], (1:10).', 3, "Outdim", 3)
 
-## Test for correct return class based on output of function. 
+## Test for correct return class based on output of function.
 %!test <*63802>
 %! x = single (1:10);
 %! y = movfun (@mean, x, 3);
--- a/scripts/signal/movslice.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/signal/movslice.m	Fri Jun 23 20:51:51 2023 +0200
@@ -112,6 +112,18 @@
   Cnf   = N - wlen(2) + 1;        # first center that can't fit the post-window
   Cpost = Cnf:N;                  # centers that can't fit centered post-window
   C     = (wlen(1) + 1):(Cnf - 1);
+  ## Convert C to minimum unsigned integer array large enough to hold indices.
+  ## This can save significant memory in resulting slcidx array over using a
+  ## double (8 bytes).
+  if (N <= 255)
+    C = uint8 (C);
+  elseif (N <= 65535)
+    C = uint16 (C);
+  elseif (N <= 4294967295)
+    C = uint32 (C);
+  else
+    C = uint64 (C);
+  endif
   win   = (-wlen(1):wlen(2)).';
   slcidx = C + win;
 
--- a/scripts/signal/stft.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/signal/stft.m	Fri Jun 23 20:51:51 2023 +0200
@@ -71,7 +71,7 @@
   endif
 
   if (ischar (win_type))
-    switch (tolower (win_type))
+    switch (lower (win_type))
       case "hanning"   , win_type = 1;
       case "hamming"   , win_type = 2;
       case "rectangle" , win_type = 3;
--- a/scripts/sparse/eigs.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/sparse/eigs.m	Fri Jun 23 20:51:51 2023 +0200
@@ -275,7 +275,7 @@
       if (nargin > 2 + offset)
         arg = varargin{3+offset};
         if (ischar (arg))
-          sigma = tolower (arg);
+          sigma = lower (arg);
         elseif (isnumeric (arg) && isscalar (arg))
           sigma = arg;
         elseif (isfield (arg, "p"))
--- a/scripts/sparse/ichol.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/sparse/ichol.m	Fri Jun 23 20:51:51 2023 +0200
@@ -182,7 +182,7 @@
   if (! isfield (opts, "type"))
     opts.type = "nofill";  # set default
   else
-    type = tolower (getfield (opts, "type"));
+    type = lower (getfield (opts, "type"));
     if (! strcmp (type, "nofill") && ! strcmp (type, "ict"))
       error ('ichol: TYPE must be "nofill" or "ict"');
     endif
@@ -202,7 +202,7 @@
   if (! isfield (opts, "michol"))
     opts.michol = "off";   # set default
   else
-    michol = tolower (getfield (opts, "michol"));
+    michol = lower (getfield (opts, "michol"));
     if (! strcmp (michol, "off") && ! strcmp (michol, "on"))
       error ('ichol: MICHOL must be "on" or "off"');
     endif
@@ -221,7 +221,7 @@
   if (! isfield (opts, "shape"))
     opts.shape = "lower";  # set default
   else
-    shape = tolower (getfield (opts, "shape"));
+    shape = lower (getfield (opts, "shape"));
     if (! strcmp (shape, "lower") && ! strcmp (shape, "upper"))
       error ('ichol: SHAPE must be "lower" or "upper"');
     endif
--- a/scripts/sparse/ilu.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/sparse/ilu.m	Fri Jun 23 20:51:51 2023 +0200
@@ -190,7 +190,7 @@
   if (! isfield (opts, "type"))
     opts.type = "nofill";  # set default
   else
-    type = tolower (getfield (opts, "type"));
+    type = lower (getfield (opts, "type"));
     if (! any (strcmp (type, {"nofill", "crout", "ilutp"})))
       error ("ilu: invalid TYPE specified");
     endif
@@ -209,7 +209,7 @@
   if (! isfield (opts, "milu"))
     opts.milu = "off";     # set default
   else
-    milu = tolower (getfield (opts, "milu"));
+    milu = lower (getfield (opts, "milu"));
     if (! any (strcmp (milu, {"off", "col", "row"})))
       error ('ilu: MILU must be one of "off", "col", or "row"');
     endif
--- a/scripts/sparse/speye.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/sparse/speye.m	Fri Jun 23 20:51:51 2023 +0200
@@ -26,36 +26,41 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{s} =} speye (@var{m}, @var{n})
 ## @deftypefnx {} {@var{s} =} speye (@var{m})
-## @deftypefnx {} {@var{s} =} speye (@var{sz})
+## @deftypefnx {} {@var{s} =} speye ([@var{m}, @var{n}])
 ## Return a sparse identity matrix of size @var{m}x@var{n}.
 ##
 ## The implementation is significantly more efficient than
-## @code{sparse (eye (@var{m}))} as the full matrix is not constructed.
+## @w{@code{sparse (eye (@var{m}))}} as the full matrix is not constructed.
 ##
-## Called with a single argument a square matrix of size
-## @var{m}-by-@var{m} is created.  If called with a single vector argument
-## @var{sz}, this argument is taken to be the size of the matrix to create.
+## When called with a single argument, a square matrix of size
+## @var{m}-by-@var{m} is created.  If called with a single vector argument,
+## this argument is taken to be the size of the matrix to create.
 ## @seealso{sparse, spdiags, eye}
 ## @end deftypefn
 
 function s = speye (m, n)
 
   if (nargin == 1)
-    if (isvector (m) && length (m) == 2)
-      n = m(2);
-      m = m(1);
-    elseif (isscalar (m))
+    if (! isvector (m) || numel (m) > 2)
+      print_usage ();
+    endif
+
+    if (isscalar (m))
       n = m;
     else
-      error ("speye: invalid matrix dimension");
+      n = m(2);
+      m = m(1);
     endif
   else
-    if (! isscalar (m) || ! isscalar (n))
-      error ("speye: invalid matrix dimension");
+    if (! (isscalar (m) && isscalar (n)))
+      error ("speye: M and N must be scalar dimensions");
     endif
   endif
 
-  lo = min ([m, n]);
+  ## Note: Matlab compatibility requires using 0 for negative dimensions.
+  m = ifelse (m < 0, 0, m);
+  n = ifelse (n < 0, 0, n);
+  lo = min (m, n);
   s = sparse (1:lo, 1:lo, 1, m, n);
 
 endfunction
@@ -66,3 +71,10 @@
 %!assert (speye (2,4), sparse (1:2,1:2,1,2,4))
 %!assert (speye (4,2), sparse (1:2,1:2,1,4,2))
 %!assert (speye ([4,2]), sparse (1:2,1:2,1,4,2))
+%!assert (speye (2, -3), sparse (2, 0))
+
+## Test input validation
+%!error <Invalid call> speye (ones (2,2))
+%!error <Invalid call> speye ([1, 2, 3])
+%!error <M and N must be scalar dimensions> speye ([1, 2], 3)
+%!error <M and N must be scalar dimensions> speye (1, [2, 3])
--- a/scripts/specfun/gammainc.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/specfun/gammainc.m	Fri Jun 23 20:51:51 2023 +0200
@@ -121,7 +121,7 @@
       && ! any (strcmpi (tail, {"lower","upper","scaledlower","scaledupper"})))
     error ("gammainc: invalid value for TAIL");
   endif
-  tail = tolower (tail);
+  tail = lower (tail);
 
   ## If any of the arguments is single then the output should be as well.
   if (strcmp (class (x), "single") || strcmp (class (a), "single"))
--- a/scripts/specfun/module.mk	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/specfun/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -18,7 +18,6 @@
   %reldir%/legendre.m \
   %reldir%/nchoosek.m \
   %reldir%/nthroot.m \
-  %reldir%/perms.m \
   %reldir%/primes.m \
   %reldir%/reallog.m \
   %reldir%/realpow.m \
--- a/scripts/specfun/perms.m	Fri Jun 23 20:51:15 2023 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2001-2023 The Octave Project Developers
-##
-## See the file COPYRIGHT.md in the top-level directory of this
-## distribution or <https://octave.org/copyright/>.
-##
-## 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{P} =} perms (@var{v})
-## @deftypefnx {} {@var{P} =} perms (@var{v}, "unique")
-## Generate all permutations of vector @var{v} with one row per permutation.
-##
-## Results are returned in inverse lexicographic order.  The result has size
-## @code{factorial (@var{n}) * @var{n}}, where @var{n} is the length of
-## @var{v}.  Any repeated elements are included in the output.
-##
-## If the optional argument @qcode{"unique"} is given then only unique
-## permutations are returned, using less memory and generally taking less time
-## than calling @code{unique (perms (@var{v}), "rows")}.
-##
-## Example 1
-##
-## @example
-## @group
-## perms ([1, 2, 3])
-## @result{}
-##   3   2   1
-##   3   1   2
-##   2   3   1
-##   2   1   3
-##   1   3   2
-##   1   2   3
-## @end group
-## @end example
-##
-## Example 2
-##
-## @example
-## @group
-## perms ([1, 1, 2, 2], "unique")
-## @result{}
-##   2   2   1   1
-##   2   1   2   1
-##   2   1   1   2
-##   1   2   2   1
-##   1   2   1   2
-##   1   1   2   2
-## @end group
-## @end example
-##
-## Programming Note: If the @qcode{"unique"} option is not used, the length of
-## @var{v} should be no more than 10-12 to limit memory consumption.  Even with
-## @qcode{"unique"}, there should be no more than 10-12 unique elements in
-## @var{v}.
-## @seealso{permute, randperm, nchoosek}
-## @end deftypefn
-
-## FIXME: In principle it should be more efficient to do indexing using uint8
-## type.  However, benchmarking shows doubles are faster.  If this changes in
-## a later version of Octave the index variables here can be made uint8.
-
-function P = perms (v, opt)
-
-  if (nargin < 1)
-    print_usage ();
-  endif
-
-  unique_v = false;
-  if (nargin == 2)
-    if (! strcmpi (opt, "unique"))
-      error ('perms: option must be the string "unique"');
-    endif
-    unique_v = true;
-  endif
-
-  v = v(:).';  # convert to row vector
-  if (isnumeric (v) || ischar (v))
-    ## Order of output is only dependent on the actual values for
-    ## character and numeric arrays.
-    v = sort (v, "ascend");
-  endif
-
-  n = numel (v);
-  if (n < 4)    # special cases for small n
-    switch (n)
-      case 0
-        P = reshape (v, 1, 0);
-      case 1
-        P = v;
-      case 2
-        P = [v([2 1]);v];
-      case 3
-        P = v([3 2 1; 3 1 2; 2 3 1; 2 1 3; 1 3 2; 1 2 3]);
-    endswitch
-    if (unique_v)
-      P = unique (P, "rows");
-    endif
-
-  elseif (! unique_v)
-    ## FIXME: Brief explanation of the algorithm being used would be useful.
-    v = v(end:-1:1);
-    n-= 1;
-
-    idx = zeros (factorial (n), n);
-    idx(1:6, n-2:n) = [1, 2, 3;1, 3, 2;2, 1, 3;2, 3, 1;3, 1, 2;3, 2, 1]+(n-3);
-    f = 2;    # jump-start for efficiency with medium n
-    for j = 3:n-1
-      b = 1:n;
-      f *= j;
-      perm = idx(1:f, n-(j-1):n);
-      idx(1:(j+1)*f, n-j) = (n-j:n)(ones (f, 1),:)(:);
-      for i = 0:j
-        b(i+n-j) -= 1;
-        idx((1:f)+i*f, n-(j-1):n) = b(perm);
-      endfor
-    endfor
-
-    n += 1;
-    f *= n-1;
-    P = v(1)(ones (factorial (n), n));
-    P(:,1) = v(ones (f, 1),:)(:);
-
-    for i = 1:n
-      b = v([1:i-1 i+1:n]);
-      P((1:f)+(i-1)*f, 2:end) = b(idx);
-    endfor
-
-  else  # unique permutations
-    [v, ~, j] = unique (v);
-    h = accumarray (j, 1)';
-    idx = m_perms (h);
-    P = v(sortrows (idx', -(1:rows(idx))));
-  endif
-
-endfunction
-
-function out_perms = m_perms (multis)
-  ## FIXME: Brief explanation of the algorithm being used would be useful.
-
-  l = numel (multis);
-  if (l == 1)
-    out_perms = uint8 (ones (multis, 1));
-  else
-    p1 = m_perms (multis (1:floor (l/2)));
-    p2 = m_perms (multis (floor (l/2+1):l)) + max (p1(:, 1));
-    l1 = rows (p1);
-    l2 = rows (p2);
-    cp1 = columns (p1);
-    cp2 = columns (p2);
-
-    p = nchoosek (1:l1+l2, l1);
-    rp = rows (p);
-
-    ii = false (l1+l2, rp);
-    ii(p + (0:rp - 1)' * (l1 + l2)) = true;
-    out_perms = zeros (l1 + l2, cp1 * cp2 * rp, "uint8");
-    out_perms(repmat ( ii, cp1 * cp2, 1)(:)) = repmat (p1, cp2, rp)(:);
-    out_perms(repmat (!ii, cp1 * cp2, 1)(:)) = repmat (p2, 1, cp1 * rp)(:);
-  endif
-
-endfunction
-
-
-%!assert (rows (perms (1:6)), factorial (6))
-%!assert (perms (pi), pi)
-%!assert (perms ([pi, e]), [pi, e; e, pi])
-%!assert (perms ([1,2,3]), [3,2,1;3,1,2;2,3,1;2,1,3;1,3,2;1,2,3])
-%!assert (perms (1:5), perms ([2 5 4 1 3]'))
-%!assert (perms ("abc"), char ("cba", "cab", "bca", "bac", "acb", "abc"))
-%!assert (perms ("fobar"), sortrows (unique (perms ("fobar"), "rows"), -(1:5)))
-%!assert (unique (perms (1:5)(:))', 1:5)
-%!assert (perms (int8 (1:4)), int8 (perms (1:4)))
-
-%!assert (sortrows (perms ("abb", "unique")), ["abb"; "bab"; "bba"])
-%!assert (size (perms ([1 1 1 1 2 2 2 3 3], "unique")), [1260 9])
-%!assert (size (perms (int8([1 1 1 1 1 2 2 2 2 3 3 3]), "unique")), [27720 12])
-
-## 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 (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})),
-%!                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])),
-%!                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])),
-%!                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))
-
-%!test <*52432>
-%! s = struct ();
-%! s(1) = [];
-%! assert (perms (reshape (s, 0, 0)), reshape (s, 1, 0));
-%! assert (perms (reshape (s, 0, 1)), reshape (s, 1, 0));
-
-## Test input validation
-%!error <Invalid call> perms ()
-%!error <option must be the string "unique"> perms (1:5, "foobar")
-%!error <option must be the string "unique"> perms (1:5, {"foo"})
-
--- a/scripts/special-matrix/gallery.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/special-matrix/gallery.m	Fri Jun 23 20:51:51 2023 +0200
@@ -437,7 +437,7 @@
     n_out = 1;
   endif
 
-  switch (tolower (name))
+  switch (lower (name))
     case "binomial"
       error ("gallery: matrix %s not implemented", name);
     case "cauchy"      , [varargout{1:n_out}] = cauchy      (varargin{:});
--- a/scripts/statistics/corr.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/corr.m	Fri Jun 23 20:51:51 2023 +0200
@@ -70,7 +70,20 @@
   ## No check for division by zero error, which happens only when
   ## there is a constant vector and should be rare.
   if (nargin == 2)
-    c = cov (x, y);
+    ## Adjust for Octave 9.1.0 compatability behavior change in two-input cov.
+    ## cov now treats cov(x,y) as cov(x(:),y(:)), returning a 2x2 covariance
+    ## of the two univariate distributions x and y.  corr will now pass [x,y]
+    ## as cov([x,y]), which for m x n inputs will return 2n x 2n outputs, with
+    ##  the off diagonal matrix quarters containing what was previously
+    ## returned by cov(x,y).
+
+    ## FIXME: Returning a larger than needed arary and discarding 3/4 of the
+    ##        information is nonideal.  Consider implementing a more
+    ##        efficient cov here as a subfunction to corr.
+
+    nx = columns(x);
+    c = cov ([x, y]);
+    c = c(1:nx, nx+1:end);
     s = std (x)' * std (y);
     r = c ./ s;
   else
--- a/scripts/statistics/corrcoef.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/corrcoef.m	Fri Jun 23 20:51:51 2023 +0200
@@ -62,7 +62,7 @@
 ## Outputs @var{lci} and @var{hci} are matrices containing, respectively, the
 ## lower and higher bounds of the 95% confidence interval of each correlation
 ## coefficient.
-## @seealso{corr, cov}
+## @seealso{corr, cov, std}
 ## @end deftypefn
 
 ## FIXME: It would be good to add a definition of the calculation method
@@ -70,7 +70,7 @@
 
 function [r, p, lci, hci] = corrcoef (x, varargin)
 
-  if (nargin == 0)
+  if (nargin < 1 || nargin > 6)
     print_usage ();
   endif
 
@@ -103,7 +103,7 @@
       endif
       value = varargin{i+1};
 
-      switch (tolower (parameter))
+      switch (lower (parameter))
         case "alpha"
           if (isnumeric (value) && isscalar (value)
               && value >= 0 && value <= 1)
@@ -116,7 +116,7 @@
           if (! ischar (value))
             error ('corrcoef: "rows" value must be a string');
           endif
-          value = tolower (value);
+          value = lower (value);
           switch (value)
             case {"all", "complete", "pairwise"}
               rows = value;
@@ -170,7 +170,19 @@
         xi(idx) = xj(idx) = [];
         mpw(i,j) = mpw(j,i) = m - nnz (idx);
       endif
-      r(i,j) = r(j,i) = corr (xi, xj);
+      ## Adjust for Octave 9.1.0 compatability behavior change in two-input
+      ## cov, which now handles cov(x,y) as cov(x(:),y(:)) and returns a 2x2
+      ## covariance of the two univariate distributions x and y. The previous
+      ## scalar covariance expected for r(i,j) is contained in the (1,2)
+      ## and (2,1) elements of the new array.
+
+      ## FIXME: Returning a larger than needed arary and discarding 3/4 of the
+      ##        information is nonideal, especially in this low efficiency
+      ##        for loop approach.  Consider implementing a more efficient cov
+      ##        here as a subfunction to corr, or see if vectorizing this
+      ##        entire code allows direct usage of current cov version.
+
+      r(i,j) = r(j,i) = (cov (xi, xj) ./ (std (xi) .* std (xj)))(2);
       if (calc_pval)
         df = m - 2;
         stat = sqrt (df) * r(i,j) / sqrt (1 - r(i,j)^2);
@@ -285,6 +297,7 @@
 %! assert (r, [1, NaN; NaN, 1]);
 
 %!error <Invalid call> corrcoef ()
+%!error <Invalid call> corrcoef (1, 2, "alpha", 0.05, "rows", "all" , 1)
 %!error <parameter 1 must be a string> corrcoef (1, 2, 3)
 %!error <parameter "alpha" missing value> corrcoef (1, 2, "alpha")
 %!error <"alpha" must be a scalar> corrcoef (1,2, "alpha", "1")
--- a/scripts/statistics/cov.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/cov.m	Fri Jun 23 20:51:51 2023 +0200
@@ -25,155 +25,488 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{c} =} cov (@var{x})
-## @deftypefnx {} {@var{c} =} cov (@var{x}, @var{opt})
 ## @deftypefnx {} {@var{c} =} cov (@var{x}, @var{y})
-## @deftypefnx {} {@var{c} =} cov (@var{x}, @var{y}, @var{opt})
+## @deftypefnx {} {@var{c} =} cov (@dots{}, @var{opt})
+## @deftypefnx {} {@var{c} =} cov (@dots{}, @var{nanflag})
 ## Compute the covariance matrix.
 ##
-## If each row of @var{x} and @var{y} is an observation, and each column is
-## a variable, then the @w{(@var{i}, @var{j})-th} entry of
-## @code{cov (@var{x}, @var{y})} is the covariance between the @var{i}-th
-## variable in @var{x} and the @var{j}-th variable in @var{y}.
+## The covariance between two variable vectors @var{A} and  @var{B} is
+## calculated as:
 ## @tex
 ## $$
-## \sigma_{ij} = {1 \over N-1} \sum_{i=1}^N (x_i - \bar{x})(y_i - \bar{y})
+## \sigma_{ij} = {1 \over N-1} \sum_{i=1}^N (a_i - \bar{a})(b_i - \bar{b})
 ## $$
-## where $\bar{x}$ and $\bar{y}$ are the mean values of @var{x} and @var{y}.
+## where $\bar{a}$ and $\bar{b}$ are the mean values of $a$ and $b$ and $N$ is
+## the length of the vectors $a$ and $b$.
 ## @end tex
 ## @ifnottex
 ##
 ## @example
-## cov (@var{x}) = 1/(N-1) * SUM_i (@var{x}(i) - mean(@var{x})) * (@var{y}(i) - mean(@var{y}))
+## cov (@var{a},@var{b}) = 1/(N-1) * SUM_i (@var{a}(i) - mean (@var{a})) * (@var{b}(i) - mean (@var{b}))
 ## @end example
 ##
 ## @noindent
-## where @math{N} is the length of the @var{x} and @var{y} vectors.
-##
+## where @math{N} is the length of the vectors @var{a} and @var{b}.
 ## @end ifnottex
 ##
-## If called with one argument, compute @code{cov (@var{x}, @var{x})}, the
-## covariance between the columns of @var{x}.
+## If called with one argument, compute @code{cov (@var{x}, @var{x})}.  If
+## @var{x} is a vector, this is the scalar variance of @var{x}.  If @var{x} is
+## a matrix, each row of @var{x} is treated as an observation, and each column
+## as a variable, and the @w{(@var{i}, @var{j})-th} entry of
+## @code{cov (@var{x})} is the covariance between the @var{i}-th and
+## @var{j}-th columns in @var{x}.  If @var{x} has dimensions n x m, the output
+## @var{c} will be a m x m square covariance matrix.
 ##
-## The argument @var{opt} determines the type of normalization to use.
-## Valid values are
+## If called with two arguments, compute @code{cov (@var{x}, @var{y})}, the
+## covariance between two random variables @var{x} and @var{y}.  @var{x} and
+## @var{y} must have the same number of elements, and will be treated as
+## vectors with the covariance computed as
+## @code{cov (@var{x}(:), @var{y}(:))}.  The output will be a 2 x 2
+## covariance matrix.
+##
+## The optional argument @var{opt} determines the type of normalization to
+## use.  Valid values are
 ##
 ## @table @asis
-## @item 0:
-##   normalize with @math{N-1}, provides the best unbiased estimator of the
-## covariance [default]
+## @item 0 [default]:
+##   Normalize with @math{N-1}.  This provides the best unbiased estimator of
+## thecovariance
 ##
 ## @item 1:
-##   normalize with @math{N}, this provides the second moment around the mean
+##   Normalize with @math{N}.  This provides the second moment around the
+## mean.  @var{opt} is set to 1 for N = 1.
 ## @end table
 ##
-## Compatibility Note:: Octave always treats rows of @var{x} and @var{y}
-## as multivariate random variables.
-## For two inputs, however, @sc{matlab} treats @var{x} and @var{y} as two
-## univariate distributions regardless of their shapes, and will calculate
-## @code{cov ([@var{x}(:), @var{y}(:)])} whenever the number of elements in
-## @var{x} and @var{y} are equal.  This will result in a 2x2 matrix.
-## Code relying on @sc{matlab}'s definition will need to be changed when
-## running in Octave.
+## The optional argument @var{nanflag} must appear last in the argument list
+## and controls how NaN values are handled by @code{cov}.  The three valid
+## values are:
+##
+## @table @asis
+## @item includenan [default]:
+##   Leave NaN values in @var{x} and @var{y}.  Output will follow the normal
+## rules for handling NaN values in arithemtic operations.
+##
+## @item omitrows:
+##   Rows containing NaN values are trimmed from both @var{x} and @var{y}
+## prior to calculating the covariance.  (A NaN in one variable will remove
+## that row from both @var{x} and @var{y}.)
+##
+## @item partialrows:
+##   Rows containing NaN values are ignored from both @var{x} and @var{y}
+##   independently for each @var{i}-th and @var{j}-th covariance
+##   calculation.  This may result in a different number of observations,
+##   @math{N}, being used to calculated each element of the covariance matrix.
+## @end table
+##
+## Compatibility Note:  Previous versions of @code{cov} treated rows
+## @var{x} and @var{y} as multivariate random variables.  This version
+## attempts to maintain full compatibility with @sc{matlab} by treating
+## @var{x} and @var{y} as two univariate distributions regardless of shape,
+## resulting in a 2x2 output matrix.  Code relying on Octave's previous
+## definition will need to be modified when running this newer version of
+## @code{cov}.  The previous behavior can be obtained by using the
+## NaN package's @code{covm} function as @code{covm (@var{x}, @var{y}, "D")}.
 ## @seealso{corr}
 ## @end deftypefn
 
-function c = cov (x, y = [], opt = 0)
+function c = cov (x, varargin)
 
-  if (nargin < 1)
+  if (nargin < 1 || nargin > 4)
     print_usage ();
   endif
 
-  if (   ! (isnumeric (x) || islogical (x))
-      || ! (isnumeric (y) || islogical (y)))
-    error ("cov: X and Y must be numeric matrices or vectors");
-  endif
-
-  if (ndims (x) != 2 || ndims (y) != 2)
-    error ("cov: X and Y must be 2-D matrices or vectors");
-  endif
-
-  if (nargin == 2 && isscalar (y))
-    opt = y;
-  endif
+  opt = 0;
+  is_y = false;
+  nanflag = "includenan";
 
-  if (opt != 0 && opt != 1)
-    error ("cov: normalization OPT must be 0 or 1");
-  endif
-
-  ## Special case, scalar has zero covariance
-  if (isscalar (x))
-    if (isa (x, "single"))
-      c = single (0);
-    else
-      c = 0;
-    endif
-    return;
+  if (! (isnumeric (x) || islogical (x)))
+      error ("cov: X must be a numeric vector or matrix");
   endif
 
   if (isrow (x))
     x = x.';
   endif
-  n = rows (x);
+
+  nvarg = numel (varargin);
+
+  if (nvarg > 0)
+    switch (nvarg)
+      case 3
+        ## Only char input should be nanflag, must be last.
+        if (ischar (varargin{1}) || ischar (varargin {2}))
+          if (ischar (varargin{3}))
+            error ("cov: only one NANFLAG parameter may be specified");
+          else
+            error ("cov: NANFLAG parameter must be the last input");
+          endif
+        endif
+
+        y = varargin{1};
+        opt = double (varargin{2}); # opt should not affect output class.
+        nanflag = lower (varargin {3});
+        is_y = true;
+
+      case 2
+        if (ischar (varargin{1}))
+          error ("cov: NANFLAG parameter must be the last input");
+        endif
+
+        if (ischar (varargin{end}))
+          nanflag = lower (varargin{end});
+
+          if (isscalar (varargin{1}) && ...
+            (varargin{1} == 0 || varargin{1} == 1))
+            opt = double (varargin {1});
+
+          else
+            y = varargin{1};
+            is_y = true;
+          endif
 
-  if (nargin == 1 || isscalar (y))
-    x = center (x, 1);
-    c = x' * x / (n - 1 + opt);
-  else
-    if (isrow (y))
-      y = y.';
+        else
+          y = varargin{1};
+          opt = double (varargin{2});
+          is_y = true;
+        endif
+
+      case 1
+        if (ischar (varargin{end}))
+          nanflag = lower (varargin{end});
+
+        elseif (isscalar (varargin{1}) && ...
+               (varargin{1} == 0 || varargin{1} == 1))
+          opt = double (varargin {1});
+
+        else
+          y = varargin{1};
+          is_y = true;
+        endif
+    endswitch
+
+    if (is_y)
+      if (! (isnumeric (y) || islogical (y)))
+        error ("cov: Y must be a numeric vector or matrix");
+
+      elseif (numel (x) != numel (y))
+        error ("cov: X and Y must have the same number of observations");
+
+      else
+        ## Flatten to single array.  Process the same as two-column x.
+        x = [x(:), y(:)];
+      endif
     endif
-    if (rows (y) != n)
-      error ("cov: X and Y must have the same number of observations");
+
+    if (! any (strcmp (nanflag, {"includenan", "omitrows", "partialrows"})))
+        error ("cov: unknown NANFLAG parameter '%s'", nanflag);
     endif
-    x = center (x, 1);
-    y = center (y, 1);
-    c = x' * y / (n - 1 + opt);
+
+    if ((opt != 0 && opt != 1) || ! isscalar (opt))
+      error ("cov: normalization paramter OPT must be 0 or 1");
+    endif
   endif
 
+  if (ndims (x) > 2)
+    ## Note: Matlab requires 2D inputs even if providing a y input results in
+    ##       reshaping for operation as cov (x(:), y(:)) (tested in 2022b).
+    ##       Octave permits arbitrarily shaped inputs for the cov(x,y) case as
+    ##       long as numel (x) == numel (y).  Only when no y is provided is X
+    ##       restricted to 2D for consistent 2D columnwise behavior of cov.
+    error ("cov: X must be a 2-D matrix or vector");
+  endif
+
+  ## Special case: empty inputs.  Output shape changes depends on number of
+  ## columns.  Inputs already verified as limited to 2D.
+  if (isempty (x))
+    sx = size (x);
+
+    if (sx == [0, 0])
+      c = NaN;
+    elseif (sx(1) > 0)
+      c = [];
+    else
+      c = NaN (sx(2));
+    endif
+
+    if (isa (x, "single"))
+      c = single (c);
+    endif
+    return;
+  endif
+
+  if (! strcmp (nanflag, "includenan") && all (nnx = ! isnan (x)))
+    ## Avoid unnecessary slower nanflag processing.
+    nanflag = "includenan";
+  endif
+
+  switch (nanflag)
+    case {"includenan", "omitrows"}
+
+      if (strcmp (nanflag, "omitrows"))
+        ## Trim any rows in x containing a NaN.
+        x = x(all (nnx, 2), :);
+      endif
+
+      n = rows (x);
+
+      if (n < 2)
+        ## Scalars and empties force opt = 1.
+        opt = 1;
+      endif
+
+      x -= sum (x, 1) / n;
+      c = x' * x / (n - 1 + opt);
+
+    case "partialrows"
+      ## Find all NaN locations for adjusted processing later.  NaN's will
+      ## only be trimmed for the columns containing them when calculating
+      ## covariance involving that row.  Each output element of c might have a
+      ## unique n, opt, and mean for each of the two vectors used to calculate
+      ## that element based on the paired column total number of non-NaN rows.
+      ## Separate out simple vector case.  Project into dim3 for general case.
+
+      if (iscolumn (x))
+        x = x(nnx);
+        n = numel (x);
+        if (n < 2)
+          opt = 1;
+        endif
+        x -= sum (x, 1) / n;
+
+        ## Matrix multiplication preserves output size compatibliity if x is
+        ## trimmed to empty.
+        c = (x' * x) / (n - 1 + opt);
+      else
+
+        ## Number of elements in each column pairing.
+        n = nnx' * nnx;
+
+        ## opt for each column pairing
+        opt = opt * ones (columns (x));
+        opt (n < 2) = 1;
+
+        ## Mean for each column pairing.
+        ## Rotate x vectors into dim3, project into dim1 with non-nan array
+        x = permute(x, [3, 2, 1]) .* permute (nnx, [2, 3, 1]);
+        mu = x;
+        mu (isnan (x)) = 0; # Exclude input NaNs from summation.
+        mu = sum (mu, 3) ./ n; # Vectors trimmed to n=0 may create more NaNs.
+        x -= mu; # Center x's.
+        x(isnan (x)) = 0; # Exclude input and mean NaNs from output.
+
+        ## Sum dim3 elements of x products to emulate x'*x.
+        c = sum (permute (x, [2,1,3]) .* x, 3) ./ (n - 1 + opt);
+
+      endif
+  endswitch
 endfunction
 
-
 %!test
 %! x = rand (10);
 %! cx1 = cov (x);
 %! cx2 = cov (x, x);
-%! assert (size (cx1) == [10, 10] && size (cx2) == [10, 10]);
-%! assert (cx1, cx2, 1e1*eps);
+%! assert (size (cx1) == [10, 10]);
+%! assert (size (cx2) == [2, 2]);
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (cov (x, x), [1 1; 1 1]);
+%! assert (cov (x, x), cov ([x, x]));
+%! assert (cov (x, y), [1 -1; -1 1]);
+%! assert (cov (x, y), cov ([x, y]));
 
 %!test
 %! x = [1:3]';
 %! y = [3:-1:1]';
-%! assert (cov (x, y), -1, 5*eps);
-%! assert (cov (x, flipud (y)), 1, 5*eps);
-%! assert (cov ([x, y]), [1 -1; -1 1], 5*eps);
+%! assert (cov (single (x)), single (1));
+%! assert (cov (single (x), x), single ([1 1; 1 1]));
+%! assert (cov (x, single (x)), single ([1 1; 1 1]));
+%! assert (cov (single (x), single (x)), single ([1 1; 1 1]));
+
+%!test
+%! x = [1:8];
+%! c = cov (x);
+%! assert (isscalar (c));
+%! assert (c, 6);
 
 %!test
-%! x = single ([1:3]');
-%! y = single ([3:-1:1]');
-%! assert (cov (x, y), single (-1), 5*eps);
-%! assert (cov (x, flipud (y)), single (1), 5*eps);
-%! assert (cov ([x, y]), single ([1 -1; -1 1]), 5*eps);
+%! x = [1 0; 1 0];
+%! y = [1 2; 1 1];
+%! z = [1/3 -1/6; -1/6 0.25];
+%! assert (cov (x, y), z, eps);
+%! assert (cov (x, y(:)), z, eps);
+%! assert (cov (x, y(:)'), z, eps);
+%! assert (cov (x', y(:)), z .* [1, -1; -1, 1], eps);
+%! assert (cov (x(:), y), z, eps);
+%! assert (cov (x(:)', y), z, eps);
 
-%!test
-%! x = [1:5];
-%! c = cov (x);
-%! assert (isscalar (c));
-%! assert (c, 2.5);
+## Test scalar inputs & class preservation
+%!assert (cov (5), 0)
+%!assert (cov (1, 0), 0)
+%!assert (cov (1, 1), 0)
+%!assert (cov (1, 0.1), [0, 0; 0, 0])
+%!assert (cov (1, 1.1), [0, 0; 0, 0])
+%!assert (cov (1, 3), [0, 0; 0, 0])
+%!assert (cov (single (5)), single (0))
+%!assert (cov (single (5), 0), single (0))
+%!assert (cov (single (5), 1), single (0))
+%!assert (cov (single (5), 1.1), single ([0, 0; 0, 0]))
+%!assert (cov (5, single (0)), double (0))
+%!assert (cov (5, single (1)), double (0))
+%!assert (cov (5, single (1.1)), single ([0, 0; 0, 0]))
+%!assert (cov (5, single (1.1), 0), single ([0, 0; 0, 0]))
+%!assert (cov (5, single (1.1), 1), single ([0, 0; 0, 0]))
+%!assert (cov (5, 1.1, single (0)), double([0, 0; 0, 0]))
 
-%!assert (cov (5), 0)
-%!assert (cov (single (5)), single (0))
-
+## Test opt
 %!test
 %! x = [1:5];
 %! c = cov (x, 0);
 %! assert (c, 2.5);
 %! c = cov (x, 1);
 %! assert (c, 2);
+%! c = cov (double (x), single (1));
+%! assert (class (c), "double");
+%!assert (cov (2, 4), zeros(2))
+%!assert (cov (2, 4, 0), zeros(2))
+%!assert (cov (2, 4, 1), zeros(2))
+%!assert (cov (NaN, 4), [NaN, NaN; NaN, 0])
+%!assert (cov (NaN, 4, 0), [NaN, NaN; NaN, 0])
+%!assert (cov (NaN, 4, 1), [NaN, NaN; NaN, 0])
+
+## Test logical inputs
+%!assert (cov (logical(0), logical(0)), double(0))
+%!assert (cov (0, logical(0)), double(0))
+%!assert (cov (logical(0), 0), double(0))
+%!assert (cov (logical([0 1; 1 0]), logical([0 1; 1 0])), double ([1 1;1 1]./3))
+
+## Test empty and NaN handling (bug #50583)
+%!assert <*50583> (cov ([]), NaN)
+%!assert <*50583> (cov (single ([])), single (NaN))
+%!assert <*50583> (cov ([], []), NaN (2, 2))
+%!assert <*50583> (cov (single ([]), single([])),  single (NaN (2, 2)))
+%!assert <*50583> (cov ([], single ([])), single (NaN (2, 2)))
+%!assert <*50583> (cov (single ([]), []), single (NaN (2, 2)))
+%!assert <*50583> (cov (ones(1, 0)), NaN)
+%!assert <*50583> (cov (ones(2, 0)), [])
+%!assert <*50583> (cov (ones(0, 1)), NaN)
+%!assert <*50583> (cov (ones(0, 2)), NaN (2, 2))
+%!assert <*50583> (cov (ones(0, 6)), NaN (6, 6))
+%!assert <*50583> (cov (ones(2, 0), []), NaN (2, 2))
+%!assert <*50583> (cov (ones(0,6), []), NaN (2, 2))
+%!assert <*50583> (cov (NaN), NaN)
+%!assert <*50583> (cov (NaN, NaN), NaN (2, 2))
+%!assert <*50583> (cov (5, NaN), [0, NaN; NaN, NaN])
+%!assert <*50583> (cov (NaN, 5), [NaN, NaN; NaN, 0])
+%!assert <*50583> (cov (single (NaN)), single (NaN))
+%!assert <*50583> (cov (NaN (2, 2)), NaN (2, 2))
+%!assert <*50583> (cov (single (NaN (2, 2))), single (NaN (2, 2)))
+%!assert <*50583> (cov (NaN(2, 9)), NaN(9, 9))
+%!assert <*50583> (cov (NaN(9, 2)), NaN(2, 2))
+%!assert <*50583> (cov ([NaN, 1, 2, NaN]), NaN)
+%!assert <*50583> (cov ([1, NaN, 2, NaN]), NaN)
+
+## Test NaN and nanflag option (bug #50571)
+%!test <*50571>
+%! x = magic(3);
+%! y = magic(3);
+%! x(3) = NaN;
+%! assert (cov (y, "omitrows"), cov(y));
+%! assert (cov (y, "partialrows"), cov(y));
+%! assert (cov (x), [NaN, NaN, NaN; NaN, 16, -8; NaN, -8, 7]);
+%! assert (cov (x, "omitrows"), ...
+%!   [12.5, -10, -2.5; -10, 8, 2; -2.5, 2, 0.5], eps);
+%! assert (cov (x, "partialrows"),
+%!   [12.5, -10, -2.5; -10, 16, -8; -2.5, -8, 7], eps);
+%! assert (cov (x, x), NaN(2,2));
+%! assert (cov (x, y), [NaN, NaN; NaN, 7.5], eps);
+%! assert (cov (y, x), [7.5, NaN; NaN, NaN], eps);
+%! assert (cov (x, x, 'omitrows'), (471/56) * ones(2), eps);
+%! assert (cov (x, x, 'partialrows'), (471/56) * ones(2), eps);
+%! assert (cov (x, y, 'omitrows'), (471/56) * ones(2), eps);
+%! assert (cov (x, y, 'partialrows'), (471/56)*[1,1;1,0] + [0,0;0,7.5], eps);
+%! assert (cov (y, x, 'omitrows'), (471/56) * ones(2), eps);
+%! assert (cov (y, x, 'partialrows'), (471/56)*[0,1;1,1] + [7.5,0;0,0], eps);
+%! assert (cov (x, y, 0, 'omitrows'), (471/56) * ones(2), eps);
+%! assert (cov (x, y, 0, 'partialrows'), (471/56)*[1,1;1,0] + [0,0;0,7.5], eps);
+%!assert (cov ([NaN NaN NaN]), NaN)
+%!assert <*50571> (cov ([NaN NaN NaN], "omitrows"), NaN)
+%!assert <*50571> (cov ([NaN NaN NaN], "partialrows"), NaN)
+%!assert (cov (NaN(3)), NaN(3))
+%!assert <*50571> (cov (NaN(3), "omitrows"), NaN(3))
+%!assert <*50571> (cov (NaN(3), "partialrows"), NaN(3))
+%!assert (cov ([NaN NaN NaN],[1 2 3]), [NaN, NaN; NaN 1])
+%!assert <*50571> (cov ([NaN NaN NaN],[1 2 3], "omitrows"), [NaN, NaN; NaN NaN])
+%!assert <*50571> (cov ([NaN NaN NaN],[1 2 3], "partialrows"), [NaN, NaN; NaN 1])
+%!test <*50571>
+%! x = magic(3);
+%! x(4:6) = NaN;
+%! assert (cov (x), [7 NaN 1; NaN NaN NaN; 1 NaN 7]);
+%! assert (cov (x, "omitrows"), NaN(3));
+%! assert (cov (x, "partialrows"), [7 NaN 1; NaN NaN NaN; 1 NaN 7]);
+%!assert <*50571> (cov (5, NaN, "omitrows"), NaN(2, 2))
+%!assert <*50571> (cov (NaN, 5, "omitrows"), NaN(2, 2))
+%!assert <*50571> (cov (5, NaN, "partialrows"), [0, NaN; NaN, NaN])
+%!assert <*50571> (cov (NaN, 5, "partialrows"), [NaN, NaN; NaN, 0])
+%!test <*50571>
+%! x = [1:10]';
+%! y = x;
+%! x(2:2:10)=NaN;
+%! y(1:2:9)=NaN;
+%! assert (cov(x,y), NaN(2));
+%! assert (cov(x,y,'omitrows'), NaN(2));
+%! assert (cov(x,y,'partialrows'), [10 NaN; NaN, 10]);
+%! x(10) = 5;
+%! assert (cov(x,y), NaN(2));
+%! assert (cov(x,y,'omitrows'), zeros(2));
+%! assert (cov(x,y,'partialrows'), [8 0; 0, 10]);
+#!assert (cov ([NaN, NaN, 3]), NaN)
+#!assert <*50571>  (cov ([NaN, NaN, 3], 'omitrows'), 0)
+#!assert <*50571> (cov ([NaN, NaN, 3], 'partialrows'), 0)
+%!assert (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3]), NaN(3))
+%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 'omitrows'), NaN(3))
+%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])
+%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 0, 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])
+%!assert <*50571> (cov ([NaN, NaN, NaN; NaN, 2, 3; NaN, NaN, 3], 1, 'partialrows'), [NaN, NaN, NaN; NaN(2,1), zeros(2)])
+%!test <*50571>
+%! x = magic(4);
+%! x([4 5 7 10 14 16]) = NaN;
+%! x1 = x(:,2);
+%! x2 = x(:,3);
+%! assert (cov(x1,x2),nan(2));
+%! assert (cov(x1,x2,'omitrows'),zeros(2));
+%! assert (cov(x1,x2, 'partialrows'), [4.5,0;0,39],eps);
+%! assert (cov(x1,x2,0,'partialrows'), [4.5,0;0,39],eps);
+%! assert (cov(x1,x2,1,'partialrows'), [2.25,0;0,26],eps);
+%! assert (cov(x), nan(4));
+%! assert (cov(x,'omitrows'), nan(4));
+%! assert (cov(x,'partialrows'), [31 0 -10.5 3.5; 0 4.5 0 NaN; -10.5 0 39 -1.5; 3.5 NaN -1.5 0.5], eps);
+%! assert (cov(x, 0, 'partialrows'), [31 0 -10.5 3.5; 0 4.5 0 NaN; -10.5 0 39 -1.5; 3.5 NaN -1.5 0.5], eps);
+%! assert (cov(x, 1,'partialrows'), [62/3 0 -5.25 1.75; 0 2.25 0 NaN; -5.25 0 26 -0.75; 1.75 NaN -0.75 0.25], eps);
 
 ## Test input validation
 %!error <Invalid call> cov ()
-%!error cov ([1; 2], ["A", "B"])
-%!error cov (ones (2,2,2))
-%!error cov (ones (2,2), ones (2,2,2))
-%!error <normalization OPT must be 0 or 1> cov (1, 3)
-%!error cov (ones (2,2), ones (3,2))
+%!error <Invalid call> cov (1, 2, 3, 4, 5)
+%!error <X must be a> cov ("foo")
+%!error <X must be a> cov ({123})
+%!error <X must be a> cov (struct())
+%!error <X must be a> cov (ones (2, 2, 2))
+%!error <X must be a> cov (ones (1, 0, 2))
+%!error <only one NANFLAG> cov (1, "foo", 0, "includenan")
+%!error <only one NANFLAG> cov (1, 1, "foo", "includenan")
+%!error <normalization paramter OPT must be> cov (1, 2, [])
+%!error <normalization paramter OPT must be> cov (1, 2, 1.1)
+%!error <normalization paramter OPT must be> cov (1, 2, -1)
+%!error <normalization paramter OPT must be> cov (1, 2, [0 1])
+%!error <X and Y must have the same number> cov (5,[1 2])
+%!error <X and Y must have the same number> cov (ones (2, 2), ones (2, 2, 2))
+%!error <X and Y must have the same number> cov (ones (2, 2), ones (3, 2))
+%!error <X and Y must have the same number> cov (1, [])
+%!error <X and Y must have the same number> cov ([1, 2], ones(1, 0, 2))
+%!error <unknown NANFLAG parameter 'foo'> cov (1, "foo")
+%!error <unknown NANFLAG parameter 'foo'> cov (1, "foo")
+%!error <unknown NANFLAG parameter 'foo'> cov (1, 2, "foo")
+%!error <unknown NANFLAG parameter 'foo'> cov (1, 2, 0, "foo")
+%!error <unknown NANFLAG parameter ''> cov (1, 2, 1, [])
+%!error <NANFLAG parameter must be the last> cov (1, "includenan", 1)
+%!error <NANFLAG parameter must be the last> cov (1, 1, "includenan", 1)
--- a/scripts/statistics/iqr.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/iqr.m	Fri Jun 23 20:51:51 2023 +0200
@@ -146,7 +146,7 @@
         error ("iqr: vector DIM must contain non-repeating positive integers");
       endif
 
-    elseif (strcmp (tolower (dim), "all"))
+    elseif (strcmp (lower (dim), "all"))
       ## "ALL" simplifies to collapsing all elements to single vector
       x = x(:);
       dim = 1;
--- a/scripts/statistics/mad.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/mad.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,10 +24,13 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn  {} {@var{y} =} mad (@var{x})
-## @deftypefnx {} {@var{y} =} mad (@var{x}, @var{opt})
-## @deftypefnx {} {@var{y} =} mad (@var{x}, @var{opt}, @var{dim})
-## Compute the mean or median absolute deviation of the elements of @var{x}.
+## @deftypefn  {} {@var{m} =} mad (@var{x})
+## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt})
+## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, @var{dim})
+## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, @var{vecdim})
+## @deftypefnx {} {@var{m} =} mad (@var{x}, @var{opt}, "all")
+## Compute the mean or median absolute deviation (MAD) of the elements of
+## @var{x}.
 ##
 ## The mean absolute deviation is defined as
 ##
@@ -41,22 +44,39 @@
 ## @var{mad} = median (abs (@var{x} - median (@var{x})))
 ## @end example
 ##
-## If @var{x} is a matrix, compute @code{mad} for each column and return
-## results in a row vector.  For a multi-dimensional array, the calculation is
-## done over the first non-singleton dimension.
+## If @var{x} is a vector, compute @code{mad} for each element in @var{x}. If
+## @var{x} is an array the calculation is performed over the first
+## non-singleton dimension.
+##
+## @code{mad} excludes NaN values from calculation similar to using the
+## @qcode{omitnan} option in @code{var}, @code{mean}, and @code{median}.
 ##
 ## The optional argument @var{opt} determines whether mean or median absolute
 ## deviation is calculated.  The default is 0 which corresponds to mean
-## absolute deviation; A value of 1 corresponds to median absolute deviation.
+## absolute deviation; a value of 1 corresponds to median absolute deviation.
+## Passing an empty input [] defaults to mean absolute deviation
+## (@var{opt} = 0).
+##
+## The optional argument @var{dim} forces @code{mad} to operate along the
+## specified dimension.  Specifying any singleton dimension in @var{x},
+## including any dimension exceeding @code{ndims (@var{x})}, will result in
+## an output of 0.
 ##
-## If the optional argument @var{dim} is given, operate along this dimension.
+## Specifying the dimension as @var{vecdim}, a vector of non-repeating
+## dimensions, will return the @code{mad} over the array slice defined by
+## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is
+## equivalent to the option @qcode{"all"}.  Any dimension included in
+## @var{vecdim} greater than @code{ndims (@var{x})} is ignored.
+##
+## Specifying the dimension as @qcode{"all"} will force @code{mad} to operate
+## on all elements of @var{x}, and is equivalent to @code{mad (@var{x}(:))}.
 ##
 ## As a measure of dispersion, @code{mad} is less affected by outliers than
 ## @code{std}.
 ## @seealso{bounds, range, iqr, std, mean, median}
 ## @end deftypefn
 
-function retval = mad (x, opt = 0, dim)
+function m = mad (x, opt = 0, dim)
 
   if (nargin < 1)
     print_usage ();
@@ -72,14 +92,21 @@
     error ("mad: OPT must be 0 or 1");
   endif
 
-  sz = size (x);
   if (nargin < 3)
-    ## Find the first non-singleton dimension.
-    (dim = find (sz > 1, 1)) || (dim = 1);
-  else
-    if (! (isscalar (dim) && dim == fix (dim) && dim > 0))
-      error ("mad: DIM must be an integer and a valid dimension");
+    ## Dim not provided
+
+    ## First check for special empty case.
+    if (isempty (x) && ndims (x) == 2 && size (x) == [0, 0])
+      if  (isa (x, "single"))
+        m = NaN ("single");
+      else
+        m = NaN;
+      endif
+      return
     endif
+
+    ## Then find the first non-singleton dimension.
+    (dim = find (size (x) != 1, 1)) || (dim = 1);
   endif
 
   if (opt == 0)
@@ -88,11 +115,13 @@
     fcn = @median;
   endif
 
-  retval = fcn (abs (x - fcn (x, dim)), dim);
+  m = fcn (abs (x - fcn (x, dim, "omitnan")), dim, "omitnan");
 
 endfunction
 
-
+%!assert (mad (123), 0)
+%!assert (mad (Inf), NaN)
+%!assert (mad ([3, Inf]),Inf)
 %!assert (mad ([0 0 1 2 100]), 31.76)
 %!assert (mad (single ([0 0 1 2 100])), single (31.76))
 %!assert (mad ([0 0 1 2 100]'), 31.76)
@@ -103,11 +132,61 @@
 %!assert (mad (magic (4), [], 2), [6; 2; 2; 6])
 %!assert (mad (magic (4), 1), [2.5, 3.5, 3.5, 2.5])
 %!assert (mad (magic (4), 1, 2), [5.5; 1.5; 1.5; 5.5])
+%!assert (mad (magic (4), 0, 3), zeros (4))
+%!assert (mad (magic (4), 1, 3), zeros (4))
+%!assert (mad (cat (3, magic (4), magic (4))), 4 * ones (1, 4, 2))
+
+## Test all and vecdim options
+%!assert (mad (magic (4), 0, "all"), 4)
+%!assert (mad (magic (4), 1, "all"), 4)
+%!assert (mad (magic (4), 0, [1 2]), 4)
+%!assert (mad (magic (4), 0, [1 3]), mad (magic(4), 0, 1))
+%!assert (mad (magic (4), 0, [1 2 3]), 4)
+%!assert (mad (magic (4), 1, [1 2]), 4)
+%!assert (mad (magic (4), 1, [1 3]), mad (magic(4), 1, 1))
+%!assert (mad (magic (4), 1, [1 2 3]), 4)
+%!assert (mad (magic (4), 0, [3 4 99]), zeros (4))
+%!assert (mad (magic (4), 1, [3 4 99]), zeros (4))
+
+## Verify ignoring NaN values unless all NaN
+%!assert (mad (NaN), NaN)
+%!assert (mad (NaN (2)), NaN(1,2))
+%!assert (mad ([1,2;3,NaN]), [1, 0])
+%!assert (mad ([1,2;3,NaN], [], 1), [1, 0])
+%!assert (mad ([1,2;3,NaN], [], 2), [0.5; 0], eps)
+%!assert (mad ([1,NaN;3,NaN], [], 1), [1, NaN])
+%!assert (mad ([1,NaN;3,NaN], [], 2), [0; 0])
+
+## Verify compatible empty handling
+%!assert (mad ([]), NaN)
+%!assert (mad ([], 0, 1), NaN (1,0))
+%!assert (mad ([], 0, 2), NaN (0,1))
+%!assert (mad ([], 0, 3), NaN (0,0))
+%!assert (mad (single ([])), NaN ('single'))
+%!assert (mad (ones (0,1)), NaN)
+%!assert (mad (ones (0,1), 0, 1), NaN (1,1))
+%!assert (mad (ones (0,1), 0, 2), NaN (0,1))
+%!assert (mad (ones (0,1), 0, 3), NaN (0,1))
+%!assert (mad (ones (1,0)), NaN)
+%!assert (mad (ones (1,0), 0, 1), NaN (1,0))
+%!assert (mad (ones (1,0), 0, 2), NaN (1,1))
+%!assert (mad (ones (1,0), 0, 3), NaN (1,0))
+%!assert (mad (ones (0,0,0)), NaN (1,0,0))
+%!assert (mad (ones (1,0,0)), NaN (1,1,0))
+%!assert (mad (ones (0,1,0)), NaN (1,1,0))
+%!assert (mad (ones (0,0,0)), NaN (1,0,0))
+%!assert (mad (ones (0,1,0), 0, 1), NaN (1,1,0))
+%!assert (mad (ones (0,1,0), 0, 2), NaN (0,1,0))
+%!assert (mad (ones (0,1,0), 0, 3), NaN (0,1,1))
+%!assert (mad (ones (0,1,0), 0, 4), NaN (0,1,0))
+%!assert (mad (ones (0,2,1,0)), ones (1,2,1,0))
+%!assert (mad (ones (2,0,1,0)), ones (1,0,1,0))
+
+## Test input case insensitivity
+%!assert (mad ([1 2 3], 0, "aLL"), 2/3, eps)
+%!assert (mad ([1 2 3], 1, "aLL"), 1)
 
 ## Test input validation
 %!error <Invalid call> mad ()
 %!error <X must be a numeric> mad (['A'; 'B'])
 %!error <OPT must be 0 or 1> mad (1, 2)
-%!error <DIM must be an integer> mad (1, [], ones (2,2))
-%!error <DIM must be an integer> mad (1, [], 1.5)
-%!error <DIM must be .* a valid dimension> mad (1, [], 0)
--- a/scripts/statistics/mean.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/mean.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,21 +24,19 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn  {} {@var{y} =} mean (@var{x})
-## @deftypefnx {} {@var{y} =} mean (@var{x}, 'all')
-## @deftypefnx {} {@var{y} =} mean (@var{x}, @var{dim})
-## @deftypefnx {} {@var{y} =} mean (@dots{}, '@var{outtype}')
-## @deftypefnx {} {@var{y} =} mean (@dots{}, '@var{nanflag}')
+## @deftypefn  {} {@var{m} =} mean (@var{x})
+## @deftypefnx {} {@var{m} =} mean (@var{x}, @var{dim})
+## @deftypefnx {} {@var{m} =} mean (@var{x}, @var{vecdim})
+## @deftypefnx {} {@var{m} =} mean (@var{x}, "all")
+## @deftypefnx {} {@var{m} =} mean (@dots{}, @var{nanflag})
+## @deftypefnx {} {@var{m} =} mean (@dots{}, @var{outtype})
 ## Compute the mean of the elements of @var{x}.
 ##
-## @itemize
-## @item
-## If @var{x} is a vector, then @code{mean (@var{x})} returns the
-## mean of the elements in @var{x} defined as
+## If @var{x} is a vector, then @code{mean (@var{x})} returns the mean of the
+## elements in @var{x} defined as
 ## @tex
 ## $$ {\rm mean}(x) = \bar{x} = {1\over N} \sum_{i=1}^N x_i $$
 ## where $N$ is the number of elements of @var{x}.
-##
 ## @end tex
 ## @ifnottex
 ##
@@ -47,29 +45,29 @@
 ## @end example
 ##
 ## @noindent
-## where @math{N} is the number of elements in the @var{x} vector.
+## where @math{N} is the number of elements in @var{x}.
 ##
 ## @end ifnottex
 ##
-## @item
-## If @var{x} is a matrix, then @code{mean} returns a row vector with the mean
-## of each column in @var{x}.
+## If @var{x} is an array, then @code{mean(@var{x})} computes the mean along
+## the first nonsingleton dimension of @var{x}.
+##
+## The optional variable @var{dim} forces @code{mean} to operate over the
+## specified dimension, which must be a positive integer-valued number.
+## Specifying any singleton dimension in @var{x}, including any dimension
+## exceeding @code{ndims (@var{x})}, will result in a mean equal to @var{x}.
 ##
-## @item
-## If @var{x} is a multi-dimensional array, then @code{mean} operates along the
-## first non-singleton dimension of @var{x}.
-## @end itemize
+## Specifying the dimensions as  @var{vecdim}, a vector of non-repeating
+## dimensions, will return the mean over the array slice defined by
+## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is
+## equivalent to the option @qcode{"all"}.  Any dimension in @var{vecdim}
+## greater than @code{ndims (@var{x})} is ignored.
 ##
-## The optional input @var{dim} forces @code{mean} to operate over the
-## specified dimension(s).  @var{dim} can either be a scalar dimension or a
-## vector of non-repeating dimensions.  Dimensions must be positive integers,
-## and the mean is calculated over the array slice defined by @var{dim}.
-##
-## Specifying dimension @qcode{"all"} will force @code{mean} to operate on all
-## elements of @var{x}, and is equivalent to @code{mean (@var{x}(:))}.
+## Specifying the dimension as @qcode{"all"} will force @code{mean} to operate
+## on all elements of @var{x}, and is equivalent to @code{mean (@var{x}(:))}.
 ##
 ## The optional input @var{outtype} specifies the data type that is returned.
-## Valid values are:
+## @var{outtype} can take the following values:
 ##
 ## @table @asis
 ## @item @qcode{'default'} : Output is of type double, unless the input is
@@ -77,169 +75,297 @@
 ##
 ## @item @qcode{'double'} : Output is of type double.
 ##
-## @item @qcode{'native'} : Output is of the same type as the input
-## (@code{class (@var{x})}), unless the input is logical in which case the
+## @item @qcode{'native'} : Output is of the same type as the input as reported
+## by (@code{class (@var{x})}), unless the input is logical in which case the
 ## output is of type double.
-##
 ## @end table
 ##
-## The optional input @var{nanflag} specifies whether to include/exclude NaN
-## values from the calculation.  By default, NaN values are included in the
-## calculation (@var{nanflag} has the value @qcode{'includenan'}).  To exclude
-## NaN values, set the value of @var{nanflag} to @qcode{'omitnan'}.
+## The optional variable @var{nanflag} specifies whether to include or exclude
+## NaN values from the calculation using any of the previously specified input
+## argument combinations.  The default value for @var{nanflag} is
+## @qcode{"includenan"} which keeps NaN values in the calculation.  To exclude
+## NaN values set the value of @var{nanflag} to @qcode{"omitnan"}.  The output
+## will still contain NaN values if @var{x} consists of all NaN values in the
+## operating dimension.
 ##
-## @seealso{median, mode}
+## @seealso{median, mode, movmean}
 ## @end deftypefn
 
-function y = mean (x, varargin)
+function m = mean (x, varargin)
+
+  if (nargin < 1 || nargin > 4)
+    print_usage ();
+  endif
 
-  if (nargin < 1 || nargin > 4 || ! all (cellfun (@ischar, varargin(2:end))))
+  ## Set initial conditions
+  all_flag = false;
+  omitnan  = false;
+  out_flag = false;
+
+  nvarg = numel (varargin);
+  varg_chars = cellfun ("ischar", varargin);
+  outtype = "default";
+  szx = size (x);
+  ndx = ndims (x);
+
+  if (nvarg > 1 && ! varg_chars(2:end))
+    ## Only first varargin can be numeric
     print_usage ();
   endif
 
-  ## Check all char arguments.
-  all_flag = false;
-  omitnan = false;
-  outtype = "default";
-
-  for i = 1:numel (varargin)
-    if (ischar (varargin{i}))
-      switch (varargin{i})
+  ## Process any other char arguments.
+  if (any (varg_chars))
+    for argin = varargin(varg_chars)
+      switch (lower (argin{:}))
         case "all"
           all_flag = true;
+
+        case "omitnan"
+          omitnan = true;
+
         case "includenan"
           omitnan = false;
-        case "omitnan"
-          omitnan = true;
-        case {"default", "double", "native"}
-          outtype = varargin{i};
+
+        case "default"
+          if (out_flag)
+            error ("mean: only one OUTTYPE can be specified");
+          endif
+          if (isa (x, "single"))
+            outtype = "single";
+          else
+            outtype = "double";
+          endif
+          out_flag = true;
+
+        case "native"
+          outtype = class (x);
+          if (out_flag)
+            error ("mean: only one OUTTYPE can be specified");
+          elseif (strcmp (outtype, "logical"))
+            outtype = "double";
+          elseif (strcmp (outtype, "char"))
+            error ("mean: OUTTYPE 'native' cannot be used with char inputs");
+          endif
+          out_flag = true;
+
+        case "double"
+          if (out_flag)
+            error ("mean: only one OUTTYPE can be specified");
+          endif
+          outtype = "double";
+          out_flag = true;
+
         otherwise
           print_usage ();
       endswitch
+    endfor
+    varargin(varg_chars) = [];
+    nvarg = numel (varargin);
+  endif
+
+  if (strcmp (outtype, "default"))
+    if (isa (x, "single"))
+      outtype = "single";
+    else
+      outtype = "double";
     endif
-  endfor
-  varargin(cellfun (@ischar, varargin)) = [];
+  endif
 
-  if (((numel (varargin) == 1) && ! (isnumeric (varargin{1}))) ...
-      || (numel (varargin) > 1))
+  if (nvarg > 1 || (nvarg == 1 && ! isnumeric (varargin{1})))
+    ## After trimming char inputs can only be one varargin left, must be numeric
     print_usage ();
   endif
 
-  if (! (isnumeric (x) || islogical (x)))
-    error ("mean: X must be either a numeric or logical vector or matrix");
+  if (! (isnumeric (x) || islogical (x) || ischar (x)))
+    error ("mean: X must be either a numeric, boolean, or character array");
   endif
 
-  if (numel (varargin) == 0)
-
+  ## Process special cases of input/output sizes.
+  if (nvarg == 0)
     ## Single numeric input argument, no dimensions given.
+
     if (all_flag)
-      n = numel (x(:));
+      x = x(:);
+
       if (omitnan)
-        idx = isnan (x);
-        n -= sum (idx(:));
-        x(idx) = 0;
+        x = x(! isnan (x));
       endif
-      y = sum (x(:), 1, "double") ./ n;
+
+      if (any (isa (x, {"int64", "uint64"})))
+        m = int64_mean (x, 1, numel (x), outtype);
+      else
+        m = sum (x, "double") ./ numel (x);
+      endif
+
     else
-      sz = size (x);
       ## Find the first non-singleton dimension.
-      (dim = find (sz != 1, 1)) || (dim = 1);
-      n = size (x, dim);
+      (dim = find (szx != 1, 1)) || (dim = 1);
+      n = szx(dim);
       if (omitnan)
         idx = isnan (x);
         n = sum (! idx, dim);
         x(idx) = 0;
       endif
-      y = sum (x, dim, "double") ./ n;
+
+      if (any (isa (x, {"int64", "uint64"})))
+        m = int64_mean (x, dim, n, outtype);
+      else
+        m = sum (x, dim, "double") ./ n;
+      endif
+
     endif
 
   else
 
     ## Two numeric input arguments, dimensions given.  Note scalar is vector!
-    dim = varargin{1};
-    if (! (isvector (dim) && all (dim > 0) && all (rem (dim, 1) == 0)))
+    vecdim = varargin{1};
+    if (isempty (vecdim) || ! (isvector (vecdim) && all (vecdim > 0)
+        && all (rem (vecdim, 1)==0)))
       error ("mean: DIM must be a positive integer scalar or vector");
     endif
 
-    if (isscalar (dim))
-
-      n = size (x, dim);
-      if (omitnan)
-        idx = isnan (x);
-        n = sum (! idx, dim);
-        x(idx) = 0;
-      endif
-      y = sum (x, dim, "double") ./ n;
-
+    if (ndx == 2 && isempty (x) && szx == [0,0])
+      ## FIXME: This special case handling could be removed once sum
+      ##        compatibly handles all sizes of empty inputs.
+      sz_out = szx;
+      sz_out (vecdim(vecdim <= ndx)) = 1;
+      m = NaN (sz_out);
     else
 
-      sz = size (x);
-      ndims = numel (sz);
-      misdim = [1:ndims];
-
-      dim(dim > ndims) = [];  # weed out dimensions larger than array
-      misdim(dim) = [];       # remove dims asked for leaving missing dims
-
-      switch (numel (misdim))
-        ## if all dimensions are given, compute x(:)
-        case 0
-          n = numel (x(:));
+      if (isscalar (vecdim))
+        if (vecdim > ndx)
+          m = x;
+        else
+          n = szx(vecdim);
           if (omitnan)
-            idx = isnan (x);
-            n -= sum (idx(:));
-            x(idx) = 0;
+            nanx = isnan (x);
+            n = sum (! nanx, vecdim);
+            x(nanx) = 0;
           endif
-          y = sum (x(:), 1, "double") ./ n;
+
+          if (any (isa (x, {"int64", "uint64"})))
+            m = int64_mean (x, vecdim, n, outtype);
+          else
+            m = sum (x, vecdim, "double") ./ n;
+          endif
+
+        endif
 
-        ## for 1 dimension left, return column vector
-        case 1
-          x = permute (x, [misdim, dim]);
-          y = zeros (size (x, 1), 1, "like", x);
-          for i = 1:size (x, 1)
-            x_vec = x(i,:)(:);
+      else
+        vecdim = sort (vecdim);
+        if (! all (diff (vecdim)))
+           error ("mean: VECDIM must contain non-repeating positive integers");
+        endif
+        ## Ignore dimensions in VECDIM larger than actual array.
+        vecdim(vecdim > ndims (x)) = [];
+
+        if (isempty (vecdim))
+          m = x;
+        else
+
+          ## Calculate permutation vector
+          remdims = 1 : ndx;     # All dimensions
+          remdims(vecdim) = [];  # Delete dimensions specified by vecdim
+          nremd = numel (remdims);
+
+          ## If all dimensions are given, it is equivalent to 'all' flag
+          if (nremd == 0)
+            x = x(:);
             if (omitnan)
-              x_vec = x_vec(! isnan (x_vec));
+              x = x(! isnan (x));
+            endif
+
+            if (any (isa (x, {"int64", "uint64"})))
+              m = int64_mean (x, 1, numel (x), outtype);
+            else
+              m = sum (x, "double") ./ numel (x);
             endif
-            y(i) = sum (x_vec, 1, "double") ./ numel (x_vec);
-          endfor
-          y = ipermute (y, [misdim, dim]);
+
+          else
+            ## Permute to push vecdims to back
+            perm = [remdims, vecdim];
+            x = permute (x, perm);
+
+            ## Reshape to squash all vecdims in final dimension
+            sznew = [szx(remdims), prod(szx(vecdim))];
+            x = reshape (x, sznew);
 
-        ## for 2 dimensions left, return matrix
-        case 2
-          x = permute (x, [misdim, dim]);
-          y = zeros (size (x, 1), size (x, 2), "like", x);
-          for i = 1:size (x, 1)
-            for j = 1:size (x, 2)
-              x_vec = x(i,j,:)(:);
-              if (omitnan)
-                x_vec = x_vec(! isnan (x_vec));
-              endif
-              y(i,j) = sum (x_vec, 1, "double") ./ numel (x_vec);
-            endfor
-          endfor
-          y = ipermute (y, [misdim, dim]);
+            ## Calculate mean on final dimension
+            dim = nremd + 1;
+            if (omitnan)
+              nanx = isnan (x);
+              x(nanx) = 0;
+              n = sum (! nanx, dim);
+            else
+              n = sznew(dim);
+            endif
 
-        ## for more than 2 dimensions left, throw error
-        otherwise
-          error ("DIM must index at least N-2 dimensions of X");
-      endswitch
+            if (any (isa (x, {"int64", "uint64"})))
+              m = int64_mean (x, dim, n, outtype);
+            else
+              m = sum (x, dim, "double") ./ n;
+            endif
+
+            ## Inverse permute back to correct dimensions
+            m = ipermute (m, perm);
+          endif
+        endif
+      endif
     endif
-
   endif
 
-  ## Convert output if requested
-  switch (outtype)
-    case "default"
-      if isa(x, "single")
-        y = single (y);
+  ## Convert output if necessary
+  if (! strcmp (class (m), outtype))
+    if (! islogical (x))
+      m = feval (outtype, m);
+    endif
+  endif
+
+endfunction
+
+function m = int64_mean (x, dim, n, outtype)
+    ## Avoid int overflow in large ints.  Smaller ints processed as double
+    ## avoids overflow but large int64 values have floating pt error as double.
+    ## Use integer math and manual remainder correction to avoid this.
+    if (any (abs (x(:)) >= flintmax / n))
+      rmdr = double (rem (x, n)) / n;
+      rmdr_hilo = logical (int8 (rmdr)); # Integer rounding direction indicator
+
+      ## Do 'native' int summation to prevent double precision error,
+      ## then add back in lost round-up/down remainders.
+
+      m = sum (x/n, dim, "native");
+
+      ## rmdr.*!rmdr_hilo = remainders that were rounded down in abs val
+      ## signs retained, can be summed and added back.
+      ## rmdr.*rmdr_hilo = remainders that were rounded up in abs val.
+      ## need to add back difference between 1 and rmdr, retaining sign.
+
+      rmdr = sum (rmdr .* !rmdr_hilo, dim) - ...
+                sum ((1 - abs (rmdr)) .* rmdr_hilo .* sign (rmdr), dim);
+
+      if (any (abs (m(:)) >= flintmax))
+        ## Avoid float errors when combining for large m.
+        ## FIXME: may also need to include checking rmdr for large numel (x),
+        ##        as its value could be on the order of numel (x).
+        if (any (strcmp (outtype, {"int64", "uint64"})))
+          m += rmdr;
+        else
+          m = double (m) + rmdr;
+        endif
+
+      else
+        m = double(m) + rmdr;
+        switch (outtype)
+          case "int64"
+            m = int64 (m);
+          case "uint64"
+            m = uint64 (m);
+        endswitch
       endif
-    case "double"
-      y = double (y);
-    case "native"
-      if (! islogical (x))
-        y = feval (class (x), y);
-      endif
-  endswitch
+    else
+      m = double (sum (x, dim, "native")) ./ n;
+    endif
 
 endfunction
 
@@ -264,28 +390,115 @@
 %! out = 2;
 %! assert (mean (in, "default"), mean (in));
 %! assert (mean (in, "default"), out);
-%!
+%! assert (mean (in, "double"), out);
+%! assert (mean (in, "native"), out);
+
+%!test
 %! in = single ([1 2 3]);
 %! out = 2;
 %! assert (mean (in, "default"), mean (in));
 %! assert (mean (in, "default"), single (out));
 %! assert (mean (in, "double"), out);
 %! assert (mean (in, "native"), single (out));
-%!
+
+%!test
+%! in = logical ([1 0 1]);
+%! out = 2/3;
+%! assert (mean (in, "default"), mean (in), eps);
+%! assert (mean (in, "default"), out, eps);
+%! assert (mean (in, "double"), out, eps);
+%! assert (mean (in, "native"), out, eps);
+
+%!test
+%! in = char ("ab");
+%! out = 97.5;
+%! assert (mean (in, "default"), mean (in), eps);
+%! assert (mean (in, "default"), out, eps);
+%! assert (mean (in, "double"), out, eps);
+
+%!test
 %! in = uint8 ([1 2 3]);
 %! out = 2;
 %! assert (mean (in, "default"), mean (in));
 %! assert (mean (in, "default"), out);
 %! assert (mean (in, "double"), out);
 %! assert (mean (in, "native"), uint8 (out));
-%!
-%! in = logical ([1 0 1]);
-%! out = 2/3;
+
+%!test
+%! in = uint8 ([0 1 2 3]);
+%! out = 1.5;
+%! out_u8 = 2;
+%! assert (mean (in, "default"), mean (in), eps);
+%! assert (mean (in, "default"), out, eps);
+%! assert (mean (in, "double"), out, eps);
+%! assert (mean (in, "native"), uint8 (out_u8));
+%! assert (class (mean (in, "native")), "uint8");
+
+%!test # internal sum exceeding intmax
+%! in = uint8 ([3 141 141 255]);
+%! out = 135;
+%! assert (mean (in, "default"), mean (in));
+%! assert (mean (in, "default"), out);
+%! assert (mean (in, "double"), out);
+%! assert (mean (in, "native"), uint8 (out));
+%! assert (class (mean (in, "native")), "uint8");
+
+%!test # fractional answer with internal sum exceeding intmax
+%! in = uint8 ([1 141 141 255]);
+%! out = 134.5;
+%! out_u8 = 135;
 %! assert (mean (in, "default"), mean (in));
 %! assert (mean (in, "default"), out);
-%! assert (mean (in, "native"), out);  # logical ignores native option
+%! assert (mean (in, "double"), out);
+%! assert (mean (in, "native"), uint8 (out_u8));
+%! assert (class (mean (in, "native")), "uint8");
 
-## Test single input and optional arguments "all", DIM, "omitnan")
+%!test <54567> # large int64 sum exceeding intmax and double precision limit
+%! in_same = uint64 ([intmax("uint64") intmax("uint64")-2]);
+%! out_same = intmax ("uint64")-1;
+%! in_opp = int64 ([intmin("int64"), intmax("int64")-1]);
+%! out_opp = -1;
+%! in_neg = int64 ([intmin("int64") intmin("int64")+2]);
+%! out_neg = intmin ("int64")+1;
+%!
+%! ## both positive
+%! assert (mean (in_same, "default"), mean (in_same));
+%! assert (mean (in_same, "default"), double (out_same));
+%! assert (mean (in_same, "double"), double (out_same));
+%! assert (mean (in_same, "native"), uint64 (out_same));
+%! assert (class (mean (in_same, "native")), "uint64");
+%!
+%! ## opposite signs
+%! assert (mean (in_opp, "default"), mean (in_opp));
+%! assert (mean (in_opp, "default"), double (out_opp));
+%! assert (mean (in_opp, "double"), double (out_opp));
+%! assert (mean (in_opp, "native"), int64 (out_opp));
+%! assert (class (mean (in_opp, "native")), "int64");
+%!
+%! ## both negative
+%! assert (mean (in_neg, "default"), mean (in_neg));
+%! assert (mean (in_neg, "default"), double(out_neg));
+%! assert (mean (in_neg, "double"), double(out_neg));
+%! assert (mean (in_neg, "native"), int64(out_neg));
+%! assert (class (mean (in_neg, "native")), "int64");
+
+## Additional tests int64 and double precision limits
+%!test <54567>
+%! in = [(intmin('int64')+5), (intmax('int64'))-5];
+%! assert (mean (in, "native"), int64(-1));
+%! assert (class (mean (in, "native")), "int64");
+%! assert (mean (double(in)), double(0) );
+%! assert (mean (in), double(-0.5) );
+%! assert (mean (in, "default"), double(-0.5) );
+%! assert (mean (in, "double"), double(-0.5) );
+%! assert (mean (in, "all", "native"), int64(-1));
+%! assert (mean (in, 2, "native"), int64(-1));
+%! assert (mean (in, [1 2], "native"), int64(-1));
+%! assert (mean (in, [2 3], "native"), int64(-1));
+%! assert (mean ([intmin("int64"), in, intmax("int64")]), double(-0.5))
+%! assert (mean ([in; int64([1 3])], 2, "native"), int64([-1; 2]));
+
+## Test input and optional arguments "all", DIM, "omitnan".
 %!test
 %! x = [-10:10];
 %! y = [x;x+5;x-5];
@@ -296,6 +509,8 @@
 %! assert (mean (y', "omitnan"), [0 5.35 -5]);
 %! z = y + 20;
 %! assert (mean (z, "all"), NaN);
+%! assert (mean (z, "all", "includenan"), NaN);
+%! assert (mean (z, "all", "omitnan"), 20.03225806451613, 4e-14);
 %! m = [20 NaN 15];
 %! assert (mean (z'), m);
 %! assert (mean (z', "includenan"), m);
@@ -316,6 +531,48 @@
 %! assert (mean ([true false NaN], 2, "omitnan"), 0.5);
 %! assert (mean ([true false NaN], 2, "omitnan", "native"), 0.5);
 
+## Test char inputs
+%!assert (mean ("abc"), double (98))
+%!assert (mean ("ab"), double (97.5), eps)
+%!assert (mean ("abc", "double"), double (98))
+%!assert (mean ("abc", "default"), double (98))
+
+## Test NaN inputs
+%!test
+%! x = magic (4);
+%! x([2, 9:12]) = NaN;
+%! assert (mean (x), [NaN 8.5, NaN, 8.5], eps);
+%! assert (mean (x,1), [NaN 8.5, NaN, 8.5], eps);
+%! assert (mean (x,2), NaN(4,1), eps);
+%! assert (mean (x,3), x, eps);
+%! assert (mean (x, 'omitnan'), [29/3, 8.5, NaN, 8.5], eps);
+%! assert (mean (x, 1, 'omitnan'), [29/3, 8.5, NaN, 8.5], eps);
+%! assert (mean (x, 2, 'omitnan'), [31/3; 9.5; 28/3; 19/3], eps);
+%! assert (mean (x, 3, 'omitnan'), x, eps);
+
+## Test empty inputs
+%!assert (mean ([]), NaN(1,1))
+%!assert (mean (single([])), NaN(1,1,"single"))
+%!assert (mean ([], 1), NaN(1,0))
+%!assert (mean ([], 2), NaN(0,1))
+%!assert (mean ([], 3), NaN(0,0))
+%!assert (mean (ones(1,0)), NaN(1,1))
+%!assert (mean (ones(1,0), 1), NaN(1,0))
+%!assert (mean (ones(1,0), 2), NaN(1,1))
+%!assert (mean (ones(1,0), 3), NaN(1,0))
+%!assert (mean (ones(0,1)), NaN(1,1))
+%!assert (mean (ones(0,1), 1), NaN(1,1))
+%!assert (mean (ones(0,1), 2), NaN(0,1))
+%!assert (mean (ones(0,1), 3), NaN(0,1))
+%!assert (mean (ones(0,1,0)), NaN(1,1,0))
+%!assert (mean (ones(0,1,0), 1), NaN(1,1,0))
+%!assert (mean (ones(0,1,0), 2), NaN(0,1,0))
+%!assert (mean (ones(0,1,0), 3), NaN(0,1,1))
+%!assert (mean (ones(0,0,1,0)), NaN(1,0,1,0))
+%!assert (mean (ones(0,0,1,0), 1), NaN(1,0,1,0))
+%!assert (mean (ones(0,0,1,0), 2), NaN(0,1,1,0))
+%!assert (mean (ones(0,0,1,0), 3), NaN(0,0,1,0))
+
 ## Test dimension indexing with vecdim in N-dimensional arrays
 %!test
 %! x = repmat ([1:20;6:25], [5 2 6 3]);
@@ -325,17 +582,29 @@
 %! assert (size (mean (x, [1 4 3])), [1 40]);
 %! assert (size (mean (x, [1 2 3 4])), [1 1]);
 
-## Test results with vecdim in N-dimensional arrays and "omitnan"
+## Test exceeding dimensions
+%!assert (mean (ones (2,2), 3), ones (2,2))
+%!assert (mean (ones (2,2,2), 99), ones (2,2,2))
+%!assert (mean (magic (3), 3), magic (3))
+%!assert (mean (magic (3), [1 3]), [5, 5, 5])
+%!assert (mean (magic (3), [1 99]), [5, 5, 5])
+
+## Test results with vecdim in n-dimensional arrays and "omitnan"
 %!test
 %! x = repmat ([1:20;6:25], [5 2 6 3]);
 %! m = repmat ([10.5;15.5], [5 1 1 3]);
 %! assert (mean (x, [3 2]), m, 4e-14);
 %! x(2,5,6,3) = NaN;
-%! m(2,3) = NaN;
+%! m(2,1,1,3) = NaN;
 %! assert (mean (x, [3 2]), m, 4e-14);
-%! m(2,3) = 15.52301255230125;
+%! m(2,1,1,3) = 15.52301255230125;
 %! assert (mean (x, [3 2], "omitnan"), m, 4e-14);
 
+## Test input case insensitivity
+%!assert (mean ([1 2 3], "aLL"), 2)
+%!assert (mean ([1 2 3], "OmitNan"), 2)
+%!assert (mean ([1 2 3], "DOUBle"), 2)
+
 ## Test limits of single precision summation limits on each code path
 %!assert <*63848> (mean (ones (80e6, 1, "single")), 1, eps)
 %!assert <*63848> (mean (ones (80e6, 1, "single"), "all"), 1, eps)
@@ -348,21 +617,23 @@
 %!                               35184372088833-1/(2^8), eps(35184372088833))
 
 ## Test input validation
-%!error <Invalid call> mean ()
-%!error <Invalid call> mean (1, 2, 3)
-%!error <Invalid call> mean (1, 2, 3, 4, 5)
-%!error <Invalid call> mean (1, "all", 3)
-%!error <Invalid call> mean (1, "b")
-%!error <Invalid call> mean (1, 1, "foo")
-%!error <X must be either a numeric or logical> mean ({1:5})
-%!error <X must be either a numeric or logical> mean ("char")
+%!error <Invalid call to mean.  Correct usage is> mean ()
+%!error <Invalid call to mean.  Correct usage is> mean (1, 2, 3)
+%!error <Invalid call to mean.  Correct usage is> mean (1, 2, 3, 4)
+%!error <Invalid call to mean.  Correct usage is> mean (1, "all", 3)
+%!error <Invalid call to mean.  Correct usage is> mean (1, "b")
+%!error <Invalid call to mean.  Correct usage is> mean (1, 1, "foo")
+%!error <OUTTYPE 'native' cannot be used with char> mean ("abc", "native")
+%!error <X must be either a numeric, boolean, or character> mean ({1:5})
 %!error <DIM must be a positive integer> mean (1, ones (2,2))
 %!error <DIM must be a positive integer> mean (1, 1.5)
+%!error <DIM must be a positive integer> mean (1, 0)
+%!error <DIM must be a positive integer> mean (1, [])
 %!error <DIM must be a positive integer> mean (1, -1)
 %!error <DIM must be a positive integer> mean (1, -1.5)
-%!error <DIM must be a positive integer> mean (1, 0)
 %!error <DIM must be a positive integer> mean (1, NaN)
 %!error <DIM must be a positive integer> mean (1, Inf)
-%!error <DIM must index at least N-2 dimensions of X>
-%!  mean (repmat ([1:20;6:25], [5 2 6 3 5]), [1 2])
-
+%!error <DIM must be a positive integer> mean (repmat ([1:20;6:25], [5 2]), -1)
+%!error <DIM must be a positive integer> mean (repmat ([1:5;5:9], [5 2]), [1 -1])
+%!error <DIM must be a positive integer> mean (1, ones(1,0))
+%!error <VECDIM must contain non-repeating> mean (1, [2 2])
--- a/scripts/statistics/median.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/median.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,9 +24,13 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn  {} {@var{y} =} median (@var{x})
-## @deftypefnx {} {@var{y} =} median (@var{x}, @var{dim})
-## Compute the median value of the elements of the vector @var{x}.
+## @deftypefn  {} {@var{m} =} median (@var{x})
+## @deftypefnx {} {@var{m} =} median (@var{x}, @var{dim})
+## @deftypefnx {} {@var{m} =} median (@var{x}, @var{vecdim})
+## @deftypefnx {} {@var{m} =} median (@var{x}, "all")
+## @deftypefnx {} {@var{m} =} median (@dots{}, @var{nanflag})
+## @deftypefnx {} {@var{m} =} median (@dots{}, @var{outtype})
+## Compute the median value of the elements of @var{x}.
 ##
 ## When the elements of @var{x} are sorted, say
 ## @code{@var{s} = sort (@var{x})}, the median is defined as
@@ -43,66 +47,406 @@
 ##
 ## @example
 ## @group
-##              |  @var{s}(ceil(N/2))           N odd
+##              |  @var{s}(ceil (N/2))          N odd
 ## median (@var{x}) = |
 ##              | (@var{s}(N/2) + @var{s}(N/2+1))/2   N even
 ## @end group
 ## @end example
 ##
 ## @end ifnottex
-## If @var{x} is of a discrete type such as integer or logical, then
-## the case of even @math{N} rounds up (or toward @code{true}).
+##
+## If @var{x} is an array, then @code{median (@var{x})} operates along the
+## first non-singleton dimension of @var{x}.
+##
+## The optional variable @var{dim} forces @code{median} to operate over the
+## specified dimension, which must be a positive integer-valued number.
+## Specifying any singleton dimension in @var{x}, including any dimension
+## exceeding @code{ndims (@var{x})}, will result in a median equal to @var{x}.
+##
+## Specifying the dimensions as  @var{vecdim}, a vector of non-repeating
+## dimensions, will return the median over the array slice defined by
+## @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it is
+## equivalent to the option @qcode{"all"}.  Any dimension in @var{vecdim}
+## greater than @code{ndims (@var{x})} is ignored.
+##
+## Specifying the dimension as @qcode{"all"} will force @code{median} to
+## operate on all elements of @var{x}, and is equivalent to
+## @code{median (@var{x}(:))}.
+##
+## @code{median (@dots{}, @var{outtype})} returns the median with a specified
+## data type, using any of the input arguments in the previous syntaxes.
+## @var{outtype} can take the following values:
 ##
-## If @var{x} is a matrix, compute the median value for each column and
-## return them in a row vector.
+## @table @asis
+## @item @qcode{"default"}
+## Output is of type double, unless the input is single in which case the
+## output is of type single.
+##
+## @item @qcode{"double"}
+## Output is of type double.
 ##
-## If the optional @var{dim} argument is given, operate along this dimension.
-## @seealso{mean, mode}
+## @item @qcode{"native"}.
+## Output is of the same type as the input (@code{class (@var{x})}), unless the
+## input is logical in which case the output is of type double.
+## @end table
+##
+## The optional variable @var{nanflag} specifies whether to include or exclude
+## NaN values from the calculation using any of the previously specified input
+## argument combinations.  The default value for @var{nanflag} is
+## @qcode{"includenan"} which keeps NaN values in the calculation.  To
+## exclude NaN values set the value of @var{nanflag} to @qcode{"omitnan"}.
+## The output will still contain NaN values if @var{x} consists of all NaN
+## values in the operating dimension.
+##
+## @seealso{mean, mode, movmedian}
 ## @end deftypefn
 
-function y = median (x, dim)
+function m = median (x, varargin)
 
-  if (nargin < 1)
+  if (nargin < 1 || nargin > 4)
     print_usage ();
   endif
 
   if (! (isnumeric (x) || islogical (x)))
-    error ("median: X must be a numeric vector or matrix");
+    error ("median: X must be either numeric or logical");
+  endif
+
+  ## Set initial conditions
+  all_flag    = false;
+  omitnan     = false;
+  perm_flag   = false;
+  out_flag    = false;
+  vecdim_flag = false;
+  dim         = [];
+
+  nvarg = numel (varargin);
+  varg_chars = cellfun ("ischar", varargin);
+  szx = sz_out = size (x);
+  ndx = ndims (x);
+  outtype = class (x);
+
+  if (nvarg > 1 && ! varg_chars(2:end))
+    ## Only first varargin can be numeric
+    print_usage ();
+  endif
+
+  ## Process any other char arguments.
+  if (any (varg_chars))
+    for argin = varargin(varg_chars)
+      switch (lower (argin{1}))
+        case "all"
+          all_flag = true;
+
+        case "omitnan"
+          omitnan = true;
+
+        case "includenan"
+          omitnan = false;
+
+        case "native"
+          if (out_flag)
+            error ("median: only one OUTTYPE can be specified");
+          endif
+          if (strcmp (outtype, "logical"))
+            outtype = "double";
+          endif
+          out_flag = true;
+
+        case "default"
+          if (out_flag)
+            error ("median: only one OUTTYPE can be specified");
+          endif
+          if (! strcmp (outtype, "single"))
+            outtype = "double";
+          endif
+          out_flag = true;
+
+        case "double"
+          if (out_flag)
+            error ("median: only one OUTTYPE can be specified");
+          endif
+          outtype = "double";
+          out_flag = true;
+
+        otherwise
+          print_usage ();
+      endswitch
+    endfor
+
+    varargin(varg_chars) = [];
+    nvarg = numel (varargin);
+  endif
+
+  if ((nvarg == 1 && ! isnumeric (varargin{1})) || nvarg > 1)
+    ## After trimming char inputs should only be one numeric varargin left
+    print_usage ();
+  endif
+
+  ## Process special cases for in/out size
+  if (nvarg > 0)
+    ## dim or vecdim provided
+    if (all_flag)
+      error ("median: 'all' cannot be used with DIM or VECDIM options");
+    endif
+
+    dim = varargin{1};
+    vecdim_flag = ! isscalar (dim);
+
+    if (! (isvector (dim) && dim > 0) || any (rem (dim, 1)))
+      error ("median: DIM must be a positive integer scalar or vector");
+    endif
+
+    ## Adjust sz_out, account for possible dim > ndx by appending singletons
+    sz_out(ndx + 1 : max (dim)) = 1;
+    sz_out(dim(dim <= ndx)) = 1;
+    szx(ndx + 1 : max (dim)) = 1;
+
+    if (vecdim_flag)
+      ## vecdim - try to simplify first
+      dim = sort (dim);
+      if (! all (diff (dim)))
+         error ("median: VECDIM must contain non-repeating positive integers");
+      endif
+
+      ## dims > ndims(x) and dims only one element long don't affect median
+      sing_dim_x = find (szx != 1);
+      dim(dim > ndx | szx(dim) == 1) = [];
+
+      if (isempty (dim))
+        ## No dims left to process, return input as output
+        if (! strcmp (class (x), outtype))
+          m = feval (outtype, x);  # convert to outtype
+        else
+          m = x;
+        endif
+        return;
+      elseif (numel (dim) == numel (sing_dim_x)
+              && unique ([dim, sing_dim_x]) == dim)
+        ## If DIMs cover all nonsingleton ndims(x) it's equivalent to "all"
+        ##   (check lengths first to reduce unique overhead if not covered)
+        all_flag = true;
+      endif
+    endif
+
+  else
+    ## Dim not provided.  Determine scalar dimension.
+    if (all_flag)
+      ## Special case 'all': Recast input as dim1 vector, process as normal.
+      x = x(:);
+      szx = [numel(x), 1];
+      dim = 1;
+      sz_out = [1 1];
+
+    elseif (isrow (x))
+      ## Special case row vector: Avoid setting dim to 1.
+      dim = 2;
+      sz_out = [1, 1];
+
+    elseif (ndx == 2 && szx == [0, 0])
+      ## Special case []: Do not apply sz_out(dim)=1 change.
+      dim = 1;
+      sz_out = [1, 1];
+
+    else
+      ## General case: Set dim to first non-singleton, contract sz_out along dim
+      (dim = find (szx != 1, 1)) || (dim = 1);
+      sz_out(dim) = 1;
+    endif
   endif
 
   if (isempty (x))
-    error ("median: X cannot be an empty matrix");
+    ## Empty input - output NaN or class equivalent in pre-determined size
+    switch (outtype)
+      case {"double", "single"}
+        m = NaN (sz_out, outtype);
+      case ("logical")
+        m = false (sz_out);
+      otherwise
+        m = cast (NaN (sz_out), outtype);
+    endswitch
+    return;
+  endif
+
+  if (szx(dim) == 1)
+    ## Operation along singleton dimension - nothing to do
+    if (! strcmp (class (x), outtype))
+      m = feval (outtype, x);  # convert to outtype
+    else
+      m = x;
+    endif
+    return;
+  endif
+
+  ## Permute dim to simplify all operations along dim1.  At func. end ipermute.
+  if (numel (dim) > 1 || (dim != 1 && ! isvector (x)))
+    perm = 1 : ndx;
+
+    if (! vecdim_flag)
+      ## Move dim to dim 1
+      perm([1, dim]) = [dim, 1];
+      x = permute (x, perm);
+      szx([1, dim]) = szx([dim, 1]);
+      dim = 1;
+
+    else
+      ## Move vecdims to front
+      perm(dim) = [];
+      perm = [dim, perm];
+      x = permute (x, perm);
+
+      ## Reshape all vecdims into dim1
+      num_dim = prod (szx(dim));
+      szx(dim) = [];
+      szx = [num_dim, ones(1, numel(dim)-1), szx];
+      x = reshape (x, szx);
+      dim = 1;
+    endif
+
+    perm_flag = true;
+  endif
+
+  ## Find column locations of NaNs
+  nanfree = ! any (isnan (x), dim);
+  if (omitnan && nanfree(:))
+    ## Don't use omitnan path if no NaNs are present.  Prevents any data types
+    ## without a defined NaN from following slower omitnan codepath.
+    omitnan = false;
   endif
 
-  nd = ndims (x);
-  sz = size (x);
-  if (nargin < 2)
-    ## Find the first non-singleton dimension.
-    (dim = find (sz > 1, 1)) || (dim = 1);
+  x = sort (x, dim); # Note: pushes any NaN's to end for omitnan compatibility
+
+  if (omitnan)
+    ## Ignore any NaN's in data.  Each operating vector might have a
+    ## different number of non-NaN data points.
+
+    if (isvector (x))
+      ## Checks above ensure either dim1 or dim2 vector
+      x = x(! isnan (x));
+      n = numel (x);
+      k = floor ((n + 1) / 2);
+      if (mod (n, 2))
+        ## odd
+        m = x(k);
+      else
+        ## even
+        m = (x(k) + x(k + 1)) / 2;
+      endif
+
+    else
+      ## Each column may have a different n and k.  Force index column vector
+      ## for consistent orientation for 2D and nD inputs, then use sub2ind to
+      ## get correct element(s) for each column.
+
+      n = sum (! isnan (x), 1)(:);
+      k = floor ((n + 1) / 2);
+      m_idx_odd = mod (n, 2) & n;
+      m_idx_even = (! m_idx_odd) & n;
+
+      m = NaN ([1, szx(2 : end)]);
+
+      if (ndims (x) > 2)
+        szx = [szx(1), prod(szx(2 : end))];
+      endif
+
+      ## Grab kth value, k possibly different for each column
+      if (any (m_idx_odd))
+        x_idx_odd = sub2ind (szx, k(m_idx_odd), find (m_idx_odd));
+        m(m_idx_odd) = x(x_idx_odd);
+      endif
+      if (any (m_idx_even))
+        k_even = k(m_idx_even);
+        x_idx_even = sub2ind (szx, [k_even, k_even + 1], ...
+                                (find (m_idx_even))(:, [1, 1]));
+        m(m_idx_even) = sum (x(x_idx_even), 2) / 2;
+      endif
+    endif
+
   else
-    if (! (isscalar (dim) && dim == fix (dim) && dim > 0))
-      error ("median: DIM must be an integer and a valid dimension");
+    ## No "omitnan".  All 'vectors' uniform length.
+    ## All types without a NaN value will use this path.
+    if (all (! nanfree))
+      m = NaN (sz_out);
+
+    else
+      if (isvector (x))
+        n = numel (x);
+        k = floor ((n + 1) / 2);
+
+        m = x(k);
+        if (! mod (n, 2))
+          ## Even
+          if (any (isa (x, "integer")))
+            ## avoid int overflow issues
+            m2 = x(k + 1);
+            if (sign (m) != sign (m2))
+              m += m2;
+              m /= 2;
+            else
+              m += (m2 - m) / 2;
+            endif
+          else
+            m += (x(k + 1) - m) / 2;
+          endif
+        endif
+
+      else
+        ## Nonvector, all operations were permuted to be along dim 1
+        n = szx(1);
+        k = floor ((n + 1) / 2);
+
+        if (isfloat (x))
+          m = NaN ([1, szx(2 : end)]);
+        else
+          m = zeros ([1, szx(2 : end)], outtype);
+        endif
+
+        if (! mod (n, 2))
+          ## Even
+          if (any (isa (x, "integer")))
+            ## avoid int overflow issues
+
+            ## Use flattened index to simplify N-D operations
+            m(1, :) = x(k, :);
+            m2 = x(k + 1, :);
+
+            samesign = prod (sign ([m(1, :); m2]), 1) == 1;
+            m(1, :) = samesign .* m(1, :) + ...
+                       (m2 + !samesign .* m(1, :) - samesign .* m(1, :)) / 2;
+
+          else
+            m(nanfree) = (x(k, nanfree) + x(k + 1, nanfree)) / 2;
+          endif
+        else
+          ## Odd.  Use flattened index to simplify N-D operations
+          m(nanfree) = x(k, nanfree);
+        endif
+      endif
     endif
   endif
 
-  n = size (x, dim);
-  k = floor ((n+1) / 2);
-  if (mod (n, 2) == 1)
-    y = nth_element (x, k, dim);
-  else
-    y = sum (nth_element (x, k:k+1, dim), dim, "native") / 2;
-    if (islogical (x))
-      y = logical (y);
-    endif
+  if (perm_flag)
+    ## Inverse permute back to correct dimensions
+    m = ipermute (m, perm);
   endif
-  ## Inject NaNs where needed, to be consistent with Matlab.
-  if (isfloat (x))
-    y(any (isnan (x), dim)) = NaN;
+
+  ## Convert output type as requested
+  if (! strcmp (class (m), outtype))
+    m = feval (outtype, m);
   endif
 
 endfunction
 
 
+%!assert (median (1), 1)
+%!assert (median ([1,2,3]), 2)
+%!assert (median ([1,2,3]'), 2)
+%!assert (median (cat(3,3,1,2)), 2)
+%!assert (median ([3,1,2]), 2)
+%!assert (median ([2,4,6,8]), 5)
+%!assert (median ([8,2,6,4]), 5)
+%!assert (median (single ([1,2,3])), single (2))
+%!assert (median ([1,2], 3), [1,2])
+
 %!test
 %! x = [1, 2, 3, 4, 5, 6];
 %! x2 = x';
@@ -111,12 +455,171 @@
 %!
 %! assert (median (x) == median (x2) && median (x) == 3.5);
 %! assert (median (y) == median (y2) && median (y) == 4);
-%! assert (median ([x2, 2*x2]), [3.5, 7]);
-%! assert (median ([y2, 3*y2]), [4, 12]);
+%! assert (median ([x2, 2 * x2]), [3.5, 7]);
+%! assert (median ([y2, 3 * y2]), [4, 12]);
+
+## Test outtype option
+%!test
+%! in = [1 2 3];
+%! out = 2;
+%! assert (median (in, "default"), median (in));
+%! assert (median (in, "default"), out);
+%!test
+%! in = single ([1 2 3]);
+%! out = 2;
+%! assert (median (in, "default"), single (median (in)));
+%! assert (median (in, "default"), single (out));
+%! assert (median (in, "double"), double (out));
+%! assert (median (in, "native"), single (out));
+%!test
+%! in = uint8 ([1 2 3]);
+%! out = 2;
+%! assert (median (in, "default"), double (median (in)));
+%! assert (median (in, "default"), double (out));
+%! assert (median (in, "double"), out);
+%! assert (median (in, "native"), uint8 (out));
+%!test
+%! in = logical ([1 0 1]);
+%! out = 1;
+%! assert (median (in, "default"), double (median (in)));
+%! assert (median (in, "default"), double (out));
+%! assert (median (in, "double"), double (out));
+%! assert (median (in, "native"), double (out));
+
+## Test single input and optional arguments "all", DIM, "omitnan")
+%!test
+%! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);
+%! y = repmat ([2 1.1 2 NaN NaN], [1, 1, 4]);
+%! assert (median (x), y);
+%! assert (median (x, 1), y);
+%! y = repmat ([2 1.1 2 3.5 4], [1, 1, 4]);
+%! assert (median (x, "omitnan"), y);
+%! assert (median (x, 1, "omitnan"), y);
+%! y = repmat ([2.05; 2.5; 1.4], [1, 1, 4]);
+%! assert (median (x, 2, "omitnan"), y);
+%! y = repmat ([NaN; NaN; 1.4], [1, 1, 4]);
+%! assert (median (x, 2), y);
+%! assert (median (x, "all"), NaN);
+%! assert (median (x, "all", "omitnan"), 2);
+%!assert (median (cat (3, 3, 1, NaN, 2), "omitnan"), 2)
+%!assert (median (cat (3, 3, 1, NaN, 2), 3, "omitnan"), 2)
+
+## Test boolean input
+%!test
+%! assert (median (true, "all"), logical (1));
+%! assert (median (false), logical (0));
+%! assert (median ([true false true]), true);
+%! assert (median ([true false true], 2), true);
+%! assert (median ([true false true], 1), logical ([1 0 1]));
+%! assert (median ([true false NaN], 1), [1 0 NaN]);
+%! assert (median ([true false NaN], 2), NaN);
+%! assert (median ([true false NaN], 2, "omitnan"), 0.5);
+%! assert (median ([true false NaN], 2, "omitnan", "native"), double(0.5));
+
+## Test dimension indexing with vecdim in n-dimensional arrays
+%!test
+%! x = repmat ([1:20;6:25], [5 2 6 3]);
+%! assert (size (median (x, [3 2])), [10 1 1 3]);
+%! assert (size (median (x, [1 2])), [1 1 6 3]);
+%! assert (size (median (x, [1 2 4])), [1 1 6]);
+%! assert (size (median (x, [1 4 3])), [1 40]);
+%! assert (size (median (x, [1 2 3 4])), [1 1]);
+
+## Test exceeding dimensions
+%!assert (median (ones (2,2), 3), ones (2,2))
+%!assert (median (ones (2,2,2), 99), ones (2,2,2))
+%!assert (median (magic (3), 3), magic (3))
+%!assert (median (magic (3), [1 3]), [4, 5, 6])
+%!assert (median (magic (3), [1 99]), [4, 5, 6])
 
-%!assert (median (single ([1,2,3])), single (2))
+## Test results with vecdim in n-dimensional arrays and "omitnan"
+%!test
+%! x = repmat ([2 2.1 2.2 2 NaN; 3 1 2 NaN 5; 1 1.1 1.4 5 3], [1, 1, 4]);
+%! assert (median (x, [3 2]), [NaN NaN 1.4]');
+%! assert (median (x, [3 2], "omitnan"), [2.05 2.5 1.4]');
+%! assert (median (x, [1 3]), [2 1.1 2 NaN NaN]);
+%! assert (median (x, [1 3], "omitnan"), [2 1.1 2 3.5 4]);
+
+## Test empty, NaN, Inf inputs
+%!assert (median (NaN), NaN)
+%!assert (median (NaN, "omitnan"), NaN)
+%!assert (median (NaN (2)), [NaN NaN])
+%!assert (median (NaN (2), "omitnan"), [NaN NaN])
+%!assert (median ([1 NaN 3]), NaN)
+%!assert (median ([1 NaN 3], 1), [1 NaN 3])
+%!assert (median ([1 NaN 3], 2), NaN)
+%!assert (median ([1 NaN 3]'), NaN)
+%!assert (median ([1 NaN 3]', 1), NaN)
+%!assert (median ([1 NaN 3]', 2), [1; NaN; 3])
+%!assert (median ([1 NaN 3], "omitnan"), 2)
+%!assert (median ([1 NaN 3]', "omitnan"), 2)
+%!assert (median ([1 NaN 3], 1, "omitnan"), [1 NaN 3])
+%!assert (median ([1 NaN 3], 2, "omitnan"), 2)
+%!assert (median ([1 NaN 3]', 1, "omitnan"), 2)
+%!assert (median ([1 NaN 3]', 2, "omitnan"), [1; NaN; 3])
+%!assert (median ([1 2 NaN 3]), NaN)
+%!assert (median ([1 2 NaN 3], "omitnan"), 2)
 %!assert (median ([1,2,NaN;4,5,6;NaN,8,9]), [NaN, 5, NaN])
-%!assert (median ([1,2], 3), [1,2])
+%!assert <*64011> (median ([1,2,NaN;4,5,6;NaN,8,9], "omitnan"), [2.5, 5, 7.5], eps)
+%!assert (median ([1 2 ; NaN 4]), [NaN 3])
+%!assert (median ([1 2 ; NaN 4], "omitnan"), [1 3])
+%!assert (median ([1 2 ; NaN 4], 1, "omitnan"), [1 3])
+%!assert (median ([1 2 ; NaN 4], 2, "omitnan"), [1.5; 4], eps)
+%!assert (median ([1 2 ; NaN 4], 3, "omitnan"), [1 2 ; NaN 4])
+%!assert (median ([NaN 2 ; NaN 4]), [NaN 3])
+%!assert (median ([NaN 2 ; NaN 4], "omitnan"), [NaN 3])
+%!assert (median (ones (1, 0, 3)), NaN (1, 1, 3))
+
+%!assert (median (NaN("single")), NaN("single"))
+%!assert (median (NaN("single"), "omitnan"), NaN("single"))
+%!assert (median (NaN("single"), "double"), NaN("double"))
+%!assert (median (single([1 2 ; NaN 4])), single([NaN 3]))
+%!assert (median (single([1 2 ; NaN 4]), "double"), double([NaN 3]))
+%!assert (median (single([1 2 ; NaN 4]), "omitnan"), single([1 3]))
+%!assert (median (single([1 2 ; NaN 4]), "omitnan", "double"), double([1 3]))
+%!assert (median (single([NaN 2 ; NaN 4]), "double"), double([NaN 3]))
+%!assert (median (single([NaN 2 ; NaN 4]), "omitnan"), single([NaN 3]))
+%!assert (median (single([NaN 2 ; NaN 4]), "omitnan", "double"), double([NaN 3]))
+
+## Test omitnan with 2D & 3D inputs to confirm correct sub2ind orientation
+%!test <*64011>
+%! x = [magic(3), magic(3)];
+%! x([3, 7, 11, 12, 16, 17]) = NaN;
+%! ynan = [NaN, 5, NaN, NaN, 5, NaN];
+%! yomitnan = [5.5, 5, 4.5, 8, 5, 2];
+%! assert (median (x), ynan);
+%! assert (median (x, "omitnan"), yomitnan, eps);
+%! assert (median (cat (3, x, x)), cat (3, ynan, ynan));
+%! assert (median (cat (3, x, x), "omitnan"), cat (3, yomitnan, yomitnan), eps);
+
+%!assert (median (Inf), Inf)
+%!assert (median (-Inf), -Inf)
+%!assert (median ([-Inf Inf]), NaN)
+%!assert (median ([3 Inf]), Inf)
+%!assert (median ([3 4 Inf]), 4)
+%!assert (median ([Inf 3 4]), 4)
+%!assert (median ([Inf 3 Inf]), Inf)
+
+%!assert (median ([]), NaN)
+%!assert (median (ones(1,0)), NaN)
+%!assert (median (ones(0,1)), NaN)
+%!assert (median ([], 1), NaN(1,0))
+%!assert (median ([], 2), NaN(0,1))
+%!assert (median ([], 3), NaN(0,0))
+%!assert (median (ones(1,0), 1), NaN(1,0))
+%!assert (median (ones(1,0), 2), NaN(1,1))
+%!assert (median (ones(1,0), 3), NaN(1,0))
+%!assert (median (ones(0,1), 1), NaN(1,1))
+%!assert (median (ones(0,1), 2), NaN(0,1))
+%!assert (median (ones(0,1), 3), NaN(0,1))
+%!assert (median (ones(0,1,0,1), 1), NaN(1,1,0))
+%!assert (median (ones(0,1,0,1), 2), NaN(0,1,0))
+%!assert (median (ones(0,1,0,1), 3), NaN(0,1,1))
+%!assert (median (ones(0,1,0,1), 4), NaN(0,1,0))
+
+## Test complex inputs (should sort by abs(a))
+%!assert (median([1 3 3i 2 1i]), 2)
+%!assert (median([1 2 4i; 3 2i 4]), [2, 1+1i, 2+2i])
 
 ## Test multidimensional arrays
 %!shared a, b, x, y
@@ -129,18 +632,86 @@
 %! y = sort (b, 3);
 %!assert <*35679> (median (a, 4), x(:, :, :, 3))
 %!assert <*35679> (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2)
+%!shared   ## Clear shared to prevent variable echo for any later test failures
+
+## Test n-dimensional arrays with odd non-NaN data points
+%!test
+%! x = ones(15,1,4);
+%! x([13,15],1,:) = NaN;
+%! assert (median (x, 1, "omitnan"), ones (1,1,4))
 
 ## Test non-floating point types
 %!assert (median ([true, false]), true)
+%!assert (median (logical ([])), false)
 %!assert (median (uint8 ([1, 3])), uint8 (2))
+%!assert (median (uint8 ([])), uint8 (NaN))
+%!assert (median (uint8 ([NaN 10])), uint8 (5))
 %!assert (median (int8 ([1, 3, 4])), int8 (3))
+%!assert (median (int8 ([])), int8 (NaN))
 %!assert (median (single ([1, 3, 4])), single (3))
 %!assert (median (single ([1, 3, NaN])), single (NaN))
 
+## Test same sign int overflow when getting mean of even number of values
+%!assert <*54567> (median (uint8 ([253, 255])), uint8 (254))
+%!assert <*54567> (median (uint8 ([253, 254])), uint8 (254))
+%!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9])), ...
+%!                  int8 ([64 65 65 67]))
+%!assert <*54567> (median (int8 ([127, 126, 125, 124; 1 3 5 9]), 2), ...
+%!                  int8 ([126; 4]))
+%!assert <*54567> (median (int64 ([intmax("int64"), intmax("int64")-2])), ...
+%!                  intmax ("int64") - 1)
+%!assert <*54567> (median ( ...
+%!                 int64 ([intmax("int64"), intmax("int64")-2; 1 2]), 2), ...
+%!                 int64([intmax("int64") - 1; 2]))
+%!assert <*54567> (median (uint64 ([intmax("uint64"), intmax("uint64")-2])), ...
+%!                  intmax ("uint64") - 1)
+%!assert <*54567> (median ( ...
+%!                 uint64 ([intmax("uint64"), intmax("uint64")-2; 1 2]), 2), ...
+%!                 uint64([intmax("uint64") - 1; 2]))
+
+## Test opposite sign int overflow when getting mean of even number of values
+%!assert <*54567> (median (...
+%! [intmin('int8') intmin('int8')+5 intmax('int8')-5 intmax('int8')]), ...
+%! int8(-1))
+%!assert <*54567> (median ([int8([1 2 3 4]); ...
+%! intmin('int8') intmin('int8')+5 intmax('int8')-5 intmax('int8')], 2), ...
+%! int8([3;-1]))
+%!assert <*54567> (median (...
+%! [intmin('int64') intmin('int64')+5 intmax('int64')-5 intmax('int64')]), ...
+%! int64(-1))
+%!assert <*54567> (median ([int64([1 2 3 4]); ...
+%! intmin('int64') intmin('int64')+5 intmax('int64')-5 intmax('int64')], 2), ...
+%! int64([3;-1]))
+
+## Test int accuracy loss doing mean of close int64/uint64 values as double
+%!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2]), ...
+%!  intmax("uint64")-1)
+%!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "default"), ...
+%!  double(intmax("uint64")-1))
+%!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "double"), ...
+%!  double(intmax("uint64")-1))
+%!assert <*54567> (median ([intmax("uint64"), intmax("uint64")-2], "native"), ...
+%!  intmax("uint64")-1)
+
+## Test input case insensitivity
+%!assert (median ([1 2 3], "aLL"), 2)
+%!assert (median ([1 2 3], "OmitNan"), 2)
+%!assert (median ([1 2 3], "DOUBle"), 2)
+
 ## Test input validation
 %!error <Invalid call> median ()
-%!error <X must be a numeric> median ({1:5})
-%!error <X cannot be an empty matrix> median ([])
-%!error <DIM must be an integer> median (1, ones (2,2))
-%!error <DIM must be an integer> median (1, 1.5)
-%!error <DIM must be .* a valid dimension> median (1, 0)
+%!error <Invalid call> median (1, 2, 3)
+%!error <Invalid call> median (1, 2, 3, 4)
+%!error <Invalid call> median (1, "all", 3)
+%!error <Invalid call> median (1, "b")
+%!error <Invalid call> median (1, 1, "foo")
+%!error <'all' cannot be used with> median (1, 3, "all")
+%!error <'all' cannot be used with> median (1, [2 3], "all")
+%!error <X must be either numeric or logical> median ({1:5})
+%!error <X must be either numeric or logical> median ("char")
+%!error <only one OUTTYPE can be specified> median(1, "double", "native")
+%!error <DIM must be a positive integer> median (1, ones (2,2))
+%!error <DIM must be a positive integer> median (1, 1.5)
+%!error <DIM must be a positive integer> median (1, 0)
+%!error <DIM must be a positive integer> median ([1 2 3], [-1 1])
+%!error <VECDIM must contain non-repeating> median(1, [1 2 2])
--- a/scripts/statistics/mode.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/mode.m	Fri Jun 23 20:51:51 2023 +0200
@@ -57,15 +57,42 @@
   sz = size (x);
   if (nargin < 2)
     ## Find the first non-singleton dimension.
-    (dim = find (sz > 1, 1)) || (dim = 1);
+    (dim = find (sz != 1, 1)) || (dim = 1);
   else
-    if (! (isscalar (dim) && dim == fix (dim) && dim > 0))
+    if (! (isscalar (dim) && dim > 0 && rem (dim, 1) == 0))
       error ("mode: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  if (dim > nd)
-    ## Special case of mode over non-existent dimension.
+  if (isempty (x))
+    ## Empty x produces NaN for m, 0 for f, , but m, f and c
+    ## shape depends on size of x.
+    if ((nargin == 1) && (nd == 2) && (sz == [0 0]))
+      f = 0; # f always a double even if x is single.
+      if (isa (x, "single"))
+        m = NaN ("single");
+        c = {(NaN (0, 1, "single"))};
+      else
+        m = NaN;
+        c = {(NaN (0, 1))};
+      endif
+    else
+      sz(dim) = 1;
+      f = zeros (sz); # f always a double even if x is single.
+      c = cell (sz);
+      if (isa (x, "single"))
+        m = (NaN (sz, "single"));
+        c(:) = NaN (1, 0, "single");
+      else
+        m = NaN (sz);
+        c(:) = NaN (1, 0);
+      endif
+    endif
+    return
+  endif
+
+  if (dim > nd || sz(dim) == 1)
+    ## Special case of mode over singleton dimension.
     m = x;
     f = ones (size (x));
     c = num2cell (x);
@@ -152,6 +179,15 @@
 %! assert (f, ones (3,3));
 %! assert (c, num2cell (x));
 
+%!test
+%! x = single (magic (3));
+%! [m, f, c] = mode (x, 3);
+%! assert (class (m), "single");
+%! assert (class (f), "double");
+%! assert (class (c), "cell");
+%! assert (class (c(1)), "cell");
+%! assert (class (c{1}), "single");
+
 %!shared x
 %! x(:,:,1) = toeplitz (1:3);
 %! x(:,:,2) = circshift (toeplitz (1:3), 1);
@@ -180,6 +216,124 @@
 %! assert (c{1}, [1; 2; 3]);
 %! assert (c{2}, [1; 2; 3]);
 %! assert (c{3}, [1; 2; 3]);
+%!shared   ## Clear shared to prevent variable echo for any later test failures
+
+## Test empty inputs
+%!test <*48690>
+%! [m, f, c] = mode ([]);
+%! assert (m, NaN);
+%! assert (f, 0);
+%! assert (c, {(NaN (0, 1))});
+%!test <*48690>
+%! [m, f, c] = mode (single ([]));
+%! assert (class (m), "single");
+%! assert (class (f), "double");
+%! assert (c, {(single (NaN (0, 1)))});
+%!test <*48690>
+%! [m, f, c] = mode ([], 1);
+%! assert (m, NaN (1, 0));
+%! assert (f, zeros (1, 0));
+%! assert (c, cell (1, 0));
+%!test <*48690>
+%! [m, f, c] = mode ([], 2);
+%! assert (m, NaN (0, 1));
+%! assert (f, zeros (0, 1));
+%! assert (c, cell(0, 1));
+%!test <*48690>
+%! [m, f, c] = mode ([], 3);
+%! assert (m, []);
+%! assert (f, []);
+%! assert (c, cell (0, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 1));
+%! assert (m, NaN);
+%! assert (f, 0);
+%! assert (c, {(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 1), 1);
+%! assert (m, NaN);
+%! assert (f, 0);
+%! assert (c, {(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 1), 2);
+%! assert (m, NaN (0, 1));
+%! assert (f, zeros (0, 1));
+%! assert (c, cell (0, 1));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 1), 3);
+%! assert (m, NaN (0, 1));
+%! assert (f, zeros (0, 1));
+%! assert (c, cell (0, 1));
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 0));
+%! assert (m, NaN);
+%! assert (f, 0);
+%! assert (c, {(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 0), 1);
+%! assert (m, NaN (1, 0));
+%! assert (f, zeros (1, 0));
+%! assert (c, cell (1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 0), 2);
+%! assert (m, NaN);
+%! assert (f, 0);
+%! assert (c, {(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 0), 3);
+%! assert (m, NaN (1, 0));
+%! assert (f, zeros (1, 0));
+%! assert (c, cell (1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 0, 0));
+%! assert (m, NaN (1, 0, 0));
+%! assert (f, zeros (1, 0, 0));
+%! assert (c, cell (1, 0, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 0, 0), 1);
+%! assert (m, NaN (1, 0, 0));
+%! assert (f, zeros (1, 0, 0));
+%! assert (c, cell (1, 0, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 0, 0), 2);
+%! assert (m, NaN (0, 1, 0));
+%! assert (f, zeros (0, 1, 0));
+%! assert (c, cell (0, 1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 0, 0), 3);
+%! assert (m, NaN (0, 0, 1));
+%! assert (f, zeros (0, 0, 1));
+%! assert (c, cell (0, 0, 1));
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 5, 0), 2);
+%! assert (m, NaN (1, 1, 0));
+%! assert (f, zeros (1, 1, 0));
+%! assert (c, cell (1, 1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (5, 1, 0), 2);
+%! assert (m, NaN (5, 1, 0));
+%! assert (f, zeros (5, 1, 0));
+%! assert (c, cell (5, 1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (2, 0));
+%! assert (m, NaN (1, 0));
+%! assert (f, zeros (1, 0));
+%! assert (c, cell (1, 0));
+%!test <*48690>
+%! [m, f, c] = mode (ones (0, 2));
+%! assert (m, NaN (1, 2));
+%! assert (f, zeros (1, 2));
+%! assert (c, {(NaN (1, 0)),(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 1, 1, 0));
+%! assert (m, NaN (1, 1));
+%! assert (f, zeros (1, 1));
+%! assert (c, {(NaN (1, 0))});
+%!test <*48690>
+%! [m, f, c] = mode (ones (1, 1, 1, 0), 1);
+%! assert (m, NaN (1, 1, 1, 0));
+%! assert (f, zeros (1, 1, 1, 0));
+%! assert (c, cell (1,1,1,0));
 
 ## Test input validation
 %!error <Invalid call> mode ()
@@ -187,3 +341,9 @@
 %!error <DIM must be an integer> mode (1, ones (2,2))
 %!error <DIM must be an integer> mode (1, 1.5)
 %!error <DIM must be .* a valid dimension> mode (1, 0)
+%!error <DIM must be .* a valid dimension> mode (1, -1)
+%!error <DIM must be .* a valid dimension> mode (1, -1.5)
+%!error <DIM must be .* a valid dimension> mode (1, Inf)
+%!error <DIM must be .* a valid dimension> mode (1, NaN)
+
+
--- a/scripts/statistics/normalize.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/normalize.m	Fri Jun 23 20:51:51 2023 +0200
@@ -30,7 +30,6 @@
 ## @deftypefnx {} {@var{z} =} normalize (@dots{}, @var{method}, @var{option})
 ## @deftypefnx {} {@var{z} =} normalize (@dots{}, @var{scale}, @var{scaleoption}, @var{center}, @var{centeroption})
 ## @deftypefnx {} {[@var{z}, @var{c}, @var{s}] =} normalize (@dots{})
-##
 ## Return a normalization of the data in @var{x} using one of several available
 ## scaling and centering methods.
 ##
@@ -61,6 +60,9 @@
 ## If the optional second argument @var{dim} is given, operate along this
 ## dimension.
 ##
+## @code{normalize} ignores NaN values is @var{x} similar to the behavior of
+## the omitnan option in @code{std}, @code{mean}, and @code{median}.
+##
 ## The optional inputs @var{method} and @var{option} can be used to specify the
 ## type of normalization performed on @var{x}.  Note that only the
 ## @option{scale} and @option{center} options may be specified together using
@@ -156,10 +158,6 @@
 ## @item
 ## The option @option{DataVariables} is not yet implemented for Table class
 ## @var{x} inputs.
-##
-## @item
-## Certain arrays containing NaN elements may not return @sc{matlab} compatible
-## output.
 ## @end enumerate
 ##
 ## @seealso{zscore, iqr, norm, rescale, std, median, mean, mad}
@@ -167,9 +165,8 @@
 
 function [z, c, s] = normalize (x, varargin)
 
-  ## FIXME: Until NANFLAG/OMITNAN option is implemented in std, mean, median,
-  ## etc., normalize cannot efficiently reproduce some behavior with NaNs in
-  ## x.  xtests added to capture this.  (See bug #50571)
+  ## FIXME: Until NANFLAG/OMITNAN option is implemented in sum, inefficient
+  ##        workaround is used for method "norm" option 1  (See bug #50571)
 
   ## FIXME: When table class is implemented, remove DataVariables error line in
   ## option checking section and add DataVariables data handling switch
@@ -186,7 +183,7 @@
 
   if (nargin == 1)
     ## Directly handle simple 1 input case.
-    [s, c] = std (x);
+    [s, c] = std (x, "omitnan");
 
   else
     ## Parse input options
@@ -216,7 +213,7 @@
         print_usage ();
       endif
 
-      prop = tolower (varargin{vararg_idx});
+      prop = lower (varargin{vararg_idx});
 
       if (strcmp (prop, "datavariables"))
         ## FIXME: Remove error on next line and undo block comment when support
@@ -268,7 +265,7 @@
           case "zscore"
             method = "zscore";
             if (vararg_idx < n_varargin)
-              nextprop = tolower (varargin{vararg_idx+1});
+              nextprop = lower (varargin{vararg_idx+1});
               if (strcmp (nextprop, "std") || strcmp (nextprop, "robust"))
                 methodoption = nextprop;
                 vararg_idx++;
@@ -312,7 +309,7 @@
           case "scale"
             method = "scale";
             if (vararg_idx < n_varargin)
-              nextprop = tolower (varargin{vararg_idx+1});
+              nextprop = lower (varargin{vararg_idx+1});
               if (isnumeric (nextprop))
                 if (! isscalar (nextprop))
                   error ("normalize: scale value must be a scalar");
@@ -333,7 +330,7 @@
           case "center"
             method = "center";
             if (vararg_idx < n_varargin)
-              nextprop = tolower (varargin{vararg_idx+1});
+              nextprop = lower (varargin{vararg_idx+1});
               if (isscalar (nextprop)
                   || any (strcmp (nextprop, {"mean", "median"})))
                 methodoption = nextprop;
@@ -385,20 +382,27 @@
       case "zscore"
         switch (methodoption)
           case "std"
-            [s, c] = std (x, [], dim);
+            [s, c] = std (x, [], dim, "omitnan");
           case "robust"
             ## center/median to zero and MAD = 1
-            c = median (x, dim);
+            c = median (x, dim, "omitnan");
             ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
-            ##        supports diagonal and sparse matrices (Bugs #41441, #35787).
-            s = median (abs (bsxfun (@minus, x , c)), dim);
-            ## s = median (abs (x - c), dim);   # Automatic broadcasting
+            ##        supports diagonal and sparse matrices.
+            ##        (Bugs #41441, #35787).
+            s = median (abs (bsxfun (@minus, x , c)), dim, "omitnan");
+            ## s = median (abs (x - c), dim, "omitnan");# Broadcasting.
         endswitch
 
       case "norm"
         switch (methodoption)
           case 1
+            ## FIXME:  when sum supports omitnan option replace entire case
+            ## with single line:
+            ## s = sum (abs (x), dim, "omitnan");
+            xnan = isnan (x);
+            x(xnan) = 0;
             s = sum (abs (x), dim);
+            x(xnan) = NaN;
           case Inf
             s = max (abs (x), [], dim);
           otherwise
@@ -439,7 +443,7 @@
         c = process_center_option (x, dim, center_option);
 
       case "medianiqr"
-        c = median (x, dim);
+        c = median (x, dim, "omitnan");
         s = iqr (x, dim);
 
     endswitch
@@ -462,9 +466,9 @@
   else
     switch (center_option)
       case "mean"
-        c = mean (x, dim);
+        c = mean (x, dim, "omitnan");
       case "median"
-        c = median (x, dim);
+        c = median (x, dim, "omitnan");
     endswitch
   endif
 
@@ -479,7 +483,7 @@
   else
     switch (scale_option)
       case "std"
-        s = std (x, [], dim);
+        s = std (x, [], dim, "omitnan");
       case "mad"
         s = mad (x, 1, dim);
       case "first"
@@ -644,10 +648,23 @@
 %! assert (issparse (c));
 %! assert (issparse (s));
 
-## Matlab ignores NaNs, operating as if the vector had one less element, then
-## returns the result retaining the NaN in the solution.
-%!assert <50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2)
-%!assert <50571> (normalize ([1 2 NaN; 1 2 3], 2), [[-1 1 NaN]*sqrt(2)/2; -1 0 1], eps)
+## Test that normalize ignores NaN values
+%!assert <*50571> (normalize ([1 2 NaN], 2), [-1, 1, NaN]*sqrt(2)/2, eps)
+%!assert <*50571> (normalize ([1 2 NaN; 1 2 3], 2), [[-1 1 NaN]*sqrt(2)/2; -1 0 1], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 1 2 NaN], 1), NaN (2, 3))
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2), [sqrt(2)/2*[-1 1 NaN]; -1 0 1], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "zscore", "robust"), [-1 1 NaN; -1 0 1])
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "norm", 1), [1/3 2/3 NaN; 2/9 1/3 4/9], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "norm", Inf), [0.5 1 NaN; 0.5 0.75 1], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "range", [1 2]), [1 2 NaN; 1 1.5 2], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "scale", 2), [0.5 1 NaN; 1 1.5 2], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "scale", "mad"), [2 4 NaN; 2 3 4], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "scale", "first"), [1 2 NaN; 1 1.5 2], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "scale", "iqr"), [1 2 NaN; 4/3 2 8/3], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "center", "mean"), [-0.5 0.5 NaN; -1 0 1], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "center", "median"), [-0.5 0.5 NaN; -1 0 1], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 4], 2, "center", -1), [2 3 NaN; 3 4 5], eps)
+%!assert <*50571> (normalize ([1 2 NaN; 2 3 NaN], 2, "center", "mean", "scale", "std"), sqrt(2)/2*[-1 1 NaN; -1 1 NaN], eps)
 
 ## Test input validation
 %!error <Invalid call> normalize ()
--- a/scripts/statistics/std.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/std.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,84 +24,106 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn  {} {@var{y} =} std (@var{x})
-## @deftypefnx {} {@var{y} =} std (@var{x}, @var{w})
-## @deftypefnx {} {@var{y} =} std (@var{x}, @var{w}, @var{dim})
-## @deftypefnx {} {@var{y} =} std (@var{x}, @var{w}, @qcode{"ALL"})
-## @deftypefnx {} {[@var{y}, @var{mu}] =} std (@dots{})
+## @deftypefn  {} {@var{s} =} std (@var{x})
+## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w})
+## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @var{dim})
+## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @var{vecdim})
+## @deftypefnx {} {@var{s} =} std (@var{x}, @var{w}, @qcode{"ALL"})
+## @deftypefnx {} {@var{s} =} std (@dots{}, @var{nanflag})
+## @deftypefnx {} {[@var{s}, @var{m}] =} std (@dots{})
 ## Compute the standard deviation of the elements of the vector @var{x}.
 ##
 ## The standard deviation is defined as
 ## @tex
-## $$
-## {\rm std} (x) = \sigma = \sqrt{{\sum_{i=1}^N (x_i - \bar{x})^2 \over N - 1}}
-## $$
-## where $\bar{x}$ is the mean value of @var{x} and $N$ is the number of elements of @var{x}.
+## $$ {\rm std}(x) = \sqrt{{1\over N-1} \sum_{i=1}^N (x_i - \bar x )^2} $$
+## where $\bar{x}$ is the mean value of @var{x} and $N$ is the number of
+## elements of @var{x}.
 ## @end tex
 ## @ifnottex
 ##
 ## @example
 ## @group
-## std (@var{x}) = sqrt ( 1/(N-1) SUM_i (@var{x}(i) - mean(@var{x}))^2 )
+## std (@var{x}) = sqrt ((1 / (N-1)) * SUM_i ((@var{x}(i) - mean(@var{x}))^2))
 ## @end group
 ## @end example
 ##
 ## @noindent
-## where @math{N} is the number of elements of the @var{x} vector.
+## where @math{N} is the number of elements of @var{x}.
 ## @end ifnottex
 ##
-## If @var{x} is an array, compute the standard deviation for each column and
-## return them in a row vector (or for an n-D array, the result is returned as
-## an array of dimension 1 x n x m x @dots{}).
+## If @var{x} is an array, compute the standard deviation along the first
+## non-singleton dimensions of @var{x}.
 ##
 ## The optional argument @var{w} determines the weighting scheme to use.  Valid
 ## values are:
 ##
 ## @table @asis
 ## @item 0 [default]:
-## Normalize with @math{N-1}.  This provides the square root of the best
-## unbiased estimator of the variance.
+## Normalize with @math{N-1} (population standard deviation).  This provides
+## the square root of the best unbiased estimator of the standard deviation.
 ##
 ## @item 1:
-## Normalize with @math{N}@.  This provides the square root of the second
-## moment around the mean.
+## Normalize with @math{N} (sample standard deviation).  This provides the
+## square root of the second moment around the mean.
 ##
 ## @item a vector:
-## Compute the weighted standard deviation with non-negative scalar weights.
-## The length of @var{w} must equal the size of @var{x} along dimension
-## @var{dim}.
+## Compute the weighted standard deviation with non-negative weights.
+## The length of @var{w} must equal the size of @var{x} in the operating
+## dimension.  NaN values are permitted in @var{w}, will be multiplied with the
+## associated values in @var{x}, and can be excluded by the @var{nanflag}
+## option.
+##
+## @item an array:
+## Similar to vector weights, but @var{w} must be the same size as @var{x}.  If
+## the operating dimension is supplied as @var{vecdim} or @qcode{"all"} and
+## @var{w} is not a scalar, @var{w} must be an same-sized array.
 ## @end table
 ##
-## If @math{N} is equal to 1 the value of @var{W} is ignored and normalization
-## by @math{N} is used.
+## Note: @var{w} must always be specified before specifying any of the
+## following dimension options.  To use the default value for @var{w} you
+## may pass an empty input argument [].
 ##
 ## The optional variable @var{dim} forces @code{std} to operate over the
-## specified dimension(s).  @var{dim} can either be a scalar dimension or a
-## vector of non-repeating dimensions.  Dimensions must be positive integers,
-## and the standard deviation is calculated over the array slice defined by
-## @var{dim}.
+## specified dimension, which must be a positive integer-valued number.
+## Specifying any singleton dimension in @var{x}, including any dimension
+## exceeding @code{ndims (@var{x})}, will result in a standard deviation of 0.
+##
+## Specifying the dimensions as  @var{vecdim}, a vector of non-repeating
+## dimensions, will return the standard deviation calculated over the array
+## slice defined by @var{vecdim}.  If @var{vecdim} indexes all dimensions of
+## @var{x}, then it is equivalent to the option @qcode{"all"}.  Any
+## dimension in @var{vecdim} greater than @code{ndims (@var{x})} is ignored.
 ##
-## Specifying dimension @qcode{"all"} will force @code{std} to operate on all
-## elements of @var{x}, and is equivalent to @code{std (@var{x}(:))}.
+## Specifying the dimension as @qcode{"all"} will force @code{std} to
+## operate on all elements of @var{x}, and is equivalent to
+## @code{std (@var{x}(:))}.
 ##
-## When @var{dim} is a vector or @qcode{"all"}, @var{w} must be either 0 or 1.
+## The optional variable @var{nanflag} specifies whether to include or exclude
+## NaN values from the calculation using any of the previously specified input
+## argument combinations.  The default value for @var{nanflag} is
+## @qcode{"includenan"} which keeps NaN values in the calculation.  To
+## exclude NaN values set the value of @var{nanflag} to @qcode{"omitnan"}.
+## The output will still contain NaN values if @var{x} consists of all NaN
+## values in the operating dimension.
 ##
-## The optional second output variable @var{mu} contains the mean or weighted
-## mean used to calculate @var{y}, and will be the same size as @var{y}.
+## The optional second output variable @var{m} contains the mean of the
+## elements of @var{x} used to calculate the standard deviation.  If @var{v} is
+## the weighted standard deviation, then @var{m} is also the weighted mean.
+##
 ## @seealso{var, bounds, mad, range, iqr, mean, median}
 ## @end deftypefn
 
-function [y, mu] = std (varargin)
+function [s, m] = std (varargin)
 
   if (nargin < 1)
     print_usage ();
   endif
 
   if (nargout < 2)
-    y = sqrt (var (varargin{:}));
+    s = sqrt (var (varargin{:}));
   else
-    [y, mu] = var (varargin{:});
-    y = sqrt (y);
+    [s, m] = var (varargin{:});
+    s = sqrt (s);
   endif
 
 endfunction
--- a/scripts/statistics/var.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/statistics/var.m	Fri Jun 23 20:51:51 2023 +0200
@@ -27,211 +27,532 @@
 ## @deftypefn  {} {@var{v} =} var (@var{x})
 ## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w})
 ## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @var{dim})
-## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @qcode{"ALL"})
+## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @var{vecdim})
+## @deftypefnx {} {@var{v} =} var (@var{x}, @var{w}, @qcode{"all"})
+## @deftypefnx {} {@var{v} =} var (@dots{}, @var{nanflag})
 ## @deftypefnx {} {[@var{v}, @var{m}] =} var (@dots{})
 ## Compute the variance of the elements of the vector @var{x}.
 ##
 ## The variance is defined as
 ## @tex
-## $$
-## {\rm var} (x) = \sigma^2 = {\sum_{i=1}^N (x_i - \bar{x})^2 \over N - 1}
-## $$
+## $$ {\rm var}(x) = {1\over N-1} \sum_{i=1}^N (x_i - \bar x )^2 $$
 ## where $\bar{x}$ is the mean value of @var{x} and $N$ is the number of
 ## elements of @var{x}.
-##
 ## @end tex
 ## @ifnottex
 ##
 ## @example
 ## @group
-## var (@var{x}) = 1/(N-1) SUM_i (@var{x}(i) - mean(@var{x}))^2
+## var (@var{x}) = (1 / (N-1)) * SUM_i ((@var{x}(i) - mean(@var{x}))^2)
 ## @end group
 ## @end example
 ##
 ## @noindent
-## where @math{N} is the length of the @var{x} vector.
-##
+## where @math{N} is the number of elements of @var{x}.
 ## @end ifnottex
-## If @var{x} is an array, compute the variance for each column and return them
-## in a row vector (or for an n-D array, the result is returned as an array of
-## dimension 1 x n x m x @dots{}).
+##
+## If @var{x} is an array, compute the variance along the first non-singleton
+## dimensions of @var{x}.
 ##
 ## The optional argument @var{w} determines the weighting scheme to use.  Valid
-## values are
+## values are:
 ##
 ## @table @asis
 ## @item 0 [default]:
-## Normalize with @math{N-1}.  This provides the square root of the best
-## unbiased estimator of the variance.
+## Normalize with @math{N-1} (population variance).  This provides the square
+## root of the best unbiased estimator of the variance.
 ##
 ## @item 1:
-## Normalize with @math{N}@.  This provides the square root of the second
-## moment around the mean.
+## Normalize with @math{N} (sample variance).  This provides the square root of
+## the second moment around the mean.
 ##
 ## @item a vector:
-## Compute the weighted variance with non-negative scalar weights.  The length
-## of @var{w} must equal the size of @var{x} along dimension @var{dim}.
+## Compute the weighted variance with non-negative weights.  The length of
+## @var{w} must equal the size of @var{x} in the operating dimension.  NaN
+## values are permitted in @var{w}, will be multiplied with the associated
+## values in @var{x}, and can be excluded by the @var{nanflag} option.
+##
+## @item an array:
+## Similar to vector weights, but @var{w} must be the same size as @var{x}.  If
+## the operating dimension is supplied as @var{vecdim} or @qcode{"all"} and
+## @var{w} is not a scalar, @var{w} must be an same-sized array.
 ## @end table
 ##
-## If @math{N} is equal to 1 the value of @var{W} is ignored and normalization
-## by @math{N} is used.
+## Note: @var{w} must always be specified before specifying any of the
+## following dimension options.  To use the default value for @var{w} you
+## may pass an empty input argument [].
 ##
 ## The optional variable @var{dim} forces @code{var} to operate over the
-## specified dimension(s).  @var{dim} can either be a scalar dimension or a
-## vector of non-repeating dimensions.  Dimensions must be positive integers,
-## and the variance is calculated over the array slice defined by @var{dim}.
+## specified dimension, which must be a positive integer-valued number.
+## Specifying any singleton dimension in @var{x}, including any dimension
+## exceeding @code{ndims (@var{x})}, will result in a variance of 0.
+##
+## Specifying the dimensions as  @var{vecdim}, a vector of non-repeating
+## dimensions, will return the variance calculated over the array slice defined
+## by @var{vecdim}.  If @var{vecdim} indexes all dimensions of @var{x}, then it
+## is equivalent to the option @qcode{"all"}.  Any dimension in @var{vecdim}
+## greater than @code{ndims (@var{x})} is ignored.
+##
+## Specifying the dimension as @qcode{"all"} will force @code{var} to
+## operate on all elements of @var{x}, and is equivalent to @code{var
+## (@var{x}(:))}.
 ##
-## Specifying dimension @qcode{"all"} will force @code{var} to operate on all
-## elements of @var{x}, and is equivalent to @code{var (@var{x}(:))}.
+## The optional variable @var{nanflag} specifies whether to include or exclude
+## NaN values from the calculation using any of the previously specified input
+## argument combinations.  The default value for @var{nanflag} is
+## @qcode{"includenan"} which keeps NaN values in the calculation.  To
+## exclude NaN values set the value of @var{nanflag} to @qcode{"omitnan"}.
+## The output will still contain NaN values if @var{x} consists of all NaN
+## values in the operating dimension.
 ##
-## When @var{dim} is a vector or @qcode{"all"}, @var{w} must be either 0 or 1.
+## The optional second output variable @var{m} contains the mean of the
+## elements of @var{x} used to calculate the variance.  If @var{v} is the
+## weighted variance, then @var{m} is also the weighted mean.
 ##
-## The optional second output variable @var{mu} contains the mean or weighted
-## mean used to calculate @var{v}, and will be the same size as @var{v}.
-## @seealso{cov, std, skewness, kurtosis, moment}
+## @seealso{std, mean, cov, skewness, kurtosis, moment}
 ## @end deftypefn
 
-function [v, mu] = var (x, w = 0, dim = [])
+function [v, m] = var (x, varargin)
+
+  if (nargin < 1 || nargin > 4)
+    print_usage ();
+  endif
 
-  if (nargin < 1)
+  ## initialize variables
+  all_flag = false;
+  omitnan = false;
+  nvarg = numel (varargin);
+  varg_chars = cellfun ('ischar', varargin);
+
+  ## Check all char arguments.
+  if (nvarg == 3 && ! varg_chars(3))
     print_usage ();
   endif
 
-  if (! (isnumeric (x) || islogical (x)))
+  if (any (varg_chars))
+    for argin = varargin(varg_chars)
+      switch (lower (argin{1}))
+        case "all"
+          all_flag = true;
+        case "omitnan"
+          omitnan = true;
+        case "includenan"
+          omitnan = false;
+        otherwise
+          print_usage ();
+      endswitch
+    endfor
+    varargin(varg_chars) = [];
+    nvarg = numel (varargin);
+  endif
+
+  ## FIXME: When sparse can broadcast ops then remove sparse checks and hacks.
+  x_issparse = issparse (x);
+  w = 0;
+  weighted = false; # true if weight vector/array used
+  vecdim = [];
+  vecempty = true;
+  vecdim_scalar_vector = [false, false]; # [false, false] for empty vecdim
+  szx = size (x);
+  ndx = ndims (x);
+
+  ## Check numeric arguments
+  if (! (isnumeric (x)))
     error ("var: X must be a numeric vector or matrix");
   endif
-
-  if (isempty (w))
-    w = 0;
+  if (isa (x, "single"))
+    outtype = "single";
+  else
+    outtype = "double";
   endif
 
-  nd = ndims (x);
-  sz = size (x);
-  emptydimflag = false;
-
-  if (isempty (dim))
-    emptydimflag = true;  # Compatibility hack for empty x, ndims==2
-
-    ## Find the first non-singleton dimension.
-    (dim = find (sz != 1, 1)) || (dim = 1);
+  if (nvarg > 0)
+    if (nvarg > 2 || any (! cellfun ('isnumeric', varargin)))
+      print_usage ();
+    endif
+    ## Process weight input
+    if (any (varargin{1} < 0))
+      error ("var: weights must not contain any negative values");
+    endif
+    if (isscalar (varargin{1}))
+      w = varargin{1};
+      if (! (w == 0 || w == 1) && ! isscalar (x))
+        error ("var: normalization scalar must be either 0 or 1");
+      endif
+    elseif (numel (varargin{1}) > 1)
+      weights = varargin{1};
+      weighted = true;
+    endif
+    if (nvarg > 1)
+    ## Process dimension input
+      vecdim = varargin{2};
+      if (! (vecempty = isempty (vecdim)))
+        ## Check for empty vecdim, won't change vsv if nonzero size empty
+        vecdim_scalar_vector = [isscalar(vecdim), isvector(vecdim)];
+      endif
+      if (! (vecdim_scalar_vector(2) && all (vecdim > 0))
+          || any (rem (vecdim, 1)))
+        error ("var: DIM must be a positive integer scalar or vector");
+      endif
+      if (vecdim_scalar_vector(1) && vecdim > ndx && ! isempty (x))
+        ## Scalar dimension larger than ndims(x), variance of any single number
+        ## is zero, except for inf, NaN, and empty values of x.
+        v = zeros (szx, outtype);
+        vn = ! isfinite (x);
+        v(vn) = NaN;
+        m = x;
+        return;
+      endif
+      if (vecdim_scalar_vector == [0 1] && (! all (diff (sort (vecdim)))))
+        error ("var: VECDIM must contain non-repeating positive integers");
+      endif
+    endif
+  endif
 
-  else
-    if (isscalar (dim))
-      if (dim < 1 || dim != fix (dim))
-        error ("var: DIM must be a positive integer scalar, vector, or 'all'");
-      endif
-    elseif (isnumeric (dim))
-      if (! isvector (dim) && all (dim > 0) && all (rem (dim, 1) == 0))
-        error ("var: DIM must be a positive integer scalar, vector, or 'all'");
-      endif
-      if (dim != unique (dim, "stable"))
-        error ("var: vector DIM must contain non-repeating positive integers");
-      endif
-      if (! isscalar (w))
-        error ("var: W must be either 0 or 1 when DIM is a vector");
+  ## Check for conflicting input arguments
+  if (all_flag && ! vecempty)
+    error ("var: 'all' flag cannot be used with DIM or VECDIM options");
+  endif
+  if (weighted)
+    if (all_flag)
+      if (isvector (weights))
+        if (numel (weights) != numel (x))
+          error ("var: weight vector element count does not match X");
+        endif
+      elseif (! (isequal (size (weights), szx)))
+        error ("var: weight matrix or array does not match X in size");
       endif
 
-      ## Reshape X to compute the variance over an array slice
-      if (iscolumn (dim))
-        dim = dim.';
+    elseif (vecempty)
+      ## Find the first non-singleton dimension.
+      (dim = find (szx > 1, 1)) || (dim = 1);
+      if (isvector (weights))
+        if (numel (weights) != szx(dim))
+          error ("var: weight vector length does not match operating dimension");
+        endif
+      elseif (! isequal (size (weights), szx))
+          error ("var: weight matrix or array does not match X in size");
+      endif
+    elseif (vecdim_scalar_vector(1))
+      if (isvector (weights))
+        if (numel (weights) != szx(vecdim))
+          error ("var: weight vector length does not match operating dimension");
+        endif
+      elseif (! isequal (size (weights), szx))
+          error ("var: weight matrix or array does not match X in size");
       endif
 
-      collapsed_dims = dim;
-      dim = dim(end);
-
-      ## Permute X to cluster the dimensions to collapse
-      max_dim = max ([nd, collapsed_dims]);
-      perm_start = perm_end = [1:max_dim];
-      perm_start(dim:end) = [];
-      perm_start(ismember (perm_start, collapsed_dims)) = [];
-      perm_end(1:dim) = [];
-      perm_end(ismember (perm_end, collapsed_dims)) = [];
-      perm = [perm_start, collapsed_dims, perm_end];
-
-      x = permute (x, perm);
-
-      ## Collapse the given dimensions
-      newshape = ones (1, max_dim);
-      newshape(1:nd) = sz;
-      newshape(collapsed_dims(1:(end-1))) = 1;
-      newshape(dim) = prod (sz(collapsed_dims));
-
-      ## New X with collapsed dimensions
-      x = reshape (x, newshape);
-
-    elseif (ischar (dim) && strcmpi (dim, "all"))
-      if (! isscalar (w))
-        error ("var: W must be either 0 or 1 when using 'all' as dimension");
-      endif
-
-      ## "all" equates to collapsing all elements to a single vector
-      x = x(:);
-      dim = 1;
-      sz = size (x);
-    else
-      error ("var: DIM must be a positive integer scalar, vector, or 'all'");
+    elseif (vecdim_scalar_vector(2) && ! (isequal (size (weights), szx)))
+      error ("var: weight matrix or array does not match X in size");
     endif
   endif
 
-  n = size (x, dim);
-  if (! isvector (w) || ! isnumeric (w)
-      || (isvector (w) && any (w < 0)) ||
-          (isscalar (w) && ((w != 0 && w != 1) && (n != 1))))
-    error ("var: W must be 0, 1, or a vector of positive integers");
+  ## Handle special cases of empty or scalar X and exit early.
+  if (isempty (x))
+    if (vecempty && (ndx == 2 || all (szx == 0)))
+      v = NaN (outtype);
+      if (nargout > 1)
+        m = NaN (outtype);
+      endif
+      return;
+    endif
+    if (vecdim_scalar_vector(1))
+      szx(vecdim) = 1;
+      v = NaN (szx, outtype);
+      if (nargout > 1)
+        m = NaN (szx, outtype);
+      endif
+      return;
+    endif
+  elseif (isscalar (x))
+    if (isfinite (x))
+      v = zeros (outtype);
+    else
+      v = NaN (outtype);
+    endif
+    if (nargout > 1)
+      m = x;
+    endif
+    return;
   endif
 
-  if (isempty (x))
-    ## Empty matrix special case
-    if (emptydimflag && nd == 2 && all (sz == [0, 0]))
-      v = NaN;
-      mu = NaN;
-    else
-      sz(dim) = 1;
-      v = NaN (sz);
-      mu = NaN (sz);
-    endif
-  elseif (n == 1)
-    ## Scalar special case
-    if (! isscalar (w))
-      error (["var: the length of W must be equal to the size of X " ...
-              "in the dimension along which variance is calculated"]);
-    endif
-    if (isa (x, "single"))
-      v = zeros (sz, "single");
-      mu = x;
-    else
-      v = zeros (sz);
-      mu = x;
-    endif
-    v(isnan (x) | isinf (x)) = NaN;
-  else
-    ## Regular algorithm
-    if (isscalar (w))
-      v = sumsq (center (x, dim), dim) / (n - 1 + w);
-      if (nargout == 2)
-        mu = mean (x, dim);
+  if (nvarg == 0)
+    ## Only numeric input argument, no dimensions or weights.
+    if (all_flag)
+      x = x(:);
+      if (omitnan)
+        x = x(! isnan (x));
+      endif
+      n = length (x);
+      m = sum (x) ./ n;
+      v = sum (abs (x - m) .^ 2) ./ (n - 1 + w);
+      if (n == 1)
+        v = 0;
       endif
     else
-      ## Weighted variance
-      if (numel (w) != n)
-        error (["var: the length of W must be equal to the size of X " ...
-                "in the dimension along which variance is calculated"]);
+      ## Find the first non-singleton dimension.
+      (dim = find (szx > 1, 1)) || (dim = 1);
+      n = szx(dim);
+      if (omitnan)
+        n = sum (! isnan (x), dim);
+        xn = isnan (x);
+        x(xn) = 0;
+      endif
+      m = sum (x, dim) ./ n;
+      dims = ones (1, ndx);
+      dims(dim) = szx(dim);
+      if (x_issparse)
+        m_exp = repmat (m, dims);
+      else
+        m_exp = m .* ones (dims);
+      endif
+      if (omitnan)
+        x(xn) = m_exp(xn);
+      endif
+      v = sumsq (x - m_exp, dim) ./ (n - 1 + w);
+      if (numel (n) == 1)
+        divby0 = (n .* ones (size (v))) == 1;
+      else
+        divby0 = n == 1;
+      endif
+      v(divby0) = 0;
+    endif
+
+  elseif (nvarg == 1)
+    ## Two numeric input arguments, w or weights given.
+    if (all_flag)
+      x = x(:);
+      if (weighted)
+        weights = weights(:);
+        wx = weights .* x;
+      else
+        weights = ones (length (x), 1);
+        wx = x;
+      endif
+
+      if (omitnan)
+        xn = isnan (wx);
+        wx = wx(! xn);
+        weights = weights(! xn);
+        x = x(! xn);
+      endif
+      n = length (wx);
+      m = sum (wx) ./ sum (weights);
+      if (weighted)
+        v = sum (weights .* (abs (x - m) .^ 2)) ./ sum (weights);
+      else
+        v = sum (weights .* (abs (x - m) .^ 2)) ./ (n - 1 + w);
+        if (n == 1)
+          v = 0;
+        endif
+      endif
+
+    else
+      ## Find the first non-singleton dimension.
+      (dim = find (szx > 1, 1)) || (dim = 1);
+      if (! weighted)
+        weights = ones (szx);
+        wx = x;
+      else
+        if (isvector (weights))
+          dims = 1:ndx;
+          dims([1, dim]) = [dim, 1];
+          weights = zeros (szx) + permute (weights(:), dims);
+        endif
+        wx = weights .* x;
+      endif
+      n = size (wx, dim);
+      if (omitnan)
+        xn = isnan (wx);
+        n = sum (! xn, dim);
+        wx(xn) = 0;
+        weights(xn) = 0;
+      endif
+      m = sum (wx, dim) ./ sum (weights, dim);
+      dims = ones (1, ndims (wx));
+      dims(dim) = size (wx, dim);
+      if (x_issparse)
+        m_exp = repmat (m, dims);
+      else
+        m_exp = m .* ones (dims);
+      endif
+      if (omitnan)
+        x(xn) = m_exp(xn);
+      endif
+      if (weighted)
+        v = sum (weights .* ((x - m_exp) .^ 2), dim) ./ sum (weights, dim);
+      else
+        v = sumsq (x - m_exp, dim) ./ (n - 1 + w);
+        if (numel (n) == 1)
+          divby0 = (n .* ones (size (v))) == 1;
+        else
+          divby0 = n == 1;
+        endif
+        v(divby0) = 0;
+      endif
+    endif
+
+  elseif (nvarg == 2)
+    ## Three numeric input arguments, both w or weights and dim or vecdim given.
+    if (vecdim_scalar_vector(1))
+      if (! weighted)
+        weights = ones (szx);
+        wx = x;
+      else
+        if (isvector (weights))
+          dims = 1:ndx;
+          dims([1, vecdim]) = [vecdim, 1];
+          weights = zeros (szx) + permute (weights(:), dims);
+        endif
+        wx = weights .* x;
+      endif
+      n = size (wx, vecdim);
+      if (omitnan)
+        n = sum (! isnan (wx), vecdim);
+        xn = isnan (wx);
+        wx(xn) = 0;
+        weights(xn) = 0;
+      endif
+      m = sum (wx, vecdim) ./ sum (weights, vecdim);
+      dims = ones (1, ndims (wx));
+      dims(vecdim) = size (wx, vecdim);
+      if (x_issparse)
+        m_exp = repmat (m, dims);
+      else
+        m_exp = m .* ones (dims);
       endif
-      if ((dim == 1 && isrow (w)) || (dim == 2 && iscolumn (w)))
-        w = w.';
-      elseif (dim > 2)
-        newdims = [ones(1, dim - 1), numel(w)];
-        w = reshape (w, newdims);
+      if (omitnan)
+        x(xn) = m_exp(xn);
+      endif
+      if (weighted)
+        v = sum (weights .* ((x - m_exp) .^ 2), vecdim) ...
+              ./ sum (weights, vecdim);
+      else
+        v = sumsq (x - m_exp, vecdim);
+        vn = isnan (v);
+        v = v ./ (n - 1 + w);
+        if (numel (n) == 1)
+          divby0 = (n .* ones (size (v))) == 1;
+        else
+          divby0 = n == 1;
+        endif
+        v(divby0) = 0;
+        v(vn) = NaN;
       endif
-      den = sum (w);
+
+    else
+      ## Weights and nonscalar vecdim specified
+
+      ## Ignore dimensions in VECDIM larger than actual array.
+      remdims = 1 : ndx;    # All dimensions
+      vecdim(vecdim > ndx) = [];
+      ## Calculate permutation vector
+      remdims(vecdim) = [];     # Delete dimensions specified by vecdim
+      nremd = numel (remdims);
+
+      ## If all dimensions are given, it is equivalent to the 'all' flag.
+      if (nremd == 0)
+        x = x(:);
+        if (weighted)
+          weights = weights(:);
+          wx = weights .* x;
+        else
+          weights = ones (length (x), 1);
+          wx = x;
+        endif
+
+        if (omitnan)
+          xn = isnan (wx);
+          wx = wx(! xn);
+          weights = weights(! xn);
+          x = x(! xn);
+        endif
+        n = length (wx);
+        m = sum (wx) ./ sum (weights);
+        if (weighted)
+          v = sum (weights .* (abs (x - m) .^ 2)) ./ sum (weights);
+        else
+          v = sum (weights .* (abs (x - m) .^ 2)) ./ (n - 1 + w);
+          if (n == 1)
+            v = 0;
+          endif
+        endif
+
+      else
+
+        ## FIXME: much of the reshaping can be skipped once Octave's sum can
+        ##        take a vecdim argument.
 
-      ## FIXME: Use bsxfun, rather than broadcasting, until broadcasting
-      ##        supports diagonal and sparse matrices (Bugs #41441, #35787).
-      mu = sum (bsxfun (@times, w , x), dim) ./ den;
-      v = sum (bsxfun (@times, w, ...
-                            bsxfun (@minus, x, mu) .^ 2), dim) ./ den;
-      ## mu = sum (w .* x, dim) ./ den; # automatic broadcasting
-      ## v = sum (w .* ((x - mu) .^ 2), dim) ./ den;
+        ## Apply weights
+        if (weighted)
+          wx = weights .* x;
+        else
+          weights = ones (szx);
+          wx = x;
+        endif
+
+        ## Permute to push vecdims to back
+        perm = [remdims, vecdim];
+        wx = permute (wx, perm);
+        weights = permute (weights, perm);
+        x = permute (x, perm);
+
+        ## Reshape to squash all vecdims in final dimension
+        szwx = size (wx);
+        sznew = [szwx(1:nremd), prod(szwx(nremd+1:end))];
+        wx = reshape (wx, sznew);
+        weights = reshape (weights, sznew);
+        x = reshape (x, sznew);
+
+        ## Calculate var on final squashed dimension
+        dim = nremd + 1;
+        n = size (wx, dim);
+        if (omitnan)
+          xn = isnan (wx);
+          n = sum (! xn, dim);
+          wx(xn) = 0;
+          weights(xn) = 0;
+        endif
+        m = sum (wx, dim) ./ sum (weights, dim);
+        m_exp = zeros (sznew) + m;
+        if (omitnan)
+          x(xn) = m_exp(xn);
+        endif
+        if (weighted)
+          v = sum (weights .* ((x - m_exp) .^ 2), dim) ./ sum (weights, dim);
+        else
+          v = sumsq (x - m_exp, dim) ./ (n - 1 + w);
+          if (numel (n) == 1)
+            divby0 = n .* ones (size (v)) == 1;
+          else
+            divby0 = n == 1;
+          endif
+          v(divby0) = 0;
+        endif
+
+        ## Inverse permute back to correct dimensions
+        v = ipermute (v, perm);
+        if (nargout > 1)
+          m = ipermute (m, perm);
+        endif
+      endif
+    endif
+  endif
+
+  ## Preserve class type
+  if (nargout < 2)
+    if (strcmp (outtype, "single"))
+      v = single (v);
+    else
+      v = double (v);
+    endif
+  else
+    if (strcmp (outtype, "single"))
+      v = single (v);
+      m = single (m);
+    else
+      v = double (v);
+      m = double (m);
     endif
   endif
 
@@ -247,6 +568,7 @@
 %!assert (var (5, 99), 0)
 %!assert (var (5, 99, 1), 0)
 %!assert (var (5, 99, 2), 0)
+%!assert (var ([5 3], [99 99], 2), 1)
 %!assert (var ([1:7], [1:7]), 3)
 %!assert (var ([eye(3)], [1:3]), [5/36, 2/9, 1/4], eps)
 %!assert (var (ones (2,2,2), [1:2], 3), [(zeros (2,2))])
@@ -254,16 +576,127 @@
 %!assert (var (reshape ([1:8], 2, 2, 2), 0, [1 3]), [17/3 17/3], eps)
 %!assert (var ([1 2 3;1 2 3], [], [1 2]), 0.8, eps)
 
+## Test single input and optional arguments "all", DIM, "omitnan")
+%!test
+%! x = [-10:10];
+%! y = [x;x+5;x-5];
+%! assert (var (x), 38.5);
+%! assert (var (y, [], 2), [38.5; 38.5; 38.5]);
+%! assert (var (y, 0, 2), [38.5; 38.5; 38.5]);
+%! assert (var (y, 1, 2), ones (3,1) * 36.66666666666666, 1e-14);
+%! assert (var (y, "all"), 54.19354838709678, 1e-14);
+%! y(2,4) = NaN;
+%! assert (var (y, "all"), NaN);
+%! assert (var (y, "all", "includenan"), NaN);
+%! assert (var (y, "all", "omitnan"), 55.01533580116342, 1e-14);
+%! assert (var (y, 0, 2, "includenan"), [38.5; NaN; 38.5]);
+%! assert (var (y, [], 2), [38.5; NaN; 38.5]);
+%! assert (var (y, [], 2, "omitnan"), [38.5; 37.81842105263158; 38.5], 1e-14);
+
+## Tests for different weight and omitnan code paths
+%!assert (var ([1 NaN 3], [1 2 3], "omitnan"), 0.75, eps)
+%!assert (var ([1 2 3], [1 NaN 3], "omitnan"), 0.75, eps)
+%!assert (var (magic(3), [1 NaN 3], "omitnan"), [3 12 3], eps)
+%!assert (var ([1 NaN 3], [1 2 3], "omitnan", "all"), 0.75, eps)
+%!assert (var ([1 NaN 3], [1 2 3], "all", "omitnan"), 0.75, eps)
+%!assert (var ([1 2 3], [1 NaN 3], "omitnan", "all"), 0.75, eps)
+%!assert (var ([1 NaN 3], [1 2 3], 2, "omitnan"), 0.75, eps)
+%!assert (var ([1 2 3], [1 NaN 3], 2, "omitnan"), 0.75, eps)
+%!assert (var (magic(3), [1 NaN 3], 1, "omitnan"), [3 12 3], eps)
+%!assert (var (magic(3), [1 NaN 3], 2, "omitnan"), [0.75;3;0.75], eps)
+%!assert (var ([4 4; 4 6; 6 6], [1 3], 2, 'omitnan'), [0;0.75;0], eps)
+%!assert (var ([4 NaN; 4 6; 6 6], [1 2 3], 1, 'omitnan'), [1 0])
+%!assert (var ([4 NaN; 4 6; 6 6], [1 3], 2, 'omitnan'), [0;0.75;0], eps)
+%!assert (var (3*reshape(1:18, [3 3 2]), [1 2 3], 1, 'omitnan'), ones(1,3,2)*5)
+%!assert (var (reshape(1:18, [3 3 2]), [1 2 3], 2, 'omitnan'), 5*ones(3,1,2))
+%!assert (var (3*reshape(1:18, [3 3 2]), ones (3,3,2), [1 2], 'omitnan'), ...
+%!         60 * ones(1,1,2))
+%!assert (var (3*reshape(1:18, [3 3 2]), ones (3,3,2), [1 4], 'omitnan'), ...
+%!         6 * ones(1,3,2))
+%!assert (var (6*reshape(1:18, [3 3 2]), ones (3,3,2), [1:3], 'omitnan'), 969)
+%!test
+%! x = reshape(1:18, [3 3 2]);
+%! x([2, 14]) = NaN;
+%! w = ones (3,3,2);
+%! assert (var (16*x, w, [1:3], 'omitnan'), 6519);
+%!test
+%! x = reshape(1:18, [3 3 2]);
+%! w = ones (3,3,2);
+%! w([2, 14]) = NaN;
+%! assert (var (16*x, w, [1:3], 'omitnan'), 6519);
+
+## Test input case insensitivity
+%!assert (var ([1 2 3], "aLl"), 1)
+%!assert (var ([1 2 3], "OmitNan"), 1)
+%!assert (var ([1 2 3], "IncludeNan"), 1)
+
+## Test dimension indexing with vecdim in n-dimensional arrays
+%!test
+%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);
+%! assert (size (var (x, 0, [3 2])), [10, 1, 1, 3]);
+%! assert (size (var (x, 1, [1 2])), [1, 1, 6, 3]);
+%! assert (size (var (x, [], [1 2 4])), [1, 1, 6]);
+%! assert (size (var (x, 0, [1 4 3])), [1, 40]);
+%! assert (size (var (x, [], [1 2 3 4])), [1, 1]);
+
+## Test matrix with vecdim, weighted, matrix weights, omitnan
+%!assert (var (3*magic(3)), [63 144 63])
+%!assert (var (3*magic(3), 'omitnan'), [63 144 63])
+%!assert (var (3*magic(3), 1), [42 96 42])
+%!assert (var (3*magic(3), 1, 'omitnan'), [42 96 42])
+%!assert (var (3*magic(3), ones(1,3), 1), [42 96 42])
+%!assert (var (3*magic(3), ones(1,3), 1, 'omitnan'), [42 96 42])
+%!assert (var (2*magic(3), [1 1 NaN], 1, 'omitnan'), [25 16 1])
+%!assert (var (3*magic(3), ones(3,3)), [42 96 42])
+%!assert (var (3*magic(3), ones(3,3), 'omitnan'), [42 96 42])
+%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1], 'omitnan'), [42 36 42])
+%!assert (var (3*magic(3), ones(3,3), 1), [42 96 42])
+%!assert (var (3*magic(3), ones(3,3), 1, 'omitnan'), [42 96 42])
+%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1], 1, 'omitnan'), [42 36 42])
+%!assert (var (3*magic(3), ones(3,3), [1 4]), [42 96 42])
+%!assert (var (3*magic(3), ones(3,3), [1 4], 'omitnan'), [42 96 42])
+%!assert (var (3*magic(3), [1 1 1; 1 1 1; 1 NaN 1],[1 4],'omitnan'), [42 36 42])
+
+## Test results with vecdim in n-dimensional arrays and "omitnan"
+%!test
+%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);
+%! v = repmat (33.38912133891213, [10, 1, 1, 3]);
+%! assert (var (x, 0, [3, 2]), v, 1e-14);
+%! v = repmat (33.250, [10, 1, 1, 3]);
+%! assert (var (x, 1, [3, 2]), v, 1e-14);
+%! x(2,5,6,3) = NaN;
+%! v(2,1,1,3) = NaN;
+%! assert (var (x, 1, [3, 2]), v, 4e-14);
+%! v = repmat (33.38912133891213, [10 1 1 3]);
+%! v(2,1,1,3) = NaN;
+%! assert (var (x, [], [3, 2]), v, 4e-14);
+%! v(2,1,1,3) = 33.40177912169048;
+%! assert (var (x, [], [3, 2], "omitnan"), v, 4e-14);
+
+## Testing weights vector & arrays
+%!assert (var (ones (2,2,2), [1:2], 3), [(zeros (2, 2))])
+%!assert (var (magic (3), [1:9], "all"), 6.666666666666667, 1e-14)
+
+## Test exceeding dimensions
+%!assert (var (ones (2,2), [], 3), zeros (2,2))
+%!assert (var (ones (2,2,2), [], 99), zeros (2,2,2))
+%!assert (var (magic (3), [], 3), zeros (3,3))
+%!assert (var (magic (3), [], 1), [7, 16, 7])
+%!assert (var (magic (3), [], [1 3]), [7, 16, 7])
+%!assert (var (magic (3), [], [1 99]), [7, 16, 7])
+
 ## Test empty inputs
 %!assert (var ([]), NaN)
+%!assert (class (var (single ([]))), "single")
 %!assert (var ([],[],1), NaN(1,0))
 %!assert (var ([],[],2), NaN(0,1))
 %!assert (var ([],[],3), [])
-%!assert (var (ones (0,1)), NaN)
+%!assert (class (var (single ([]), [], 1)), "single")
 %!assert (var (ones (1,0)), NaN)
 %!assert (var (ones (1,0), [], 1), NaN(1,0))
 %!assert (var (ones (1,0), [], 2), NaN)
 %!assert (var (ones (1,0), [], 3), NaN(1,0))
+%!assert (class (var (ones (1, 0, "single"), [], 1)), "single")
 %!assert (var (ones (0,1)), NaN)
 %!assert (var (ones (0,1), [], 1), NaN)
 %!assert (var (ones (0,1), [], 2), NaN(0,1))
@@ -273,8 +706,11 @@
 %!assert (var (ones (1,3,0,2), [], 2), NaN(1,1,0,2))
 %!assert (var (ones (1,3,0,2), [], 3), NaN(1,3,1,2))
 %!assert (var (ones (1,3,0,2), [], 4), NaN(1,3,0))
+%!test
+%! [~, m] = var ([]);
+%! assert (m, NaN);
 
-## Test second output
+## Test optional mean output
 %!test <*62395>
 %! [~, m] = var (13);
 %! assert (m, 13);
@@ -289,9 +725,9 @@
 %! [~, m] = var ([1, 2, 3; 3 2 1], [], 3);
 %! assert (m, [1 2 3; 3 2 1]);
 
-## 2nd output, weighted inputs, vector dims
+## Test mean output, weighted inputs, vector dims
 %!test <*62395>
-%! [~, m] = var(5,99);
+%! [~, m] = var (5,99);
 %! assert (m, 5);
 %! [~, m] = var ([1:7], [1:7]);
 %! assert (m, 5);
@@ -303,19 +739,38 @@
 %! assert (m, 2.5, eps);
 %! [~, m] = var (reshape ([1:8], 2, 2, 2), 0, [1 3]);
 %! assert (m, [3.5, 5.5], eps);
+%!test
+%! [v, m] = var (4 * eye (2), [1, 3]);
+%! assert (v, [3, 3]);
+%! assert (m, [1, 3]);
 
-## 2nd output, empty inputs
+## Test mean output, empty inputs, omitnan
 %!test <*62395>
 %! [~, m] = var ([]);
 %! assert (m, NaN);
-%! [~, m] = var ([],[],1);
-%! assert (m, NaN(1,0));
-%! [~, m] = var ([],[],2);
-%! assert (m, NaN(0,1));
-%! [~, m] = var ([],[],3);
-%! assert (m, []);
-%! [~, m] = var (ones (1,3,0,2));
-%! assert (m, NaN(1,1,0,2));
+#%! [~, m] = var ([],[],1);
+#%! assert (m, NaN(1,0));
+#%! [~, m] = var ([],[],2);
+#%! assert (m, NaN(0,1));
+#%! [~, m] = var ([],[],3);
+#%! assert (m, []);
+#%! [~, m] = var (ones (1,3,0,2));
+#%! assert (m, NaN(1,1,0,2));
+
+## Test mean output, nD array
+%!test <*62395>
+%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);
+%! [~, m] = var (x, 0, [3 2]);
+%! assert (m, mean (x, [3 2]));
+%! [~, m] = var (x, 0, [1 2]);
+%! assert (m, mean (x, [1 2]));
+%! [~, m] = var (x, 0, [1 3 4]);
+%! assert (m, mean (x, [1 3 4]));
+%!test
+%! x = repmat ([1:20;6:25], [5, 2, 6, 3]);
+%! x(2,5,6,3) = NaN;
+%! [~, m] = var (x, 0, [3 2], "omitnan");
+%! assert (m, mean (x, [3 2], "omitnan"));
 
 ## Test Inf and NaN inputs
 %!test <*63203>
@@ -440,27 +895,63 @@
 %! [v, m] = var (sparse (4 * eye (2)), [1, 3]);
 %! assert (full (v), [3, 3]);
 %! assert (full (m), [1, 3]);
-
-%!test <63291>
+%!test<*63291>
 %! [v, m] = var (sparse (eye (2)));
 %! assert (issparse (v));
 %! assert (issparse (m));
-%!test <63291>
+%!test<*63291>
 %! [v, m] = var (sparse (eye (2)), [1, 3]);
 %! assert (issparse (v));
 %! assert (issparse (m));
 
 ## Test input validation
 %!error <Invalid call> var ()
-%!error <X must be a numeric> var (['A'; 'B'])
-%!error <W must be 0> var ([1 2 3], 2)
-%!error <W must be .* a vector of positive integers> var ([1 2], [-1 0])
-%!error <W must be .* a vector of positive integers> var ([1 2], eye (2))
-%!error <W must be either 0 or 1> var (ones (2, 2), [1 2], [1 2])
-%!error <W must be either 0 or 1> var ([1 2], [1 2], 'all')
-%!error <the length of W must be> var ([1 2], [1 2 3])
-%!error <the length of W must be> var (1, [1 2])
-%!error <the length of W must be> var ([1 2], [1 2], 1)
+%!error <Invalid call> var (1, 2, "omitnan", 3)
+%!error <Invalid call> var (1, 2, 3, 4)
+%!error <Invalid call> var (1, 2, 3, 4, 5)
+%!error <Invalid call> var (1, "foo")
+%!error <Invalid call> var (1, [], "foo")
+%!error <normalization scalar must be either 0 or 1> var ([1 2 3], 2)
+%!error <normalization scalar must be either 0 or 1> var ([1 2], 2, "all")
+%!error <normalization scalar must be either 0 or 1> var ([1 2],0.5, "all")
+%!error <weights must not contain any negative values> var (1, -1)
+%!error <weights must not contain any negative values> var (1, [1 -1])
+%!error <weights must not contain any negative values> ...
+%! var ([1 2 3], [1 -1 0])
+%!error <X must be a numeric vector or matrix> var ({1:5})
+%!error <X must be a numeric vector or matrix> var ("char")
+%!error <X must be a numeric vector or matrix> var (['A'; 'B'])
 %!error <DIM must be a positive integer> var (1, [], ones (2,2))
+%!error <DIM must be a positive integer> var (1, 0, 1.5)
+%!error <DIM must be a positive integer> var (1, [], 0)
 %!error <DIM must be a positive integer> var (1, [], 1.5)
-%!error <DIM must be a positive integer> var (1, [], 0)
+%!error <DIM must be a positive integer> var ([1 2 3], [], [-1 1])
+%!error <VECDIM must contain non-repeating positive integers> ...
+%! var (repmat ([1:20;6:25], [5 2 6 3]), 0, [1 2 2 2])
+%!error <weight matrix or array does not match X in size> ...
+%! var ([1 2], eye (2))
+%!error <weight matrix or array does not match X in size> ...
+%! var ([1 2 3 4], [1 2; 3 4])
+%!error <weight matrix or array does not match X in size> ...
+%! var ([1 2 3 4], [1 2; 3 4], 1)
+%!error <weight matrix or array does not match X in size> ...
+%! var ([1 2 3 4], [1 2; 3 4], [2 3])
+%!error <weight matrix or array does not match X in size> ...
+%! var (ones (2, 2), [1 2], [1 2])
+%!error <weight matrix or array does not match X in size> ...
+%! var ([1 2 3 4; 5 6 7 8], [1 2 1 2 1; 1 2 1 2 1], 1)
+%!error <weight matrix or array does not match X in size> ...
+%! var (repmat ([1:20;6:25], [5 2 6 3]), repmat ([1:20;6:25], [5 2 3]), [2 3])
+%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3 4])
+%!error <weight vector length does not match> var ([1 2], [1 2 3])
+%!error <weight vector length does not match> var (1, [1 2])
+%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3 4], 1)
+%!error <weight vector length does not match> var ([1 2 3; 2 3 4], [1 3], 2)
+%!error <weight vector length does not match> var ([1 2], [1 2], 1)
+%!error <'all' flag cannot be used with DIM or VECDIM options> ...
+%! var (1, [], 1, "all")
+%!error <weight vector element count does not match X> ...
+%! var ([1 2 3; 2 3 4], [1 3], "all")
+%!error <weight matrix or array does not match X in size> ...
+%! var (repmat ([1:20;6:25], [5 2 6 3]), repmat ([1:20;6:25], [5 2 3]), "all")
+
--- a/scripts/strings/base2dec.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/base2dec.m	Fri Jun 23 20:51:51 2023 +0200
@@ -82,7 +82,7 @@
   elseif (! (base >= 2 && base <= length (symbols)))
     error ("base2dec: BASE must be between 2 and 36, or a string of symbols");
   else
-    str = toupper (str);
+    str = upper (str);
   endif
 
   ## Right justify the values and squeeze out any spaces.
--- a/scripts/strings/dec2base.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/dec2base.m	Fri Jun 23 20:51:51 2023 +0200
@@ -26,8 +26,9 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {@var{str} =} dec2base (@var{d}, @var{base})
 ## @deftypefnx {} {@var{str} =} dec2base (@var{d}, @var{base}, @var{len})
+## @deftypefnx {} {@var{str} =} dec2base (@var{d}, @var{base}, @var{len}, @var{decimals})
 ## Return a string of symbols in base @var{base} corresponding to the
-## non-negative integer @var{d}.
+## value @var{d}.
 ##
 ## @example
 ## @group
@@ -36,6 +37,10 @@
 ## @end group
 ## @end example
 ##
+## If @var{d} is negative, then the result will represent @var{d} in complement
+## notation.  For example, negative binary numbers are in twos-complement, and
+## analogously for other bases.
+##
 ## If @var{d} is a matrix or cell array, return a string matrix with one row
 ## per element in @var{d}, padded with leading zeros to the width of the
 ## largest value.
@@ -52,11 +57,38 @@
 ## @end example
 ##
 ## The optional third argument, @var{len}, specifies the minimum number of
-## digits in the result.
+## digits in the integer part of the result.  If this is omitted, then
+## @code{dec2base} uses enough digits to accommodate the input.
+##
+## The optional fourth argument, @var{decimals}, specifies the number of
+## digits to represent the fractional part of the input.  If this is omitted,
+## then it is set to zero, and @code{dec2base} returns an integer output for
+## backward compatibility.
+##
+## @example
+## @group
+## dec2base (100*pi, 16)
+## @result{} "13A"
+## dec2base (100*pi, 16, 4)
+## @result{} "013A"
+## dec2base (100*pi, 16, 4, 6)
+## @result{} "013A.28C59D"
+## dec2base (-100*pi, 16)
+## @result{} "EC6"
+## dec2base (-100*pi, 16, 4)
+## @result{} "FEC6"
+## dec2base (-100*pi, 16, 4, 6)
+## @result{} "FEC5.D73A63"
+## @end group
+## @end example
+##
+## Programming tip: When passing negative inputs to @code{dec2base}, it is
+## best to explicitly specify the length of the output required.
+##
 ## @seealso{base2dec, dec2bin, dec2hex}
 ## @end deftypefn
 
-function str = dec2base (d, base, len)
+function str = dec2base (d, base, len, decimals = 0)
 
   if (nargin < 2)
     print_usage ();
@@ -72,10 +104,23 @@
   ## Treat logical as numeric for compatibility with ML
   if (islogical (d))
     d = double (d);
-  elseif (! isnumeric (d) || iscomplex (d) || any (d < 0 | d != fix (d)))
-    error ("dec2base: input must be real non-negative integers");
+  elseif (! isnumeric (d) || iscomplex (d))
+    error ("dec2base: input must be real numbers");
   endif
 
+  ## Note which elements are negative for processing later.
+  ## This also needs special processing for the corresponding intmax.
+  belowlim = false (size (d));
+  if (isinteger (d))
+    belowlim = (d <= intmin (class (d)));
+  endif
+  neg = (d < 0);
+  d(neg) = -d(neg);
+
+  ## Pull out the fractional part for processing later
+  fracpart = d - floor (d);
+  d = floor (d);
+
   symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   if (ischar (base))
     symbols = base(:).';  # force a row vector
@@ -90,34 +135,100 @@
     error ("dec2base: BASE must be an integer between 2 and 36, or a string of symbols");
   endif
 
-  ## determine number of digits required to handle all numbers, can overflow
-  ## by 1 digit
+  ## Determine number of digits required to handle all numbers.
   max_len = round (log (max (max (d), 1)) / log (base)) + 1;
 
-  if (nargin == 3)
+  if (nargin >= 3)
     if (! (isscalar (len) && isreal (len) && len >= 0 && len == fix (len)))
       error ("dec2base: LEN must be a non-negative integer");
     endif
     max_len = max (max_len, len);
   endif
 
-  ## determine digits for each number
-  digits = zeros (length (d), max_len);
+  ## Determine digits for each number
+  digits = zeros (numel (d), max_len);
   for k = max_len:-1:1
-    digits(:,k) = mod (d, base);
-    d = round ((d - digits(:,k)) / base);
+    digits(:, k) = mod (d, base);
+    d = round ((d - digits(:, k)) / base);
   endfor
 
-  ## convert digits to symbols
+  ## Compute any fractional part and append
+  digits2 = zeros (rows (digits), decimals);
+  if (nargin == 4 && decimals > 0)
+    for k = 1:decimals
+      fracpart *= base;
+      digits2(:, k) = floor (fracpart);
+      fracpart -= floor (fracpart);
+    endfor
+  endif
+
+  ## Handle negative inputs now
+  for k = find (neg)(:)'
+    digits(k, :) = (base-1) - digits(k, :);
+    if (! isempty (digits2))
+      digits2(k, :) = (base - 1) - digits2(k, :);
+    endif
+
+    if (! isempty (digits2))
+      j = columns (digits2);
+      digits2 (k, j) += 1;  # this is a generalization of two's complement
+      while (digits2(j) >= base && j > 1)
+        digits2(k, j) -= base;
+        digits2(k, j-1) += 1;
+        j -= 1;
+      endwhile
+      if (digits2(k, 1) >= base)  # carry over to integer part
+        digits2(k, 1) -= base;
+        digits(k, end) += 1;
+      endif
+    else  # no fractional part ==> increment integer part
+      digits(k, end) += 1;
+    endif
+
+    if (belowlim (k))  # we need to handle an extra +1
+      digits(k, end) -= 1;
+      ## Reason: consider the input intmin("int64"),
+      ## which is -(2)^64 of type int64.
+      ## The code above takes its negation but that exceeds intmax("int64"),
+      ## so it's pegged back to 1 lower than what it needs to be, due to
+      ## the inherent limitation of the representation.
+      ## We add that 1 back here, but because the original sign was negative,
+      ## and we are dealing with complement notation, we subtract it instead.
+    endif
+
+    j = columns (digits);
+    while (digits(k, j) >= base && j > 1)
+      digits(k, j) -= base;
+      digits(k, j-1) += 1;
+      j -= 1;
+    endwhile
+
+    if (digits(k, 1) >= base)  # augment by one place if really needed
+      digits(k, 1) -= base;
+      digits = [zeros(rows(digits), 1), digits];
+      digits(k, 1) += 1;
+      ## FIXME Should we left-pad with zeros or with (base-1) in this context?
+    endif
+  endfor
+
+  ## Convert digits to symbols: integer part
   str = reshape (symbols(digits+1), size (digits));
 
+  ## Convert digits to symbols: fractional part
+  ## Append fractional part to str if needed.
+  if (! isempty (digits2))
+    str2 = reshape (symbols(digits2+1), size (digits2));
+    str = [str, repmat('.', rows(str), 1), str2];
+  endif
+
   ## Check if the first element is the zero symbol.  It seems possible
   ## that LEN is provided, and is less than the computed MAX_LEN and
   ## MAX_LEN is computed to be one larger than necessary, so we would
   ## have a leading zero to remove.  But if LEN >= MAX_LEN, we should
   ## not remove any leading zeros.
-  if ((nargin == 2 || (nargin == 3 && max_len > len))
-      && columns (str) != 1 && ! any (str(:,1) != symbols(1)))
+  if ((nargin == 2 || (nargin >= 3 && max_len > len))
+      && columns (str) != 1 && ! any (str(:,1) != symbols(1))
+      && (~any(neg)))
     str = str(:,2:end);
   endif
 
@@ -135,12 +246,49 @@
 %!   s0 = [s0,'0'];
 %! endfor
 
+## Test positive fractional inputs
+%!assert (dec2base (pi,  2, 0, 16), "11.0010010000111111")
+%!assert (dec2base ( e,  2, 2, 16), "10.1011011111100001")
+%!assert (dec2base (pi,  3, 0, 16), "10.0102110122220102")
+%!assert (dec2base ( e,  3, 0, 16), "2.2011011212211020")
+%!assert (dec2base (pi, 16, 0, 10), "3.243F6A8885")
+%!assert (dec2base ( e, 16, 0, 10), "2.B7E151628A")
+
+## Test negative inputs: all correct in complement notation
+%!assert (dec2base (-1,   10),        "9")
+%!assert (dec2base (-1,   10, 3),     "999")
+%!assert (dec2base (-1,   10, 3,  2), "999.00")
+%!assert (dec2base (-1.1, 10, 3,  2), "998.90")
+%!assert (dec2base (-pi,  2,  8, 16), "11111100.1101101111000001")
+%!assert (dec2base (-pi,  3,  8, 16), "22222212.2120112100002121")
+%!assert (dec2base (-pi, 16,  8, 10), "FFFFFFFC.DBC095777B")
+%!assert (dec2base ( -e,  2,  8, 16), "11111101.0100100000011111")
+%!assert (dec2base ( -e,  3,  8, 16), "22222220.0211211010011210")
+%!assert (dec2base ( -e, 16,  8, 10), "FFFFFFFD.481EAE9D76")
+
+## Test negative inputs close to powers of bases
+%!assert (dec2base (-128, 2), "10000000")
+%!assert (dec2base (-129, 2, 9), "101111111")
+%!assert (dec2base (-129, 2), "01111111")
+## FIXME: should dec2base (-129, 2) return "01111111" or ""101111111"?
+## The second is an explicit 9-bit universe. The first is an implied 9-bit
+## universe but the user needs to be careful not to mistake it for +127, which
+## is true in modular arithmetic anyway (i.e., +127 == -129 in 8-bits).
+## Currently we work around this by telling the user in `help dec2base` to
+## explicitly set the lengths when working with negative numbers.
+
+## Test intmin values
+%!assert (dec2base (intmin ("int8"), 2), "10000000")
+%!assert (dec2base (intmin ("int16"), 2), "1000000000000000")
+%!assert (dec2base (intmin ("int32"), 2), "10000000000000000000000000000000")
+%!assert (dec2base (intmin ("int64"), 2), "1000000000000000000000000000000000000000000000000000000000000000")
+
 %!test
 %! digits = "0123456789ABCDEF";
 %! for n = 1:13
 %!   for b = 2:16
 %!     pm = dec2base (b^n-1, b);
-%!     assert (length (pm), n);
+%!     assert (numel (pm), n);
 %!     assert (all (pm == digits(b)));
 %!   endfor
 %! endfor
@@ -166,10 +314,8 @@
 ## Test input validation
 %!error <Invalid call> dec2base ()
 %!error <Invalid call> dec2base (1)
-%!error <input must be real non-negative integers> dec2base ("A", 10)
-%!error <input must be real non-negative integers> dec2base (2i, 10)
-%!error <input must be real non-negative integers> dec2base (-1, 10)
-%!error <input must be real non-negative integers> dec2base (1.1, 10)
+%!error <dec2base: input must be real numbers> dec2base ("A", 10)
+%!error <dec2base: input must be real numbers> dec2base (2i, 10)
 %!error <symbols representing digits must be unique> dec2base (1, "ABA")
 %!error <whitespace characters are not valid symbols> dec2base (1, "A B")
 %!error <BASE must be an integer> dec2base (1, ones (2))
--- a/scripts/strings/dec2bin.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/dec2bin.m	Fri Jun 23 20:51:51 2023 +0200
@@ -39,9 +39,7 @@
 ## For negative elements of @var{d}, return the binary value of the two's
 ## complement.  The result is padded with leading ones to 8, 16, 32, or 64
 ## bits as appropriate for the magnitude of the input.  Positive input
-## elements are padded with leading zeros to the same width.  If the second
-## argument @var{len} exceeds that calculated width, the result is further
-## padded with leading zeros, for compatibility with @sc{matlab}.
+## elements are padded with leading zeros to the same width.
 ##
 ## Examples:
 ##
@@ -55,12 +53,11 @@
 ## @end group
 ## @end example
 ##
-## Known @sc{matlab} Incompatibility: @sc{matlab}'s @code{dec2bin} allows
-## non-integer values for @var{d} as of Release 2022b, but is inconsistent
-## with truncation versus rounding and is also inconsistent with its own
-## @code{dec2hex} function.  For self-consistency, Octave gives an error for
-## non-integer inputs.  Users requiring compatible code for non-integer inputs
-## should make use of @code{fix} or @code{round} as appropriate.
+## Programming tip: @code{dec2bin} discards any fractional part of the input.
+## If you need the fractional part to be converted too, call @code{dec2base}
+## with a nonzero number of decimal places.  You can also use @code{fix} or
+## @code{round} on fractional inputs to ensure predictable rounding behavior.
+##
 ## @seealso{bin2dec, dec2base, dec2hex}
 ## @end deftypefn
 
@@ -73,49 +70,43 @@
   if (iscell (d))
     d = cell2mat (d);
   endif
-
-  if (! isnumeric (d) || iscomplex (d) || any (d(:) != round (d(:))))
-    error ("dec2bin: input must be integers");
-  endif
-
-  ## Create column vector for algorithm (output is always col. vector anyways)
   d = d(:);
 
-  neg = (d < 0);  # keep track of which elements are negative
-  if (any (neg))  # must be a signed type
-    ## Cast to a suitable signed integer type, then to unsigned.
-    ## Ensure that the left-most bit of the unsigned number is 1,
-    ## to signify negative input.
-    tmp = int64 (d);
-    if (all (tmp >= -128 & tmp <= 127))
-      d = int8 (d);
-      d(neg) = (d(neg) + intmax (d)) + 1;
-      d = uint8 (d);
-      d(neg) += uint8 (128);
-    elseif (all (tmp >= -32768 & tmp <= 32767))
-      d = int16 (d);
-      d(neg) = (d(neg) + intmax (d)) + 1;
-      d = uint16 (d);
-      d(neg) += uint16 (32768);
-    elseif (all (tmp >= -2147483648 & tmp <= 2147483647))
-      d = int32 (d);
-      d(neg) = (d(neg) + intmax (d)) + 1;
-      d = uint32 (d);
-      d(neg) += uint32 (2147483648);
-    else
-      d = int64 (d);
-      d(neg) = (d(neg) + intmax (d)) + 1;
-      d = uint64 (d);
-      d(neg) += uint64 (9223372036854775808);
-    endif
+  if (nargin == 1)
+    bstr = dec2base (d, 2);  # this will use a default len picked by dec2base
+  else  # nargin == 2
+    bstr = dec2base (d, 2, len);
+  endif
+
+  if (all (d >= 0))
+    return
   endif
 
-  if (nargin == 1)
-    bstr = dec2base (d, 2);
+  ## If we are here, there are negative inputs, so we need to
+  ## left-pad those outputs with ones to Matlab-compatible lengths.
+  len = columns (bstr);
+  if (all (d >= -128 & d <= 127))
+    len = max (len, 8);  # pad to 8 bits
+  elseif (all (d >= -32768 & d <= 32767))
+    len = max (len, 16);  # pad to 16 bits
+  elseif (all (d >= -2147483648 & d <= 2147483647))
+    len = max (len, 32);  # pad to 32 bits
   else
-    bstr = dec2base (d, 2, len);
+    len = max (len, 64);  # pad to 64 bits
   endif
 
+  tmp = repmat (' ', rows (bstr), len);
+  tmp(:, (end+1-columns(bstr)):end) = bstr;  # left-pad with spaces
+  bstr = tmp;
+
+  ## Change spaces to "1" for negative inputs
+  tmp = bstr(d < 0, :);
+  tmp(tmp == ' ') = '1';
+  bstr(d < 0, :) = tmp;
+
+  ## Change all other spaces to "0".
+  bstr(bstr == ' ') = '0';
+
 endfunction
 
 
@@ -129,7 +120,7 @@
 ## Test negative inputs
 %!assert (dec2bin (-3), "11111101")
 %!assert (dec2bin (-3, 3), "11111101")
-%!assert (dec2bin (-3, 9), "011111101")
+%!assert (dec2bin (-3, 9), "111111101")
 %!assert (dec2bin (-2^7 - 1), "1111111101111111")
 %!assert (dec2bin (-2^15 - 1), "11111111111111110111111111111111")
 %!assert (dec2bin (-2^31 - 1),
@@ -151,11 +142,13 @@
 %!assert (dec2bin ({1, 2; 3, -4}),
 %!        ["00000001"; "00000011"; "00000010"; "11111100"])
 
+## Test fractional inputs
+%!assert (dec2bin (+2.1), "10")
+%!assert (dec2bin (-2.1), "11111110")
+%!assert (dec2bin (+2.9), "10")
+%!assert (dec2bin (-2.9), "11111110")
+
 ## Test input validation
 %!error <Invalid call> dec2bin ()
-%!error <input must be integer> dec2bin (+2.1)
-%!error <input must be integer> dec2bin (-2.1)
-%!error <input must be integer> dec2bin (+2.9)
-%!error <input must be integer> dec2bin (-2.9)
-%!error <input must be integer> dec2bin (1+i)
+%!error <input must be real> dec2bin (1+i);
 
--- a/scripts/strings/dec2hex.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/dec2hex.m	Fri Jun 23 20:51:51 2023 +0200
@@ -29,8 +29,8 @@
 ## Return a string representing the conversion of the integer @var{d} to a
 ## hexadecimal (base16) number.
 ##
-## If @var{d} is negative, return the hexadecimal equivalent of the two's
-## complement binary value of @var{d}.
+## If @var{d} is negative, return the hexadecimal complement of @var{d}.
+##
 ## If @var{d} is a matrix or cell array, return a string matrix with one row
 ## for each element in @var{d}, padded with leading zeros to the width of the
 ## largest value.
@@ -50,6 +50,11 @@
 ## @end group
 ## @end example
 ##
+## Programming tip: @code{dec2hex} discards any fractional part of the input.
+## If you need the fractional part to be converted too, call @code{dec2base}
+## with a nonzero number of decimal places.  You can also use @code{fix} or
+## @code{round} on fractional inputs to ensure predictable rounding behavior.
+##
 ## @seealso{hex2dec, dec2base, dec2bin}
 ## @end deftypefn
 
@@ -59,24 +64,38 @@
     print_usage ();
   endif
 
-  ## To avoid repeating a lot of code, including input validation, we call dec2bin.
+  if (iscell (d))
+    d = cell2mat (d);
+  endif
+  d = d(:);
+
+  neg = (d < 0);
+
   if (nargin == 2)
     d = dec2bin (d, len*4);
   else
     d = dec2bin (d);
   endif
 
-  ## Left-pad with zeros to make the number of columns divisible by 4
+  ## Left-pad to a multiple of 4 columns.
   n = mod (columns (d), 4);
   if (n > 0)
-    d = [repmat("0", rows(d), 4-n), d];
+    tmp = "01"(neg + 1);  # leftpad with "0" for positive, "1" for negative
+    d = [repmat(tmp(:), 1, 4 - n), d];
   endif
 
-  d -= "0"; # convert to numeric
+  d -= '0';  # convert to numeric
   d = d(:, 1:4:end) * 8 + d(:, 2:4:end) * 4 + d(:, 3:4:end) * 2 + d(:, 4:4:end);
-  ## Elements of d are now in the range 0 to 15
+  ## Elements of d are now in the range 0 to 15.
 
-  hstr = "0123456789ABCDEF"(d+1); # convert to char and return
+  hstr = "0123456789ABCDEF"(d+1);
+  if (rows (hstr) < rows (d))  # this edge case happens when
+    hstr = hstr(:);            # passing multiple inputs in the range 0 to 15.
+    ## If we don't manually convert it to column, we'd get all those
+    ## hex digits on the same line as one big string instead of one per line.
+    ## Good test for this:    dec2hex (0:15)
+    ## compared with:         dec2hex (uint64 (81985529216486895), 16)
+  endif
 
 endfunction
 
@@ -90,7 +109,7 @@
 ## Test negative inputs
 %!assert (dec2hex (-3), "FD")
 %!assert (dec2hex (-3, 1), "FD")
-%!assert (dec2hex (-3, 3), "0FD")
+%!assert (dec2hex (-3, 3), "FFD")
 %!assert (dec2hex (-2^7 - 1), "FF7F")
 %!assert (dec2hex (-2^15 - 1), "FFFF7FFF")
 %!assert (dec2hex (-2^31 - 1), "FFFFFFFF7FFFFFFF")
@@ -103,6 +122,12 @@
 %!assert (dec2hex ([1, 2; 3, -4]), ["01"; "03"; "02"; "FC"])
 %!assert (dec2hex ({1, 2; 3, -4}), ["01"; "03"; "02"; "FC"])
 
+## Test that the output is of the correct shape.
+## Next line should return a column vector:
+%!assert (dec2hex (0:15), "0123456789ABCDEF"(:))
+## Next line should return a row vector:
+%!assert (dec2hex (uint64 (18364758544493064720)), "FEDCBA9876543210")
+
 ## Test input validation
 %!error <Invalid call> dec2hex ()
 
--- a/scripts/strings/index.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/index.m	Fri Jun 23 20:51:51 2023 +0200
@@ -67,7 +67,7 @@
     f(cellfun ("isempty", f)) = {0};
   endif
 
-  direction = tolower (direction);
+  direction = lower (direction);
 
   if (strcmp (direction, "first"))
     if (iscell (f))
--- a/scripts/strings/isstring.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/isstring.m	Fri Jun 23 20:51:51 2023 +0200
@@ -46,7 +46,7 @@
     print_usage ();
   endif
 
-  tf = false;
+  tf = isa (s, 'string');
 
 endfunction
 
@@ -60,4 +60,3 @@
 %!assert (isstring ({"b"}), false)
 
 %!error <Invalid call> isstring ()
-%!error isstring ("a", "b")
--- a/scripts/strings/isstrprop.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/isstrprop.m	Fri Jun 23 20:51:51 2023 +0200
@@ -24,7 +24,8 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{tf} =} isstrprop (@var{str}, @var{prop})
+## @deftypefn  {} {@var{tf} =} isstrprop (@var{str}, @var{prop})
+## @deftypefnx {} {@var{tf} =} isstrprop (@var{str}, @var{prop}, 'ForceCellOutput', @var{flag})
 ## Test character string properties.
 ##
 ## For example:
@@ -87,14 +88,27 @@
 ##
 ## @end table
 ##
+## If the option @qcode{'ForceCellOutput'} is given and @var{flag} is true then
+## a cell value is returned rather than a logical array.
+##
 ## @seealso{isalpha, isalnum, islower, isupper, isdigit, isxdigit,
 ## isspace, ispunct, iscntrl, isgraph, isprint, isascii}
 ## @end deftypefn
 
-function tf = isstrprop (str, prop)
+function tf = isstrprop (str, prop, opt, flag)
+
+  if (nargin != 2 && nargin != 4)
+    print_usage ();
+  endif
 
-  if (nargin != 2)
-    print_usage ();
+  force_cell_output = false;
+  if (nargin > 2)
+    if (! (isrow (opt) && strcmpi (opt, 'ForceCellOutput')))
+      error ("isstrprop: only accepted option is 'ForceCellOutput'");
+    elseif (! (isscalar (flag) && isreal (flag)))
+      error ("isstrprop: FLAG must be a real scalar");
+    endif
+    force_cell_output = flag;
   endif
 
   switch (prop)
@@ -126,6 +140,10 @@
       error ("isstrprop: invalid string property");
   endswitch
 
+  if (force_cell_output)
+    tf = {tf};
+  endif
+
 endfunction
 
 
@@ -134,11 +152,21 @@
 %!assert (isstrprop ("Hello World", "wspace"), isspace ("Hello World"))
 %!assert (isstrprop ("Hello World", "graphic"), isgraph ("Hello World"))
 %!assert (isstrprop (char ("AbC", "123"), "upper"), logical ([1 0 1; 0 0 0]))
+%!assert (isstrprop (char ("AbC", "123"), "upper", 'ForceCellOutput', true),
+%!        {logical([1 0 1; 0 0 0])})
 %!assert (isstrprop ({"AbC", "123"}, "lower"),
 %!        {logical([0 1 0]), logical([0 0 0])})
 
 ## Test input validation
 %!error <Invalid call> isstrprop ()
-%!error isstrprop ("abc123")
-%!error isstrprop ("abc123", "alpha", "alpha")
+%!error <Invalid call> isstrprop ("abc")
+%!error <Invalid call> isstrprop ("abc", 'alpha', 'ForceCellOutput')
+%!error <only accepted option is 'ForceCellOutput'>
+%! isstrprop ('a', 'alpha', ['ForceCellOutput';'ForceCellOutput'], true)
+%!error <only accepted option is 'ForceCellOutput'>
+%! isstrprop ('a', 'alpha', 'Foobar', true)
+%!error <FLAG must be a real scalar>
+%! isstrprop ('a', 'alpha', 'ForceCellOutput', [true, true])
+%!error <FLAG must be a real scalar>
+%! isstrprop ('a', 'alpha', 'ForceCellOutput', {true})
 %!error <invalid string property> isstrprop ("abc123", "foo")
--- a/scripts/strings/regexptranslate.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/regexptranslate.m	Fri Jun 23 20:51:51 2023 +0200
@@ -69,7 +69,7 @@
     error ("regexptranslate: operation OP must be a string");
   endif
 
-  op = tolower (op);
+  op = lower (op);
   if (strcmp ("wildcard", op))
     str = strrep (strrep (strrep (s, '.', '\.'),
                                      '*', '.*'),
--- a/scripts/strings/strsplit.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/strings/strsplit.m	Fri Jun 23 20:51:51 2023 +0200
@@ -159,7 +159,7 @@
   fields = fieldnames (args);
   for n = 1:2:numel (params)
     if (any (strcmpi (params{n}, fields)))
-      args.(tolower (params{n})) = params{n+1};
+      args.(lower (params{n})) = params{n+1};
     elseif (ischar (varargin{n}))
       error ("Octave:strsplit:invalid_parameter_name",
              "strsplit: invalid parameter name, '%s'", varargin{n});
--- a/scripts/testfun/__run_test_suite__.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/testfun/__run_test_suite__.m	Fri Jun 23 20:51:51 2023 +0200
@@ -55,7 +55,7 @@
   pso = page_screen_output ();
   orig_wquiet = warning ("query", "quiet");
   orig_wstate = warning ();
-  orig_mfile_encoding = __mfile_encoding__ ("utf-8");
+  orig_mfile_encoding = mfile_encoding ("utf-8");
   logfile = make_absolute_filename ("fntests.log");
   unwind_protect
     page_screen_output (false);
@@ -156,7 +156,7 @@
     warning ("off", "all");
     warning (orig_wstate);
     warning (orig_wquiet.state, "quiet");
-    __mfile_encoding__ (orig_mfile_encoding);
+    mfile_encoding (orig_mfile_encoding);
     page_screen_output (pso);
   end_unwind_protect
 
--- a/scripts/testfun/assert.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/testfun/assert.m	Fri Jun 23 20:51:51 2023 +0200
@@ -128,7 +128,7 @@
       if (ischar (expected))
         if (! ischar (cond))
           err.index{end+1} = ".";
-          err.expected{end+1} = expected;
+          err.expected{end+1} = ["'" expected "'"];
           if (isnumeric (cond))
             err.observed{end+1} = num2str (cond);
             err.reason{end+1} = "Expected string, but observed number";
@@ -138,8 +138,8 @@
           endif
         elseif (! strcmp (cond, expected))
           err.index{end+1} = "[]";
-          err.observed{end+1} = cond;
-          err.expected{end+1} = expected;
+          err.observed{end+1} = ["'" cond(:).' "'"];
+          err.expected{end+1} = ["'" expected(:).' "'"];
           err.reason{end+1} = "Strings don't match";
         endif
 
@@ -745,6 +745,18 @@
 %!   assert (isempty (strfind (errmsg, "sprintf: invalid field width")));
 %! end_try_catch
 
+%!test <*63988>
+%! A = ["ab"; "cd"];
+%! B = ["ad"; "cb"];
+%! try
+%!   assert (A, B);
+%! catch
+%!   errmsg = lasterr ();
+%!   if (regexp (errmsg, 'horizontal dimensions mismatch'))
+%!     error ("assert failed for char arrays with multiple rows");
+%!   endif
+%! end_try_catch
+
 ## test input validation
 %!error <Invalid call> assert ()
 %!error <Invalid call> assert (1,2,3,4)
--- a/scripts/testfun/oruntests.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/testfun/oruntests.m	Fri Jun 23 20:51:51 2023 +0200
@@ -71,29 +71,34 @@
   no_tests = {};
   printf ("Processing files in %s:\n\n", directory);
   fflush (stdout);
-  for i = 1:numel (flist)
-    f = flist{i};
-    if ((length (f) > 2 && strcmpi (f((end-1):end), ".m"))
-        || (length (f) > 3 && strcmpi (f((end-2):end), ".cc")))
-      ff = fullfile (directory, f);
-      if (! isfile (ff))
-        continue;
+  unwind_protect
+    old_dir = cd (directory);
+    for i = 1:numel (flist)
+      f = flist{i};
+      if ((length (f) > 2 && strcmpi (f((end-1):end), ".m"))
+          || (length (f) > 3 && strcmpi (f((end-2):end), ".cc")))
+        ff = fullfile (directory, f);
+        if (! isfile (ff))
+          continue;
+        endif
+        if (has_tests (ff))
+          print_test_file_name (f);
+          [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet");
+          print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
+          fflush (stdout);
+        elseif (has_functions (ff))
+          no_tests(end+1) = f;
+        endif
+      elseif (f(1) == "@")
+        f = fullfile (directory, f);
+        if (isfolder (f))
+          dirs(end+1) = f;
+        endif
       endif
-      if (has_tests (ff))
-        print_test_file_name (f);
-        [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet");
-        print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs);
-        fflush (stdout);
-      elseif (has_functions (ff))
-        no_tests(end+1) = f;
-      endif
-    elseif (f(1) == "@")
-      f = fullfile (directory, f);
-      if (isfolder (f))
-        dirs(end+1) = f;
-      endif
-    endif
-  endfor
+    endfor
+  unwind_protect_cleanup
+    cd (old_dir);
+  end_unwind_protect
   if (! isempty (no_tests))
     printf ("\nThe following files in %s have no tests:\n\n", directory);
     printf ("%s", list_in_columns (no_tests));
--- a/scripts/time/datestr.m	Fri Jun 23 20:51:15 2023 +0200
+++ b/scripts/time/datestr.m	Fri Jun 23 20:51:51 2023 +0200
@@ -330,16 +330,16 @@
 ## Mac OS X interprets %p parameter to strftime as lower case am/pm indicator.
 ## Accommodate this, although no other UNIX-based OS does this.
 %!test
-%! obs = toupper (datestr (testtime,14));
+%! obs = upper (datestr (testtime,14));
 %! assert (obs, " 2:33:17 AM");
 %!assert (datestr (testtime,15), "02:33")
 %!test
-%! obs = toupper (datestr (testtime,16));
+%! obs = upper (datestr (testtime,16));
 %! assert (obs, " 2:33 AM");
 %!test <*48071>
 %! testtime2 = testtime;
 %! testtime2(4) = 15;
-%! obs = toupper (datestr (testtime2,16));
+%! obs = upper (datestr (testtime2,16));
 %! assert (obs, " 3:33 PM");
 %!assert (datestr (testtime,17), "Q4-05")
 %!assert (datestr (testtime,18), "Q4")
--- a/src/main-cli.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/main-cli.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,7 +52,7 @@
 #include "sysdep.h"
 
 static void
-check_hg_versions (void)
+check_hg_versions ()
 {
   bool ok = true;
 
--- a/src/main-gui.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/main-gui.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -52,9 +52,10 @@
 #include "octave-build-info.h"
 #include "qt-application.h"
 #include "sysdep.h"
+#include "version.h"
 
 static void
-check_hg_versions (void)
+check_hg_versions ()
 {
   bool ok = true;
 
@@ -143,7 +144,8 @@
 
   octave::sys::env::set_program_name (argv[0]);
 
-  octave::qt_application app (argc, argv);
+  octave::qt_application app ("octave", "octave-gui", OCTAVE_VERSION,
+                              argc, argv);
 
   int ret = app.execute ();
 
--- a/src/main.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/main.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -111,7 +111,7 @@
 }
 
 static void
-install_signal_handlers (void)
+install_signal_handlers ()
 {
   // FIXME: do we need to handle and forward all the signals that Octave
   // handles, or is it sufficient to only forward things like SIGINT,
@@ -169,7 +169,7 @@
 }
 
 static std::string
-get_octave_bindir (void)
+get_octave_bindir ()
 {
   // Accept value from the environment literally, but substitute
   // OCTAVE_HOME in the configuration value OCTAVE_BINDIR in case Octave
@@ -183,7 +183,7 @@
 }
 
 static std::string
-get_octave_archlibdir (void)
+get_octave_archlibdir ()
 {
   // Accept value from the environment literally, but substitute
   // OCTAVE_HOME in the configuration value OCTAVE_ARCHLIBDIR in case
--- a/src/mkoctfile.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/mkoctfile.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -356,11 +356,6 @@
   vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG",
                                          %OCTAVE_CONF_LD_STATIC_FLAG%);
 
-  // FIXME: Remove LFLAGS in Octave 9
-  vars["LFLAGS"] = get_variable ("LFLAGS", DEFAULT_LDFLAGS);
-  if (vars["LFLAGS"] != DEFAULT_LDFLAGS)
-    std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl;
-
   vars["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG",
                                             %OCTAVE_CONF_F77_INTEGER_8_FLAG%);
   vars["ALL_FFLAGS"] = vars["FFLAGS"] + ' ' + vars["F77_INTEGER8_FLAG"];
@@ -608,7 +603,7 @@
 }
 
 static std::string
-get_temp_directory (void)
+get_temp_directory ()
 {
   std::string tempd;
 
@@ -648,7 +643,7 @@
 }
 
 static std::string
-create_interleaved_complex_file (void)
+create_interleaved_complex_file ()
 {
   std::string tmpl = get_temp_directory () + "/oct-XXXXXX.c";
 
@@ -674,7 +669,7 @@
 }
 
 static std::string
-tmp_objfile_name (void)
+tmp_objfile_name ()
 {
   std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";
 
@@ -888,10 +883,6 @@
             {
               ++i;
 
-              // FIXME: Remove LFLAGS checking in Octave 9
-              if (argv[i] == "LFLAGS")
-                std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl;
-
               if (! var_to_print.empty ())
                 std::cerr << "mkoctfile: warning: only one '" << arg
                           << "' option will be processed" << std::endl;
@@ -1317,13 +1308,12 @@
           octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
                         + ' ' + vars["OCTAVE_LIBS"];
 
-          // FIXME: Remove LFLAGS in Octave 9
           std::string cmd
             = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' '
                + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
                + pass_on_options + ' ' + output_option + ' ' + objfiles + ' '
                + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' '
-               + vars["LFLAGS"] + ' ' + octave_libs + ' '
+               + octave_libs + ' '
                + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);
 
           int status = run_command (cmd, verbose, printonly);
@@ -1348,12 +1338,11 @@
                     + ' ' + vars["OCTAVE_LIBS"];
 #endif
 
-      // FIXME: Remove LFLAGS in Octave 9
       std::string cmd
         = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
            + pass_on_options + " -o " + octfile + ' ' + objfiles + ' '
            + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' '
-           + vars["LDFLAGS"] + ' ' + vars["LFLAGS"] + ' ' + octave_libs + ' '
+           + vars["LDFLAGS"] + ' ' + octave_libs + ' '
            + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);
 
 #if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
--- a/src/octave-build-info.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/octave-build-info.h	Fri Jun 23 20:51:51 2023 +0200
@@ -30,6 +30,6 @@
 
 #include <string>
 
-extern std::string octave_hg_id (void);
+extern std::string octave_hg_id ();
 
 #endif
--- a/src/octave-build-info.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/octave-build-info.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -32,7 +32,7 @@
 #include "octave-build-info.h"
 
 std::string
-octave_hg_id (void)
+octave_hg_id ()
 {
   return "%OCTAVE_HG_ID%";
 }
--- a/src/octave-config.in.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/octave-config.in.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -99,7 +99,7 @@
   "\n";
 
 static void
-initialize (void)
+initialize ()
 {
   set_octave_home ();
 
--- a/src/octave-qsvghandler.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/octave-qsvghandler.h	Fri Jun 23 20:51:51 2023 +0200
@@ -39,11 +39,16 @@
 
 // --------------------------------------------------------------------------
 // Build a QPainterPath from the "d" attribute of a path element
-// These functions are extracted from Qt-5.12 sources (qtsvghandler.cpp)
+// These functions were originally extracted from Qt-5.12 sources
+//   (qsvghandler.cpp)
 // Modifications:
 //   * use static_cast<qreal> to avoid old style cast warning.
+// Some portions are extracted from Qt6.5:
+// https://github.com/qt/qtsvg/blob/6.5.0/src/svg/qsvghandler.cpp
 // --------------------------------------------------------------------------
 
+#include <cmath>
+
 #include <QPainterPath>
 
 static inline bool isDigit(ushort ch)
@@ -124,20 +129,33 @@
             val = -val;
     } else {
         val = QByteArray::fromRawData(temp, pos).toDouble();
+        // Do not tolerate values too wild to be represented normally by floats
+        if (std::fpclassify (static_cast<float> (val)) != FP_NORMAL)
+            val = 0;
     }
     return val;
 
 }
 
-static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
+static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points,
+                                     const char *pattern = nullptr)
 {
+    const size_t patternLen = qstrlen(pattern);
     while (str->isSpace())
         ++str;
     while (isDigit(str->unicode()) ||
            *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
            *str == QLatin1Char('.')) {
 
-        points.append(toDouble(str));
+        if (patternLen && pattern[points.size() % patternLen] == 'f') {
+            // flag expected, may only be 0 or 1
+            if (*str != QLatin1Char('0') && *str != QLatin1Char('1'))
+                return;
+            points.append(*str == QLatin1Char('0') ? 0.0 : 1.0);
+            ++str;
+        } else {
+            points.append(toDouble(str));
+        }
 
         while (str->isSpace())
             ++str;
@@ -149,6 +167,7 @@
             ++str;
     }
 }
+
 static void pathArcSegment(QPainterPath &path,
                            qreal xc, qreal yc,
                            qreal th0, qreal th1,
@@ -218,13 +237,19 @@
                     qreal               y,
                     qreal curx, qreal cury)
 {
+    const qreal Pr1 = rx * rx;
+    const qreal Pr2 = ry * ry;
+
+    if (!Pr1 || !Pr2)
+        return;
+
     qreal sin_th, cos_th;
     qreal a00, a01, a10, a11;
     qreal x0, y0, x1, y1, xc, yc;
     qreal d, sfactor, sfactor_sq;
     qreal th0, th1, th_arc;
     int i, n_segs;
-    qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
+    qreal dx, dy, dx1, dy1, Px, Py, check;
 
     rx = qAbs(rx);
     ry = qAbs(ry);
@@ -236,8 +261,6 @@
     dy = (cury - y) / 2.0;
     dx1 =  cos_th * dx + sin_th * dy;
     dy1 = -sin_th * dx + cos_th * dy;
-    Pr1 = rx * rx;
-    Pr2 = ry * ry;
     Px = dx1 * dx1;
     Py = dy1 * dy1;
     /* Spec : check if radii are large enough */
@@ -261,6 +284,8 @@
        The arc fits a unit-radius circle in this space.
     */
     d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
+    if (!d)
+        return;
     sfactor_sq = 1.0 / d - 0.25;
     if (sfactor_sq < 0) sfactor_sq = 0;
     sfactor = qSqrt(sfactor_sq);
@@ -288,14 +313,23 @@
     }
 }
 
+#if HAVE_QSTRINGVIEW
+static QTransform parseTransformationMatrix(QStringView value)
+#else
 static QTransform parseTransformationMatrix(const QStringRef &value)
+#endif
 {
     if (value.isEmpty())
         return QTransform();
 
     QTransform matrix;
+#if HAVE_QSTRINGVIEW
+    const QChar *str = value.data();
+    const QChar *end = str + value.size();
+#else
     const QChar *str = value.constData();
     const QChar *end = str + value.length();
+#endif
 
     while (str < end) {
         if (str->isSpace() || *str == QLatin1Char(',')) {
@@ -420,37 +454,49 @@
     return matrix;
 }
 
+#if HAVE_QSTRINGVIEW
+static bool parsePathDataFast(QStringView dataStr, QPainterPath &path)
+#else
 static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
+#endif
 {
+    const int maxElementCount = 0x7fff; // Assume file corruption if more path elements than this
     qreal x0 = 0, y0 = 0;              // starting point
     qreal x = 0, y = 0;                // current point
     char lastMode = 0;
     QPointF ctrlPt;
+#if HAVE_QSTRINGVIEW
+    const QChar *str = dataStr.data();
+#else
     const QChar *str = dataStr.constData();
+#endif
     const QChar *end = str + dataStr.size();
 
-    while (str != end) {
+    bool ok = true;
+    while (ok && str != end) {
         while (str->isSpace() && (str + 1) != end)
             ++str;
         QChar pathElem = *str;
         ++str;
         QChar endc = *end;
-        *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
+        *const_cast<QChar *>(end) = u'\0'; // parseNumbersArray requires 0-termination that QStringView cannot guarantee
+        const char *pattern = nullptr;
+        if (pathElem == QLatin1Char('a') || pathElem == QLatin1Char('A'))
+            pattern = "rrrffrr";
         QVarLengthArray<qreal, 8> arg;
-        parseNumbersArray(str, arg);
+        parseNumbersArray(str, arg, pattern);
         *const_cast<QChar *>(end) = endc;
         if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
             arg.append(0);//dummy
         const qreal *num = arg.constData();
         int count = arg.count();
-        while (count > 0) {
+        while (ok && count > 0) {
             qreal offsetX = x;        // correction offsets
             qreal offsetY = y;        // for relative commands
             switch (pathElem.unicode()) {
             case 'm': {
                 if (count < 2) {
-                    num++;
-                    count--;
+                    ok = false;
                     break;
                 }
                 x = x0 = num[0] + offsetX;
@@ -467,8 +513,7 @@
                 break;
             case 'M': {
                 if (count < 2) {
-                    num++;
-                    count--;
+                    ok = false;
                     break;
                 }
                 x = x0 = num[0];
@@ -494,8 +539,7 @@
                 break;
             case 'l': {
                 if (count < 2) {
-                    num++;
-                    count--;
+                    ok = false;
                     break;
                 }
                 x = num[0] + offsetX;
@@ -508,8 +552,7 @@
                 break;
             case 'L': {
                 if (count < 2) {
-                    num++;
-                    count--;
+                    ok = false;
                     break;
                 }
                 x = num[0];
@@ -549,8 +592,7 @@
                 break;
             case 'c': {
                 if (count < 6) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c1(num[0] + offsetX, num[1] + offsetY);
@@ -566,8 +608,7 @@
             }
             case 'C': {
                 if (count < 6) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c1(num[0], num[1]);
@@ -583,8 +624,7 @@
             }
             case 's': {
                 if (count < 4) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c1;
@@ -605,8 +645,7 @@
             }
             case 'S': {
                 if (count < 4) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c1;
@@ -627,8 +666,7 @@
             }
             case 'q': {
                 if (count < 4) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c(num[0] + offsetX, num[1] + offsetY);
@@ -643,8 +681,7 @@
             }
             case 'Q': {
                 if (count < 4) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF c(num[0], num[1]);
@@ -659,8 +696,7 @@
             }
             case 't': {
                 if (count < 2) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF e(num[0] + offsetX, num[1] + offsetY);
@@ -680,8 +716,7 @@
             }
             case 'T': {
                 if (count < 2) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 QPointF e(num[0], num[1]);
@@ -701,8 +736,7 @@
             }
             case 'a': {
                 if (count < 7) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 qreal rx = (*num++);
@@ -724,8 +758,7 @@
                 break;
             case 'A': {
                 if (count < 7) {
-                    num += count;
-                    count = 0;
+                    ok = false;
                     break;
                 }
                 qreal rx = (*num++);
@@ -746,10 +779,13 @@
             }
                 break;
             default:
-                return false;
+                ok = false;
+                break;
             }
             lastMode = pathElem.toLatin1();
+            if (path.elementCount() > maxElementCount)
+                ok = false;
         }
     }
-    return true;
+    return ok;
 }
--- a/src/octave-svgconvert.cc	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/octave-svgconvert.cc	Fri Jun 23 20:51:51 2023 +0200
@@ -44,7 +44,7 @@
 #include <QImage>
 #include <QPainter>
 #include <QPrinter>
-#include <QRegExp>
+#include <QRegularExpression>
 
 // Include a set of path rendering functions extracted from Qt-5.12 source
 #include "octave-qsvghandler.h"
@@ -53,30 +53,32 @@
 class pdfpainter : public QPainter
 {
 public:
+
+  pdfpainter () = delete;
+
   pdfpainter (QString fname, QRectF sz)
-      :  m_printer ()
+    : m_printer ()
   {
     // Printer settings
     m_printer.setOutputFormat (QPrinter::PdfFormat);
     m_printer.setFontEmbeddingEnabled (true);
     m_printer.setOutputFileName (fname);
     m_printer.setFullPage (true);
-#if defined (HAVE_QPRINTER_SETPAGESIZE)
     m_printer.setPageSize (QPageSize (sz.size (), QPageSize::Point,
                                       QString ("custom"),
                                       QPageSize::ExactMatch));
-#else
-    m_printer.setPaperSize (sz.size (), QPrinter::Point);
-#endif
 
     // Painter settings
     begin (&m_printer);
     setWindow (sz.toRect ());
   }
 
-  ~pdfpainter (void) { end (); }
+  OCTAVE_DISABLE_COPY_MOVE (pdfpainter)
+
+  ~pdfpainter () { end (); }
 
 private:
+
   QPrinter m_printer;
 };
 
@@ -85,23 +87,20 @@
 {
   QVector<double> pts;
   QStringList coords = str.split (",");
-  for (QStringList::iterator p = coords.begin (); p != coords.end (); p += 1)
-    {
-      double pt = (*p).toDouble ();
-      pts.append (pt);
-    }
+  for (auto& p : coords)
+    pts.append (p.toDouble ());
+
   return pts;
 }
 
+// FIXME: What's the difference between qstr2vectorf and qstr2vectord?
+// Can one be called from the other to avoid code duplication, or deleted?
 QVector<double> qstr2vectord (QString str)
 {
   QVector<double> pts;
   QStringList coords = str.split (",");
-  for (QStringList::iterator p = coords.begin (); p != coords.end (); p += 1)
-    {
-      double pt = (*p).toDouble ();
-      pts.append (pt);
-    }
+  for (auto& p : coords)
+    pts.append (p.toDouble ());
 
   return pts;
 }
@@ -120,6 +119,8 @@
   return pts;
 }
 
+// FIXME: What's the difference between qstr2ptsvector and qstr2ptsvectord?
+// Can one be called from the other to avoid code duplication, or deleted?
 QVector<QPoint> qstr2ptsvectord (QString str)
 {
   QVector<QPoint> pts;
@@ -137,12 +138,9 @@
 // Extract field arguments in a style-like string, e.g. "bla field(1,34,56) bla"
 QString get_field (QString str, QString field)
 {
-  QString retval;
-  QRegExp rx (field + "\\(([^\\)]*)\\)");
-  int pos = 0;
-  pos = rx.indexIn (str, pos);
-  if (pos > -1)
-    retval = rx.cap (1);
+  QRegularExpression rx (field + "\\(([^\\)]*)\\)");
+  QRegularExpressionMatch match = rx.match (str);
+  QString retval = match.captured (1);
 
   return retval;
 }
@@ -151,18 +149,16 @@
 class octave_polygon
 {
 public:
-  octave_polygon (void)
-  { }
 
   octave_polygon (QPolygonF p)
   { m_polygons.push_back (p); }
 
-  ~octave_polygon (void) { }
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (octave_polygon)
 
-  int count (void) const
+  int count () const
   { return m_polygons.count (); }
 
-  void reset (void)
+  void reset ()
   { m_polygons.clear (); }
 
   QList<QPolygonF> reconstruct (int reconstruct_level)
@@ -173,9 +169,7 @@
       return m_polygons;
 
     // Once a polygon has been merged to another, it is marked unsuded
-    QVector<bool> unused;
-    for (auto it = m_polygons.begin (); it != m_polygons.end (); it++)
-      unused.push_back (false);
+    QVector<bool> unused (m_polygons.count (), false);
 
     bool tryagain = (m_polygons.count () > 1);
 
@@ -451,7 +445,11 @@
               painter.save ();
               if (! str.isEmpty ())
                 {
-                  QStringRef tf (&str);
+#if HAVE_QSTRINGVIEW
+                  QStringView tf {str};
+#else
+                  QStringRef tf {&str};
+#endif
                   QTransform  tform =
                     parseTransformationMatrix (tf) * painter.transform ();
                   painter.setTransform (tform);
@@ -481,7 +479,11 @@
 
               if (! d.isEmpty ())
                 {
-                  QStringRef data (&d);
+#if HAVE_QSTRINGVIEW
+                  QStringView data {d};
+#else
+                  QStringRef data {&d};
+#endif
                   QPainterPath path;
                   if (! parsePathDataFast (data, path))
                     continue; // Something went wrong, pass
@@ -1007,7 +1009,11 @@
     {
       // Return modified svg document
       QTextStream out (&fout);
+#if HAVE_QTEXTSTREAM_SETENCODING
+      out.setEncoding (QStringConverter::Utf8);
+#else
       out.setCodec ("UTF-8");
+#endif
       out << document.toByteArray ();
     }
 
--- a/src/shared-fcns.h	Fri Jun 23 20:51:15 2023 +0200
+++ b/src/shared-fcns.h	Fri Jun 23 20:51:51 2023 +0200
@@ -45,7 +45,7 @@
 #  endif
 
 static std::string
-w32_get_octave_home (void)
+w32_get_octave_home ()
 {
   std::string retval;
 
@@ -108,7 +108,7 @@
 static std::string Voctave_exec_home;
 
 static void
-set_octave_home (void)
+set_octave_home ()
 {
   std::string op = OCTAVE_PREFIX;
   std::string oep = OCTAVE_EXEC_PREFIX;
--- a/test/Makefile.am	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/Makefile.am	Fri Jun 23 20:51:51 2023 +0200
@@ -112,6 +112,8 @@
 include classdef-multiple-inheritance/module.mk
 include classes/module.mk
 include colon-op/module.mk
+include compile-bench/module.mk
+include compile/module.mk
 include ctor-vs-method/module.mk
 include fcn-handle/module.mk
 include file-encoding/module.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-48693/bug-48693.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,3 @@
+%!test
+%! x = bug48693();
+%! assert ({x{1:10}}, num2cell (zeros(1,10)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-48693/bug48693.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,7 @@
+classdef bug48693 < handle
+  methods
+    function varargout = subsref (x, idx)
+      varargout = num2cell (zeros (size (idx(1).subs{1})));
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-48693/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+bug_48693_TEST_FILES = \
+  %reldir%/bug48693.m \
+  %reldir%/bug-48693.tst
+
+TEST_FILES += $(bug_48693_TEST_FILES)
--- a/test/bug-53579.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/bug-53579.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -13,6 +13,7 @@
 %! assert (isglobal ("bb"));
 %! aa = 3;
 %! xx = 5;
+%! warning ('off', 'Octave:global-local-conflict', 'local');
 %! [raa, rbb, igaa, igbb] = sub1 (aa, xx);
 %! assert (raa, 1);
 %! assert (rbb, []);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/bench.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,173 @@
+function bench (varargin)
+
+  % The tests to run
+  %
+  % {name, {arg_type, n}, ...}
+  tests = {
+    {"for_loop_empty", {"n", 206824596}, 1, {}},
+    {"for_loop_silly", {"n", 34894840}, 1, {}},
+    {"for_loop_binop_1", {"n", 20300088}, 1, {}},
+    {"for_loop_sinpi", {"n", 12991066}, 1, {}},
+    {"for_loop_ifs", {"n", 5874007}, 1, {}},
+    {"while_loop_empty", {"n", 24237997}, 1, {}},
+    {"do_until_loop_empty", {"n", 27109647}, 1, {}},
+    {"for_loop_subfun_1", {"n", 11930390}, 1, {}},
+    {"for_loop_matselfmul", {"rand sq",150}, 3, {}},
+    {"for_sum_1", {"rand rowvec", 19267692}, 1, {}},
+    {"for_sum_2", {"rand rowvec", 8742659}, 1, {}},
+    {"qsort_recursive", {"rand rowvec", 107851}, 1, {}}, % Mostly copies vectors around
+    {"qsort_iterative", {"rand rowvec", 344418}, 1, {}},
+    {"for_loop_fncall", {"n", 2164885}, 1, {}},
+    {"bench_median", {"rand rowvec", 1927}, 1, {}},
+    {"bench_cov", {"rand rowvec", 15261}, 1, {}},
+    {"str_mod", {"n", 2335290}, 1, {}},
+    {"fib", {"n", 31}, 1, {}},
+  };
+
+  reg = '';
+  calibrate = 0;
+  do_both = 1;
+  n_factor = 1;
+  filter = "";
+  i = 1;
+  while i <= nargin
+    arg = varargin{i++};
+    if strcmp (arg, "reg")
+      assert (i <= nargin)
+      reg = varargin{i++};
+    elseif strcmp (arg, "calibrate")
+      calibrate = 1;
+    elseif strcmp (arg, "n_factor")
+      assert (i <= nargin)
+      n_factor = varargin{i++};
+    end
+  end
+
+  % For compatibility with older releases and Matlab
+  if ~exist("__compile")
+    __compile = @(varargin) true;
+  end
+  if ~exist("__dummy_mark_1")
+    __dummy_mark_1 = @() true;
+  end
+  if ~exist("__dummy_mark_2")
+    __dummy_mark_2 = @() true;
+  end
+
+  cal_res = {};
+
+  for i = 1:length(tests)
+
+    test = tests{i};
+    name = test{1};
+    complexity = test{3};
+    also_compile = test{4};
+    j = 1;
+
+    % Skip on not matching regex, if there is one
+    if length (reg) && isempty (regexp (name, reg))
+      continue;
+    end
+
+    fn = str2func (name);
+
+    printf ("%s:\n", name);
+
+    n = 0;
+    arg = 0;
+    conf = test{2};
+    conf_type = conf {1}; %"n", "rand sq" etc
+    n_norm = conf{2};
+
+    if strcmp (conf_type, "n")
+      n = round (conf{2} * n_factor);
+      arg = n;
+    elseif strcmp (conf_type, "rand sq")
+      rng (0); % Reset rng
+      n = round (conf{2} * n_factor);
+      arg = randn (n);
+    elseif strcmp (conf_type, "rand rowvec")
+      rng (0); % Reset rng
+      n = round (conf{2} * n_factor);
+      arg = randn (n, 1);
+    end
+    n = round (n);
+
+    iters = 1:1;
+    if calibrate
+      iters = 1:40;
+      e_i = 0;
+    end
+
+    for j = iters
+
+      if strcmp (conf_type, "n")
+        n = round (n_norm * n_factor);
+        arg = n;
+      elseif strcmp (conf_type, "rand sq")
+        rng (0); % Reset rng
+        n = round (n_norm * n_factor);
+        arg = randn (n);
+      elseif strcmp (conf_type, "rand rowvec")
+        rng (0); % Reset rng
+        n = round (n_norm * n_factor);
+        arg = randn (n, 1);
+      end
+      n = round (n);
+
+
+      tic;
+      [ccttot0, cctuser0, cctsys0] = cputime;
+      assert (__compile (name));
+      [ccttot1, cctuser1, cctsys1] = cputime;
+      cctwall = toc;
+
+      [cttot0, ctuser0, ctsys0] = cputime;
+      tic;
+      __dummy_mark_1 ();
+      fn (arg);
+      __dummy_mark_2 ();
+      [cttot1, ctuser1, ctsys1] = cputime;
+      ctwall = toc;
+
+      printf ("                %-16s %-16s %-16s %-16s %-16s\n", "t tic","t cpu", "t usr" , "t sys", "n");
+      printf ("    Runtime:    %-16g %-16g %-16g %-16g %-16g\n", ctwall, cttot1 - cttot0, ctuser1 - ctuser0, ctsys1 - ctsys0, n);
+      printf ("    Compiletime %-16g %-16g %-16g %-16g\n\n", cctwall, ccttot1 - ccttot0, cctuser1 - cctuser0, cctsys1 - cctsys0);
+
+      if calibrate
+        t_target = 1;
+        e = ctwall - t_target;
+        if e > 0.5
+          e = 0.5;
+        elseif e < -0.5
+          e = -0.5;
+        end
+
+        n_norm_new = n_norm * (1 - e);
+        if j > 30
+          n_norm = 0.998 * n_norm + 0.002 * n_norm_new;
+        elseif j > 20
+          n_norm = 0.99 * n_norm + 0.01 * n_norm_new;
+        elseif j > 10
+          n_norm = 0.95 * n_norm + 0.05 * n_norm_new;
+        else
+          n_norm = n_norm_new;
+        end
+
+        printf ("    n = %g, e = %g, e_i = %g\n", n_norm, e, e_i);
+      end
+    end
+
+    if calibrate
+      printf ("    Calibrated n: %d\n\n", n);
+      cal_res{end + 1} = {name, n};
+    end
+  end
+
+  if calibrate
+    printf ("Calibrated n:s for 1s\n\n");
+    for e = cal_res
+      printf ("%s %d\n", e{1}{1}, e{1}{2});
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/bench_cov.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function bench_cov (v)
+  for i = 1:10000
+    cov (v, v);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/bench_median.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function bench_median (v)
+  for i = 1:10000
+    median (v);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/do_until_loop_empty.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,7 @@
+function do_until_loop_empty (n)
+  i = 0;
+  do
+    i++;
+  until i >= n
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/fib.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,8 @@
+function b = fib (n)
+    if n <= 1
+        b = 1;
+        return;
+    endif
+
+    b = fib (n - 1) + fib (n - 2);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_binop_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,6 @@
+function for_loop_binop_1 (n)
+  for i = 1:n
+    j = 1*2*3*4;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_binop_2.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,8 @@
+function for_loop_binop_2 (n)
+  for i = 1:n
+    j = 1*2*3*4 * i;
+    g = j / 2 + 1;
+    f = g + j - 3;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_empty.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function for_loop_empty (n)
+  for i = 1:n
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_fncall.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function for_loop_fncall (n)
+  for i = 1:n
+    max (i, 2);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_ifs.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,30 @@
+function for_loop_ifs (n)
+  for i = 1:n
+    if i == 100
+      continue;
+    elseif i == 300
+      continue;
+    end
+
+    if i * 2 == 3002
+      continue;
+    end
+
+    if i < 0
+      break;
+    end
+
+    if i == -1024
+      disp ("foooo");
+    end
+
+    if i == n + 1
+      break;
+    end
+
+    if ~i
+      break;
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_matselfmul.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,18 @@
+function A = for_loop_matselfmul (sq)
+  A = zeros (size (sq));
+
+  cols = size (sq, 2);
+  rows = size (sq, 1);
+
+  assert (cols == rows);
+
+  n = cols;
+
+  for i=1:n
+    for j=1:n
+      for k=1:n
+        A(i,j) = A(i,j)+sq(i,k)*sq(k,j);
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_silly.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,6 @@
+function for_loop_silly (n)
+  for i = 1:n
+    j = i;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_sinpi.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function for_loop_sinpi (n)
+  for i = 1:n
+    j = sin (pi * i);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_loop_subfun_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,9 @@
+function for_loop_subfun_1 (n)
+
+  for i = 1:n
+    suby ();
+  end
+end
+
+function suby ()
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_sum_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,7 @@
+function for_sum_1 (mat)
+  sum = 0;
+  for i = 1:length (mat)
+    sum = sum + mat (i);
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/for_sum_2.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,7 @@
+function sum = for_sum_2 (arg)
+  sum = 0;
+  for i = arg'
+    sum = sum + i;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/qsort_iterative.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,48 @@
+function A = qsort_iterative (A)
+  len = length (A);
+  stack = zeros (64, 1);
+
+  top = 0;
+
+  % Push initial indices to the stack
+  stack (++top) = 1;
+  stack (++top) = len;
+
+  while top > 0
+    % Pop indices
+    high = stack (top--);
+    low = stack (top--);
+
+    % Partion part of the algorithm
+    p = low - 1; % pivot index
+    x = A (high);% pivot value
+
+    % Swap so that there are two parts. One less than or equal to the pivot
+    % value and one higher
+    for j = low:high - 1
+      if A(j) <= x
+        p++;
+        tmp = A(j);
+        A(j) = A(p);
+        A(p) = tmp;
+      end
+    end
+    % Swap the pivot value with the first value bigger than the pivot
+    p++;
+    tmp = A(high);
+    A(high) = A(p);
+    A(p) = tmp;
+    % End partion
+
+    % Push left and right indices (if there are any value to the left or right)
+    if p - 1 > low
+      stack(++top) = low;
+      stack(++top) = p - 1;
+    end
+
+    if p + 1 < high
+      stack(++top) = p + 1;
+      stack(++top) = high;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/qsort_recursive.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,36 @@
+% Most time is spent copying vectors anyway so terrible test really.
+
+function A = qsort_recursive (A)
+  if isempty (A) || length(A) == 1
+    return;
+  end
+
+  [p, A] = partion (A);
+
+  left = qsort_recursive (A(1:p - 1));
+  right = qsort_recursive (A(p + 1:end));
+
+  A = [left A(p) right];
+end
+
+function [p, A] = partion (A)
+  lo = 1;
+  hi = length (A);
+
+  pivot = A(hi);
+
+  p = lo - 1;
+
+  for j = lo:1:hi-1
+    if A(j) <= pivot
+      p++;
+      tmp = A(j);
+      A (j) = A (p);
+      A (p) = tmp;
+    end
+  end
+  p++;
+  tmp = A(hi);
+  A(hi) = A(p);
+  A(p) = tmp;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/str_mod.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,9 @@
+function str_mod (n)
+
+  s1 = "qweasd";
+  s2 = "zxccvb";
+  for i = 1:n
+    s1 (2) = "f";
+    s2 (1) = s1(3);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-octave/while_loop_empty.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,7 @@
+function while_loop_empty (n)
+  i = 0;
+  while i < n
+    i++;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/bench-py3/bench.py	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+
+from timeit import default_timer as timer
+from array import *
+import random
+import math
+
+def fib (n):
+    if n <= 1:
+        return 1
+
+    return fib (n - 1) + fib (n - 2)
+
+def for_loop_empty (n):
+    for i in range (1, n + 1):
+        continue
+
+def for_loop_silly (n):
+    for i in range (1, n + 1):
+        j = i
+
+def for_loop_binop_1(n):
+    for i in range (1, n + 1):
+        j = 1*2*3*4
+
+def for_loop_sinpi (n):
+    for i in range (1, n):
+        j = math.sin (math.pi * i)
+
+def for_loop_ifs (n):
+    for i in range (1, n + 1):
+        if i == 100.0:
+            continue
+        elif i == 300.0:
+            continue
+
+        if i * 2.0 == 3002.0:
+            continue
+
+        if i < 0.0:
+            break
+
+        if i == -1024.0:
+            print ("fooo")
+
+        if i == n + 1.0:
+            break
+
+        if not i:
+            break
+
+def while_loop_empty (n):
+    i = 0.0
+    while i < n:
+        i += 1
+
+def for_loop_subfun_1 (n):
+    for i in range (n):
+        suby ()
+
+def suby ():
+    return
+
+def qsort_iterative (A):
+    l = len (A)
+    stack = [0] * 128 # Probably big enough
+
+    top = 0
+    stack[top] = 0
+    top += 1
+    stack[top] = l - 1
+    top += 1
+
+    while top > 0:
+        top -= 1
+        high = stack[top]
+        top -= 1
+        low = stack[top]
+
+        p = low - 1
+        x = A[high]
+
+        for j in range (low, high):
+            if A[j] <= x:
+                p += 1
+                tmp = A[j]
+                A[j] = A[p]
+                A[p] = tmp
+        p += 1
+        tmp = A[high]
+        A[high] = A[p]
+        A[p] = tmp
+
+        if p - 1 > low:
+            stack[top] = low
+            top += 1
+            stack[top] = p - 1
+            top += 1
+        if p + 1 < high:
+            stack[top] = p + 1
+            top += 1
+            stack[top] = high
+            top += 1
+
+    return A
+
+def time_fn_call (fn, arg):
+    start = timer()
+    fn (arg)
+    end = timer()
+
+    return end - start
+
+def randn (rows, cols):
+    if rows == 1:
+        arr = array('d')
+        for i in range(cols):
+            arr.append(random.gauss (0, 1))
+        return arr
+
+    arr = array()
+    for i in range (rows):
+        arr_row = array('d')
+        for j in range(cols):
+          arr_row.append(random.gauss (0, 1))
+        arr.append (arr_row)
+    return arr
+
+tests = \
+   [[for_loop_empty, 206824596],
+    [for_loop_silly, 34894840],
+    [for_loop_binop_1, 20300088],
+    [for_loop_sinpi, 12991066],
+    [for_loop_ifs, 5874007],
+    [while_loop_empty, 24237997],
+    [for_loop_subfun_1, 11930390],
+    [fib, 31],
+    [qsort_iterative, "rowvec", 344418]]
+
+def main():
+    for t in tests:
+        if (t[1] == "rowvec"):
+            dt = time_fn_call (t[0], randn (1, t[2]))
+        else:
+            dt = time_fn_call (t[0], t[1])
+        print (t[0].__name__ + " in %g s" % dt)
+
+if __name__ == "__main__":
+    main ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile-bench/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,23 @@
+compile_bench_TEST_FILES = \
+  %reldir%/bench-octave/bench.m \
+  %reldir%/bench-octave/bench_cov.m \
+  %reldir%/bench-octave/bench_median.m \
+  %reldir%/bench-octave/do_until_loop_empty.m \
+  %reldir%/bench-octave/fib.m \
+  %reldir%/bench-octave/for_loop_binop_1.m \
+  %reldir%/bench-octave/for_loop_empty.m \
+  %reldir%/bench-octave/for_loop_fncall.m \
+  %reldir%/bench-octave/for_loop_ifs.m \
+  %reldir%/bench-octave/for_loop_matselfmul.m \
+  %reldir%/bench-octave/for_loop_silly.m \
+  %reldir%/bench-octave/for_loop_sinpi.m \
+  %reldir%/bench-octave/for_loop_subfun_1.m \
+  %reldir%/bench-octave/for_sum_1.m \
+  %reldir%/bench-octave/for_sum_2.m \
+  %reldir%/bench-octave/qsort_iterative.m \
+  %reldir%/bench-octave/qsort_recursive.m \
+  %reldir%/bench-octave/str_mod.m \
+  %reldir%/bench-octave/while_loop_empty.m \
+  %reldir%/bench-py3/bench.py
+
+TEST_FILES += $(compile_bench_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,663 @@
+########################################################################
+##
+## Copyright (C) 2022-2023 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## 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/Test/>.
+##
+########################################################################
+
+## Just clear the cached string in __prog_output_assert__() and clear
+## classes method lookups due to maybe bug
+%!test
+%! __prog_output_assert__ ("");
+%! % Overloading of class-methods seems to stick so we need to clear them since we overload
+%! % double's display. Is this a bug ???
+%! clear classes
+
+## Test binary expressions
+%!test
+%! __enable_vm_eval__ (0, "local"); % Disable the vm for the tree_walker run
+%!
+%! clear all % We want all compiled functions to be cleared so that we can run the tree_walker
+%!
+%! key = "10 -10 24 0.041666666666666664 1 -5.0915810909090906 13 1 0 1 0 truthy1 1 falsy3 falsy4 truthy5 1 truthy7 truthy8 1 falsy9 falsy11 0 1 0 1 0 0 1 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 1 1 1 1 1 1 ";
+%!
+%! __compile bytecode_binops clear;
+%! bytecode_binops ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! % We wanna know the function compiles, so do a explicit compile
+%! assert (__compile ("bytecode_binops"));
+%! bytecode_binops ();
+%! assert (__prog_output_assert__ (key));
+
+## Test subfunctions
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 2 2 11 30 10 30 5  0 0 double 1 2 1 2 double 30 11 5  0 0 double 1 2 1 2 double 11 11 12 13 1 1 double 14 1 1 double 11 11 5 13 1 1 double 14 1 1 double 11 3 3 3 2 2 2 313 ret32:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ret32:1 ret32:ret32:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 take32:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 18 59 64 ";
+%! a = 313;
+%! % Gets called to ensure anonymous functions calls with
+%! % externally scoped variables work
+%! h = @() __printf_assert__ ("%d ", a);
+%!
+%! __compile bytecode_subfuncs clear;
+%! bytecode_subfuncs (h);
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_subfuncs"));
+%! bytecode_subfuncs (h);
+%! assert (__prog_output_assert__ (key));
+
+## Test if:s
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "0 1 2 3 4 5 6 7 8 1 2 yay1 3 5 7 8 1 yay1 3 4 yay2 5 6 7 yay3 ";
+%!
+%! __compile bytecode_if clear;
+%! bytecode_if ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_if"));
+%! bytecode_if ();
+%! assert (__prog_output_assert__ (key));
+
+## Test for:s
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 2 3 4 4 1 3 5 5 4 3 2 1 1 1 4 2 2 16 4 3 3 256 3 2 1  double 1 3 size 2 size 1 2 4 size 2 size 1  double q size 1 size 1 w size 1 size 1 e size 1 size 1 char single single 5 1 11 2 12 key:a val:1 1val:1 key:b val:1 3val:2 4val:2 2key:c val:string ";
+%!
+%! __compile bytecode_for clear;
+%! bytecode_for ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_for"));
+%! bytecode_for ();
+%! assert (__prog_output_assert__ (key));
+
+## Test while
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "5 4 3 2 1 3 5 4 4 3 3 4 1 2 1 3 2 8 3 1 3 ";
+%!
+%! __compile bytecode_while clear;
+%! bytecode_while ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_while"));
+%! bytecode_while ();
+%! assert (__prog_output_assert__ (key));
+
+## Test assign
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 3 1 1 2 3 2 3 2 2 6 18 2.000000 2.000000 3.000000 4.000000 5.000000 1 4 double 729.000000 324.000000 182.250000 116.640000 4 1 double 37.000000 81.000000 54.000000 118.000000 2 2 double ";
+%!
+%! __compile bytecode_assign clear;
+%! bytecode_assign ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_assign"));
+%! bytecode_assign ();
+%! assert (__prog_output_assert__ (key));
+
+## Test unary
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "-1 4 1 2 3 4 1 3 2 4 0 0 ";
+%!
+%! __compile bytecode_unary clear;
+%! bytecode_unary ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_unary"));
+%! bytecode_unary ();
+%! assert (__prog_output_assert__ (key));
+
+## Test range
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 2 3 1 3 5 1 3 5 1 1.1 1.2 1.3 1.4 1 0.9 0.8 0.7 7 7 1 8 10 8 10 8 9 10 11 8 9 10 11 10 8 10 8 -10 -9 -8 -7 -10 -9 -8 -7 ";
+%!
+%! __compile bytecode_range clear;
+%! bytecode_range ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_range"));
+%! bytecode_range ();
+%! assert (__prog_output_assert__ (key));
+
+## Test multi assign
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "3 4 2 2 1 2 3 4 1 2 3 4 1 1 3 2 3 4 1 1 1 2 3 4 1 1 1 2 3 4 1 2 3 ";
+%!
+%! __compile bytecode_multi_assign clear;
+%! bytecode_multi_assign ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_multi_assign"));
+%! bytecode_multi_assign ();
+%! assert (__prog_output_assert__ (key));
+
+## Test subsasgn
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! clear functions  % persistent variables in bytecode_subsasgn
+%! key = "3 5 9 8 11 13 1 2 3 4 5 6 77 88 99 1010 1 2 3 987 987 6 77 88 99 1010 0 0 0 0 0 13 double 3 2 4 2 3 cell 1 3 6 7 2 3 1 4 5 1 3 5 2 4 6 7 7 7 7 7 7 1 2 3 1 3 3 2 3 2 3 1 3 1 2 3 4 4 4 3 4 5 6 1 5 3 4 1 5 -1 4 1 5 -1 8 ";
+%!
+%! __compile bytecode_subsasgn clear;
+%! bytecode_subsasgn ();
+%! assert (__prog_output_assert__ (key), "bytecode_subsasgn failed uncompiled");
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_subsasgn"));
+%! bytecode_subsasgn ();
+%! assert (__prog_output_assert__ (key), "bytecode_subsasgn failed compiled");
+
+## Test end
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 3 2 4 1 5 6 7 2 2 5 5 6 6 1 2 3 4 5 2 2 2 3 3 4 fs 2 3 1 foo oo ";
+%!
+%! __compile bytecode_end clear;
+%! bytecode_end ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_end"));
+%! bytecode_end ();
+%! assert (__prog_output_assert__ (key));
+
+## Test matrix
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 2 3 4 1 4 1 2 3 4 4 1 1 3 2 4 2 2 1 3 1 3 2 4 2 4 4 2  0 0 a b c d 7 15 10 22 2 2 30 1 1 1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16 4 4 1 1 1 0.0333333 0.0666667 0.1 0.133333 0.0666667 0.133333 0.2 0.266667 0.1 0.2 0.3 0.4 0.133333 0.266667 0.4 0.533333 4 4 1 0 0 1 2 2 30 1 1 10 14 14 20 2 2 0.0333333 0.0666667 0.1 0.133333 0.0666667 0.133333 0.2 0.266667 0.1 0.2 0.3 0.4 0.133333 0.266667 0.4 0.533333 4 4 2.5 -0.5 2 0 2 2 2 6 4 8 2 2 2 3 4 5 3 4 5 6 4 5 6 7 5 6 7 8 4 4 3 4 5 6 1 4 3 4 5 6 1 4 -1 0 1 2 1 4 2 4 6 8 1 4 0.5 1 1.5 2 1 4 0.5 1 1.5 2 1 4 1 4 9 16 1 4 1 1 1 1 1 4 1 1 1 1 1 4 1 4 27 256 1 4 1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16 4 4 1 0.5 0.333333 0.25 2 1 0.666667 0.5 3 1.5 1 0.75 4 2 1.33333 1 4 4 1 2 3 4 0.5 1 1.5 2 0.333333 0.666667 1 1.33333 0.25 0.5 0.75 1 4 4 1 4 27 256 4 1 qzwxeca s d  zzxxccz x c  1 258 33264 258 1 33264 ";
+%!
+%! __compile bytecode_matrix clear;
+%! bytecode_matrix ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_matrix"));
+%! bytecode_matrix ();
+%! assert (__prog_output_assert__ (key));
+
+## Test return
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 baaar bääär baaaaz bääääz bååååz booz 1 1 2 1 1 1 2 1 silly silly ";
+%!
+%! __compile bytecode_return clear;
+%! bytecode_return ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_return"));
+%! bytecode_return ();
+%! assert (__prog_output_assert__ (key));
+
+## Test word list command
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "A B C QWE ";
+%!
+%! __compile bytecode_wordlistcmd clear;
+%! bytecode_wordlistcmd ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_wordlistcmd"));
+%! bytecode_wordlistcmd ();
+%! assert (__prog_output_assert__ (key));
+
+## Test do until
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "5 3 5 5 4 4 3 4 1 2 1 3 2 12 3 0 3 ";
+%!
+%! __compile bytecode_dountil clear;
+%! bytecode_dountil ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_dountil"));
+%! bytecode_dountil ();
+%! assert (__prog_output_assert__ (key));
+
+## Test cell
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "a b a b 1 2 b c b c 1 2 char b c c d b d c e 2 2 b d f h j l c e g i k m 6 2 1 2 2 3 1 3 2 4 1 3 1 2 1 3 2 4 2 2 double qwe 1 3 char 1 2 ";
+%!
+%! __compile bytecode_cell clear;
+%! bytecode_cell ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_cell"));
+%! bytecode_cell ();
+%! assert (__prog_output_assert__ (key));
+
+## Test varargin
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 3 1 2 1 1 1 1 1 2 3 4 1 4 4 0 0 0 1 2 3 4 1 3 4 2 3 4 1 3 3 2 2 3 4 1 4 4 1 0 0 1 0 0 0 2 1 1 1 1 2 3 4 1 3 4 2 3 4 1 3 3 2 2 3 4 1 4 4 2 1 2 4 1 2 3 4 3 3 2 1 0 ";
+%!
+%! __compile bytecode_varargin clear;
+%! bytecode_varargin (1,2,3);
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_varargin"));
+%! bytecode_varargin (1,2,3);
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "0 0 1 1 1 1 1 2 3 4 1 4 4 0 0 0 1 2 3 4 1 3 4 2 3 4 1 3 3 2 2 3 4 1 4 4 1 0 0 1 0 0 0 2 1 1 1 1 2 3 4 1 3 4 2 3 4 1 3 3 2 2 3 4 1 4 4 2 1 2 4 1 2 3 4 1 3 2 1 0 ";
+%!
+%! __compile bytecode_varargin clear;
+%! bytecode_varargin (1);
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_varargin"));
+%! bytecode_varargin (1);
+%! assert (__prog_output_assert__ (key));
+
+## Test global variables
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "double 0 0 1 1 1 1 1 2 2 2 400 100 0 1 3 double 1 1 1 2 double 1 2 1 1 11 eclass:double 1 1 3 4 double 1 2 400 100 1 1 1 1 3 4 1 1 5 6 1 1 1 2 double 1 2 1 2 double 1 2 1 1 3 4 eclass:double 1 2 3 4 double 1 2 0 0 1 1 3 4 1 1 5 6 1 0 2 double 2 double 11 2 6 4 5 double 1 5 11 double 1 1 22 double 1 1 33 double 1 1 3 double 1 1 4 double 1 1 10 double 1 1 2 3 double 1 2 3 double 1 1 2 double 1 1 55 double 1 1 7 double 1 1 0 ";
+%!
+%! __compile bytecode_global_1 clear;
+%! clear global a;
+%! clear global b;
+%! clear global q
+%! global q % Used in test function
+%! q = 55;
+%! bytecode_global_1 ();
+%! assert (__prog_output_assert__ (key));
+%! assert (length(who('global','a')));
+%! assert (length(who('global','b')));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_global_1"));
+%! clear global a;
+%! clear global b;
+%! clear global q;
+%! global q % Used in test function
+%! q = 55;
+%! bytecode_global_1 ();
+%! assert (length(who('global','a')));
+%! assert (length(who('global','b')));
+%! assert (__prog_output_assert__ (key));
+%!
+%! global a b;
+%! assert (a == 5);
+%! assert (b == 6);
+%!
+%! clear global a;
+%! clear global b;
+%! clear global q;
+
+## Test switch
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "yay yay2 yay3 yay4 yay5 yay6 yay7 yay8 1 2 3 3 1 3 3 4 4 1 3 3 4 4 2 yoo 2 3 3 1:1 for-end:12:2 3:3 for-end:3breaking:4 ";
+%!
+%! __compile bytecode_switch clear;
+%! bytecode_switch;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_switch"));
+%! bytecode_switch;
+%! assert (__prog_output_assert__ (key));
+
+## Test eval (dynamic stack frames)
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "3.000000 1.000000 1.000000 double 4.000000 1.000000 1.000000 double 4.000000 1.000000 1.000000 double 5.000000 4.000000 2.000000 3.000000 1.000000 1.000000 double 4.000000 1.000000 1.000000 double 4.000000 1.000000 1.000000 double 5.000000 4.000000 2.000000 1:11.000000 2:22.000000 3:33.000000 4:3.000000 5:22.000000 6:3.000000 7:3.000000 3 3 2 2 3.000000 3.000000 ";
+%!
+%! __compile bytecode_eval_1 clear;
+%! bytecode_eval_1;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_eval_1"));
+%! bytecode_eval_1;
+%! assert (__prog_output_assert__ (key));
+
+## Test evalin and assignin
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! % We want to test all combinations of compiled and uncompiled evalin_1 and 2.
+%!
+%! key = "2.000000 yoyo yobase 3.000000 yoyo2 yobase2 123.000000 124.000000 11.000000 33.000000 ";
+%!
+%! caller_a = 2;
+%!
+%!
+%! __compile bytecode_evalin_1 clear;
+%! __compile bytecode_evalin_2 clear;
+%! bytecode_evalin_1 ();
+%! assert (__prog_output_assert__ (key));
+%!
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_evalin_1"));
+%! bytecode_evalin_1 ();
+%! assert (__prog_output_assert__ (key));
+%!
+%!
+%! __compile bytecode_evalin_1 clear;
+%! __compile bytecode_evalin_2 clear;
+%! assert (__compile ("bytecode_evalin_1"));
+%! assert (__compile ("bytecode_evalin_2"));
+%! bytecode_evalin_1 ();
+%! assert (__prog_output_assert__ (key));
+%!
+%! __compile bytecode_evalin_1 clear;
+%! __compile bytecode_evalin_2 clear;
+%! assert (__compile ("bytecode_evalin_2"));
+%! bytecode_evalin_1 ();
+%! assert (__prog_output_assert__ (key));
+%!
+
+## Test error messages
+%!test
+%! ## Interpreter reference
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! __compile bytecode_errors clear;
+%! fail ("bytecode_errors (0)", ...
+%!       "'qweqwe' undefined near line 9, column 6");
+%! fail ("bytecode_errors (1)", ...
+%!       "'b' undefined near line 15, column 7");
+%! fail ("bytecode_errors (2)", ...
+%!       "'b' undefined near line 19, column 7");
+%! fail ("bytecode_errors (3)", ...
+%!       "'b' undefined near line 23, column 7");
+%! fail ("bytecode_errors (4)", ...
+%!       "'b' undefined near line 27, column 3");
+%! fail ("bytecode_errors (5)", ...
+%!       "'b' undefined near line 31, column 3");
+%! fail ("bytecode_errors (6)", ...
+%!       'a\(3\): out of bound 2 \(dimensions are 1x2\)');
+%! fail ("bytecode_errors (7)", ...
+%!       'a\(-1\): subscripts must be either integers 1 to \(2\^63\)-1 or logicals');
+%! fail ("bytecode_errors (8)", ...
+%!       'operator \+: nonconformant arguments \(op1 is 1x3, op2 is 1x2\)');
+%!
+%! __enable_vm_eval__ (1, "local");
+%! ## Bytecode running the same errors
+%! __compile bytecode_errors;
+%! fail ("bytecode_errors (0)", ...
+%!       "'qweqwe' undefined near line 9, column 6");
+%! fail ("bytecode_errors (1)", ...
+%!       "'b' undefined near line 15, column 7");
+%! fail ("bytecode_errors (2)", ...
+%!       "'b' undefined near line 19, column 7");
+%! fail ("bytecode_errors (3)", ...
+%!       "'b' undefined near line 23, column 7");
+%! fail ("bytecode_errors (4)", ...
+%!       "'b' undefined near line 27, column 3");
+%! fail ("bytecode_errors (5)", ...
+%!       "'b' undefined near line 31, column 3");
+%! fail ("bytecode_errors (6)", ...
+%!       'a\(3\): out of bound 2 \(dimensions are 1x2\)');
+%! fail ("bytecode_errors (7)", ...
+%!       'a\(-1\): subscripts must be either integers 1 to \(2\^63\)-1 or logicals');
+%! fail ("bytecode_errors (8)", ...
+%!       'operator \+: nonconformant arguments \(op1 is 1x3, op2 is 1x2\)');
+
+## Test try catch
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "yay yay2 yay3 ooo yay2 yay3 ooo2 ooo2 yay3 yay4 Nested error yay5 yay6 In catch yay7 qwe yay8 Error in subfunction yay9 'asd' undefined near line 87, column 11 yay10 operator *: nonconformant arguments (op1 is 1x2, op2 is 1x3) yay11 yoyo yay12 foo yay12 foo yay12 foo yay13 foo yay13 foo yay13 foo ";
+%!
+%! __compile bytecode_trycatch clear;
+%! bytecode_trycatch;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_trycatch"));
+%! bytecode_trycatch;
+%! assert (__prog_output_assert__ (key));
+
+## Test unwind protect
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "yay1 yay2 yay3 e1 subyyay1 subyyay2 subyyay3 subyyay4 subyyay5 subyyay6 subyyay7 subyyay8 subyyay9 subyyay10 subyyay11 subyyay12 subyyay13 subyyay14 subyyay15 subyyay16 subyyay17 subyyay18 yay4 yay5 yay6 ";
+%! __compile bytecode_unwind clear;
+%! bytecode_unwind;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_unwind"));
+%! bytecode_unwind;
+%! assert (__prog_output_assert__ (key));
+
+## Test persistant
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! clear functions  % clear persistent variables in bytecode_persistant
+%! key = "a:3 b: double 0 0 0 c:3 c:4 a:4 b:1 double 1 1 0 c:5 c:6 ";
+%!
+%! __compile bytecode_persistant clear;
+%! bytecode_persistant;
+%! bytecode_persistant;
+%! assert (__prog_output_assert__ (key));
+%!
+%! clear all;
+%! __enable_vm_eval__ (1, "local");
+%! key = "a:3 b: double 0 0 0 c:3 c:4 a:4 b:1 double 1 1 0 c:5 c:6 ";
+%! assert (__compile ("bytecode_persistant"));
+%! bytecode_persistant;
+%!
+%! bytecode_persistant;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (0, "local");
+%! __compile bytecode_persistant clear;
+%! clear all;
+%! key = "a:3 b: double 0 0 0 c:3 c:4 a:4 b:1 double 1 1 0 c:5 c:6 ";
+%! bytecode_persistant;
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_persistant"));
+%!
+%! bytecode_persistant;
+%! assert (__prog_output_assert__ (key));
+
+## Test structs
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 2 double 1 1 struct 3 4 ";
+%! __compile bytecode_struct clear;
+%! bytecode_struct;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_struct"));
+%! bytecode_struct;
+%! assert (__prog_output_assert__ (key));
+
+## Test indexing chained objects and strange indexing
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 2 3 3 2 cell 1 1 3 3 2 3 22 double 33 3 4 matlab.lang.MemoizedFunction 2 ";
+%! __compile bytecode_index_obj clear;
+%! bytecode_index_obj;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_index_obj"));
+%! bytecode_index_obj;
+%! assert (__prog_output_assert__ (key));
+
+## Test varargout
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "7 8 1 1 2 1 0 0 0 1 0 1 0 0 0 1 0 ";
+%! __compile bytecode_varargout clear;
+%! bytecode_varargout;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_varargout"));
+%! bytecode_varargout;
+%! assert (__prog_output_assert__ (key));
+
+## Test inputname
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "a a b + 1  a a b b aa aa bb bb aa + 1  bb * 3  a + 1  b * 3  aa aa bb bb aa + 1  bb * 3  a a b b a + 1  b * 3  ";
+%! __compile bytecode_inputname clear;
+%! a = 9; b = 8;
+%! bytecode_inputname (a, b + 1);
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_inputname"));
+%! bytecode_inputname (a, b + 1);
+%! assert (__prog_output_assert__ (key));
+
+## Test ans
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "2 5 1 1 1 ";
+%! __compile bytecode_ans clear;
+%! bytecode_ans;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_ans"));
+%! bytecode_ans;
+%! assert (__prog_output_assert__ (key));
+
+## Test using classdef
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! global cdef_foo_ctor_cnt; clear global cdef_foo_ctor_cnt;
+%! global cdef_foo_dtor_cnt; clear global cdef_foo_dtor_cnt;
+%! key = ". 1 f1 . 2 f3 3 f2 . sumf2f3 2 . . call14 f4 . a a_1 . 5 f8 . 6 f10 7 f9 . sumf9f10 2 . . call18 f11 . 2 2 3 4 4 4 3 2 2 3 . 9 sumf9f10 10 f12 11 f13 12 f14 13 sumf2f3 14 f5 15 f6 16 f7 ";
+%! __compile bytecode_cdef_use clear;
+%! bytecode_cdef_use ();
+%! assert (__prog_output_assert__ (key));
+%! global cdef_foo_ctor_cnt; global cdef_foo_dtor_cnt;
+%! assert (cdef_foo_ctor_cnt == cdef_foo_dtor_cnt); % Check, as many ctor and dtor executions
+%!
+%! __enable_vm_eval__ (1, "local");
+%! global cdef_foo_ctor_cnt; clear global cdef_foo_ctor_cnt;
+%! global cdef_foo_dtor_cnt; clear global cdef_foo_dtor_cnt;
+%! assert (__compile ("bytecode_cdef_use"));
+%! bytecode_cdef_use ();
+%! assert (__prog_output_assert__ (key));
+%! global cdef_foo_ctor_cnt; global cdef_foo_dtor_cnt;
+%! assert (cdef_foo_ctor_cnt == cdef_foo_dtor_cnt);
+%!
+%! global cdef_foo_ctor_cnt; clear global cdef_foo_ctor_cnt;
+%! global cdef_foo_dtor_cnt; clear global cdef_foo_dtor_cnt;
+%!
+%! clear global __assert_printf__
+
+## Test anonymous function handles
+%!test
+%! __enable_vm_eval__ (0, "local");
+%! clear all
+%! key = "1 2 12 3 4 1 2 3 1 2 11 12 1 ";
+%! __compile bytecode_anon_handles clear;
+%! bytecode_anon_handles;
+%! assert (__prog_output_assert__ (key));
+%!
+%! __enable_vm_eval__ (1, "local");
+%! assert (__compile ("bytecode_anon_handles"));
+%! bytecode_anon_handles;
+%! assert (__prog_output_assert__ (key));
+
+## Test compling a function named differently from its
+## m-file
+%!test
+%! clear all
+%! __enable_vm_eval__ (1, "local");
+%! __compile wrongname_fn clear;
+%! assert (__compile ("wrongname_fn"));
+%!
+%! assert (wrongname_fn (77) == 78);
+
+## Test some misc stuff
+%!test
+%! clear all
+%! __enable_vm_eval__ (1, "local");
+%!
+%! bytecode_misc; % asserts inernally
+
+## Leak check
+%!test
+%! clear all
+%! __enable_vm_eval__ (1, "local");
+%!
+%! c = 2;
+%! d = 3;
+%! n_c = __ref_count (c);
+%! n_d = __ref_count (d);
+%! bytecode_leaks (c, d); % asserts inernally
+%!
+%! assert (n_c == __ref_count (c))
+%! assert (n_d == __ref_count (d))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_anon_handles.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,27 @@
+function bytecode_anon_handles ()
+  h1 = @(x) __printf_assert__ ("%d ", x);
+  h1 (1);
+  h1 (2);
+  h11 = h1;
+  h11 (12);
+
+  a = 3;
+  h2 = @() __printf_assert__ ("%d ", a);
+  h2 ();
+
+  h3 = @(a,b,c) a + b + c;
+  __printf_assert__ ("%d ", h3 (1, 2, 1));
+
+  h4 = @() {1,2,3}{:};
+  [a b c] = h4();
+  __printf_assert__ ("%d %d %d ", a, b, c);
+  [a b] = h4();
+  __printf_assert__ ("%d %d ", a, b);
+
+  h5 = @(x) @(y) __printf_assert__ ("%d %d ", x, y);
+  h5(11)(12)
+
+  % max not in parent scope
+  h6 = @(x, y) max (x, y);
+  __printf_assert__ ("%d ", h6 (-1, 1));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_ans.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,13 @@
+function bytecode_ans ()
+    max (1, 2);
+    __printf_assert__ ("%d ", ans);
+    1 + 1 + 3;
+    __printf_assert__ ("%d ", ans);
+    !false;
+    __printf_assert__ ("%d ", ans);
+    true;
+    __printf_assert__ ("%d ", ans);
+
+    c = 13; % Not written to ans
+    __printf_assert__ ("%d ", ans);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_assign.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,57 @@
+function bytecode_assign ()
+
+  a = 2;
+  __printf_assert__ ("%d ", a);
+
+  a = 3;
+  __printf_assert__ ("%d ", a);
+
+  b = a = 1;
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  c = [2 2; 3 3];
+  d = c (1,2);
+  __printf_assert__ ("%d ", c);
+  __printf_assert__ ("%d ", d);
+
+  % Compound assignment
+  d = 1;
+  d += 1;
+  __printf_assert__ ("%d ", d);
+  d += d * 2;
+  __printf_assert__ ("%d ", d);
+  d *= 3;
+  __printf_assert__ ("%d ", d);
+  d /= 9;
+  __printf_assert__ ("%f ", d);
+
+  b = [1 2 3 4];
+  b += 1;
+  __printf_assert__ ("%f ", b);
+  __printf_assert__ ("%d ", size(b));
+  __printf_assert__ ("%s ", class(b));
+  b \= 2;
+  b -= 2;
+  b *= 2;
+  b /= 2;
+  b += 2;
+
+  b .\= 2;
+  %b .-= 2; % TODO: Removed in interpreter. Remove in VM too.
+  b .*= 2;
+  b ./= 2;
+  %b .+= 2; % TODO: Removed in interpreter. Remove in VM too.
+  b .^= 2;
+
+  __printf_assert__ ("%f ", b);
+  __printf_assert__ ("%d ", size(b));
+  __printf_assert__ ("%s ", class(b));
+
+  b = [1 2; 3 4];
+  b ^= 3;
+
+  __printf_assert__ ("%f ", b);
+  __printf_assert__ ("%d ", size(b));
+  __printf_assert__ ("%s ", class(b));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_binops.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,117 @@
+function bytecode_binops()
+  % Root level binary expressions8
+  % should not mess up the operand stack
+  2 * 3 + 1;
+  max (3, 2) - min (3, 2);
+  sin (3) * sin (2);
+
+  % General
+  a = 1 + 2 + 3 + 4;
+  __printf_assert__ ("%.17g ", a);
+  a = -1 - 2 - 3 - 4;
+  __printf_assert__ ("%.17g ", a);
+  a = 1 * 2 * 3 * 4;
+  __printf_assert__ ("%.17g ", a);
+  a = 1 / 2 / 3 / 4;
+  __printf_assert__ ("%.17g ", a);
+  a = 1^2^3^4;
+  __printf_assert__ ("%.17g ", a);
+
+  % Order
+  a = 1 + 2 - 3 * 4 / 5 ^ 6 * 7 / 8 - 9 + 10 / 11;
+  __printf_assert__ ("%.17g ", a);
+
+  % Function calls
+  a = max (3, 2) * min (2, 1) + max (10, 9);
+  __printf_assert__ ("%.17g ", a);
+
+  % Logical
+  a = 1 && 2;
+  __printf_assert__ ("%d ", a);
+  a = 1 && 0;
+  __printf_assert__ ("%d ", a);
+  a = 1 || 2;
+  __printf_assert__ ("%d ", a);
+  a = 0 || 0;
+  __printf_assert__ ("%d ", a);
+
+  % Need to not linger on stack
+  1 && 1;
+  1 && 0;
+  0 && 1;
+  0 || 0;
+  0 || 1;
+  1 || 0;
+
+  % We wanna make sure there actually is a short circuit
+  % and that the operands are only evaluated once
+  a = truthy (1) || falsy(2);
+  __printf_assert__ ("%d ", a);
+
+  a = falsy (3) || falsy (4) || truthy (5) || falsy (6);
+  __printf_assert__ ("%d ", a);
+
+  a = truthy (7) && truthy (8) || falsy (12);
+  __printf_assert__ ("%d ", a);
+
+  a = falsy (9) && truthy (10) || falsy (11);
+  __printf_assert__ ("%d ", a);
+
+  % Compares
+
+  a = 1 == 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 == 2;
+  __printf_assert__ ("%d ", a);
+  a = 1 < 2;
+  __printf_assert__ ("%d ", a);
+  a = 2 < 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 > 2;
+  __printf_assert__ ("%d ", a);
+  a = 2 > 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 <= 2;
+  __printf_assert__ ("%d ", a);
+  a = 2 <= 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 <= 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 >= 2;
+  __printf_assert__ ("%d ", a);
+  a = 2 >= 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 >= 1;
+  __printf_assert__ ("%d ", a);
+  a = 2 ~= 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 ~= 1;
+  __printf_assert__ ("%d ", a);
+  a = 2 != 1;
+  __printf_assert__ ("%d ", a);
+  a = 1 != 1;
+  __printf_assert__ ("%d ", a);
+
+  a = 1 == 1 && 2 > 1 && 3 > -3 || 1 < 10;
+  __printf_assert__ ("%d ", a);
+
+  % Elementwise logical
+
+  a = ones (2,2) & zeros (2,2);
+  __printf_assert__ ("%d ", a);
+  a = ones (2,2) & ones (2,2);
+  __printf_assert__ ("%d ", a);
+  a = ones (2,2) | zeros (2,2);
+  __printf_assert__ ("%d ", a);
+
+endfunction
+
+function out = truthy (i)
+  __printf_assert__ ("truthy%d ", i);
+  out = 1;
+end
+
+function out = falsy (i)
+  __printf_assert__ ("falsy%d ", i);
+  out = 0;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_cdef_use.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,82 @@
+function bytecode_cdef_use ()
+  % The classdef handle class cdef_foo prints its ctor argument
+  % in the dtor with __printf_assert__ aswell asd
+  % adds one to the globals cdef_foo_ctor_cnt and cdef_foo_dtor_cnt
+  % in the ctor and dtor.
+
+  h1 = cdef_foo("f1");
+  __printf_assert__ (". ");
+  h1 = 2; % Triggers dtor
+  __printf_assert__ (". ");
+
+  h4 = make_obj ("f2") + make_obj ("f3"); % Two dtors will trigger here
+  __printf_assert__ (". ");
+  __printf_assert__ ("%s %d ", h4.msg, h4.val);
+
+  __printf_assert__ (". ");
+  make_obj ("f4");          % Saved in ans
+  __printf_assert__ (". "); % Wont trigger dtor since no defined return value
+  print_arg_ret_one ("call1"); % ans' dtor executed after rhs eval
+  __printf_assert__ (". ");
+
+  % Test calling function in packages. Not really a classdef
+  u = matlab.lang.makeUniqueStrings ({"a","a"});
+  __printf_assert__ ("%s %s ", u{1}, u{2});
+
+  % Check dtor call order
+  a = make_obj ("f5");
+  b = make_obj ("f6");
+  c = make_obj ("f7");
+
+  suby (); % Same tests in a subfunction
+end
+
+function suby ()
+  h1 = cdef_foo("f8");
+  __printf_assert__ (". ");
+  h1 = 2; % Triggers dtor
+  __printf_assert__ (". ");
+
+  h4 = make_obj ("f9") + make_obj ("f10"); % Two dtors will trigger here
+  __printf_assert__ (". ");
+  __printf_assert__ ("%s %d ", h4.msg, h4.val);
+
+  __printf_assert__ (". ");
+  make_obj ("f11");          % Saved in ans
+  __printf_assert__ (". "); % Wont trigger dtor since no defined return value
+  print_arg_ret_one ("call1"); % ans' dtor executed after rhs eval
+  __printf_assert__ (". ");
+
+  % Check that the classdef object is called
+  m = containers.Map;
+  m("qwe") = 2;
+  __printf_assert__ ("%d ", m("qwe"));
+  __printf_assert__ ("%d ", m("qwe")++); % Test ++-- on objects
+  __printf_assert__ ("%d ", m("qwe"));
+  __printf_assert__ ("%d ", ++m("qwe"));
+  __printf_assert__ ("%d ", m("qwe"));
+  __printf_assert__ ("%d ", m("qwe")--);
+  __printf_assert__ ("%d ", m("qwe"));
+  __printf_assert__ ("%d ", --m("qwe"));
+  __printf_assert__ ("%d ", m("qwe"));
+  % Different op code than cmd form call
+  m = containers.Map();
+  m("qwe") = 3;
+  __printf_assert__ ("%d ", m("qwe"));
+
+  __printf_assert__ (". ");
+  % Check dtor call order
+  a = make_obj ("f12");
+  b = make_obj ("f13");
+  c = make_obj ("f14");
+end
+
+
+function h = make_obj (msg)
+    h = cdef_foo (msg);
+end
+
+function a = print_arg_ret_one (msg)
+  __printf_assert__ (msg);
+  a = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_cell.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,65 @@
+function bytecode_cell ()
+  a = {'a','b'};
+  __printf_assert__ ("%s ", a{1});
+  __printf_assert__ ("%s ", a{2});
+  __printf_assert__ ("%s ", a{:});
+  __printf_assert__ ("%d ", size (a));
+
+  b = 'b';
+  c = 'c';
+
+  a = {b, c};
+  __printf_assert__ ("%s ", a{1});
+  __printf_assert__ ("%s ", a{2});
+  __printf_assert__ ("%s ", a{:});
+  __printf_assert__ ("%d ", size (a));
+  __printf_assert__ ("%s ", class (a{1}));
+
+  d = 'd';
+  e = 'e';
+
+  a = {b, c; d, e};
+  __printf_assert__ ("%s ", a{1});
+  __printf_assert__ ("%s ", a{3});
+  __printf_assert__ ("%s ", a{1,2});
+  __printf_assert__ ("%s ", a{2,1});
+  __printf_assert__ ("%s ", a{:});
+  __printf_assert__ ("%d ", size (a));
+
+  f = 'f';
+  g = 'g';
+  h = 'h';
+  i = 'i';
+  a = {b, c; d, e; f g; h, i; 'j', 'k'; 'l', 'm'};
+  __printf_assert__ ("%s ", a{:});
+  __printf_assert__ ("%d ", size (a));
+
+  b = 1;
+  c = 2;
+  d = 3;
+  e = 4;
+  a = {b, c; d, e};
+  __printf_assert__ ("%d ", a{1});
+  __printf_assert__ ("%d ", a{3});
+  __printf_assert__ ("%d ", a{1,2});
+  __printf_assert__ ("%d ", a{2,1});
+  __printf_assert__ ("%d ", a{:});
+  __printf_assert__ ("%d ", a{:, 1});
+  __printf_assert__ ("%d ", a{1, :});
+  __printf_assert__ ("%d ", a{:, :});
+  __printf_assert__ ("%d ", size (a));
+  __printf_assert__ ("%s ", class (a{1}));
+
+  a = {'qwe','asd','zxc'};
+  f = a{:};
+  __printf_assert__ ("%s ", f);
+  __printf_assert__ ("%d ", size (f));
+  __printf_assert__ ("%s ", class (f));
+
+  % Command form function call subref
+  __printf_assert__ ("%d ", suby{:});
+end
+
+function a = suby()
+  a = {1,2};
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_dountil.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,115 @@
+function bytecode_dountil ()
+  i = 5;
+  do
+    __printf_assert__ ("%d ", i);
+    i--;
+  until i
+
+  i = 0;
+  do
+    i++;
+  until i >= 3
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  do
+    ctr++;
+  until i++ >= 4
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  ctr = 0;
+  do
+    ctr++;
+  until ++i >= 4
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  ctr = 0;
+  do
+    i++;
+    if i == 2
+      continue
+    end
+    ctr++;
+  until i >= 4
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  do
+    i++;
+    if i == 2
+      break
+    end
+    ctr++;
+  until i >= 4
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  do
+    i++;
+    if i == 2
+      continue
+    elseif i == 3
+      break
+    end
+    ctr++;
+  until i >= 4
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  do
+    i++;
+    if i == 1
+      continue
+    else
+      break
+    end
+  until i > 100
+  __printf_assert__ ("%d ", i);
+
+  ctr = 0;
+  j = 0;
+  do
+    i = 0;
+    do
+      k = 0;
+      do
+        k++;
+        ctr++;
+      until k >= 2
+      i++;
+    until i > 2
+    j++;
+  until j >= 2
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  do
+    i++;
+    if i == 4
+      break;
+    end
+    continue;
+  until i == 3
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  do
+    break
+  until i++ > 2
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  do
+  until i++ == 2
+  __printf_assert__ ("%d ", i);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_end.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,58 @@
+function bytecode_end ()
+
+  A = [1 2; 3 4];
+  __printf_assert__ ("%d ", A(1:end));
+
+  A(2:end) = [5 6 7];
+  __printf_assert__ ("%d ", A);
+  __printf_assert__ ("%d ", size (A));
+
+  A = [1 2; 3 4];
+  A(end, end) = 5;
+  __printf_assert__ ("%d ", A(2, 2));
+  __printf_assert__ ("%d ", A(end, end));
+
+  A = [1 2; 3 4];
+  A(end - 1, end - 1) = 6;
+  __printf_assert__ ("%d ", A(1, 1));
+  __printf_assert__ ("%d ", A(end - 1, end - 1));
+
+  A = [1:4];
+  A(end + 1) = 5;
+  __printf_assert__ ("%d ", A);
+
+  A = 1;
+  A(end) = 2;
+  __printf_assert__ ("%d ", A);
+  __printf_assert__ ("%d ", A(end));
+
+  A(end + 1) = 3;
+  __printf_assert__ ("%d ", A);
+  __printf_assert__ ("%d ", A(end));
+
+  __printf_assert__ ("%d ", suby1()(end));
+
+  % End indexing an object that is not an id
+  s = {"ifs"};
+  a = s{1}(2:end);
+  __printf_assert__ ("%s ", a);
+
+  % Nested index expressions
+  M = [1 2 3 4];
+  __printf_assert__ ("%d ", M (min (2, end))); % End of M
+  __printf_assert__ ("%d ", M (max (3, min (2, end)))); % End of M
+
+  min_h = @min;
+  __printf_assert__ ("%d ", M (min_h (2, end))); % End of min_h
+
+  s = [struct struct struct];
+  s(2).name = "foo";
+  __printf_assert__ ("%s ", s(min (2, end)).name);
+
+  % end together with struct refs are annoying
+  __printf_assert__ ("%s ", s(2).name (end - 1: end));
+end
+
+function a = suby1()
+  a = [1 2 3 4];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_errors.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,68 @@
+function bytecode_errors (idx)
+  % We put test dispatch last, so that we don't have
+  % to update all columns and rows each time we
+  % add a test ...
+  run_test (idx);
+end
+
+function if_undefined_value ()
+  if qweqwe
+    a = 2;
+  end
+end
+
+function assign_undef ()
+  a = b;
+end
+
+function subsref_undef_id ()
+  a = b(1,2,3);
+end
+
+function subsref_cell_undef_id ()
+  a = b{1,2,3};
+end
+
+function wordcmd_undef_id ()
+  b 1 2 3;
+end
+
+function binary_undef ()
+  b * a;
+end
+
+function id_index_oob_error_1 ()
+  a = [1, 2];
+  b = a (3);
+end
+
+function id_index_oob_error_2 ()
+  a = [1, 2];
+  b = a (-1);
+end
+
+function binary_wrong_size_1 ()
+  a = [1 2 3] + [1 2];
+end
+
+function run_test (idx)
+  if idx == 0
+    if_undefined_value ();
+  elseif idx == 1
+    assign_undef ();
+  elseif idx == 2
+    subsref_undef_id ();
+  elseif idx == 3
+    subsref_cell_undef_id ();
+  elseif idx == 4
+    wordcmd_undef_id ();
+  elseif idx == 5
+    binary_undef ();
+  elseif idx == 6
+    id_index_oob_error_1 ();
+  elseif idx == 7
+    id_index_oob_error_2 ();
+  elseif idx == 8
+    binary_wrong_size_1 ();
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_eval_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,126 @@
+function bytecode_eval_1 ()
+  % Simple
+  assert (2 == eval ("2"));
+  assert (2 == eval ("2;"));
+
+  v = eval("11");
+  assert (v == 11);
+
+  % ans
+  eval ("12;");
+  assert (ans == 12);
+
+  % Change variable value
+  a = 2;
+  eval ("a = 3;");
+
+  __printf_assert__ ("%f ", a)
+  __printf_assert__ ("%f ", size (a))
+  __printf_assert__ ("%s ", class (a));
+
+  % Create new variable in an eval
+  eval ("b = 4;");
+  __printf_assert__ ("%f ", b)
+  __printf_assert__ ("%f ", size (b))
+  __printf_assert__ ("%s ", class (b));
+
+  % Create new variable in an eval, that is also not
+  % not in a bytecode slot
+  eval ("c = 4;");
+  __printf_assert__ ("%f ", eval("c"))
+  __printf_assert__ ("%f ", size (eval("c")))
+  __printf_assert__ ("%s ", class (eval("c")));
+  eval ("c = 5;");
+  __printf_assert__ ("%f ", eval("c"))
+
+  % Change a global in an eval
+  clear global d
+  global d = 3;
+  eval ("d = 4;")
+  __printf_assert__ ("%f ", d);
+  clear global d
+  d = 2;
+  __printf_assert__ ("%f ", d);
+
+  % Create a global in an eval
+
+  %% TODO: Not supported. Does it have to be?
+  % eval ("clear global e");
+  % eval ("global e = 5;")
+  % __printf_assert__ ("%f ", e);
+  % __printf_assert__ ("%d ", length(who('global','e')));
+
+  % Just test the same thing in a subfunction
+  sub1 ();
+
+  % Change the value of arguments and returns in an eval
+  % Also do nargin and nargout in a subfunction
+  [aa bb] = suby2 (11, 22, 33);
+  __printf_assert__ ("%f ", aa);
+  __printf_assert__ ("%f ", bb);
+end
+
+function sub1()
+  % Simple
+  assert (2 == eval ("2;"));
+  assert (2 == eval ("2;"));
+
+  v = eval("11;");
+  assert (v == 11);
+
+  % ans
+  eval ("12;");
+  assert (ans == 12);
+
+  % Change variable value
+  a = 2;
+  eval ("a = 3;");
+
+  __printf_assert__ ("%f ", a)
+  __printf_assert__ ("%f ", size (a))
+  __printf_assert__ ("%s ", class (a));
+
+  % Create new variable in an eval
+  eval ("b = 4;");
+  __printf_assert__ ("%f ", b)
+  __printf_assert__ ("%f ", size (b))
+  __printf_assert__ ("%s ", class (b));
+
+  % Create new variable in an eval, that is also not
+  % not in a bytecode slot
+  eval ("c = 4;");
+  __printf_assert__ ("%f ", eval("c"))
+  __printf_assert__ ("%f ", size (eval("c")))
+  __printf_assert__ ("%s ", class (eval("c")));
+  eval ("c = 5;");
+  __printf_assert__ ("%f ", eval("c"))
+
+  % Change a global in an eval
+  clear global d
+  global d = 3;
+  eval ("d = 4;")
+  __printf_assert__ ("%f ", d);
+  clear global d
+  d = 2;
+  __printf_assert__ ("%f ", d);
+end
+
+function [c d] = suby2 (a, b, c)
+  __printf_assert__ ("1:%f ", a);
+  __printf_assert__ ("2:%f ", b);
+  __printf_assert__ ("3:%f ", c);
+
+  eval ("c = 3;")
+  eval ("a = c;")
+  eval ("d = a;")
+  __printf_assert__ ("4:%f ", a);
+  __printf_assert__ ("5:%f ", b);
+  __printf_assert__ ("6:%f ", c);
+  __printf_assert__ ("7:%f ", d);
+
+  __printf_assert__ ("%d ", nargin);
+  __printf_assert__ ("%d ", eval ("nargin"));
+
+  __printf_assert__ ("%d ", nargout);
+  __printf_assert__ ("%d ", eval ("nargout"));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_evalin_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,35 @@
+function bytecode_evalin_1 ()
+  b = evalin ("caller", "caller_a");
+  __printf_assert__ ("%f ", b);
+
+  evalin ("caller", "__printf_assert__('yoyo ')");
+
+  evalin ("base", "__printf_assert__('yobase ')");
+
+  caller_b = 3;
+  sub1();
+  __printf_assert__ ("%f ", caller_e);
+  __printf_assert__ ("%f ", eval ("caller_f")); % No slot for caller_f
+
+  caller_c = 11;
+  bytecode_evalin_2 ();
+  __printf_assert__ ("%f ", caller_c); % Changes to 33
+
+  %%% TODO: Can't create a variable with evalin in the treewalker
+  %%%       need to verify it aint working with the VM too.
+  %% __printf_assert__ ("%f ", caller_d); % Is initialized to 22
+
+
+end
+
+function sub1()
+  b = evalin ("caller", "caller_b");
+  __printf_assert__ ("%f ", b);
+
+  evalin ("caller", "__printf_assert__('yoyo2 ')");
+
+  evalin ("base", "__printf_assert__('yobase2 ')");
+
+  assignin ("caller", "caller_e", 123);
+  assignin ("caller", "caller_f", 124);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_evalin_2.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,8 @@
+function bytecode_evalin_2 ()
+  __printf_assert__ ("%f ", evalin ("caller", "caller_c"));
+
+  evalin ("caller", "caller_c = 33;");
+
+  %% %Can't create local in caller in the treewalker
+  %% evalin ("caller", "caller_d = 22;");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_for.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,188 @@
+function bytecode_for()
+  ctr = 0;
+
+  for i = 1:4
+    __printf_assert__ ("%d ", i);
+  end
+  __printf_assert__ ("%d ", i);
+
+  for i = 1:2:5
+    __printf_assert__ ("%d ", i);
+  end
+  __printf_assert__ ("%d ", i);
+
+  for i = 4:-1:1
+    __printf_assert__ ("%d ", i);
+  end
+  __printf_assert__ ("%d ", i);
+
+  for j = 1:4
+    break
+  end
+  __printf_assert__ ("%d ", j);
+
+  for j = 1:4
+    continue
+  end
+  __printf_assert__ ("%d ", j);
+
+  for j = 1:4
+    if j == 2
+      break
+    end
+  end
+  __printf_assert__ ("%d ", j);
+
+  for j = 1:4
+    if j == 2
+      break
+    else
+      continue
+    end
+  end
+  __printf_assert__ ("%d ", j);
+
+  ctr = 0;
+  for i = 1:4
+    for j = 1:4
+      ctr++;
+    end
+  end
+  __printf_assert__ ("%d ", ctr);
+
+  ctr = 0;
+  for i = 1:4
+    if i == 2
+      continue
+    end
+
+    for j = 1:4
+      if j == 2
+        continue
+      end
+
+      ctr++;
+
+      if j == 3
+        break
+      end
+    end
+
+    if i == 3
+      break
+    end
+  end
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%d ", j);
+
+  ctr = 0;
+  for i = 1:2
+    for j = 1:2
+      for k = 1:2
+        for l = 1:2
+          for m = 1:2
+            for n = 1:2
+              for o = 1:2
+                for p = 1:2
+                  ctr++;
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+  end
+  __printf_assert__ ("%d ", ctr);
+
+  for i = 1:3
+  end
+  __printf_assert__ ("%d ", i);
+
+  % sclar range, only executed once
+  for i = 2
+    __printf_assert__ ("%d ", i);
+  end
+
+  n = 1;
+  for i = 1:n
+    __printf_assert__ ("%d ", i);
+  end
+
+  n = 1;
+  for i = 2:n
+    __printf_assert__ ("boo");
+  end
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%s ", class (i));
+
+  %Matrix
+  M = [1 2; 3 4];
+  for i = M
+    __printf_assert__ ("%d ", i);
+    __printf_assert__ ("size %d ", size (i));
+  end
+
+  for i = []
+    __printf_assert__ ("boo");
+  end
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%s ", class (i));
+
+
+  n = 'qwe';
+  for i = n
+    __printf_assert__ ("%s ", i);
+    __printf_assert__ ("size %d ", size (i));
+  end
+  __printf_assert__ ("%s ", class (i));
+
+  % The iteration variable is a double
+  % ??? Changed in someones patch? TODO: Bug?
+  for i = single(1):single(3)
+    if i == 1
+      __printf_assert__ ("%s ", class (i));
+    end
+  end
+
+  % ... unless rhs is a scalar ...
+  for i = single (1)
+  end
+  __printf_assert__ ("%s ", class (i));
+
+  % Test return from for loop (need to pop native integers from stack)
+  __printf_assert__ ("%d ", foo ());
+
+  % Iterate over struct
+  for s = struct ("a", {"1", "2"}, "b", {"11", "12"})
+    __printf_assert__ ("%s %s ", s.a, s.b);
+  end
+
+  % Complex for loop
+
+  x.a = 1;
+  x.b = [1, 2; 3, 4];
+  x.c = "string";
+  for [val, key] = x
+    __printf_assert__ ("key:%s ", key)
+    if isa(val, "char")
+      __printf_assert__ ("val:%s ", val)
+    else
+      __printf_assert__ ("val:%d %d", val, size(val))
+    end
+  endfor
+
+  for [val, key] = struct ()
+    __printf_assert__ ("boo");
+  end
+end
+
+
+function i = foo ()
+  for i = 1:10
+    if i == 5
+      return
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_global_1.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,201 @@
+% TODO: When clear and dynamic stack works, test
+% that behavoiur is the same when clearing globals
+% in another function while they are on the stack in the
+% caller.
+
+function bytecode_global_1 ()
+  % General test. a and b are also read and verified in test .tst file
+  global a b
+  __printf_assert__ ("%s ", class (a));
+  __printf_assert__ ("%d ", size (a));
+
+  __printf_assert__ ("%d ", length (who ('global','a')));
+  __printf_assert__ ("%d ", length (who ('global','b')));
+  __printf_assert__ ("%d ", isglobal ('a'));
+  __printf_assert__ ("%d ", isglobal ('b'));
+
+  a = 1;
+  __printf_assert__ ("%d ", a);
+  b = 2;
+  __printf_assert__ ("%d ", b);
+
+  a = b;
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+  b = 100;
+  a = 3 * b + max (a, b);
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  % Test that we can make globals in subfunctions
+  global e %sub1 needs a global "e"
+  e = 11;
+  sub1 (1);
+
+  __printf_assert__ ("%d ", isglobal ('a'));
+  __printf_assert__ ("%d ", isglobal ('b'));
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  sub1 (0);
+
+  __printf_assert__ ("%d ", isglobal ('a'));
+  __printf_assert__ ("%d ", isglobal ('b'));
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  % Declare global, clear it, use identifier as local, declare
+  % it as global ...
+  global c
+  __printf_assert__ ("%d ", length (who ('global','c')));
+  clear global c;
+  __printf_assert__ ("%d ", length (who ('global','c')));
+
+  c = 2;
+  __printf_assert__ ("%d ", c);
+  __printf_assert__ ("%s ", class(c));
+
+  global c
+  __printf_assert__ ("%d ", c);
+  __printf_assert__ ("%s ", class(c));
+
+  % Subassign
+  global f
+  f = [1 2 3 4 5];
+  f(3) = 6;
+  f(1) = 11;
+  __printf_assert__ ("%d ", f);
+  __printf_assert__ ("%s ", class(f));
+  __printf_assert__ ("%d ", size (f));
+
+  % Multiassign
+  global g h
+  [g h f] = returns3 ();
+  __printf_assert__ ("%d ", g);
+  __printf_assert__ ("%s ", class(g));
+  __printf_assert__ ("%d ", size (g));
+  __printf_assert__ ("%d ", h);
+  __printf_assert__ ("%s ", class(h));
+  __printf_assert__ ("%d ", size (h));
+  __printf_assert__ ("%d ", f);
+  __printf_assert__ ("%s ", class(f));
+  __printf_assert__ ("%d ", size (f));
+
+  % Init expression
+  global k = 3;
+  __printf_assert__ ("%d ", k);
+  __printf_assert__ ("%s ", class(k));
+  __printf_assert__ ("%d ", size (k));
+
+  global l = 4 m = max (10,9) n = [2,3] o = k;
+  __printf_assert__ ("%d ", l);
+  __printf_assert__ ("%s ", class(l));
+  __printf_assert__ ("%d ", size (l));
+  __printf_assert__ ("%d ", m);
+  __printf_assert__ ("%s ", class(m));
+  __printf_assert__ ("%d ", size (m));
+  __printf_assert__ ("%d ", n);
+  __printf_assert__ ("%s ", class(n));
+  __printf_assert__ ("%d ", size (n));
+  __printf_assert__ ("%d ", o);
+  __printf_assert__ ("%s ", class(o));
+  __printf_assert__ ("%d ", size (o));
+
+  % Init expression for existing local
+  p = 2;
+  global p = 3;
+  __printf_assert__ ("%d ", p);
+  __printf_assert__ ("%s ", class(p));
+  __printf_assert__ ("%d ", size (p));
+  % q created in caller already
+  global q = 4;
+  __printf_assert__ ("%d ", q);
+  __printf_assert__ ("%s ", class(q));
+  __printf_assert__ ("%d ", size (q));
+
+  % Reinit does nothing
+  global r = 7
+  global r = 8
+  __printf_assert__ ("%d ", r);
+  __printf_assert__ ("%s ", class(r));
+  __printf_assert__ ("%d ", size (r));
+
+  clear global c
+  __printf_assert__ ("%d ", length (who ('global','c')));
+
+  clear global d
+  clear global e
+  clear global f
+  clear global g
+  clear global h
+  clear global k
+  clear global l
+  clear global m
+  clear global n
+  clear global o
+  clear global p
+  clear global r
+end
+
+function [q w e] = returns3()
+  q = 11;
+  w = 22;
+  e = 33;
+end
+
+
+function sub1(make_global)
+  % Already defined local, later declared global
+  d = 3;
+  __printf_assert__ ("%d ", length(who('global','d')));
+  global d
+  __printf_assert__ ("%d ", length(who('global','d')));
+  __printf_assert__ ("%d ", d);
+  __printf_assert__ ("%s ", class(d));
+  __printf_assert__ ("%d ", size (d));
+  d = [1 2];
+  __printf_assert__ ("%d ", d);
+  __printf_assert__ ("%s ", class(d));
+  __printf_assert__ ("%d ", size (d));
+
+  % Already defined local, later declared global,
+  % but with the global already with a value from the caller
+  e = 4;
+  __printf_assert__ ("%d ", length(who('global','e')));
+  global e
+  __printf_assert__ ("%d ", length(who('global','e')));
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("eclass:%s ", class(e));
+  __printf_assert__ ("%d ", size (e));
+  e = [3 4];
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("%s ", class(e));
+  __printf_assert__ ("%d ", size (e));
+
+
+  % Conditionally global a and b
+  if make_global
+    global a
+    global b
+
+    __printf_assert__ ("%d ", a);
+    __printf_assert__ ("%d ", b);
+  end
+
+  __printf_assert__ ("%d ", isglobal ('a'));
+  __printf_assert__ ("%d ", isglobal ('b'));
+  __printf_assert__ ("%d ", length(who('global','a')));
+  __printf_assert__ ("%d ", length(who('global','b')));
+
+  a = 3;
+  b = 4;
+
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  if make_global
+    a = 5;
+    b = 6;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_if.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,142 @@
+function bytecode_if()
+  ctr = 0;
+  a = 1;
+  b = 0;
+
+  if a
+    __printf_assert__ ("%d ", ctr++);
+  end
+
+  if a
+    __printf_assert__ ("%d ", ctr++);
+  else
+    __printf_assert__ ("booo ");
+  end
+
+  if a
+    __printf_assert__ ("%d ", ctr++);
+  elseif a
+    __printf_assert__ ("booo ");
+  else
+    __printf_assert__ ("booo ");
+  end
+
+  if b
+    __printf_assert__ ("booo ", ctr++);
+  end
+
+  if b
+    __printf_assert__ ("booo ");
+  else
+    __printf_assert__ ("%d ", ctr++);
+  end
+
+  if b
+    __printf_assert__ ("booo ");
+  elseif b
+    __printf_assert__ ("booo ");
+  else
+    __printf_assert__ ("%d ", ctr++);
+  end
+
+  if b
+    __printf_assert__ ("booo ");
+  elseif a
+    __printf_assert__ ("%d ", ctr++);
+  else
+    __printf_assert__ ("booo ");
+  end
+
+  if a
+    if a
+      if a
+        if a
+          if a
+            if b
+              __printf_assert__ ("booo ");
+            else
+              if a
+                if a
+                  if b
+                    __printf_assert__ ("booo ");
+                  elseif a
+                    if b
+                      __printf_assert__ ("booo ");
+                    else
+                      __printf_assert__ ("%d ", ctr++);
+                    end
+                  else
+                    __printf_assert__ ("booo ");
+                  end
+                end
+              end
+            end
+          end
+        else
+          __printf_assert__ ("booo ");
+        end
+      end
+    end
+  end
+
+  if 3 > 2
+    __printf_assert__ ("%d ", ctr++);
+  end
+
+  if []
+    __printf_assert__ ("booo ");
+  end
+
+  if ~b
+    __printf_assert__ ("%d ", ctr++);
+  end
+
+  if b
+  end
+
+  % "Braindead" short circuit
+  %
+  % We also check that there is a proper short circuit
+  if truthy (1) & truthy (2)
+    __printf_assert__ ("yay1 ");
+  end
+
+  if falsy (3) & truthy (4)
+    __printf_assert__ ("booo ");
+  end
+
+  if falsy (5) & falsy (6)
+    __printf_assert__ ("booo ");
+  end
+
+  if truthy (7) & falsy (8)
+    __printf_assert__ ("booo ");
+  end
+
+  if truthy (1)| truthy (2)
+    __printf_assert__ ("yay1 ");
+  end
+
+  if falsy (3) | truthy (4)
+    __printf_assert__ ("yay2 ");
+  end
+
+  if falsy (5) | falsy (6)
+    __printf_assert__ ("booo ");
+  end
+
+  if truthy (7) | falsy (8)
+    __printf_assert__ ("yay3 ");
+  end
+end
+
+function a = truthy (b)
+  __printf_assert__ ("%d ", b);
+  a = 1;
+end
+
+function a = falsy (b)
+  __printf_assert__ ("%d ", b);
+  a = 0;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_index_obj.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,63 @@
+function bytecode_index_obj ()
+
+    % Chained indexing with struct
+    __printf_assert__ ("%d ", suby1 ().a);
+    __printf_assert__ ("%d ", suby1.a); % cmd fn call
+    __printf_assert__ ("%d ", suby1 ().b.a);
+    __printf_assert__ ("%d ", suby1.b.a);
+
+    % Chained indexing with matrix
+    __printf_assert__ ("%d ", suby_mat1 ()(2));
+
+    % Chained indexing with cells
+    __printf_assert__ ("%s ", class(suby_cell1 ()(2)));
+    __printf_assert__ ("%d ", size(suby_cell1 ()(2)));
+    __printf_assert__ ("%d ", suby_cell1 (){1}{3});
+    __printf_assert__ ("%d ", suby_cell1 (){1}{3}(1));
+    __printf_assert__ ("%d ", suby_cell1 ()(1){1}{2});
+    __printf_assert__ ("%d ", suby_cell1{1}{3}); % cmd fn call
+
+    % Dynamic struct field
+    s = struct;
+    s.qwe = 22;
+    s.asd = struct ("qwe", 33);
+
+    __printf_assert__ ("%d ", s.("qwe"));
+    __printf_assert__ ("%s ", class (s.("asd").("qwe")));
+    __printf_assert__ ("%d ", s.("asd").("qwe"));
+
+    % Subassign dynamic field
+    t.qwe = 3;
+    t.("asd") = 4;
+    __printf_assert__ ("%d ", t.qwe);
+    __printf_assert__ ("%d ", t.asd);
+
+    % : and end for eg. foo()(:,end) etc
+
+    % Check that classdef metas can be used to construct a classdef object
+    h = @sin;
+    o = matlab.lang.MemoizedFunction (h);
+    __printf_assert__ ("%s ", class (o))
+
+    % Check proper argument order
+    s = [struct struct ; struct struct];
+    M = [1:10 ; 11:20];
+    s(1,2).a = M;
+    __printf_assert__ ("%d ", s(1,2).a(1,2));
+end
+
+function s = suby1()
+    s = struct;
+    s.a = 2;
+    b = struct;
+    b.a = 3;
+    s.b = b;
+end
+
+function m = suby_mat1()
+    m = [1 2 3];
+end
+
+function c = suby_cell1()
+    c = {{1 2 3}, 4, 5};
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_inputname.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,28 @@
+function bytecode_inputname (arg1, arg2)
+    __printf_assert__ ("%s ", inputname (1, 0));
+    __printf_assert__ ("%s ", inputname (1, 1));
+    __printf_assert__ ("%s ", inputname (2, 0));
+    __printf_assert__ ("%s ", inputname (2, 1));
+
+    a = 2;
+    b = 3;
+    suby (a, b);
+    suby (a + 1, b * 3);
+
+    % inputname from non-compiled function
+    inputname_args (a, b);
+    inputname_args (a + 1, b * 3);
+end
+
+function suby (arg1, arg2)
+    __printf_assert__ ("%s ", inputname (1, 0));
+    __printf_assert__ ("%s ", inputname (1, 1));
+    __printf_assert__ ("%s ", inputname (2, 0));
+    __printf_assert__ ("%s ", inputname (2, 1));
+
+    aa = 22;
+    bb = 33;
+    % inputname from non-compiled function
+    inputname_args (aa, bb);
+    inputname_args (aa + 1, bb * 3);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_leaks.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,158 @@
+#
+# We are looking for leaks of octave_value:s by checking the refrence counts
+# in different code paths of the calling convention.
+#
+function [a b] = bytecode_leaks (c, d)
+  cc = c;
+  b = d;
+
+  e = 1+1;
+  refs_e = __ref_count (e);
+  suby1(e);
+  assert (refs_e, __ref_count (e))
+
+  aa = suby2(e);
+  assert (refs_e, __ref_count (e))
+
+  % Test special code path for assigning argument to return value
+  aa = suby3(e);
+  assert (refs_e + 1, __ref_count (e))
+  aa = 0;
+  assert (refs_e, __ref_count (e))
+
+  % varargin
+  suby4 (e,e,e,e);
+  assert (refs_e, __ref_count (e))
+  suby5 (e,e,e,e);
+  assert (refs_e, __ref_count (e))
+
+  % varargout
+  suby6(e);
+  assert (refs_e, __ref_count (e))
+  [tmp1, tmp2, tmp3, tmp4, tmp5] = suby6(e);
+  tmp1 = 0; tmp2 = 0; tmp3 = 0; tmp4 = 0; tmp5 = 0;
+  assert (refs_e, __ref_count (e))
+
+  suby7(e);
+  assert (refs_e, __ref_count (e))
+  [tmp1, tmp2, tmp3, tmp4, tmp5] = suby6(e);
+  tmp1 = 0; tmp2 = 0; tmp3 = 0; tmp4 = 0; tmp5 = 0;
+  assert (refs_e, __ref_count (e))
+
+  % Call non-vm function
+  sin (e);
+  assert (refs_e, __ref_count (e))
+
+  % Index matrix
+  m = [1 2 3 4];
+  m (e);
+  assert (refs_e, __ref_count (e))
+
+  % Ops
+  tmp1 = -e + e * e - e / e ^ e;
+  assert (refs_e, __ref_count (e))
+
+  % Dynamic matrix
+  m = [1 2 3 e; e 4 5 6];
+  m = 0;
+  assert (refs_e, __ref_count (e))
+
+  % Cell
+  m = {1,2,3, e; 4, 5, e, 6};
+  m = 0;
+  assert (refs_e, __ref_count (e))
+
+  % "command call" with disp
+  disp ("The disp of e and pi underneath is on purpose. There should be a 'e = 2' and 'ans = 3.14...'")
+  e % Should print "e = 2"
+  assert (refs_e + 1, __ref_count (e)) % in ans
+  ans = 0;
+  assert (refs_e, __ref_count (e))
+
+  % This will be a function call and should print "ans = 3.14..."
+  pi
+
+  % no disp
+  e;
+  assert (refs_e + 1, __ref_count (e)) % in ans
+  ans = 0;
+  assert (refs_e, __ref_count (e))
+
+
+  % Too many or few args
+  try
+    suby1 (e,e,e);
+  catch
+  end
+  assert (refs_e, __ref_count (e))
+
+  try
+    subsuby5 (e);
+  catch
+  end
+  assert (refs_e, __ref_count (e))
+
+  try
+    m = [];
+    m(e)
+  catch
+  end
+  assert (refs_e, __ref_count (e))
+
+  try
+    m = [];
+    m(e) = 123;
+  catch
+  end
+  assert (refs_e, __ref_count (e))
+
+  % eval dynamic stack
+  suby8 (e);
+  assert (refs_e, __ref_count (e))
+end
+
+function suby1 (a)
+  aa = 1 + a;
+  bb = a;
+end
+
+function aa = suby2 (a)
+  aa = 1 + a;
+  bb = a;
+end
+
+function a = suby3(a)
+end
+
+function b = suby4(varargin)
+  b = 3 + varargin{1};
+  c = varargin{2};
+end
+
+function b = suby5(a, b, varargin)
+  b = 3 + varargin{1};
+  c = varargin{2};
+  d = a;
+end
+
+function varargout = suby6(a)
+  varargout{1} = 3;
+  varargout{2} = a;
+  varargout{3} = 1;
+  varargout{4} = 1;
+  varargout{5} = a;
+  cc = a;
+end
+
+function [aa bb varargout] = suby7(a)
+  varargout{1} = 3;
+  varargout{2} = a;
+  varargout{3} = 1;
+  aa = 1;
+  bb = a;
+  cc = a;
+end
+
+function suby8(a)
+  eval ("g = a;");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_matrix.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,222 @@
+function bytecode_matrix ()
+  % Dynamically built matrixes, i.e. those
+  % who are not built by the parser, with a dynamic value
+  % inside the initializer.
+
+  a = 1;
+  b = 2;
+  c = 3;
+  d = 4;
+  A = [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [A; A];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Evalorder
+  A = [hi('a') hi('b'); hi('c') hi('d')];
+
+  % Matrix multiply
+  A = [a b; c d] * [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] * [a; b; c; d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a; b; c; d] * [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Matrix div
+  A = [a b c d] / [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] \ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b; c d] / [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Compound mul herm
+  A = [a b c d] * [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Compound herm mul
+  A = [a b; c d]' * [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Compound trans ldiv
+  A = [a; b; c; d].' \ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Compound trans ldiv
+  A = [a b; c d].' \ [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Matrix add
+  A = [a b; c d] + [a b; c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] + [a; b; c; d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Scalar
+  A = [a b c d] + 2;
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = 2 + [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] - 2;
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = 2 * [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] / 2;
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = 2 \ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Dot
+
+  A = [a b c d] .* [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] ./ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] .\ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] .^ [a b c d];
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] .* [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] ./ [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] .\ [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  A = [a b c d] .^ [a b c d]';
+  __printf_assert__ ("%g ", A);
+  __printf_assert__ ("%g ", size (A));
+
+  % Matrixes with unequal row length
+  s = "zxc";
+  A = ["qweasd"; s];
+  __printf_assert__ ("%s ", A);
+  A = [s s; s];
+  __printf_assert__ ("%s ", A);
+
+  % Matrixes with more than 255 elements use
+  % a differens op-code.
+  a = 111;
+        % note a here
+  b = [ a 1   2   3   4   5   6   7   8   9  10 ...
+        11  12  13  14  15  16  17  18  19  20 ...
+        21  22  23  24  25  26  27  28  29  30 ...
+        31  32  33  34  35  36  37  38  39  40 ...
+        41  42  43  44  45  46  47  48  49  50 ...
+        51  52  53  54  55  56  57  58  59  60 ...
+        61  62  63  64  65  66  67  68  69  70 ...
+        71  72  73  74  75  76  77  78  79  80 ...
+        81  82  83  84  85  86  87  88  89  90 ...
+        91  92  93  94  95  96  97  98  99 100 ...
+        101 102 103 104 105 106 107 108 109 110 ...
+        111 112 113 114 115 116 117 118 119 120 ...
+        121 122 123 124 125 126 127 128 129 130 ...
+        131 132 133 134 135 136 137 138 139 140 ...
+        141 142 143 144 145 146 147 148 149 150 ...
+        151 152 153 154 155 156 157 158 159 160 ...
+        161 162 163 164 165 166 167 168 169 170 ...
+        171 172 173 174 175 176 177 178 179 180 ...
+        181 182 183 184 185 186 187 188 189 190 ...
+        191 192 193 194 195 196 197 198 199 200 ...
+        201 202 203 204 205 206 207 208 209 210 ...
+        211 212 213 214 215 216 217 218 219 220 ...
+        221 222 223 224 225 226 227 228 229 230 ...
+        231 232 233 234 235 236 237 238 239 240 ...
+        241 242 243 244 245 246 247 248 249 250 ...
+        251 252 253 254 255 256 257];
+  __printf_assert__ ("%d ", size (b));
+  __printf_assert__ ("%d ", sum (b));
+  a = 111;
+        % note a here
+  b = [ a;   1;   2;   3;   4;   5;   6;   7;   8;   9;  10; ...
+        11;  12;  13;  14;  15;  16;  17;  18;  19;  20; ...
+        21;  22;  23;  24;  25;  26;  27;  28;  29;  30; ...
+        31;  32;  33;  34;  35;  36;  37;  38;  39;  40; ...
+        41;  42;  43;  44;  45;  46;  47;  48;  49;  50; ...
+        51;  52;  53;  54;  55;  56;  57;  58;  59;  60; ...
+        61;  62;  63;  64;  65;  66;  67;  68;  69;  70; ...
+        71;  72;  73;  74;  75;  76;  77;  78;  79;  80; ...
+        81;  82;  83;  84;  85;  86;  87;  88;  89;  90; ...
+        91;  92;  93;  94;  95;  96;  97;  98;  99; 100; ...
+        101; 102; 103; 104; 105; 106; 107; 108; 109; 110; ...
+        111; 112; 113; 114; 115; 116; 117; 118; 119; 120; ...
+        121; 122; 123; 124; 125; 126; 127; 128; 129; 130; ...
+        131; 132; 133; 134; 135; 136; 137; 138; 139; 140; ...
+        141; 142; 143; 144; 145; 146; 147; 148; 149; 150; ...
+        151; 152; 153; 154; 155; 156; 157; 158; 159; 160; ...
+        161; 162; 163; 164; 165; 166; 167; 168; 169; 170; ...
+        171; 172; 173; 174; 175; 176; 177; 178; 179; 180; ...
+        181; 182; 183; 184; 185; 186; 187; 188; 189; 190; ...
+        191; 192; 193; 194; 195; 196; 197; 198; 199; 200; ...
+        201; 202; 203; 204; 205; 206; 207; 208; 209; 210; ...
+        211; 212; 213; 214; 215; 216; 217; 218; 219; 220; ...
+        221; 222; 223; 224; 225; 226; 227; 228; 229; 230; ...
+        231; 232; 233; 234; 235; 236; 237; 238; 239; 240; ...
+        241; 242; 243; 244; 245; 246; 247; 248; 249; 250; ...
+        251; 252; 253; 254; 255; 256; 257];
+  __printf_assert__ ("%d ", size (b));
+  __printf_assert__ ("%d ", sum (b));
+
+end
+
+function i = hi (s)
+  __printf_assert__ ("%s ", s);
+  i = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_misc.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,121 @@
+function bytecode_misc ()
+  % Assure "set_internal_variable" are reset properly
+  max_stack = max_stack_depth;
+  set_max_stack_depth_1p (max_stack + 1);
+  assert (max_stack_depth == max_stack);
+
+  % Check that the WIDE opcode extension works
+  wide_sub();
+
+  % Try to run out of allowed number of stack frames
+  threw_up = false;
+  try
+    stack_overflow (max_stack * 2); % Should hit the limit
+  catch
+    threw_up = true;
+  end
+
+  assert (threw_up);
+
+  % Try to run out of VM stack space
+  % Assure that the VM is running, since we will disable the tree_evaluators
+  % stack limit mechanism.
+  if __vm_is_executing ()
+    absurd_frame_limit = max_stack_depth * 10000;
+    max_stack_depth (absurd_frame_limit, "local");
+
+    threw_up = false;
+    try
+      stack_overflow (absurd_frame_limit); % Should hit the VM limit
+    catch
+      threw_up = true;
+    end
+    assert (threw_up);
+  end
+end
+
+function set_max_stack_depth_1p (x)
+  max_stack_depth (x + 1, "local");
+  assert (max_stack_depth == x + 1);
+end
+
+function stack_overflow (n)
+  if n != 0
+    stack_overflow (n - 1);
+  end
+end
+
+function wide_sub ()
+  % 512 locals
+  a001=1; a002=2; a003=3; a004=4; a005=5; a006=6; a007=7; a008=8; a009=9; a010=10; a011=11; a012=12; a013=13; a014=14; a015=15; a016=16; a017=17; a018=18; a019=19; a020=20; a021=21; a022=22; a023=23; a024=24; a025=25; a026=26; a027=27; a028=28; a029=29; a030=30; a031=31; a032=32; a033=33; a034=34; a035=35; a036=36; a037=37; a038=38; a039=39; a040=40; a041=41; a042=42; a043=43; a044=44; a045=45; a046=46; a047=47; a048=48; a049=49; a050=50; a051=51; a052=52; a053=53; a054=54; a055=55; a056=56; a057=57; a058=58; a059=59; a060=60; a061=61; a062=62; a063=63; a064=64; a065=65; a066=66; a067=67; a068=68; a069=69; a070=70; a071=71; a072=72; a073=73; a074=74; a075=75; a076=76; a077=77; a078=78; a079=79; a080=80; a081=81; a082=82; a083=83; a084=84; a085=85; a086=86; a087=87; a088=88; a089=89; a090=90; a091=91; a092=92; a093=93; a094=94; a095=95; a096=96; a097=97; a098=98; a099=99; a100=100; a101=101; a102=102; a103=103; a104=104; a105=105; a106=106; a107=107; a108=108; a109=109; a110=110; a111=111; a112=112; a113=113; a114=114; a115=115; a116=116; a117=117; a118=118; a119=119; a120=120; a121=121; a122=122; a123=123; a124=124; a125=125; a126=126; a127=127; a128=128; a129=129; a130=130; a131=131; a132=132; a133=133; a134=134; a135=135; a136=136; a137=137; a138=138; a139=139; a140=140; a141=141; a142=142; a143=143; a144=144; a145=145; a146=146; a147=147; a148=148; a149=149; a150=150; a151=151; a152=152; a153=153; a154=154; a155=155; a156=156; a157=157; a158=158; a159=159; a160=160; a161=161; a162=162; a163=163; a164=164; a165=165; a166=166; a167=167; a168=168; a169=169; a170=170; a171=171; a172=172; a173=173; a174=174; a175=175; a176=176; a177=177; a178=178; a179=179; a180=180; a181=181; a182=182; a183=183; a184=184; a185=185; a186=186; a187=187; a188=188; a189=189; a190=190; a191=191; a192=192; a193=193; a194=194; a195=195; a196=196; a197=197; a198=198; a199=199; a200=200; a201=201; a202=202; a203=203; a204=204; a205=205; a206=206; a207=207; a208=208; a209=209; a210=210; a211=211; a212=212; a213=213; a214=214; a215=215; a216=216; a217=217; a218=218; a219=219; a220=220; a221=221; a222=222; a223=223; a224=224; a225=225; a226=226; a227=227; a228=228; a229=229; a230=230; a231=231; a232=232; a233=233; a234=234; a235=235; a236=236; a237=237; a238=238; a239=239; a240=240; a241=241; a242=242; a243=243; a244=244; a245=245; a246=246; a247=247; a248=248; a249=249; a250=250; a251=251; a252=252; a253=253; a254=254; a255=255; a256=256; a257=257; a258=258; a259=259; a260=260; a261=261; a262=262; a263=263; a264=264; a265=265; a266=266; a267=267; a268=268; a269=269; a270=270; a271=271; a272=272; a273=273; a274=274; a275=275; a276=276; a277=277; a278=278; a279=279; a280=280; a281=281; a282=282; a283=283; a284=284; a285=285; a286=286; a287=287; a288=288; a289=289; a290=290; a291=291; a292=292; a293=293; a294=294; a295=295; a296=296; a297=297; a298=298; a299=299; a300=300; a301=301; a302=302; a303=303; a304=304; a305=305; a306=306; a307=307; a308=308; a309=309; a310=310; a311=311; a312=312; a313=313; a314=314; a315=315; a316=316; a317=317; a318=318; a319=319; a320=320; a321=321; a322=322; a323=323; a324=324; a325=325; a326=326; a327=327; a328=328; a329=329; a330=330; a331=331; a332=332; a333=333; a334=334; a335=335; a336=336; a337=337; a338=338; a339=339; a340=340; a341=341; a342=342; a343=343; a344=344; a345=345; a346=346; a347=347; a348=348; a349=349; a350=350; a351=351; a352=352; a353=353; a354=354; a355=355; a356=356; a357=357; a358=358; a359=359; a360=360; a361=361; a362=362; a363=363; a364=364; a365=365; a366=366; a367=367; a368=368; a369=369; a370=370; a371=371; a372=372; a373=373; a374=374; a375=375; a376=376; a377=377; a378=378; a379=379; a380=380; a381=381; a382=382; a383=383; a384=384; a385=385; a386=386; a387=387; a388=388; a389=389; a390=390; a391=391; a392=392; a393=393; a394=394; a395=395; a396=396; a397=397; a398=398; a399=399; a400=400; a401=401; a402=402; a403=403; a404=404; a405=405; a406=406; a407=407; a408=408; a409=409; a410=410; a411=411; a412=412; a413=413; a414=414; a415=415; a416=416; a417=417; a418=418; a419=419; a420=420; a421=421; a422=422; a423=423; a424=424; a425=425; a426=426; a427=427; a428=428; a429=429; a430=430; a431=431; a432=432; a433=433; a434=434; a435=435; a436=436; a437=437; a438=438; a439=439; a440=440; a441=441; a442=442; a443=443; a444=444; a445=445; a446=446; a447=447; a448=448; a449=449; a450=450; a451=451; a452=452; a453=453; a454=454; a455=455; a456=456; a457=457; a458=458; a459=459; a460=460; a461=461; a462=462; a463=463; a464=464; a465=465; a466=466; a467=467; a468=468; a469=469; a470=470; a471=471; a472=472; a473=473; a474=474; a475=475; a476=476; a477=477; a478=478; a479=479; a480=480; a481=481; a482=482; a483=483; a484=484; a485=485; a486=486; a487=487; a488=488; a489=489; a490=490; a491=491; a492=492; a493=493; a494=494; a495=495; a496=496; a497=497; a498=498; a499=499; a500=500; a501=501; a502=502; a503=503; a504=504; a505=505; a506=506; a507=507; a508=508; a509=509; a510=510; a511=511; a512=512;
+
+  assert (a511 == 511);
+  assert (a512 == 512);
+  assert (a400 + a500 == 900);
+
+  % Do some ops to check that WIDE does not mess things up
+
+  % Loop to test specializations and despecializations
+  for j = 1:4
+    b = 3;
+    c = 4;
+    d = b * c;
+    assert (d == 12);
+
+    e = [1 2 3 4];
+    two = 2;
+    if (j == 3)
+      e = single (e); % despecialization
+      two = single (two);
+    end
+
+    assert (e(2) == 2);
+    assert (e(2) == two);
+    e(3) = 11;
+    assert (e(3) == 11);
+
+    assert (e(end) == 4);
+    assert (e(end - 1) == 11);
+
+    f = [5 6 7 8; 9 10 11 12];
+    six = 6;
+    if (j == 3)
+      f = single (f); % despecialization
+      six = single (six);
+    end
+    assert (f(1,2) == 6);
+    assert (f(1,2) == six);
+    f(1,2) = 7;
+    assert (f(1,2) == 7);
+
+    g = 0;
+    if (j == 3)
+      g = single (g); % despecialization
+    end
+
+    g++;
+    assert (g == 1);
+    ++g;
+    assert (g == 2);
+    g += 3;
+    assert (g == 5);
+    eval ("assert (g == 5);")
+
+    sum = 0;
+    for i = 1:3 % WIDE FOR_COND
+      sum += i;
+    end
+    assert (sum == 6);
+
+    s.s = 2;
+    assert (s.s == 2);
+    s.w.s = 3;
+    assert (s.w.s == 3);
+  end
+
+
+  % Check that a001 to a512 have to correct values
+  for i = 1:512
+    eval (sprintf ("assert (a%03d == %d);", i, i));
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_multi_assign.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,56 @@
+function bytecode_multi_assign ()
+  A = [1 2; 3 4];
+  [a, b] = max (A);
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  [a,b,c,d] = foo ();
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+  __printf_assert__ ("%d ", c);
+  __printf_assert__ ("%d ", d);
+
+  % Non ids in lhs
+  % Eval is used as a cheat since
+  % rhs need to know how many lhs values
+  % there are.
+
+  [e, f.a, g, h.b] = foo ();
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("%d ", f.a);
+  __printf_assert__ ("%d ", g);
+  __printf_assert__ ("%d ", h.b);
+
+  e = [1 2 3];
+  g = {1, 2, 3};
+  [e(2), f.a, g{2}, h.b] = foo ();
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("%d ", f.a);
+  __printf_assert__ ("%d ", g{2});
+  __printf_assert__ ("%d ", h.b);
+
+  [e(end), f.a, g{min (100, end)}, h.b] = foo ();
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("%d ", f.a);
+  __printf_assert__ ("%d ", g{min (100, end)});
+  __printf_assert__ ("%d ", h.b);
+
+  [e(end), f.a, ~, h.b] = foo ();
+  __printf_assert__ ("%d ", e);
+  __printf_assert__ ("%d ", f.a);
+  __printf_assert__ ("%d ", g{end});
+  __printf_assert__ ("%d ", h.b);
+
+
+  [C{1:2}, D] = {1,2,3}{:};
+  __printf_assert__ ("%d ", C{1});
+  __printf_assert__ ("%d ", C{2});
+  __printf_assert__ ("%d ", D);
+end
+
+function [a,b,c,d] = foo ()
+  a = 1;
+  b = 2;
+  c = 3;
+  d = 4;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_persistant.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,23 @@
+function bytecode_persistant ()
+  q = 3;
+  l = 4;
+
+  persistent a = 3;
+  __printf_assert__ ("a:%d ", a++);
+
+  persistent b;
+  __printf_assert__ ("b:%d ", b);
+  __printf_assert__ ("%s ", class (b));
+  __printf_assert__ ("%d ", size (b));
+  b = 0;
+  __printf_assert__ ("%d ", b++);
+
+  suby ();
+  suby ();
+end
+
+function suby ()
+  persistent c = 2;
+  c++;
+  __printf_assert__ ("c:%d ", c);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_range.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,68 @@
+function bytecode_range ()
+
+  % The should be range constants, but I think
+  % negative limits are not folded to range constants
+
+  a = 1:3;
+  __printf_assert__ ("%d ", a);
+
+  a = 1:2:6;
+  __printf_assert__ ("%d ", a);
+
+  a = 1:2:5;
+  __printf_assert__ ("%d ", a);
+
+  a = 1:0.1:1.4;
+  __printf_assert__ ("%d ", a);
+
+  a = 1:-0.1:0.7;
+  __printf_assert__ ("%d ", a);
+
+  a = 7:7;
+  __printf_assert__ ("%d ", a);
+
+  a = 7:-1:7;
+  __printf_assert__ ("%d ", a);
+
+  a = 7:-1:8;
+  __printf_assert__ ("%d ", isempty (a));
+
+  % Dynamically created with COLON2 or 3 opcode.
+  % Colons behave differently when in command expression,
+  % they use the COLONX_CMD opcodes.
+  %
+  % ??? I don't think the ranges are allocated as matrixes
+  % when used in commands.
+  base = 8;
+  inc = 2;
+  lim = 11;
+
+  a = base : inc : lim;
+  __printf_assert__ ("%d ", a);
+  for i = base : inc : lim
+    __printf_assert__ ("%d ", i);
+  end
+
+  a = base : lim;
+  __printf_assert__ ("%d ", a);
+  for i = base : lim
+    __printf_assert__ ("%d ", i);
+  end
+
+  base = 10;
+  inc = -2;
+  lim = 7;
+
+  a = base : inc : lim;
+  __printf_assert__ ("%d ", a);
+  for i = base : inc : lim
+    __printf_assert__ ("%d ", i);
+  end
+
+  a = -base : -lim;
+  __printf_assert__ ("%d ", a);
+  for i = -base : -lim
+    __printf_assert__ ("%d ", i);
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_return.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,93 @@
+function bytecode_return ()
+  a = foo ();
+  __printf_assert__ ("%d ", a);
+
+  bar (1);
+  bar (0);
+
+  baz (0);
+  baz (1);
+  baz (2);
+
+  boz();
+
+  meh ();
+
+  a = return_1 ();
+  __printf_assert__ ("%d ", a);
+  [a b] = return_2 ();
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  % Drop one output variable
+  a = return_2 ();
+  __printf_assert__ ("%d ", a);
+
+  % Drop all output variables
+  return_2 ();
+
+  % Command form call
+  a = return_1;
+  __printf_assert__ ("%d ", a);
+
+  [a b] = return_2;
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", b);
+
+  a = return_2;
+  __printf_assert__ ("%d ", a);
+
+  return_2;
+
+  silly();
+  silly(2);
+end
+
+function [a b] = silly(i)
+  __printf_assert__ ("silly ");
+end
+
+function a = return_1 ()
+  a = 1;
+end
+
+function [a b] = return_2 ()
+  a = 1;
+  b = 2;
+end
+
+function out = foo ()
+  out = 2;
+  return
+end
+
+function bar (i)
+  if i
+    __printf_assert__ ("baaar ");
+    return
+  end
+
+  __printf_assert__ ("bääär ");
+end
+
+function out = baz (i)
+  if i == 0
+    __printf_assert__ ("baaaaz ");
+    return
+  elseif i == 1
+    __printf_assert__ ("bääääz ");
+    return
+  end
+
+  __printf_assert__ ("bååååz ");
+end
+
+function boz ()
+  __printf_assert__ ("booz ");
+  return
+  __printf_assert__ ("booo ");
+end
+
+function meh ()
+  return
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_struct.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,24 @@
+function bytecode_struct ()
+  s = struct ('a', 1, 'b', 2);
+  __printf_assert__ ("%d ", s.a);
+  __printf_assert__ ("%d ", s.b);
+  __printf_assert__ ("%s ", class (s.a));
+  __printf_assert__ ("%d ", size (s.a));
+
+  % Should not mess up stack
+  s.a;
+
+  % Test simple assigns
+  r.a = 3;
+
+  __printf_assert__ ("%s ", class (r));
+  __printf_assert__ ("%d ", r.a);
+
+  % Test word command struct subref
+
+  __printf_assert__ ("%d ", suby.b);
+end
+
+function a = suby ()
+  a.b = 4;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_subfuncs.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,128 @@
+function bytecode_subfuncs (h_to_anon_fn)
+  a = foo ();
+  __printf_assert__ ("%.17g ", a);
+  b = bar ();
+  __printf_assert__ ("%.17g ", b);
+  c = baz ();
+  __printf_assert__ ("%.17g ", c);
+
+  meh ();
+
+  a = para_ret_same_name (11);
+  __printf_assert__ ("%.17g ", a);
+
+  % Test default args
+  a = defaultarg ();
+  __printf_assert__ ("%.17g ", a);
+
+  a = defaultarg (10);
+  __printf_assert__ ("%.17g ", a);
+
+  a = defaultarg2 ();
+  __printf_assert__ ("%.17g ", a);
+
+  a = defaultarg2 (11);
+  __printf_assert__ ("%.17g ", a);
+
+  a = defaultarg2 (11, 12, 13, 14);
+  __printf_assert__ ("%.17g ", a);
+
+  % Magic colon
+  a = defaultarg2 (11, :, 13, 14);
+  __printf_assert__ ("%.17g ", a);
+
+  % Functions handles
+  h = @max;
+  __printf_assert__ ("%d ", h ([1 3]));
+  __printf_assert__ ("%d ", just_call_handle_with_arg (h, [1 3]));
+  __printf_assert__ ("%d ", just_call_handle_with_arg_bytecode (h, [1 3]));
+
+  h = @foo;
+  __printf_assert__ ("%d ", h ());
+  __printf_assert__ ("%d ", just_call_handle_with_arg (h));
+  __printf_assert__ ("%d ", just_call_handle_with_arg_bytecode (h));
+
+  % Call an anonymous function from the tst-file
+  h_to_anon_fn ();
+
+  % Many args and returns
+  [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = ret32 ();
+  __printf_assert__ ("%d ", a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32);
+  __printf_assert__ ("%d ", ret32 ()); % nargout = 1
+  ret32 (); % nargout = 0
+  [args32{1:32}] = ret32 ();
+  __printf_assert__ ("%d ", args32{:});
+
+  [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = ret32take32 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
+  __printf_assert__ ("%d ", a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32);
+
+  take32 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
+
+  [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, ...
+   a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64] = ...
+      takeXp32retXp32 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ...
+                       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64);
+  __printf_assert__ ("%d ", a01, a18, a59, a64);
+end
+
+function [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, varargout] = takeXp32retXp32 (b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, varargin)
+  for i = 1:32
+    eval (sprintf ("a%02.f = b%02.f;", i, i));
+  end
+  varargout = varargin;
+end
+
+function take32 (b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32)
+  __printf_assert__ ("take32:");
+  __printf_assert__ ("%d ", b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32);
+end
+
+function [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = ret32 ()
+  __printf_assert__ ("ret32:");
+  for i = 1:32
+    eval (sprintf ("a%02.f = %f;", i, i));
+  end
+end
+
+function [a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = ret32take32 (b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32)
+  for i = 1:32
+    eval (sprintf ("a%02.f = b%02.f;", i, i));
+  end
+end
+
+function out = just_call_handle_with_arg_bytecode (h, varargin)
+  out = h (varargin{:});
+end
+
+function out = foo ()
+  out = 2;
+end
+
+function out = bar ()
+  out = foo ();
+end
+
+function out = baz ()
+  out = bar ();
+end
+
+function meh()
+end
+
+function i = para_ret_same_name (i)
+end
+
+function a = defaultarg (b = 30)
+  a = b;
+end
+
+function a = defaultarg2 (a = 30, b = max (4, 5), c = [], d = [1 2])
+  __printf_assert__ ("%.17g ", a);
+  __printf_assert__ ("%.17g ", b);
+  __printf_assert__ ("%.17g ", c);
+  __printf_assert__ ("%d ", size(c));
+  __printf_assert__ ("%s ", class(c));
+  __printf_assert__ ("%.17g ", d);
+  __printf_assert__ ("%d ", size(d));
+  __printf_assert__ ("%s ", class(d));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_subsasgn.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,95 @@
+function bytecode_subsasgn ()
+  A = [1 2; 3 4];
+  A(1) = 3;
+  __printf_assert__ ("%d ", A(1));
+
+  A(1,2) = 5;
+  __printf_assert__ ("%d ", A(1,2));
+
+  A(:,1) = [9;8];
+  __printf_assert__ ("%d ", A(:,1));
+
+  A(:,:) = [11 12; 13 14];
+  __printf_assert__ ("%d ", A(:,1));
+
+  B = [1:10];
+  B(7:end) = [77 88 99 1010];
+  __printf_assert__ ("%d ", B);
+  B(4:min (5, end)) = 987;
+  __printf_assert__ ("%d ", B);
+
+  % Subassign to a undefined variable
+  C(3,2) = 13;
+  __printf_assert__ ("%d ", C);
+  __printf_assert__ ("%s ", class (C));
+  __printf_assert__ ("%d ", size (C));
+
+  % Subassign cells
+  D = {1,2,3};
+  D{1} = 4;
+  __printf_assert__ ("%d ", D{:});
+  __printf_assert__ ("%s ", class (D));
+  __printf_assert__ ("%d ", size (D));
+
+  D{2,3} = {6,7};
+  dd = D{2,3};
+  __printf_assert__ ("%d ", dd{:});
+  __printf_assert__ ("%d ", size (D));
+
+  E = {1,2,3};
+  E(2:3) = {4,5};
+  __printf_assert__ ("%d ", E{:});
+
+  % Use cells as a subscript
+  M = [1 2 3; 3 4 5; 5 6 7];
+  s = {":", [1;2]};
+  __printf_assert__ ("%d ", M(s{:}));
+  M(s{:}) = 7;
+  __printf_assert__ ("%d ", M(s{:}));
+
+  % Assure that sources are not modified
+  x = [1 2 3];
+  y = x;
+  y(2) = 3;
+  __printf_assert__ ("%d %d ", x, y);
+
+  x = {1 2 3};
+  y = x;
+  y{2} = 3;
+  __printf_assert__ ("%d %d ", x{2}, y{2});
+
+  % Chained assigns
+  a.b.c.d = 2;
+  __printf_assert__ ("%d ", a.b.c.d);
+  a.("a").c.d = 3;
+  __printf_assert__ ("%d ", a.a.c.d);
+  q.w = {{1},{2}};
+  __printf_assert__ ("%d ", q.w{1}{1});
+  q.w{1} = {3};
+  __printf_assert__ ("%d ", q.w{1}{1});
+
+  z.x.c = [1 2 3];
+  __printf_assert__ ("%d ", z.x.c);
+  z.x.c(:) = 4;
+  __printf_assert__ ("%d ", z.x.c);
+
+  x = {[1 2 3], [4 5 6]; [8 9 10], [11 12 13]};
+  q.y = {{}, {}; {} {}};
+  q.y{1, 2} = x;
+  q.y{1, 2}{2, 1} = 3;
+
+  __printf_assert__ ("%d ", q.y{1, 2}{2, 1});
+  __printf_assert__ ("%d ", q.y{1, 2}{1, 2});
+
+  % += etc
+  A = [1 2 3 4];
+  A(2) += 3;
+  __printf_assert__ ("%d ", A);
+  A(3) -= 4;
+  __printf_assert__ ("%d ", A);
+
+  C = struct ();
+  C.A = A;
+  C.A(4) *= 2;
+  __printf_assert__ ("%d ", C.A);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_switch.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,164 @@
+function bytecode_switch ()
+  a = 2;
+  switch (a)
+    case 1
+      __printf_assert__ ("boo ");
+    case 2
+      __printf_assert__ ("yay ");
+    otherwise
+      __printf_assert__ ("boo ");
+  end
+
+  switch (a)
+    case 1
+      __printf_assert__ ("boo ");
+    case 3
+      __printf_assert__ ("boo ");
+    otherwise
+      __printf_assert__ ("yay2 ");
+  end
+
+  b = "yay3 ";
+  switch (b)
+    case "boo1"
+      __printf_assert__ ("boo ");
+    case "yay3 "
+      __printf_assert__ ("yay3 ");
+    otherwise
+      __printf_assert__ ("boo ");
+  end
+
+  % Cells
+  a = 2;
+  switch (a)
+    case {1,0}
+      __printf_assert__ ("boo ");
+    case {2,3}
+      __printf_assert__ ("yay4 ");
+    otherwise
+      __printf_assert__ ("boo ");
+  end
+
+  switch (a)
+    case {1,0}
+      __printf_assert__ ("boo ");
+    case {3,2} %Swapped
+      __printf_assert__ ("yay5 ");
+    otherwise
+      __printf_assert__ ("boo ");
+  end
+
+  switch (a)
+    case {1,0}
+      __printf_assert__ ("boo ");
+    case {3,4}
+      __printf_assert__ ("boo ");
+    otherwise
+      __printf_assert__ ("yay6 ");
+  end
+
+  % Silly
+  switch (a)
+    otherwise
+      __printf_assert__ ("yay7 ");
+  end
+
+  % Empty
+  switch (a)
+  end
+
+  % No default case
+  a = 2;
+  switch (a)
+    case 1
+      __printf_assert__ ("boo ");
+    case 2
+      __printf_assert__ ("yay8 ");
+  end
+
+  switch (a)
+    case 1
+      __printf_assert__ ("boo ");
+    case 3
+      __printf_assert__ ("boo ");
+  end
+
+  % Return from switch
+  __printf_assert__ ("%d ", returnfromswitch (1));
+  __printf_assert__ ("%d ", returnfromswitch (2));
+  __printf_assert__ ("%d ", returnfromswitch (3));
+  __printf_assert__ ("%d ", returnfromswitch2 (1));
+  __printf_assert__ ("%d ", returnfromswitch2 (2));
+  __printf_assert__ ("%d ", returnfromswitch2 (3));
+
+  % switch with continue
+
+  for i = 1:4
+    switch (i)
+      case 1
+        __printf_assert__ ("1:%d ", i);
+      case 2
+        __printf_assert__ ("2:%d ", i);
+        continue;
+      case 3
+        __printf_assert__ ("3:%d ", i);
+      otherwise
+        __printf_assert__ ("breaking:%d ", i);
+        break;
+    endswitch
+    __printf_assert__ ("for-end:%d", i);
+  end
+
+end
+
+
+function a = returnfromswitch (b)
+  switch (b)
+    case 1
+      a = 1;
+      return
+    case 2
+      a = 2;
+      return;
+    otherwise
+      a = 3;
+      return
+  end
+
+  __printf_assert__ ("boo ");
+end
+
+function a = returnfromswitch2 (b)
+  % switches and fors cleans the stack at returns
+  % in a special way so test that that works properly
+  %
+  % The for loops puts native ints on the stack, so we can't just pop
+  % the stack assuming everything is octave values.
+  %
+  for i = [1, 2] % Puts int n,int i and the range on the stack
+    switch (b) % Puts b on the stack
+      case 10
+        return
+      otherwise
+        for j = [3, 4] % Puts int n,int i and the range on the stack
+          __printf_assert__ ("%d ", j);
+          switch (b) % Puts b on the stack
+            case 1
+              a = 1;
+              return %pop, popint popint pop, pop, popint popint pop
+            case 2
+              a = 2;
+            otherwise
+              a = 3;
+              return
+          end
+
+          __printf_assert__ ("%d ", j);
+        end
+    end
+
+    __printf_assert__ ("%d ", i);
+  end
+
+  __printf_assert__ ("yoo ");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_trycatch.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,173 @@
+function bytecode_trycatch ()
+  % TODO: Check identifier in error object too
+
+  try
+    __printf_assert__ ("yay ");
+  catch
+    __printf_assert__ ("boo ");
+  end
+
+  try
+    __printf_assert__ ("yay2 ");
+    error ("ooo");
+    __printf_assert__ ("boo ");
+  catch
+    __printf_assert__ ("yay3 ");
+
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+
+  % Empty body/catch
+  try
+  catch
+    __printf_assert__ ("boo ");
+  end
+
+  try
+  catch
+  end
+
+  try
+  catch err
+  end
+
+  try
+    error("foo");
+  catch
+  end
+
+  % Error object
+  try
+    __printf_assert__ ("yay2 ");
+    error ("ooo2");
+    __printf_assert__ ("boo ");
+  catch err
+    __printf_assert__ ("yay3 ");
+
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+    __printf_assert__ ("%s ", getfield (err, 'message'));
+  end
+
+  % Nested
+  try
+    __printf_assert__ ("yay3 ");
+    try
+      __printf_assert__ ("yay4 ");
+      error ("Nested error");
+      __printf_assert__ ("boo ");
+    catch
+      __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+      try
+        __printf_assert__ ("yay5 ");
+        error ("In catch");
+        __printf_assert__ ("boo ");
+      catch
+        __printf_assert__ ("yay6 ");
+        __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+      end
+    end
+
+    error ("qwe");
+    __printf_assert__ ("boo ");
+  catch
+    __printf_assert__ ("yay7 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+
+  % Unwind subfunction
+  try
+    suby ();
+  catch
+    __printf_assert__ ("yay8 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+
+  % Catch undefined id
+  try
+    qwe = asd;
+    __printf_assert__ ("boo ");
+  catch
+    __printf_assert__ ("yay9 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+  % Catch unconformant arguments
+  try
+    a = [1 2];
+    b = [1 2 3];
+    c = a * b;
+  catch
+    __printf_assert__ ("yay10 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+
+  % Rethrow
+  try
+    try
+      error ("yoyo");
+    catch err
+      rethrow (err);
+      __printf_assert__ ("boo ");
+    end
+  catch
+    __printf_assert__ ("yay11 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+  end
+
+  % There are some shenanigans going on poping native ints belonging
+  % to for-loops' iteration counters going on, so test that.
+  for i = 1:3
+    try
+      error ("foo");
+    catch
+      __printf_assert__ ("yay12 ");
+    __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+    end
+  end
+
+  % switch statements save the value on the stack so add some switches
+  % to check that they are unwound properly nested in fors etc
+
+  zxc = '1';
+  switch zxc
+    case '1'
+      for m = 1:3
+      end
+      switch m
+        case 2
+      end
+
+      for i = 1:3
+        try
+          qwe = '1';
+          switch qwe
+            case '1'
+              for j = 1:3
+                asd = '1';
+                switch asd
+                  case '1'
+                    error ("foo");
+                end
+
+                for k = 1:3
+                end
+              end
+          end
+        catch
+          __printf_assert__ ("yay13 ");
+          __printf_assert__ ("%s ", getfield (lasterror (), 'message'));
+        end
+      end
+
+      for l = 1:2
+      end
+  end
+  % TODO: Test more types of errors ...
+end
+
+function suby ()
+  for j = 1:2
+    for i = 1:3
+      error ("Error in subfunction");
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_unary.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,22 @@
+function bytecode_unary ()
+  a = 1;
+  a = -a;
+  __printf_assert__ ("%d ", a);
+
+  c = +4;
+  b = +c;
+  __printf_assert__ ("%d ", c);
+
+  a = [1 2; 3 4]';
+  __printf_assert__ ("%d ", a);
+  a = a';
+  __printf_assert__ ("%d ", a);
+
+  b = true;
+  b = ~b;
+  __printf_assert__ ("%d ", b);
+
+  b = true;
+  b = !b;
+  __printf_assert__ ("%d ", b);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_unwind.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,170 @@
+function bytecode_unwind ()
+  unwind_protect
+    __printf_assert__ ("yay1 ");
+  unwind_protect_cleanup
+    __printf_assert__ ("yay2 ");
+  end
+
+  try
+    unwind_protect
+      error ("e1");
+      __printf_assert__ ("boo ");
+    unwind_protect_cleanup
+      __printf_assert__ ("yay3 ");
+    end
+  catch e
+    __printf_assert__ ("%s ", getfield (e, 'message'));
+  end
+
+  suby (1);
+  suby (2);
+
+  try
+    suby (3);
+  catch
+  end
+
+  suby (4);
+  suby (5);
+  suby (6);
+
+  % Break and returns that are not executed
+  %
+  % The combination "break and return", "break" and "return"
+  % takes different codepaths in the walker so we test all
+  % combinations here.
+
+  unwind_protect
+    for i = 1:3
+      if i == 4
+        break
+      elseif i == 5
+        return
+      end
+    end
+  unwind_protect_cleanup
+    __printf_assert__ ("yay4 ");
+  end
+
+  % Break only
+  unwind_protect
+    for i = 1:3
+      if i == 4
+        break
+      end
+    end
+  unwind_protect_cleanup
+    __printf_assert__ ("yay5 ");
+  end
+
+  % Return only
+  unwind_protect
+    for i = 1:3
+      if i == 4
+        return
+      end
+    end
+  unwind_protect_cleanup
+    __printf_assert__ ("yay6 ");
+  end
+end
+
+function suby (a)
+  if a == 1
+    unwind_protect
+      __printf_assert__ ("subyyay1 ");
+      return
+      __printf_assert__ ("boo ");
+    unwind_protect_cleanup
+      __printf_assert__ ("subyyay2 ");
+    end
+    __printf_assert__ ("boo ");
+  elseif a == 2
+    % Nested unwind protect with return in body
+    unwind_protect
+      unwind_protect
+        __printf_assert__ ("subyyay3 ");
+        return
+        __printf_assert__ ("boo ");
+      unwind_protect_cleanup
+        __printf_assert__ ("subyyay4 ");
+      end
+      __printf_assert__ ("boo ");
+    unwind_protect_cleanup
+      __printf_assert__ ("subyyay5 ");
+    end
+    __printf_assert__ ("boo ");
+  elseif a == 3
+    % Nested unwind protect with error in body
+    unwind_protect
+      unwind_protect
+        __printf_assert__ ("subyyay6 ");
+        error foooo
+        __printf_assert__ ("boo ");
+      unwind_protect_cleanup
+        __printf_assert__ ("subyyay7 ");
+      end
+      __printf_assert__ ("boo ");
+    unwind_protect_cleanup
+      __printf_assert__ ("subyyay8 ");
+    end
+    __printf_assert__ ("boo ");
+  elseif a == 4
+    for i = 1:3
+      unwind_protect
+        __printf_assert__ ("subyyay9 ");
+        break;
+        __printf_assert__ ("boo ");
+      unwind_protect_cleanup
+        __printf_assert__ ("subyyay10 ");
+      end
+      __printf_assert__ ("boo ");
+    end
+  elseif a == 5
+    for i = 1:3
+      unwind_protect
+        __printf_assert__ ("subyyay11 ");
+        for j = 1:3
+          unwind_protect
+            __printf_assert__ ("subyyay12 ");
+            break;
+            __printf_assert__ ("boo ");
+          unwind_protect_cleanup
+            __printf_assert__ ("subyyay13 ");
+          end
+          __printf_assert__ ("boo ");
+        end
+        break;
+        __printf_assert__ ("boo ");
+      unwind_protect_cleanup
+        __printf_assert__ ("subyyay14 ");
+      end
+      __printf_assert__ ("boo ");
+    end
+  elseif a == 6
+    % Mixing unwind protect with for loops. error and break
+    for i = 1:3
+      unwind_protect
+        __printf_assert__ ("subyyay15 ");
+        try
+          for j = 1:3
+            unwind_protect
+              __printf_assert__ ("subyyay16 ");
+              error ('qwe');
+              __printf_assert__ ("boo ");
+            unwind_protect_cleanup
+              __printf_assert__ ("subyyay17 ");
+            end
+            __printf_assert__ ("boo ");
+          end
+        catch
+          break;
+        end
+        __printf_assert__ ("boo ");
+      unwind_protect_cleanup
+        __printf_assert__ ("subyyay18 ");
+      end
+      __printf_assert__ ("boo ");
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_varargin.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,64 @@
+function bytecode_varargin (b, varargin)
+  __printf_assert__ ("%d ", varargin{:});
+  __printf_assert__ ("%d ", size (varargin))
+
+  varg1 (1);
+  varg1 (1,2,3,4);
+  varg1 ();
+
+  varg2 (1,2,3,4);
+  varg2 (1);
+
+  cslist = {1,2,3,4};
+  varg2 (cslist{:});
+
+  justnamenotpos (1, 2);
+
+  out = inout (1,2,3,4);
+  __printf_assert__ ("%d ", out{:});
+
+  __printf_assert__ ("%d ", nargin);
+
+  % TODO: Check in caller that return is the same
+  % b = varargin{:}
+
+  suby (1,2,3);
+end
+
+function varg1 (varargin)
+  __printf_assert__ ("%d ", varargin{:});
+  __printf_assert__ ("%d ", size (varargin));
+  __printf_assert__ ("%d ", nargin);
+end
+
+function varg2 (a, varargin)
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", varargin{:});
+  __printf_assert__ ("%d ", size (varargin));
+  __printf_assert__ ("%d ", nargin);
+
+  varg1 (varargin{:})
+  varg1 (2, varargin{:})
+end
+
+function justnamenotpos (varargin, a)
+  __printf_assert__ ("%d ", a);
+  __printf_assert__ ("%d ", varargin);
+  __printf_assert__ ("%d ", nargin);
+end
+
+function [varargin] = inout (varargin)
+  __printf_assert__ ("%d ", nargin);
+end
+
+function suby(a,b,c)
+  __printf_assert__ ("%d ", nargin);
+
+  if nargin == 3
+    suby (1,2);
+  elseif nargin == 2
+    suby (1);
+  elseif nargin == 1
+    suby ();
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_varargout.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,65 @@
+function bytecode_varargout ()
+
+    % Just check this works
+    [a b] = {7, 8}{:};
+    __printf_assert__ ("%d %d ", a, b);
+
+    % n amount of vargouts from suby1(n)
+    a = suby1 (1);
+    __printf_assert__ ("%d ", a);
+    [a b] = suby1 (2);
+    __printf_assert__ ("%d %d ", a, b);
+
+    % Test that ignored outputs are set properly
+    % when calling interpreted functions.
+    %
+    % return_isargout (n) returns isargout (n) in its
+    % first output.
+    [a b c] = return_isargout (2);
+    __printf_assert__ ("%d ", a);
+
+    [a b c] = return_isargout (4);
+    __printf_assert__ ("%d ", a);
+
+    [a, ~, c] = return_isargout (2);
+    __printf_assert__ ("%d ", a);
+
+    [a, ~, ~] = return_isargout (2);
+    __printf_assert__ ("%d ", a);
+    [a, ~, ~] = return_isargout (1);
+    __printf_assert__ ("%d ", a);
+    [a, ~, ~] = return_isargout (3);
+    __printf_assert__ ("%d ", a);
+
+    [~, ~, ~] = return_isargout (3);
+
+    % Do the same for a vm function
+    [a b c] = sub_return_isargout (2);
+    __printf_assert__ ("%d ", a);
+
+    [a b c] = sub_return_isargout (4);
+    __printf_assert__ ("%d ", a);
+
+    [a, ~, c] = sub_return_isargout (2);
+    __printf_assert__ ("%d ", a);
+
+    [a, ~, ~] = sub_return_isargout (2);
+    __printf_assert__ ("%d ", a);
+    [a, ~, ~] = sub_return_isargout (1);
+    __printf_assert__ ("%d ", a);
+    [a, ~, ~] = sub_return_isargout (3);
+    __printf_assert__ ("%d ", a);
+
+    [~, ~, ~] = sub_return_isargout (3);
+end
+
+function [a b c ] = sub_return_isargout (n)
+    b = 0; c = 0;
+    a = isargout (n);
+end
+
+function varargout = suby1(n)
+    for i = 1:n
+        varargout{i} = i;
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_while.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,111 @@
+function bytecode_while ()
+  i = 5;
+  while i
+    __printf_assert__ ("%d ", i);
+    i--;
+  end
+
+  i = 0;
+  while i < 3
+    i++;
+  end
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  while i++ < 4
+    ctr++;
+  end
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  ctr = 0;
+  while ++i < 4
+    ctr++;
+  end
+  __printf_assert__ ("%d ", i);
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  ctr = 0;
+  while i < 4
+    i++;
+    if i == 2
+      continue
+    end
+    ctr++;
+  end
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  while i < 4
+    i++;
+    if i == 2
+      break
+    end
+    ctr++;
+  end
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  ctr = 0;
+  while i < 4
+    i++;
+    if i == 2
+      continue
+    elseif i == 3
+      break
+    end
+    ctr++;
+  end
+  __printf_assert__ ("%d ", ctr);
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  while i < 4
+    i++;
+    if i == 1
+      continue
+    else
+      break
+    end
+  end
+  __printf_assert__ ("%d ", i);
+
+  ctr = 0;
+  j = 0;
+  while j < 2
+    i = 0;
+    while i < 2
+      k = 0;
+      while k < 2
+        k++;
+        ctr++;
+      end
+      i++;
+    end
+    j++;
+  end
+  __printf_assert__ ("%d ", ctr);
+
+  i = 0;
+  while i++ < 2
+    continue
+  end
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  while i++ < 2
+    break
+  end
+  __printf_assert__ ("%d ", i);
+
+  i = 0;
+  while i++ < 2
+  end
+  __printf_assert__ ("%d ", i);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/bytecode_wordlistcmd.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,25 @@
+function bytecode_wordlistcmd ()
+  foo A B C;
+
+  bar QWE;
+
+  boz
+  boz A
+  boz A B
+end
+
+
+function foo (a,b,c)
+  __printf_assert__ ("%s ", a);
+  __printf_assert__ ("%s ", b);
+  __printf_assert__ ("%s ", c);
+end
+
+function [a b] = bar (c)
+  __printf_assert__ ("%s ", c);
+  a = 1;
+  b = 2;
+end
+
+function boz (a,b,c)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/cdef_foo.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,21 @@
+classdef cdef_foo < handle
+  properties
+    msg = "";
+    val = 1;
+  end
+  methods
+    function f = cdef_foo(msg)
+        global cdef_foo_ctor_cnt = 0;
+        f.msg = msg;
+        cdef_foo_ctor_cnt++;
+    end
+    function delete (self)
+      global cdef_foo_dtor_cnt = 0;
+      __printf_assert__ ("%d %s ", ++cdef_foo_dtor_cnt, self.msg);
+    endfunction
+    function c = plus (a, b)
+        c = cdef_foo (strcat("sum", a.msg, b.msg));
+        c.val = a.val + b.val;
+    end
+  endmethods
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/inputname_args.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,6 @@
+function inputname_args (arg1, arg2)
+    __printf_assert__ ("%s ", inputname (1, 0));
+    __printf_assert__ ("%s ", inputname (1, 1));
+    __printf_assert__ ("%s ", inputname (2, 0));
+    __printf_assert__ ("%s ", inputname (2, 1));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/just_call_handle_with_arg.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,3 @@
+function a = just_call_handle_with_arg (h, varargin)
+    a = h (varargin{:});
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/module.mk	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,48 @@
+compile_TEST_FILES = \
+  %reldir%/bytecode.tst \
+  %reldir%/bytecode_ans.m \
+  %reldir%/bytecode_assign.m \
+  %reldir%/bytecode_binops.m \
+  %reldir%/bytecode_anon_handles.m \
+  %reldir%/bytecode_cdef_use.m \
+  %reldir%/bytecode_cell.m \
+  %reldir%/bytecode_dountil.m \
+  %reldir%/bytecode_end.m \
+  %reldir%/bytecode_errors.m \
+  %reldir%/bytecode_eval_1.m \
+  %reldir%/bytecode_evalin_1.m \
+  %reldir%/bytecode_evalin_2.m \
+  %reldir%/bytecode_for.m \
+  %reldir%/bytecode_global_1.m \
+  %reldir%/bytecode_if.m \
+  %reldir%/bytecode_index_obj.m \
+  %reldir%/bytecode_inputname.m \
+  %reldir%/bytecode_leaks.m \
+  %reldir%/bytecode_matrix.m \
+  %reldir%/bytecode_misc.m \
+  %reldir%/bytecode_multi_assign.m \
+  %reldir%/bytecode_persistant.m \
+  %reldir%/bytecode_range.m \
+  %reldir%/bytecode_return.m \
+  %reldir%/bytecode_struct.m \
+  %reldir%/bytecode_subfuncs.m \
+  %reldir%/bytecode_subsasgn.m \
+  %reldir%/bytecode_switch.m \
+  %reldir%/bytecode_trycatch.m \
+  %reldir%/bytecode_unary.m \
+  %reldir%/bytecode_unwind.m \
+  %reldir%/bytecode_varargin.m \
+  %reldir%/bytecode_varargout.m \
+  %reldir%/bytecode_while.m \
+  %reldir%/bytecode_wordlistcmd.m \
+  %reldir%/cdef_foo.m \
+  %reldir%/inputname_args.m \
+  %reldir%/just_call_handle_with_arg.m \
+  %reldir%/return_isargout.m \
+  %reldir%/shutup_operator_test/@double/display.m \
+  %reldir%/shutup_operator_test/@logical/display.m \
+  %reldir%/shutup_operator_test/bytecode_disp.m \
+  %reldir%/shutup_operator_test/bytecode_disp.tst \
+  %reldir%/wrongname_fn.m
+
+TEST_FILES += $(compile_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/return_isargout.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,5 @@
+function [a b c] = return_isargout (n)
+    b = 0;
+    c = 0;
+    a = isargout (n);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/shutup_operator_test/@double/display.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,11 @@
+% For use by bytecode_disp().
+%
+% Overload display
+%
+function display (x)
+    if (inputname(1))
+        __printf_assert__ ("%s = %d ", inputname(1), x);
+    else
+        __printf_assert__ ("%d ", x);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/shutup_operator_test/@logical/display.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,11 @@
+% For use by bytecode_disp().
+%
+% Overload display
+%
+function display (x)
+    if (inputname(1))
+        __printf_assert__ ("%s = %d ", inputname(1), x);
+    else
+        __printf_assert__ ("%d ", x);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/shutup_operator_test/bytecode_disp.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,38 @@
+function bytecode_disp()
+  %  int8 type's display is overloaded with a __printf_assert__
+  1               % "ans = 1"
+  print_dot;
+  2 + 3           % "ans = 5"
+  print_dot;
+  0;              %
+  0 + 0;          %
+  print_dot;
+  ~4              % "ans = 0"
+  print_dot;
+  2^3             % "ans = 8"
+  print_dot       %
+
+  if 2
+    3             % "ans = 3"
+  end
+  print_dot;
+  x = 4 - 1       % "x = 3"
+
+  print_dot;
+  [x, y] = deal (1,2) % "x = 1" "y = 2"
+  print_dot;
+  [x, ~] = deal (1,2) % "x = 1"
+  print_dot;
+  % If all lvalues are black holes, nothing is printed
+  [~, ~] = deal (1,2) %
+  print_dot;
+  [x, ~, ~] = deal (1,2, 3) % "x = 1"
+  print_dot;
+  [~, y, ~] = deal (1,2, 3) % "y = 2"
+  print_dot;
+  x
+end
+
+function print_dot()
+  __printf_assert__(". ");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/shutup_operator_test/bytecode_disp.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,18 @@
+## Test display due to no ";" at eol
+##
+## We are overloading display for double so we place this test
+## in its own folder to not mess double up for the other
+## tests.
+
+%!test
+%! % Overloading of class-methods seems to stick so we need to clear them since we overload
+%! % double's display. Is this a bug ???
+%! clear classes
+%! key = "ans = 1 . ans = 5 . . ans = 0 . ans = 8 . ans = 3 . x = 3 . x = 1 y = 2 . x = 1 . . x = 1 . y = 2 . x = 1 ";
+%! __compile bytecode_disp clear;
+%! bytecode_disp;
+%! assert (__prog_output_assert__ (key));
+%!
+%! assert (__compile ("bytecode_disp"));
+%! bytecode_disp;
+%! assert (__prog_output_assert__ (key));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compile/wrongname_fn.m	Fri Jun 23 20:51:51 2023 +0200
@@ -0,0 +1,3 @@
+function a = wrongname_fn (b)
+  a = b + 1;
+end
--- a/test/file-encoding/file-encoding.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/file-encoding/file-encoding.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -123,14 +123,14 @@
 %! end_unwind_protect
 
 ## oruntests with file in different folder (not in load path) with
-## "__mfile_encoding__"
+## "mfile_encoding"
 %!test <*62780>
-%! old_mfile_encoding = __mfile_encoding__ ("windows-1251");
+%! old_mfile_encoding = mfile_encoding ("windows-1251");
 %! unwind_protect
 %!   ## use "evalc" to suppress output to the log
 %!   evalc ('oruntests ("CP1251");');
 %! unwind_protect_cleanup
-%!   __mfile_encoding__ (old_mfile_encoding);
+%!   mfile_encoding (old_mfile_encoding);
 %! end_unwind_protect
 
 ## oruntests with file in different folder with .oct-config file (in load path)
--- a/test/for.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/for.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -169,24 +169,51 @@
 %!
 %! fail ("for i = 0:-1:-inf; break; end", "warning",
 %!       "FOR loop limit is infinite");
+%!
+%! fail ("for i = inf:-1:1; break; end", "warning",
+%!       "FOR loop limit is infinite");
+%!
+%! fail ("for i = -inf:+1:1; break; end", "warning",
+%!       "FOR loop limit is infinite");
 
 %!test <*45143>
 %! warning ("on", "Octave:infinite-loop", "local");
-%! k = 0;
-%! for i = 1:Inf
-%!   if (++k > 10)
-%!     break;
-%!   endif
-%! endfor
-%! assert (i, 11);
+%
+%! code = cstrcat ("k = 0;               ",
+%!                 "for i = 1:Inf;       ",
+%!                 "  if (++k > 10);     ",
+%!                 "    break;           ",
+%!                 "  endif;             ",
+%!                 "endfor;              ",
+%!                 "assert (i, 11);      ");
+%! fail (code, "warning", "FOR loop limit is infinite");
 %!
-%! k = 0;
-%! for i = -1:-1:-Inf
-%!   if (++k > 10)
-%!     break;
-%!   endif
-%! endfor
-%! assert (i, -11);
+%! code = cstrcat ("k = 0;               ",
+%!                 "for i = -1:-1:-Inf;  ",
+%!                 "  if (++k > 10);     ",
+%!                 "    break;           ",
+%!                 "  endif;             ",
+%!                 "endfor;              ",
+%!                 "assert (i, -11);     ");
+%! fail (code, "warning", "FOR loop limit is infinite");
+%!
+%! code = cstrcat ("k = 0;               ",
+%!                 "for i = Inf:-1:1;    ",
+%!                 "  if (++k > 10);     ",
+%!                 "    break;           ",
+%!                 "  endif;             ",
+%!                 "endfor;              ",
+%!                 "assert (i, Inf);     ");
+%! fail (code, "warning", "FOR loop limit is infinite");
+%!
+%! code = cstrcat ("k = 0;               ",
+%!                 "for i = -Inf:+1:1;   ",
+%!                 "  if (++k > 10);     ",
+%!                 "    break;           ",
+%!                 "  endif;             ",
+%!                 "endfor;              ",
+%!                 "assert (i, -Inf);    ");
+%! fail (code, "warning", "FOR loop limit is infinite");
 %!
 %! k = 0;
 %! for i = 1:-Inf
--- a/test/io.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/io.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -297,6 +297,118 @@
 %!assert (sscanf ('0177 08', '%i'), [127; 0; 8])
 %!assert (sscanf ('0177 08', '%d'), [177; 8])
 
+## Extensive testing of '%c'
+%!test
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%c');
+%! assert (val, 'abcde');
+%! assert (cnt, 5);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%10c');
+%! assert (val, 'abcde');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c');
+%! assert (val, 'abcde');
+%! assert (cnt, 2);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c', 1);
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%c', 5);
+%! assert (val, 'abcde');
+%! assert (cnt, 5);
+%! assert (msg, '');
+%! assert (pos, 6);
+
+## Extensive testing of '%s'
+%!test
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%s');
+%! assert (val, 'abcde');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%10s');
+%! assert (val, 'abcde');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s');
+%! assert (val, 'abcde');
+%! assert (cnt, 2);
+%! assert (msg, '');
+%! assert (pos, 6);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s', 1);
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%1s', 5);
+%! assert (val, 'abcde');
+%! assert (cnt, 5);
+%! assert (msg, '');
+%! assert (pos, 6);
+
+## Extensive testing of '%[]'
+%!test
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]');
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[a-c]');
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]');
+%! assert (val, 'abc');
+%! assert (cnt, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]', 1);
+%! assert (val, 'ab');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 3);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]', 1);
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+
+## Extensive testing of '%[^]'
+%!test
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]');
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[^de]');
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]');
+%! assert (val, 'abc');
+%! assert (cnt, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 4);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]', 1);
+%! assert (val, 'ab');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 3);
+%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]', 1);
+%! assert (val, 'abc');
+%! assert (cnt, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+
 ## bug #47741
 %!assert (sscanf ('2147483647', '%d'), 2147483647)
 %!assert (sscanf ('2147483647', '%i'), 2147483647)
@@ -386,10 +498,169 @@
 
 %!test <*62723>
 %! [val, count, msg, pos] = sscanf ("p", "%c");
-%! assert (val, "p");
+%! assert (val, 'p');
+%! assert (count, 1);
+%! assert (msg, '');
+%! assert (pos, 2);
+
+%!test <*62723>
+%! [val, count, msg, pos] = sscanf (' ,1 ', ' %s ', 1);
+%! assert (val, ',1');
 %! assert (count, 1);
-%! assert (msg, "");
-%! assert (pos, 2);
+%! assert (msg, '');
+%! assert (pos, 5);
+
+## Test NaN at EOF
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 n', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 na', '%f');
+%! assert (val, [2; 3; NA]);
+%! assert (count, 3);
+%! assert (msg, '');
+%! assert (pos, 7);
+%! [val, count, msg, pos] = sscanf ('2 3 nan', '%f');
+%! assert (val, [2; 3; NaN]);
+%! assert (count, 3);
+%! assert (msg, '');
+%! assert (pos, 8);
+
+## Test NaN within string
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 n 4', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 na 4', '%f');
+%! assert (val, [2; 3; NA; 4]);
+%! assert (count, 4);
+%! assert (msg, '');
+%! assert (pos, 9);
+%! [val, count, msg, pos] = sscanf ('2 3 nan 4', '%f');
+%! assert (val, [2; 3; NaN; 4]);
+%! assert (count, 4);
+%! assert (msg, '');
+%! assert (pos, 10);
+
+## Test Inf at EOF
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 i', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 in', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 inf', '%f');
+%! assert (val, [2; 3; Inf]);
+%! assert (count, 3);
+%! assert (msg, '');
+%! assert (pos, 8);
+
+## Test Inf within string
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 i 4', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 in 4', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 inf 4', '%f');
+%! assert (val, [2; 3; Inf; 4]);
+%! assert (count, 4);
+%! assert (msg, '');
+%! assert (pos, 10);
+
+## Test '-' at EOF
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 -', '%d');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 -', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+
+## Test '-' within string
+%!test <63383>
+%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%d');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%f');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+
+## Test '+' at EOF
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('2 3 +', '%d');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('2 3 +', '%f');
+%! assert (val, [2; 3]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+
+## Test '+' within string
+%!test <63383>
+%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%d');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%f');
+%! assert (val, [1; 2]);
+%! assert (count, 2);
+%! assert (msg, 'sscanf: format failed to match');
+%! assert (pos, 5);
+
+%## Test +NA, -NA, +NAN, -NAN
+%!test <*63383>
+%! [val, count, msg, pos] = sscanf ('+NA -NA 1 +NAN -NAN', '%f');
+%! assert (val, [NA; NA; 1; NaN; NaN]);
+%! assert (count, 5);
+%! assert (msg, '');
+%! assert (pos, 20);
+%! [val, count, msg, pos] = sscanf ('-NA', '%f');
+%! assert (val, NA);
+%! assert (count, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+%! [val, count, msg, pos] = sscanf ('+NA', '%f');
+%! assert (val, NA);
+%! assert (count, 1);
+%! assert (msg, '');
+%! assert (pos, 4);
+%! [val, count, msg, pos] = sscanf ('-NaN', '%f');
+%! assert (val, NaN);
+%! assert (count, 1);
+%! assert (msg, '');
+%! assert (pos, 5);
+%! [val, count, msg, pos] = sscanf ('+NaN', '%f');
+%! assert (val, NaN);
+%! assert (count, 1);
+%! assert (msg, '');
+%! assert (pos, 5);
 
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");
@@ -400,14 +671,16 @@
 %!          && v1 == [1; 2; 3; 4; 5; 6] && c1 == 6 && ischar (m1)
 %!          && v2 == [1; 2] && c2 == 2 && ischar (m2)));
 
-%!error <Invalid call to sscanf> sscanf ()
-%!error sscanf (1, 2)
-%!error <Invalid call to sscanf> sscanf ("foo", "bar", "C", 1)
-
 %!test
 %! [x, n] = sscanf ("   0.024000 0.200 0.200 2.000         1987           5           0  0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 4 5 1 2    2 5 5 8 2 8 12 6 15 18 28 26 47 88 118 162 192 130 88 56 27 23 14 9 6 3 4 1 0    2 3 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0   0.026000 0.250 0.250 2.100         3115           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0    0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0 1    1 1 0 1 0 1 3 2 0 5 15 25 44 66 145 179 193 172 104 57 17 11 12 2 1 0 1 1 0 1    0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.028000 0.300 0.300 2.200         4929           3           0  1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0    1 0 1 0 1 2 2 3 2 3 14 21 49 80 148 184 218 159 124 63 37 13 12 3 1 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.030000 0.350 0.350 2.300         7051           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1    0 0 1 0 0 0 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1    0 0 0 2 0 0 0 1 5 6 14 28 51 88 154 177 208 169 124 65 39 15 5 3 3 2 1 0 1 0 1   0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.032000 0.400 0.400 2.400         9113           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0    1 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 2 0    1 0 0 1 1 0 2 3 5 3 17 30 60 117 156 189 209 129 102 64 56 16 11 4 2 2 0 0 0 0   1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0   0.034000 0.450 0.450 2.500        11811           6           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0    0 0 2 1 0 0 1 0 5 5 15 21 57 99 149 190 195 159 130 69 41 16 10 2 5 3 0 1 0 0    0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.036000 0.500 0.500 2.600        14985           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0    0 0 0 0 1 0 0 2 2 6 10 34 60 95 126 177 194 155 99 71 44 17 6 7 2 0 0 0 3 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.038000 0.550 0.550 2.700        18391           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0    0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 1 1 0 1    2 1 0 0 0 1 0 1 3 6 19 27 52 95 161 154 169 134 94 64 37 19 9 6 0 2 1 0 0 0 0    1 2 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 2 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0    0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.040000 0.600 0.600 2.800        22933           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1    0 0 0 0 0 2 0 3 4 7 18 27 47 82 134 163 133 138 101 58 34 26 10 5 2 1 2 1 1 0    2 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.042000 0.650 0.650 2.900        27719           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 1 1 2 8 16 37 51 87 128 153 146 123 105 62 35 24 8 3 5 0 1 2 1 0 0   0 1 1 1 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0    0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.044000 0.700 0.700 3.000        32922           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 2 0    0 0 0 0 0 0 0 2 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1    1 1 0 0 0 1 4 3 5 5 15 35 54 88 132 168 149 105 92 62 30 16 17 4 5 1 0 0 1 0 1   1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.046000 0.750 0.750 3.100        38973           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0    0 0 0 1 0 0 0 4 3 5 20 37 56 94 110 135 149 124 84 58 36 17 14 7 1 0 2 0 1 0 0   1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1    1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0    1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.048000 0.800 0.800 3.200        45376           5           0  1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 2 1 1 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0    0 0 0 1 0 0 0 0 1 3 18 34 55 82 104 135 116 99 79 60 51 29 10 4 3 1 1 1 0 0 1    0 0 0 1 0 0 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1    0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.050000 0.850 0.850 3.300        52060           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1    0 0 0 0 0 2 2 1 3 12 24 40 39 107 121 127 138 100 86 68 44 23 15 7 3 1 1 0 1 1   0 0 2 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 2 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.052000 0.900 0.900 3.400        59454           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 1    0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0    0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 2 0 2 1 0 0 0 1 0    0 1 0 0 0 0 0 3 3 6 21 32 68 90 132 111 122 107 73 57 47 24 11 7 4 2 2 1 0 0 0   0 0 0 0 0 1 0 0 1 0 0 2 0 1 1 0 0 1 0 0 0 0 0 3 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0   0.054000 0.950 0.950 3.500        67013           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0    1 0 1 0 1 2 4 3 7 9 28 31 71 94 115 96 108 78 82 60 38 17 12 11 4 3 1 1 0 2 1    0 0 0 2 1 3 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 2 0 0 0 1 0 2 0 1 0 2 0 1 0 0 1 0 0    0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0   0.056000 1.000 1.000 3.600        75475           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 3 0 0 1    1 2 0 1 4 0 1 8 6 7 17 41 56 71 109 113 84 103 72 54 35 22 6 9 1 7 5 4 0 0 1 0   0 0 0 0 0 1 0 0 2 1 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 0 0 1 0 1    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 1 1 0 0 2 0 0 0 0    0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.058000 1.050 1.050 3.700        83558           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0    2 0 0 1 0 3 2 3 6 15 27 41 77 73 94 94 92 76 61 56 42 23 13 11 6 2 1 2 0 1 2 0   0 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 1 2 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0   0.060000 1.100 1.100 3.800        93087           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1    0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 2 2 0 0 0 1 0 1 1 0 0 0 1 1 0 4    0 0 1 2 0 3 1 3 5 13 33 31 65 75 77 96 97 80 59 45 36 32 18 2 5 0 1 0 0 1 0 0    3 0 0 0 0 1 0 0 0 0 0 1 0 0 1 2 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 2 0 0 2 0 1 0    0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0    0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.062000 1.150 1.150 3.900       102829           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0    0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 2 0 2    1 2 0 0 2 4 3 5 11 9 23 43 53 68 65 87 83 77 59 49 34 18 15 9 4 2 3 2 0 0 0 4    0 1 1 0 0 2 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 2 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 0    0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0   0.064000 1.200 1.200 4.000       113442           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0    0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1    2 0 0 0 2 0 4 5 11 13 29 39 61 68 61 75 76 74 73 44 37 29 19 6 3 3 2 0 1 2 1 0   0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 1 2 0 2 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0    0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0    0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0   0.066000 1.250 1.250 4.100       126668           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1    0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 1 2 3 0 2 1 2 0 1 0 3 0 0 0 1 0 1 1 3    0 0 1 3 0 2 4 3 12 12 30 48 56 66 77 78 71 82 52 31 32 19 20 16 8 2 1 3 0 0 2    1 0 1 0 1 0 0 0 1 3 1 0 1 0 1 1 1 0 0 0 0 0 2 0 2 0 0 0 0 0 1 0 0 0 0 1 1 0 0    0 0 0 1 0 0 0 0 0 2 0 3 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.068000 1.300 1.300 4.200       138042           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 2 0 0 1 0 1 0 0 0 0 0    0 0 0 1 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0    0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 3 0 0 1 0 0 1 2 0 0 0 3 0 1 0 0 3 0    1 0 1 1 3 1 4 7 11 14 27 36 44 68 72 70 71 45 44 46 29 13 16 11 5 2 0 3 0 0 0    0 1 1 2 0 0 1 1 2 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 2 0 0 1 1 0 1 1 1 0    0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    0 0 0 1 0 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   0.070000 1.350 1.350 4.300       152335           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0    0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0    1 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 1 1 1 0 1 1 0 1 1 1 1 0 2 0    0 0 0 0 2 0 1 7 14 19 34 35 54 72 68 72 68 58 48 36 37 27 25 17 1 4 1 0 0 0 1    2 2 0 0 1 1 1 2 1 0 3 1 0 1 0 2 1 0 0 0 1 1 1 2 0 0 0 0 1 1 0 1 1 0 2 1 1 1 1    0 0 0 1 1 0 0 2 0 0 1 0 0 0 1 1 0 2 1 1 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 0 1    0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0   0.072000 1.400 1.400 4.400       166280           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0    0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0    2 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 3 4 2 2 0 0 0 0 0 1 1 3 1 0 3 2 2    1 2 2 0 2 2 1 8 14 26 24 29 47 47 68 65 63 55 42 41 26 29 17 8 4 4 1 0 1 2 0 0   0 1 1 2 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 1 2 1 2 1 0 0 0 0 0 1 1 2 0 2 2 0    0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0    0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0   0.074000 1.450 1.450 4.500       179484           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0    1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 1 0    0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 2 0 0 1 1 2 1 0    1 1 2 2 0 1 5 6 10 20 43 50 57 62 53 62 66 45 42 33 27 26 23 14 3 0 2 0 1 0 0    1 1 0 0 2 1 1 0 0 3 0 1 1 1 0 1 1 0 1 0 1 2 1 0 0 1 2 0 2 0 0 0 0 1 1 3 1 0 0    2 1 1 1 0 0 0 0 0 0 1 2 0 1 0 0 0 0 0 1 1 0 2 0 0 0 0 0 1 0 2 1 0 0 0 0 0 0 1    0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0   0.076000 1.500 1.500 4.600       197657           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0    0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0    0 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 0 2 1 1 0 1 1 0 1 1 3 2 1 1 2 1 0 1 0 0 0 0    0 1 1 1 0 5 3 7 12 24 38 32 41 48 54 66 71 49 46 31 38 25 15 8 6 6 5 0 1 3 0 1   1 1 1 1 0 1 2 0 1 0 0 0 1 0 2 1 2 0 0 0 0 1 3 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0    4 1 1 1 0 3 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0    0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0   0.078000 1.550 1.550 4.700       212054           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0    0 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1    0 0 2 0 0 0 1 0 0 1 0 1 1 0 1 3 1 0 0 1 2 0 0 0 1 0 0 0 0 0 2 1 2 1 1 1 0 0 1    5 1 1 2 3 5 7 9 11 22 31 37 48 50 52 54 57 37 38 38 33 24 11 19 11 3 1 2 0 3 3   2 1 0 1 3 0 1 1 1 1 1 2 0 0 0 1 1 2 0 1 1 3 0 1 1 0 0 1 0 2 0 1 0 0 1 3 0 2 0    1 0 1 2 0 1 1 1 1 1 0 3 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0    0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0   0.080000 1.600 1.600 4.800       231971           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1    0 0 0 0 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 2 1 0 1 1 1 0 1 0 0 1 0 1 3 0 0 0 1 0    0 0 1 1 1 0 0 4 1 1 0 2 0 1 1 1 2 0 0 0 1 0 1 2 1 2 3 2 0 1 0 4 3 1 1 1 1 3 1    0 0 0 2 1 0 2 7 17 13 29 47 58 59 52 38 51 51 38 34 35 21 14 13 4 1 0 1 1 1 0    2 2 4 1 0 1 1 4 0 0 0 2 0 2 2 2 0 0 1 3 2 1 1 2 2 2 2 1 0 3 0 2 1 2 1 2 2 0 0    1 1 0 2 0 2 2 0 1 0 2 2 3 1 2 3 1 1 0 1 0 2 0 1 2 1 2 0 2 1 0 0 3 0 0 1 1 1 1    0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0   0.082000 1.650 1.650 4.900       252503           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0    0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0    0 0 0 0 2 0 0 1 0 1 2 2 2 1 0 2 0 1 0 1 1 2 2 0 3 0 0 4 1 0 0 3 0 0 1 2 0 1 1    1 3 0 1 0 2 9 11 25 27 34 53 41 49 43 47 36 31 38 22 30 22 18 9 5 9 2 2 1 2 2    3 1 4 1 1 0 0 1 2 0 2 1 0 0 1 3 2 2 1 0 0 0 1 2 1 0 0 0 2 1 1 0 2 0 0 1 0 0 2    1 3 1 1 1 0 2 1 1 0 2 1 0 1 3 0 0 0 0 2 0 0 1 0 0 0 0 0 1 2 1 1 1 0 2 1 0 0 0    2 0 1 0 0 0 0 1 0 0 0 0 1 0 0 2 0 1 0 1 0 0 0 0 0 0 0 0 0 0   0.084000 1.700 1.700 5.000       267889           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 1    0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0    0 1 0 1 1 0 3 0 1 1 1 0 1 2 1 0 2 0 2 4 0 1 0 0 0 1 1 0 1 3 2 0 2 0 4 0 0 2 0    1 4 2 4 3 3 6 10 14 28 37 54 36 40 52 40 50 46 40 32 26 29 12 18 5 2 0 2 4 1 2   1 0 2 1 2 2 1 0 1 0 2 1 2 4 1 1 5 1 0 2 0 1 2 3 2 2 1 2 1 0 2 1 2 1 1 4 1 2 1    4 0 2 2 0 0 3 1 0 2 0 0 1 1 1 0 0 2 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 1 0    0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0   0.086000 1.750 1.750 5.100       290294           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0    0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 3 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 2    1 0 1 0 1 0 0 2 2 0 1 2 2 0 2 0 2 0 1 0 0 1 1 1 3 1 1 1 1 3 4 1 1 2 2 2 1 0 3    0 0 0 2 4 5 6 16 18 20 31 40 54 55 46 41 52 35 27 21 28 27 20 15 8 6 7 1 0 0 3   0 0 2 2 0 3 1 3 1 1 2 0 0 1 2 1 3 2 0 1 2 1 3 1 1 1 1 1 2 0 2 1 0 1 1 1 3 1 1    2 0 1 0 1 0 2 1 1 0 0 1 2 0 3 1 1 0 0 0 1 3 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 1 0    0 0 0 0 0 2 0 1 0 0 0 2 1 0 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0   0.088000 1.800 1.800 5.200       312476           6           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0    0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 2 0 0 0 1 0 1 0 0 0 0 0 0 2    1 0 0 1 0 0 1 1 1 1 4 2 0 1 0 0 3 0 0 0 0 0 1 1 4 0 0 0 0 1 1 2 1 0 3 0 0 2 2    4 0 3 1 6 9 10 13 21 24 32 43 33 41 43 49 50 32 26 31 27 12 16 17 3 3 3 5 0 3    0 2 1 3 3 2 1 2 3 1 2 1 1 1 2 0 1 1 0 2 0 3 0 0 2 0 0 0 0 1 0 1 1 3 3 0 1 1 1    1 1 1 2 2 2 0 3 1 0 2 2 2 0 0 0 0 3 1 2 5 1 1 2 0 0 3 3 0 2 2 0 0 0 0 1 2 0 0    1 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0   0.090000 1.850 1.850 5.300       337348           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 2 0 1 0 1 0 0 0 1 0 0 0    0 0 0 1 0 0 0 0 2 0 1 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0    2 0 0 0 1 3 2 0 0 2 2 3 3 2 2 2 0 0 1 1 3 1 3 0 0 0 0 0 0 1 2 1 2 1 2 2 2 0 1    1 0 4 2 2 7 6 15 22 21 39 37 50 31 51 30 33 34 34 26 21 14 13 10 9 4 3 3 4 2 2   0 1 2 3 3 0 1 3 2 5 3 2 2 4 0 2 3 0 4 2 1 2 2 2 4 2 1 3 1 3 2 1 3 1 2 4 1 1 1    1 2 4 1 3 3 3 1 0 4 1 0 1 1 1 1 2 3 0 3 0 0 4 1 1 1 0 2 2 2 1 2 2 0 1 1 0 0 0    2 0 1 0 1 0 0 1 0 0 0 1 3 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0   0.092000 1.900 1.900 5.400       357303           3           0  0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0    0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 3 1 0 1 0 0 0 0 1 0 0 1 0 0 1 1 2 2 0 0 2    2 1 1 1 1 1 1 0 1 0 0 1 1 1 3 1 1 1 1 1 0 1 4 0 1 1 1 3 0 1 1 2 2 2 0 2 3 2 2    2 2 1 2 1 3 8 22 14 32 36 46 39 42 39 29 36 38 26 24 26 18 16 19 10 9 3 6 5 0    3 2 1 1 1 2 0 2 1 1 0 1 1 3 1 0 2 4 2 2 1 4 1 2 2 1 1 0 1 2 0 2 2 2 4 2 1 1 0    2 1 3 1 2 3 4 2 3 2 3 0 1 2 1 0 0 0 4 1 1 1 2 1 3 1 0 5 1 0 0 0 0 0 0 1 0 2 0    1 2 1 0 1 0 0 0 0 0 1 1 0 1 0 1 4 0 0 0 1 0 1 0 0 0 0 0 0 0 0   0.094000 1.950 1.950 5.500       383138           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 0    0 0 1 0 0 2 1 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 2 1 1 1 1    2 1 0 2 0 1 0 3 2 1 3 0 1 3 1 1 0 5 0 1 0 1 2 0 0 1 1 2 0 0 6 1 0 3 2 2 3 4 5    0 4 2 1 5 4 11 15 22 27 28 57 38 38 40 38 39 38 27 26 30 18 14 10 10 4 4 4 3 3   2 2 2 2 1 1 1 1 2 2 3 4 1 2 3 1 2 1 2 2 2 1 3 2 1 5 0 1 1 1 3 2 2 2 1 3 1 1 0    3 2 2 0 0 2 2 2 0 0 0 2 0 1 3 1 2 3 2 1 1 0 1 1 1 0 3 2 2 1 0 0 1 3 1 1 0 1 0    0 0 0 0 1 0 0 0 0 1 0 0 3 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0   0.096000 2.000 2.000 5.600       409868           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 2 0 0    1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 2 0 2 0 0 0 0 1 0 0 2 1    2 2 2 1 2 1 1 1 1 1 2 0 0 1 1 0 1 0 2 1 2 0 2 0 3 1 2 1 3 1 5 0 2 2 1 2 4 1 2    0 3 1 4 7 5 9 13 22 19 31 27 28 41 34 39 37 22 23 21 22 17 23 15 8 9 3 8 0 3 1   2 2 2 3 1 0 4 2 4 2 2 2 2 4 2 1 1 0 2 0 3 0 3 2 2 1 2 2 1 4 1 2 2 1 1 5 2 1 2    1 2 2 1 0 2 4 3 2 1 2 2 3 2 3 1 2 1 1 1 1 2 1 1 2 2 1 2 3 2 1 1 0 2 2 4 0 1 1    1 1 1 0 0 1 1 3 0 0 0 0 0 1 0 0 2 0 1 2 0 1 1 1 0 1 0 1 0 0   0.098000 2.050 2.050 5.700       439102           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 1 0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0    0 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 1 2 0 1 1 0 0 0 0 1 1 1 0 4 0 0    0 2 1 1 0 3 4 0 1 2 2 1 0 3 0 3 2 0 0 2 0 1 0 0 1 0 1 3 1 3 5 0 2 2 3 5 2 2 2    0 3 2 3 6 5 16 21 19 23 28 29 35 42 42 44 39 33 23 30 18 25 24 15 13 5 4 2 2 0   3 3 0 0 1 3 0 1 1 3 2 4 3 4 2 1 1 1 3 1 0 0 2 2 4 2 2 1 4 2 4 2 2 2 1 2 2 1 2    0 4 2 2 3 1 2 1 1 2 2 1 2 4 2 1 4 1 2 2 2 2 0 2 0 3 0 1 0 2 1 0 4 2 1 3 2 1 0    2 1 1 1 1 0 1 1 2 1 1 1 2 0 1 0 2 1 1 0 0 1 0 0 1 0 0 0 0 0 0   0.100000 2.100 2.100 5.800       467340           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 0 1 2 0 0 0 0 0 1 0 2 0 0 2 0 0 1 1 0 0    0 1 0 0 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 2 0 2    2 4 1 0 1 1 2 3 4 1 4 1 5 1 2 1 0 2 2 2 1 5 4 1 5 4 0 1 2 4 2 2 0 2 1 2 5 4 1    1 1 2 5 7 9 16 23 31 15 22 36 36 44 42 29 31 28 28 18 35 12 10 13 8 4 3 2 2 5    1 2 3 3 1 3 3 5 2 0 3 4 1 2 2 3 0 0 5 2 3 6 2 1 2 5 3 4 3 1 1 1 1 2 2 4 0 2 3    1 2 1 2 4 5 4 3 5 2 1 2 0 5 0 2 2 4 1 0 4 1 0 2 1 2 0 0 1 3 2 4 3 0 2 3 3 3 4    2 2 0 0 0 0 1 1 0 3 2 0 1 2 0 4 2 1 1 1 2 0 0 0 0 0 0 0 0 0 0   0.102000 2.150 2.150 5.900       497495           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 2 1 0 0 0 0 1 0 1 0 0 0 0 1 2    0 0 0 0 0 2 0 0 1 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 2 0 0 1 0 0 0 1 0 2 2 1 0 0 0    2 0 2 1 1 1 6 3 2 0 3 2 2 2 1 1 3 4 1 0 1 2 4 2 3 3 1 1 1 1 3 3 1 4 1 3 4 3 2    3 1 2 2 5 11 11 14 26 27 28 28 28 36 39 42 29 33 24 20 29 18 13 17 13 6 10 4 3   3 6 1 0 1 0 2 1 3 2 3 1 2 3 1 2 1 2 0 2 2 3 1 3 1 1 2 4 4 1 4 3 2 2 3 5 5 3 0    2 5 3 5 1 4 1 1 3 4 2 2 2 2 1 3 0 1 1 2 2 4 2 1 3 2 0 1 2 1 0 2 3 1 2 0 0 0 2    0 0 1 3 0 0 1 2 0 3 1 0 3 1 2 2 1 1 2 0 0 0 0 2 0 0 1 0 0 0 0 0   0.104000 2.200 2.200 6.000       529288           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0    0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 3 0 2 0 2 0 0    3 2 2 0 4 0 3 2 2 1 3 1 7 3 1 1 0 4 3 2 1 0 0 3 2 3 5 2 1 4 1 5 1 0 3 2 3 0 1    2 4 7 3 7 8 12 15 20 24 34 39 34 35 27 36 34 23 22 26 15 24 12 12 14 5 3 0 7 1   1 3 5 1 2 2 2 4 3 1 2 5 2 2 3 1 1 4 2 1 3 0 4 5 4 6 4 5 3 3 3 3 1 1 5 0 6 1 2    4 2 3 2 1 3 2 0 0 0 1 3 3 0 1 4 0 3 2 3 0 3 3 0 2 3 4 3 1 1 1 2 5 3 1 2 1 1 2    4 1 0 2 4 1 3 0 0 3 0 1 3 0 1 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0   0.106000 2.250 2.250 6.100       560628           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 1 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1    1 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 2 0 0 0 0 2 0 3 1 1 0 0 2 2 2 0 5 2 1    1 1 1 3 1 2 3 0 1 0 0 0 0 1 0 2 2 1 2 1 0 4 3 2 1 2 1 0 4 2 2 0 2 1 1 2 3 1 2    1 2 4 4 11 12 17 19 19 29 30 24 30 35 51 32 36 34 31 19 22 17 11 19 11 7 6 6 3   4 0 3 3 2 0 2 2 2 3 1 5 3 2 3 5 1 0 2 2 5 4 2 3 2 0 1 6 1 2 2 2 2 1 1 2 2 1 4    3 2 2 1 2 5 2 0 2 0 2 5 4 5 2 1 3 6 1 3 4 4 0 0 6 0 2 6 1 2 2 2 0 1 3 1 3 4 2    1 4 2 1 2 3 3 0 3 1 0 2 0 2 1 0 2 1 2 0 0 1 1 0 2 0 0 0 0 0 0 0   0.108000 2.300 2.300 6.200       593293           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 2 0 2 2 1 0 0 2 0 1 0 1 0 0 1 2 2 1 0    0 1 0 2 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 1 2 2 1 0 1 1 0 1 5 0 2 4 1 0 1 4    2 1 3 2 2 3 2 3 2 0 0 3 4 3 1 3 2 2 0 3 0 2 4 0 3 2 5 1 2 1 4 6 1 2 4 0 3 6 1    7 6 4 5 4 10 16 24 22 20 40 37 44 34 29 21 28 36 36 27 23 24 14 10 4 5 2 5 3 6   2 3 3 1 4 2 1 5 1 3 5 3 2 1 2 2 6 2 3 1 1 0 5 3 3 3 4 5 2 2 3 3 5 5 1 6 2 3 2    6 0 5 2 4 3 5 1 2 2 5 1 2 3 1 2 2 2 4 2 5 5 2 2 2 5 0 1 2 5 2 3 2 3 1 1 2 4 0    2 1 4 2 1 1 1 0 1 2 0 0 1 3 1 0 2 1 1 3 3 2 0 0 0 1 2 0 0 0 0   0.110000 2.350 2.350 6.300       636559           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 0 0 0 1 1 2 0 0 1 0 0 0 0 0 0 0    1 2 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 2 0 1 0 1 0 1 0 0 1 1 3 0 1 2 2 0 2 1    1 1 1 0 1 0 1 3 0 3 2 3 4 3 3 4 3 3 2 6 3 1 1 1 2 4 2 3 1 5 1 3 1 4 5 3 3 2 1    3 7 4 3 10 19 17 19 23 27 28 33 39 36 23 23 32 32 16 19 35 23 12 11 12 8 4 5 7   1 2 2 1 2 3 5 4 2 3 2 6 4 4 2 4 1 2 2 1 2 3 0 4 2 1 2 6 2 2 1 3 3 1 6 4 8 5 2    3 5 2 3 0 3 2 3 1 2 2 3 4 3 8 6 2 1 4 6 3 1 2 0 2 0 2 5 0 3 3 3 3 1 3 3 2 5 4    2 1 4 2 2 4 4 1 3 2 5 2 3 1 2 0 4 0 1 0 6 3 1 2 0 2 0 1 0 0 0 0   0.112000 2.400 2.400 6.400       670484           3           0  0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2    0 1 1 1 3 0 0 0 2 1 3 0 1 1 1 0 1 1 1 0 0 1 2 0 1 3 1 5 2 3 0 4 0 2 0 0 1 2 1    0 1 0 0 1 0 2 2 3 2 3 2 2 2 3 4 4 2 3 5 3 3 2 3 3 4 2 4 0 3 2 4 4 1 3 1 3 4 2    2 5 2 8 6 12 17 14 22 27 26 29 39 30 24 36 22 22 20 9 19 15 5 12 16 4 7 5 7 5    5 1 4 5 5 4 4 1 4 4 3 3 3 4 2 2 4 2 4 4 4 4 0 2 3 2 1 4 3 6 1 3 3 3 4 5 4 2 2    2 5 3 0 2 5 4 2 5 3 5 1 1 3 1 1 3 6 6 2 3 2 0 3 2 4 3 4 1 2 2 6 2 0 3 2 2 5 3    3 5 2 1 0 3 1 1 2 2 0 1 1 3 2 3 2 1 1 1 1 3 2 1 0 0 0 0 0 0 0   0.114000 2.450 2.450 6.500       711783           4           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 1 0 2 1 2 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1    1 2 0 1 1 0 0 0 2 1 1 1 1 1 2 1 2 3 3 1 1 1 2 3 1 3 2 2 1 0 1 1 4 4 4 1 0 4 0    0 1 1 2 1 3 2 0 3 4 1 1 1 1 3 2 0 1 3 2 1 2 1 0 3 3 2 5 4 2 5 3 4 2 2 5 3 3 3    3 5 5 8 7 14 12 28 22 24 23 36 33 26 32 27 26 18 30 24 15 13 19 15 17 6 5 7 5    4 3 5 3 1 4 4 9 5 3 1 4 0 0 6 2 5 3 3 3 1 2 3 2 4 1 5 5 3 8 2 1 1 4 1 7 5 6 6    4 4 3 2 6 3 3 3 3 1 3 4 5 4 3 4 3 1 2 3 1 2 1 2 2 6 5 2 2 2 4 2 2 0 2 3 3 2 7    4 4 1 4 2 0 3 1 1 2 1 2 3 1 3 2 2 4 3 1 4 0 0 4 2 2 2 1 0 0 0 0   0.116000 2.500 2.500 6.600       745364           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 2 1 1 2 1 1 1 0 1 0 2 0 1 1    0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 2 3 0 1 4 4 0 4 0 1 0 1 3 3 0 2 1 2 3    2 1 1 1 2 0 4 0 0 4 5 2 5 4 1 3 5 5 4 0 4 4 2 3 2 3 5 2 2 4 2 3 4 2 3 3 3 3 3    2 4 12 10 13 14 19 22 23 24 36 19 32 25 25 36 24 18 20 21 14 18 13 8 6 9 2 9 5   2 5 3 4 4 3 3 0 4 3 2 5 3 4 2 2 6 3 4 0 2 4 1 3 4 7 4 5 3 2 4 5 5 3 4 4 4 2 3    2 4 4 2 1 5 7 1 5 2 4 1 5 5 3 4 4 3 2 4 2 4 0 6 2 3 4 1 2 2 2 4 1 4 2 2 2 5 6    5 1 4 4 2 3 3 3 1 4 3 4 2 6 2 5 3 2 2 1 3 2 2 5 1 1 0 0 1 0 0 0   0.118000 2.550 2.550 6.700       791846           4           0  0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 1 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 0 1 0    1 4 1 2 3 0 3 1 0 1 1 1 0 3 1 2 1 1 1 0 0 1 1 1 3 1 3 2 3 1 2 2 1 3 2 4 1 4 0    2 4 1 4 3 2 1 1 2 1 3 2 3 3 2 1 1 5 3 3 3 3 2 3 4 3 5 3 1 1 2 2 3 5 1 2 1 1 4    4 6 9 6 6 13 17 21 20 24 22 25 20 29 23 28 30 26 27 18 20 17 16 17 12 10 8 5 6   6 6 4 3 1 2 4 6 9 2 2 3 5 7 6 2 3 8 5 4 5 6 4 6 5 3 5 3 2 5 3 2 8 3 5 4 5 3 5    4 3 4 8 4 3 8 3 3 3 1 1 2 2 5 4 7 3 2 3 3 2 2 3 6 3 2 2 1 1 5 2 5 6 3 5 3 4 1    3 1 2 1 0 4 1 4 2 2 2 3 1 1 1 1 3 2 0 1 6 1 1 0 2 1 0 1 0 0 0 0   0.120000 2.600 2.600 6.800       833394           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 2 1 1 1 2 1 0 0 0 1 0 1 0 0 0 1 0 0 1 1 2 1 0 0    0 0 0 2 2 0 3 1 0 0 2 1 1 1 1 0 1 2 1 5 0 1 0 2 2 1 2 0 4 2 1 4 3 4 2 2 1 2 1    5 2 3 1 3 0 2 2 2 2 3 4 0 4 2 3 3 4 5 2 2 6 3 4 5 5 5 3 4 6 5 1 3 0 5 4 5 1 3    2 2 6 18 13 17 27 27 21 28 28 24 26 27 29 23 21 16 17 19 22 14 11 9 5 14 7 7 6   4 4 12 3 6 4 5 4 6 4 2 0 1 8 1 6 8 5 2 3 4 5 6 4 2 5 8 3 1 1 6 3 7 8 4 1 6 5 2   8 11 5 6 5 6 2 4 5 1 2 7 2 2 5 5 6 3 3 2 3 8 5 1 9 3 3 2 3 6 3 5 3 2 4 6 3 1 3   5 4 4 4 6 3 3 5 0 2 2 5 1 3 2 2 1 4 2 0 2 2 2 2 4 1 2 1 2 1 1 0   0.122000 2.650 2.650 6.900       876007           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 1 1 1 1 2 2 1 0 0 1 0 0 0 1 1 0 0 0 2 0 0    4 1 0 2 1 2 0 1 2 0 1 3 2 1 0 1 1 0 1 2 1 0 2 3 3 5 3 3 3 0 1 4 0 1 5 3 4 3 1    2 2 2 4 1 3 3 3 2 3 2 3 2 1 4 4 2 2 5 5 3 4 1 2 1 2 4 2 4 7 2 4 4 2 7 3 5 7 5    3 6 8 10 10 18 21 22 24 14 25 27 29 31 22 25 24 21 27 20 19 22 19 14 13 14 10    5 7 3 4 5 5 3 1 4 3 8 4 5 4 0 3 4 3 4 1 7 6 1 1 3 4 4 3 4 3 6 4 3 4 2 4 4 3 5    6 5 1 1 6 2 6 6 3 5 5 3 2 6 5 4 3 4 6 4 3 5 5 6 5 6 2 4 2 1 2 2 4 2 7 6 2 1 3    1 5 2 1 2 4 3 3 3 2 5 2 4 1 4 3 2 2 5 5 1 1 3 3 2 2 2 2 1 0 0 0 0 0   0.124000 2.700 2.700 7.000       925764           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 1 3 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0    1 2 0 0 3 2 0 1 2 1 1 2 0 2 1 2 2 0 0 2 3 2 3 2 2 3 2 2 4 0 2 0 5 1 3 2 3 1 2    3 2 0 6 4 3 6 2 5 0 5 2 1 4 4 5 7 4 2 3 5 2 0 2 5 2 4 7 4 4 4 8 5 3 1 7 2 2 1    5 5 5 14 19 16 22 18 30 29 25 36 23 23 22 25 25 27 26 23 14 20 16 16 10 6 6 6    4 2 6 6 6 6 6 4 6 1 0 3 4 4 5 2 4 3 2 4 4 5 5 5 6 10 6 3 6 8 5 5 8 7 4 6 4 3 4   8 5 5 7 4 6 3 5 8 4 3 4 4 3 4 3 1 3 3 7 2 4 8 3 6 4 3 3 2 5 4 4 3 7 4 5 4 4 3    4 7 2 3 3 4 3 0 2 2 4 3 4 2 4 2 2 6 4 4 6 6 1 5 1 1 2 1 0 0 0 0 0   0.126000 2.750 2.750 7.100       969560           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 0 1 2 0 2 0 2 2 0 1 1 1 0 0 1 0 1 1 1 1 2 0    1 2 2 1 2 0 0 1 0 1 0 2 1 0 1 0 1 1 2 0 3 0 3 4 3 1 3 2 0 4 0 1 2 0 3 1 1 2 3    2 2 2 5 1 7 1 5 1 5 4 2 0 0 1 2 1 3 2 3 3 5 4 10 10 2 5 11 4 1 2 1 7 3 5 4 4 1   5 10 8 7 9 9 20 20 21 33 21 28 20 27 32 21 29 22 20 24 15 13 27 14 13 15 10 9    3 11 6 7 5 3 6 8 5 4 4 1 3 3 5 2 7 3 6 6 1 6 4 6 5 3 4 2 4 3 3 9 4 5 4 4 5 2 3   10 4 3 2 6 10 6 3 6 5 5 5 4 8 8 5 4 3 6 4 4 2 4 4 4 5 7 4 4 4 4 5 2 2 3 4 5 2    1 3 2 6 2 7 7 1 6 4 4 6 5 5 4 0 2 2 3 2 7 5 0 4 1 1 4 6 1 0 3 2 0 0 1   0.128000 2.800 2.800 7.200      1022713           5           0  0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 2 1 0 0 4 0 0 1 2 3    1 1 0 1 0 1 0 3 1 1 1 2 2 1 1 1 3 1 0 2 4 2 1 2 1 2 0 3 1 3 2 1 5 2 1 3 1 2 1    5 3 2 1 2 5 3 8 2 3 2 5 5 4 3 6 4 4 4 3 2 3 8 4 3 4 5 4 5 4 7 6 5 3 3 3 5 2 9    10 7 9 12 11 13 17 15 22 19 33 24 28 30 26 21 24 22 27 20 26 16 10 10 9 20 10    7 4 5 7 7 2 7 5 3 5 1 6 1 5 7 5 6 3 1 5 1 1 3 4 8 6 3 9 5 5 3 6 7 4 6 7 6 4 2    4 6 2 3 6 5 6 7 6 4 4 9 6 8 6 9 7 1 2 6 2 7 5 4 4 4 4 5 5 4 4 3 6 3 5 3 6 4 3    6 6 2 5 2 8 4 5 3 6 5 4 5 8 4 3 5 6 5 5 2 8 1 2 2 5 4 1 3 0 0 0 0 0   0.130000 2.850 2.850 7.300      1081669           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 5 0 0 2 2 0 0 1 0 0 0 1 1 0 2 0 2 2 2 1 0    1 0 2 2 3 1 1 0 2 0 1 0 2 1 1 2 2 0 1 4 3 0 2 1 1 0 2 5 2 1 0 1 3 2 5 2 1 2 5    2 3 4 3 6 6 6 4 6 6 3 1 3 2 3 4 7 5 2 9 7 4 1 4 4 3 2 2 2 7 4 8 4 7 4 6 8 5 1    8 6 10 18 21 18 15 21 24 21 26 22 30 28 27 23 22 21 17 25 20 17 13 17 9 12 7 8   5 4 4 5 5 2 4 1 1 2 5 7 6 4 9 7 7 5 5 5 5 5 2 4 5 3 6 8 2 4 9 4 10 5 1 4 5 5 5   10 3 2 8 6 5 7 3 13 3 3 6 5 1 4 5 9 5 2 7 4 5 6 3 5 6 5 4 5 9 6 4 3 4 4 4 5 8    5 5 0 3 6 3 4 3 7 5 6 4 3 3 6 8 4 1 3 1 2 7 3 4 6 6 1 3 4 1 0 1 0 0   0.132000 2.900 2.900 7.400      1131887           3           0  0 0 0 0 0 0 0 0 1 0 0 1 2 1 1 0 0 0 1 2 2 1 1 0 2 1 1 0 1 1 1 0 2 2 3 1 0 1 0    1 0 2 0 2 0 1 4 0 1 2 2 0 0 0 2 3 0 1 2 3 0 1 2 3 5 6 2 2 3 1 4 4 8 4 3 3 3 7    2 2 5 7 4 1 2 4 8 1 5 2 7 3 4 2 9 6 5 5 6 2 2 3 6 2 5 6 7 7 2 8 3 3 3 3 6 6 5    3 10 15 15 17 19 13 29 20 23 22 34 28 28 33 20 20 22 17 22 18 15 19 14 11 9 13   6 6 13 4 2 9 8 8 7 6 5 6 4 4 9 6 2 8 9 7 2 6 3 7 3 6 3 7 4 4 5 4 5 6 4 7 5 4     10 2 6 6 8 3 6 6 9 5 8 8 7 6 4 8 5 7 5 5 7 3 5 5 5 10 7 3 8 7 5 7 2 4 4 6 4 10   7 6 4 4 4 4 3 2 4 2 6 5 9 7 3 2 6 2 5 1 5 6 2 2 1 9 2 5 2 5 1 0 0 0 1 1   0.134000 2.950 2.950 7.500      1185706           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 2 1 0 1 1 0 0 0 0 0 1 0 1 1 2 0 1 0 1 2 0 0 0    1 1 0 1 1 1 0 2 2 0 1 3 3 2 3 0 0 2 2 3 2 1 1 3 0 0 1 1 3 4 3 1 1 9 1 4 0 1 3    4 1 3 2 6 4 7 7 3 2 8 5 2 5 2 4 6 7 3 7 7 8 4 7 2 4 7 7 9 9 2 5 5 8 3 5 7 3 6    10 6 10 15 10 13 14 29 21 23 37 26 20 28 20 16 24 25 16 19 21 20 20 17 11 10     12 8 7 7 5 5 5 4 5 6 7 3 6 5 7 5 11 9 6 8 11 6 4 6 8 8 7 7 7 4 5 4 8 5 4 3 4 8   10 7 9 4 7 6 8 9 7 3 5 7 7 6 2 6 4 7 3 9 8 12 7 6 6 6 4 5 7 2 4 7 3 2 4 4 7 1    4 5 0 4 6 3 10 8 5 4 3 4 5 7 5 7 5 7 3 5 2 5 6 4 5 2 4 1 6 6 2 4 2 0 0 1 0   0.136000 3.000 3.000 7.600      1238426           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 4 0 2 0 2 2 0 1 1 1 0 2 1 1 2 1 0 1 1 0 3 1 0    0 1 0 1 0 0 2 1 1 0 4 0 2 6 3 3 4 0 3 1 2 4 0 4 4 0 1 5 2 2 5 1 3 4 3 3 5 2 4    4 6 2 5 3 4 5 4 5 6 7 5 6 2 8 3 4 7 2 4 4 3 7 6 5 1 4 8 3 7 10 3 3 6 1 5 3 8     11 5 7 15 11 15 17 21 23 21 24 28 16 21 29 15 22 27 28 20 13 19 13 7 15 10 11    9 6 8 8 4 7 5 4 6 5 10 6 7 8 9 3 5 5 9 5 9 4 4 4 3 5 7 4 10 6 8 4 9 8 4 6 7 9    11 6 8 3 5 8 12 3 6 9 7 11 9 6 7 4 7 7 7 2 5 4 5 0 2 9 5 5 5 10 7 5 6 3 9 4 4    13 2 7 5 7 4 7 2 0 4 5 4 4 6 8 1 2 5 6 4 7 3 11 4 3 3 5 5 4 4 3 1 4 2 2 1 1 0   0.138000 3.050 3.050 7.700      1299809           6           0  0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1 2 1 1 0 0 1 0 0 2 0 1 2 0 0 3 0 0 1 3 1    2 0 2 0 1 1 2 1 2 3 2 1 2 5 2 2 2 4 3 2 5 3 0 3 2 4 5 4 3 0 5 4 1 4 3 8 6 4 4    7 4 5 4 3 6 5 6 10 3 6 6 2 6 3 4 4 3 6 7 6 8 3 4 7 5 4 9 2 4 8 5 9 8 3 7 5 7 7   13 7 11 15 17 16 18 18 18 20 17 26 25 19 20 26 31 22 18 20 18 14 11 16 4 7 11    10 8 9 9 6 3 8 8 7 5 6 10 3 5 6 6 3 12 7 8 8 2 10 4 13 9 9 12 4 5 9 7 9 5 7 4    8 9 6 7 8 10 8 7 5 7 11 6 4 4 4 6 4 9 4 5 9 10 7 4 12 7 4 9 5 10 10 6 8 4 7 2    4 7 2 6 8 4 11 3 3 9 7 6 7 3 8 7 4 8 5 3 7 4 5 5 7 4 6 7 5 5 3 5 2 5 4 1 2 0 0   1   0.140000 3.100 3.100 7.800      1361810           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 2 1 0 0 0 1 1 1 2 0 0 0 0 1 0 2 2 2 1 0 0 3 3 0    2 0 6 2 3 1 0 3 3 1 2 2 5 3 5 3 3 2 2 7 3 2 2 3 4 2 3 4 4 1 3 7 4 5 4 2 3 5 4    2 1 3 6 3 4 3 8 7 6 5 3 5 11 5 5 3 3 7 3 6 4 4 2 4 4 4 1 5 5 9 6 6 9 3 10 8 6    8 3 10 8 16 16 13 18 23 29 25 19 19 20 27 19 22 27 24 21 15 18 11 20 21 17 12    5 18 6 12 7 9 11 7 12 11 4 8 8 4 8 7 7 2 6 4 4 9 6 9 3 4 7 7 7 4 10 4 11 5 8 8   8 5 4 4 8 6 4 9 8 12 12 8 5 8 3 10 8 7 5 3 5 6 8 5 6 10 7 2 11 2 5 5 6 8 10 2    7 5 5 14 2 7 3 9 3 5 2 8 2 3 4 4 7 9 5 4 7 6 7 5 6 3 5 4 7 6 7 7 9 3 0 2 1 1 1   0 0   0.142000 3.150 3.150 7.900      1429499           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 1 2 1 1 0 0 0 3 0 2 2 1 0 3 0 2 1 3 0 0 1    1 3 1 2 4 1 5 3 5 1 0 7 1 3 2 3 2 2 2 3 0 0 1 3 6 3 2 2 4 4 4 6 4 3 6 4 10 3 7   2 5 4 7 4 5 8 4 7 4 1 7 11 5 2 10 2 11 3 7 8 10 9 6 3 5 3 6 3 10 11 5 5 9 7 10   8 9 5 15 11 9 18 18 15 24 17 23 17 19 25 17 24 18 37 16 17 21 17 14 20 17 15     15 9 4 11 7 3 8 10 8 8 6 8 3 4 5 8 4 6 3 9 9 6 2 10 4 4 3 8 4 9 1 7 5 9 7 10 9   10 4 6 5 8 6 6 10 10 6 5 7 6 6 10 5 7 8 8 8 7 7 11 12 8 3 10 6 9 13 11 4 6 7 6   3 10 5 8 4 7 7 7 5 8 4 9 5 5 7 6 6 7 11 11 7 8 5 3 5 7 7 10 3 3 6 5 7 9 2 3 7    1 0 0 0 0 1   0.144000 3.200 3.200 8.000      1493946           3           0  0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 2 3 0 0 1 2 1 1 1 4 1 0 1 0 1 2 1 3 1 1 1 1 2    1 1 3 2 6 0 4 0 1 4 2 4 5 2 1 3 0 2 2 4 2 3 2 4 3 5 4 4 4 1 5 1 3 4 5 6 4 7 2    8 8 8 5 3 6 0 7 3 2 2 5 7 5 7 5 8 9 6 4 3 6 8 6 10 2 5 6 3 3 6 6 6 6 17 5 10 6   6 11 11 13 12 21 26 18 24 21 24 23 30 18 22 20 24 19 13 17 25 22 17 15 8 13 7    10 8 9 6 7 9 8 7 8 9 7 7 6 12 5 9 9 12 9 12 6 9 7 10 7 7 4 9 7 4 2 7 4 5 8 8 9   7 6 7 5 9 4 8 13 6 5 4 7 9 6 7 7 9 4 4 5 8 10 9 10 6 6 7 9 12 11 8 8 9 11 5 8    7 5 5 8 5 9 10 5 5 11 11 6 8 8 4 8 5 5 5 4 7 4 5 6 5 6 6 7 7 4 2 6 3 2 1 0 0 0   0 0   0.146000 3.250 3.250 8.100      1562352           5           0  0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 2 0 1 2 1 1 0 0 1 0 1 2 0 0 0 3 1 2 0 4 4 2 0    0 2 3 2 0 1 3 3 4 0 1 4 3 3 4 5 5 4 2 1 4 2 5 3 2 7 6 3 5 6 5 5 5 1 5 2 7 4 8    7 4 6 5 7 5 3 5 8 1 6 4 6 8 7 6 7 6 3 4 6 3 5 8 4 10 3 3 11 6 5 3 9 6 4 3 17 9   11 11 24 13 15 14 25 26 26 21 17 32 32 22 18 25 29 29 27 24 21 12 23 14 12 11    9 17 7 9 11 3 7 6 5 5 12 3 6 8 7 4 7 11 10 8 9 5 8 2 10 9 8 10 10 7 7 4 7 5 7    7 9 10 8 7 7 16 6 8 10 5 6 6 12 12 7 11 11 8 9 7 8 12 10 7 8 7 11 8 9 7 7 4 9    4 7 14 9 8 8 13 9 8 7 13 5 9 5 7 4 9 5 7 8 7 8 7 3 10 9 3 4 4 4 5 2 6 6 3 5 10   4 4 2 3 0 1 0 0   0.148000 3.300 3.300 8.200      1630559           3           0  0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 4 2 1 1 1 2 1 2 0 2 1 5 0 1 1 4 0 2 1 4 5 3 0    1 1 1 2 1 3 3 3 1 1 1 1 1 3 4 6 6 8 8 4 3 2 7 2 2 1 7 4 4 5 1 10 6 4 4 4 3 3 3   6 11 6 4 5 4 8 5 5 9 4 5 5 7 6 4 13 12 3 6 7 5 2 7 9 7 8 8 4 7 6 4 10 6 8 9 9    9 13 15 17 23 25 13 16 24 22 26 21 27 24 24 21 21 21 15 17 22 25 21 22 17 14     11 8 12 5 9 7 8 5 11 10 6 6 5 9 13 10 9 8 8 8 6 4 9 10 9 9 7 8 7 5 7 8 14 13 5   14 5 12 11 8 9 6 5 4 9 13 7 10 13 11 11 8 5 9 10 8 7 6 7 13 3 13 8 7 13 17 5 8   5 10 7 12 7 6 6 9 7 8 8 11 8 11 9 11 11 8 5 6 10 4 9 3 10 8 7 10 8 7 8 10 10 7   4 11 5 7 8 2 4 3 0 0 1 0 1   0.150000 3.350 3.350 8.300      1707576           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 2 1 0 2 0 2 3 1 3 2 2 2 2 0 2 1 4 3 2 2 3    1 2 1 0 2 2 4 2 5 3 3 5 2 8 4 5 4 2 3 6 7 6 1 0 7 4 7 7 6 5 4 3 4 6 6 7 6 2 7    4 4 2 5 5 6 9 3 3 3 6 6 5 3 5 7 8 8 6 8 8 6 8 3 9 6 6 8 8 6 4 8 6 6 10 4 11 6    11 15 23 16 8 17 20 21 19 24 15 14 19 21 30 25 21 15 19 16 18 21 21 15 14 12     16 8 10 12 7 10 9 8 10 10 7 9 8 10 12 6 6 9 11 6 5 9 12 6 7 12 7 5 6 8 5 9 4     11 9 8 8 10 7 6 10 7 11 13 7 4 13 11 8 11 9 16 6 12 11 10 10 19 2 9 11 8 7 8 8   6 13 6 10 12 12 9 12 9 9 8 7 7 9 6 12 8 4 9 9 8 5 7 8 9 5 12 5 7 5 9 10 9 10 3   6 6 8 7 11 3 5 5 4 2 0 0 0 0   0.152000 3.400 3.400 8.400      1777231           3           0  0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 3 1 0 3 4 2 3 3 3 3 3 2 1 1 1 1 3 3 0    1 8 0 0 5 3 7 4 4 4 4 4 3 5 2 2 5 3 6 1 7 6 1 2 2 5 2 1 6 6 8 7 7 5 10 4 1 6 9   3 4 5 3 5 8 4 9 8 11 8 3 2 7 7 9 10 9 10 8 6 8 6 8 7 10 8 7 3 8 4 10 7 6 8 9 6   5 16 9 19 24 23 17 23 24 22 30 21 15 23 27 20 20 20 18 20 23 18 17 15 19 17 18   13 9 4 4 7 12 7 10 4 8 6 10 5 6 13 2 3 8 7 8 7 3 11 8 7 9 7 19 7 8 9 6 14 8 8    11 10 11 13 14 10 16 8 9 13 8 9 9 12 7 12 11 6 9 15 5 9 9 9 11 11 13 6 10 6 4    12 9 9 12 11 8 6 9 16 10 10 10 8 10 10 6 7 4 1 15 6 8 4 9 13 11 8 10 11 9 8 3    3 6 6 7 9 4 6 8 7 4 2 1 2 2 1 0   0.154000 3.450 3.450 8.500      1849489           6           0  0 0 0 0 0 0 0 0 0 0 1 1 3 0 1 2 2 0 1 4 1 1 0 1 0 2 1 0 0 1 1 1 1 6 3 6 1 3 1    3 3 0 6 0 4 2 7 4 6 4 4 3 7 4 5 7 5 5 2 3 9 9 2 5 5 3 9 4 2 7 6 2 8 2 5 7 12 6   5 4 5 10 4 12 10 6 4 14 7 9 10 11 7 7 7 7 3 9 7 4 3 8 7 5 7 9 6 8 9 6 8 8 12 6   5 11 12 13 11 13 21 26 19 23 25 18 23 22 23 23 18 27 20 15 20 25 24 19 18 12     14 13 15 8 15 10 11 7 9 13 11 12 13 11 11 7 11 13 6 5 10 6 6 10 8 14 5 14 11 8   5 9 7 10 10 8 7 15 13 3 13 12 18 15 7 10 9 10 8 15 9 6 8 9 10 10 9 5 7 7 5 10    11 13 12 12 12 10 6 17 10 11 9 4 8 7 6 6 9 12 8 16 18 7 5 10 8 12 10 15 6 13     11 6 10 16 10 11 16 8 9 5 11 10 14 11 5 2 5 7 3 1 1 0 1 0   0.156000 3.500 3.500 8.600      1920727           4           0  0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 2 1 2 0 3 0 1 1 0 1 0 3 0 4 4 1 3 1 2 3 3 4 3    1 2 3 9 5 2 3 7 3 3 6 5 2 6 1 4 3 2 3 6 5 1 8 3 8 5 3 7 6 13 11 9 5 8 7 7 5 8    7 4 8 6 4 10 4 6 5 6 9 9 12 6 7 10 9 9 8 8 3 8 9 8 8 2 12 11 13 8 13 7 8 6 6 9   6 8 16 13 14 16 16 22 20 21 21 17 20 18 19 22 20 11 20 22 21 14 19 15 23 17 15   12 14 19 16 10 11 14 11 9 11 9 12 8 16 14 9 6 18 10 11 7 10 11 17 10 13 8 10     12 9 12 7 7 10 10 11 11 9 8 8 14 10 10 9 14 9 14 13 9 19 16 17 4 11 8 12 11 10   21 6 10 8 9 12 9 7 7 12 7 16 14 10 13 6 13 8 9 10 6 10 8 7 10 4 6 11 19 12 6 7   5 8 11 10 12 13 9 6 10 5 11 11 4 14 10 7 2 6 5 1 2 5 1 1 0 0   0.158000 3.550 3.550 8.700      1999833           3           0  0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 3 2 2 2 1 2 3 0 1 0 1 3 2 0 0 3 2 3 2 5 7 0    3 4 1 10 7 7 4 5 2 3 4 3 8 3 6 4 4 4 8 2 3 4 5 5 7 1 6 7 8 1 6 8 1 4 4 11 9 4    7 11 9 10 5 6 8 4 3 9 7 9 11 5 5 8 8 4 8 7 8 11 9 12 6 4 13 4 12 10 6 9 11 10    11 10 11 11 11 14 15 14 23 18 17 29 16 26 23 15 19 14 18 19 22 31 13 21 20 12    16 15 14 18 17 15 8 12 14 13 10 10 10 10 10 13 11 6 8 11 8 14 8 10 11 11 8 10    13 5 14 7 12 9 10 10 12 15 18 8 6 9 9 12 8 9 20 14 16 10 11 14 5 5 13 6 11 9     11 15 6 9 13 11 7 8 7 10 8 16 12 11 8 10 14 11 17 11 8 16 13 9 10 5 10 17 13     14 16 8 10 9 11 5 10 9 10 12 8 11 12 11 8 6 7 12 15 13 12 7 13 5 0 3 2 0 0 0 0   0.160000 3.600 3.600 8.800      2073149           3           0  0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 1 2 1 2 2 1 0 2 2 1 0 3 6 4 5 5 2 2 2 5 5 3 6 4    6 4 5 2 4 4 3 2 4 6 3 3 6 5 7 4 5 7 5 3 5 6 13 5 3 10 5 9 7 4 5 6 5 10 6 5 5 6   6 4 14 7 6 11 6 9 10 9 8 5 3 8 10 10 6 6 8 9 5 6 14 7 11 10 9 9 11 13 8 4 5 10   12 6 16 8 8 7 19 20 23 10 16 27 25 23 19 26 21 16 20 21 24 18 25 8 11 13 16 18   13 22 18 9 16 4 16 10 12 13 9 7 9 8 17 11 10 13 10 14 4 9 12 16 8 9 16 17 13     11 14 8 8 13 9 11 15 10 11 14 8 6 4 9 11 18 9 9 8 9 15 11 11 11 9 6 13 13 10 7   8 10 15 14 9 7 4 10 12 17 10 14 13 10 10 12 20 9 7 6 11 15 11 10 8 9 6 10 13     17 6 8 9 6 13 13 16 10 15 5 11 14 11 12 6 5 12 9 4 9 2 4 1 1 0 0 0   0.162000 3.650 3.650 8.900      2156456           5           0  0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 2 0 1 1 3 2 3 4 3 3 2 1 3 6 5 2 3 4 4 3 6 2 3    4 4 5 5 3 4 1 4 5 9 3 3 4 3 3 8 5 6 12 2 10 3 4 6 8 9 8 8 2 2 7 5 8 2 8 9 7 2    6 8 6 5 8 2 7 5 6 13 5 6 8 11 6 10 5 6 3 8 10 11 10 10 14 10 11 8 11 8 12 6 12   5 15 12 13 10 13 13 18 23 12 21 18 21 23 20 30 20 23 26 24 24 21 21 29 19 21     16 23 20 13 19 13 16 11 15 13 13 11 8 11 14 14 13 4 16 15 18 13 9 19 8 11 6 9    14 8 13 12 13 10 13 10 14 11 13 11 8 10 13 11 11 14 11 8 14 11 10 9 14 12 14     18 8 12 7 13 12 10 14 14 8 12 17 11 13 9 12 12 15 7 9 13 17 11 11 11 12 17 12    11 16 15 8 9 12 7 13 15 11 16 7 10 7 14 5 18 10 10 8 8 6 6 13 14 6 9 11 9 9 3    5 1 1 3 0 0   0.164000 3.700 3.700 9.000      2234753           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 4 1 4 2 1 3 1 1 3 2 3 3 1 3 6 2 4 4 3 3 3 6 5 2    6 4 1 3 3 7 1 4 4 6 12 4 5 2 6 4 9 3 1 8 11 5 2 7 6 3 8 4 7 3 8 3 9 6 7 8 9 2    7 6 9 6 15 6 9 5 9 4 9 17 15 10 2 10 6 8 12 12 11 12 10 9 7 11 8 7 5 11 10 14    16 7 7 7 13 15 10 16 17 21 19 14 18 24 19 27 27 24 20 22 24 21 20 14 24 17 17    18 32 15 12 13 15 12 8 14 11 11 19 11 14 15 18 10 5 12 11 11 9 15 9 7 9 16 12    9 12 10 15 9 18 7 11 12 14 7 20 8 10 13 14 11 6 6 9 11 8 10 16 8 17 13 17 9 16   11 10 9 13 20 17 14 12 10 13 11 9 9 17 20 10 16 8 14 13 14 18 15 15 8 10 12 11   22 12 13 9 12 9 11 14 19 12 12 8 8 12 11 19 11 11 12 15 11 15 13 9 9 10 9 4 9    4 2 1 0 0   0.166000 3.750 3.750 9.100      2327990           3           0  0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 0 1 2 2 1 1 0 0 3 1 4 2 6 4 2 4 3 2 5 5 2 3 1 3    1 2 10 2 7 4 3 4 3 3 4 3 10 6 9 6 3 8 5 5 3 4 4 6 8 4 4 7 5 5 11 14 5 3 6 8 8    7 10 11 7 17 7 11 10 8 7 8 12 13 11 12 6 13 9 7 7 6 5 8 13 10 10 14 11 11 8 12   15 14 9 13 10 9 18 13 18 12 23 14 17 24 15 23 25 31 19 17 29 19 19 19 26 25 19   17 22 19 19 19 11 11 12 22 21 8 10 18 10 14 19 17 13 14 10 6 9 10 15 11 5 13     13 11 11 17 16 9 7 14 7 19 6 10 13 7 12 18 14 7 12 15 13 13 9 13 13 13 12 12     14 12 19 10 16 18 18 12 8 10 10 9 7 14 9 11 13 12 8 15 12 11 10 12 11 17 15 19   14 14 12 7 7 12 11 15 16 12 11 12 10 19 19 12 14 12 15 11 20 13 7 18 9 15 19     16 11 5 9 8 6 2 4 0 2 0 1   0.168000 3.800 3.800 9.200      2406866           3           0  0 0 0 0 0 0 0 0 0 1 0 2 0 1 0 2 3 2 3 1 2 1 2 2 5 2 1 2 3 2 2 2 5 3 5 3 3 1 3    6 8 6 1 3 9 6 3 6 10 5 5 7 4 5 7 12 9 5 7 5 6 6 8 3 5 4 7 8 5 6 5 8 13 4 10 2    10 9 7 7 16 9 10 9 13 8 12 9 13 15 9 15 9 10 11 6 6 6 7 7 6 8 15 9 8 9 6 12 12   11 14 12 11 13 8 17 18 18 11 14 19 14 25 21 15 10 15 19 27 23 22 24 17 19 18     12 16 22 21 25 9 25 15 19 15 21 15 8 11 13 12 10 12 7 13 11 17 11 13 10 16 19    14 23 11 8 12 13 10 9 17 4 14 10 7 10 17 14 11 11 20 18 13 8 12 6 8 13 12 23     15 14 15 16 9 14 9 13 14 17 11 17 11 10 15 17 11 6 12 12 14 15 17 12 16 16 8     17 15 15 10 15 11 10 15 12 13 9 12 9 12 15 12 6 18 7 15 14 12 21 18 11 10 18     11 19 11 7 11 3 2 5 4 0 1 1   0.170000 3.850 3.850 9.300      2508471           7           0  0 0 0 0 0 0 0 0 0 0 0 0 1 3 1 2 1 4 3 3 1 2 7 0 3 2 2 2 2 5 2 3 2 3 3 4 3 7 3    5 3 4 4 6 2 3 10 4 11 3 13 7 7 5 6 3 8 10 6 6 4 10 11 4 12 7 8 9 7 7 8 4 6 7 9   9 5 9 11 5 14 9 10 7 9 8 8 5 6 11 13 14 10 10 10 10 8 9 9 9 9 14 14 13 11 8 18   9 10 9 16 12 13 15 13 10 17 16 20 14 22 20 26 29 29 27 24 20 37 21 24 13 18 13   28 24 22 25 21 13 14 15 9 11 18 8 16 17 16 13 12 16 11 11 17 15 11 15 10 11 12   13 12 12 20 15 14 15 16 12 17 15 15 12 10 14 14 17 15 19 15 13 13 11 12 16 14    17 16 8 16 12 8 14 13 13 10 10 9 12 11 19 20 13 11 4 15 11 14 11 20 18 18 13     20 12 20 21 15 15 12 13 18 18 11 16 9 14 9 18 11 10 11 20 11 13 17 13 13 12 14   16 10 12 12 23 12 11 12 8 8 1 0 1 2 0   0.172000 3.900 3.900 9.400      2591210           3           0  0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 4 4 3 2 1 3 3 2 3 0 3 6 1 3 1 5 5 4 3 9 9 0 4 7    5 3 5 5 8 7 3 3 5 5 8 5 11 10 8 10 3 6 6 6 7 7 8 8 12 9 6 10 8 7 10 8 8 10 4 6   12 20 4 6 11 7 9 10 7 5 10 6 12 11 7 13 13 16 12 6 8 14 13 9 7 5 14 17 17 10     12 11 6 13 11 17 3 23 13 21 12 21 28 11 23 30 28 23 24 26 26 17 21 15 27 23 33   16 22 25 11 20 22 23 21 20 7 21 13 16 12 16 16 13 18 18 9 13 16 15 9 20 13 19    15 8 9 11 14 13 10 9 10 16 15 14 17 15 19 16 12 14 12 14 14 16 19 19 4 24 8 12   15 16 11 15 14 20 14 13 13 14 16 19 14 13 19 14 18 23 15 15 4 14 17 14 8 10 15   20 11 15 19 12 9 13 12 11 16 12 16 13 14 16 13 16 16 19 19 12 11 10 19 15 15     14 12 5 11 18 17 10 13 12 9 6 2 0 0 1 0   0.174000 3.950 3.950 9.500      2675515           3           0  0 0 0 0 0 0 0 0 0 0 2 0 1 1 0 2 1 2 3 3 1 3 1 3 7 5 3 6 4 3 9 4 5 2 5 3 3 3 6    9 5 5 2 6 8 5 8 4 8 5 6 5 6 4 6 3 7 11 6 9 9 3 6 6 7 6 8 7 9 12 18 6 9 8 11 11   8 14 15 15 11 15 13 9 19 10 15 14 9 4 18 5 8 10 8 10 13 9 12 11 8 8 12 6 15 8    9 9 18 7 17 21 9 13 18 14 21 24 18 22 17 26 15 21 23 25 19 26 23 20 27 17 27     20 26 15 22 15 19 15 16 24 12 15 24 13 13 17 11 7 10 21 15 15 16 13 20 22 12     16 12 16 15 14 18 11 12 14 14 24 10 13 16 19 8 11 18 19 15 15 23 16 16 11 12     18 11 13 14 16 10 14 13 18 12 15 15 14 8 11 17 12 22 13 12 14 15 10 11 15 19     15 12 17 8 21 23 13 19 11 8 12 15 11 14 15 19 15 10 17 9 16 14 18 14 16 14 14    23 14 14 13 16 12 14 15 14 9 14 7 5 2 3 1 1 1   0.176000 4.000 4.000 9.600      2779386           5           0  0 0 0 0 0 0 0 0 0 0 0 2 2 3 0 1 3 0 6 2 6 3 1 5 0 4 1 6 5 1 6 3 6 5 6 2 5 4 5    3 9 8 5 7 5 8 4 12 8 12 6 8 5 7 5 7 10 5 5 6 7 9 7 10 7 10 10 8 12 10 6 13 10    11 12 11 10 10 16 9 6 12 9 11 17 10 11 10 14 11 16 7 11 13 12 10 17 14 11 13     12 10 13 16 16 17 17 15 14 11 8 15 13 27 22 14 19 17 22 22 27 18 28 19 27 32     24 33 21 17 23 12 27 25 20 20 17 22 14 15 22 21 14 9 16 12 19 16 17 16 16 20     14 18 15 14 18 10 12 9 16 12 12 10 13 19 12 12 15 14 15 22 12 11 15 18 19 18     10 6 11 14 10 23 17 14 16 19 10 10 16 19 17 23 16 18 19 18 16 12 14 14 14 13     11 10 24 21 22 26 18 18 18 14 17 5 13 17 11 13 16 14 18 16 9 15 15 18 16 14 21   13 22 17 9 8 16 17 16 16 19 7 20 19 18 16 10 6 10 6 3 5 1 0 0 2   0.178000 4.050 4.050 9.700      2869617           3           0  0 0 0 0 0 0 0 0 0 0 2 2 2 0 1 4 1 3 2 2 1 2 3 2 2 4 4 7 5 6 5 3 6 6 5 7 8 1 5    2 3 5 5 8 10 7 6 10 9 6 8 9 7 8 10 15 4 10 5 8 8 6 11 8 8 11 7 5 8 14 5 11 7     13 10 9 7 8 9 14 12 10 9 11 6 14 15 14 13 11 9 18 18 10 14 14 10 12 16 12 9 8    14 15 6 11 11 12 10 14 12 11 18 13 13 27 16 23 23 20 21 32 20 18 25 22 24 32     25 34 19 23 21 25 22 25 19 23 19 21 16 19 16 18 9 18 6 13 12 13 18 12 8 19 14    14 11 16 13 15 14 21 11 14 14 13 11 20 14 14 26 10 22 16 18 15 20 24 18 19 19    16 14 14 14 21 13 19 18 20 13 17 11 17 14 22 17 15 15 20 8 21 15 16 16 23 17     13 19 21 20 12 15 18 15 19 15 18 17 20 15 13 14 24 18 15 15 14 18 20 19 17 19    20 21 21 15 19 19 17 11 16 16 11 23 10 20 13 10 5 10 2 3 1 1 0   0.180000 4.100 4.100 9.800      2975040           3           0  0 0 0 0 0 0 0 0 1 0 0 1 2 2 4 4 2 4 4 1 2 5 0 3 3 5 2 5 5 4 9 2 7 8 4 8 3 11 6   10 4 7 8 6 6 5 8 8 7 11 4 4 11 12 7 11 7 10 11 7 11 11 10 9 7 13 12 18 8 14 12   14 12 8 8 16 10 10 14 16 10 6 8 15 15 15 22 13 19 18 12 6 11 10 7 12 12 24 15    17 9 17 21 10 17 18 14 14 14 9 22 11 23 17 15 23 32 20 11 12 20 15 23 30 20 25   19 26 29 19 27 23 15 19 11 30 16 21 24 18 18 14 8 6 25 13 21 13 13 19 13 21 25   23 18 14 14 13 20 12 14 8 10 25 14 15 20 15 10 15 16 21 8 15 20 21 20 13 16 15   20 11 18 17 17 9 12 24 19 13 18 17 20 14 15 20 10 23 19 25 8 7 13 14 11 15 18    13 10 12 10 17 11 24 16 17 11 12 13 16 20 14 26 12 17 13 14 16 16 6 20 16 23     22 11 17 16 14 25 19 17 21 22 19 13 19 16 18 10 11 7 4 6 0 0 2   0.182000 4.150 4.150 9.900      3083416           6           0  0 0 0 0 0 0 0 0 0 0 2 1 1 4 1 3 4 3 5 6 2 1 4 2 3 5 6 6 7 2 4 1 11 7 5 2 6 6 8   9 8 12 7 11 9 6 12 7 8 9 6 6 8 11 6 6 8 11 8 11 12 11 13 9 10 7 9 6 11 9 13 12   12 8 14 15 8 9 8 8 11 22 16 6 11 16 15 9 13 12 12 13 11 15 9 9 16 14 14 12 21    12 12 12 16 19 10 15 18 8 16 14 16 16 21 30 22 9 25 19 19 26 23 33 25 22 21 19   21 20 20 21 20 26 20 29 27 25 25 21 20 25 21 21 18 14 19 15 6 20 18 16 20 16     13 13 15 15 15 15 22 16 15 15 11 21 19 11 19 13 14 15 17 21 12 18 12 22 18 21    18 13 23 15 18 9 21 11 14 23 18 21 25 18 22 15 21 23 15 15 16 19 21 18 19 21     17 13 24 23 22 19 14 20 22 15 14 14 20 20 23 13 18 15 18 20 20 24 9 12 17 21     21 12 16 17 16 16 21 26 19 15 21 22 24 15 11 13 13 6 8 1 4 0 1 0   0.184000 4.200 4.200 10.00      3174897           3           0  0 0 0 0 0 0 0 0 0 0 1 1 2 3 0 5 4 3 3 0 7 3 2 4 2 8 6 4 5 9 3 8 6 4 2 7 6 8 7    9 3 5 8 5 9 7 7 6 11 14 7 12 9 9 5 15 12 14 15 12 9 11 5 8 13 11 12 10 9 17 12   11 8 17 11 19 11 15 9 11 7 15 14 16 16 16 7 12 10 14 13 13 16 16 11 15 13 14     12 16 11 12 13 17 10 13 19 11 17 11 13 14 13 10 19 19 23 24 22 24 24 31 19 23    22 28 21 25 29 17 23 17 21 30 22 19 25 27 27 22 23 23 17 25 17 20 17 12 23 21    9 17 20 16 19 16 17 20 9 16 11 22 16 15 12 15 17 23 24 16 16 18 26 11 16 20 18   10 14 17 26 19 17 15 17 19 12 21 20 24 17 27 13 16 18 19 23 14 19 14 10 11 18    19 6 15 21 23 25 17 17 18 21 27 20 17 18 20 25 22 20 18 22 18 17 15 24 16 15     22 18 22 14 20 20 22 18 22 25 19 26 12 19 19 13 12 16 19 14 9 7 5 4 2 0 2   0.186000 4.250 4.250 10.10      3283256           3           0  0 0 0 0 0 0 0 1 0 0 1 1 4 1 5 2 5 5 3 4 6 3 2 4 7 8 2 6 6 4 10 7 8 7 5 4 4 9 8   18 10 7 6 6 13 12 10 13 10 7 15 4 7 10 13 12 8 8 13 5 14 6 9 14 9 10 16 12 13    11 8 12 11 10 13 9 11 15 17 23 18 13 10 12 11 12 14 14 14 10 12 12 16 13 15 13   13 14 18 10 13 17 14 14 14 12 12 8 18 14 23 20 16 19 16 16 16 27 18 21 19 20     19 37 22 21 22 28 24 26 18 21 28 21 22 21 21 22 16 15 13 22 22 27 22 11 13 20    10 17 16 19 20 30 18 25 8 7 22 18 17 14 23 16 17 11 16 24 19 18 22 15 15 23 16   13 15 22 14 8 12 18 13 15 22 17 15 15 17 27 21 19 21 24 17 10 12 14 19 17 22     18 19 17 28 19 15 14 16 28 17 20 15 11 22 18 19 16 21 17 24 19 22 22 20 10 20    18 18 18 21 18 23 18 32 26 21 21 22 20 22 16 17 20 22 21 17 13 13 11 9 5 0 1 1   1   0.188000 4.300 4.300 10.20      3396610           5           0  0 0 0 0 0 0 0 0 0 0 1 2 3 0 2 5 5 4 3 3 5 1 2 3 6 9 3 3 3 8 7 2 9 5 7 5 11 8 9   7 6 9 6 4 5 8 6 10 9 14 10 15 6 7 13 15 10 13 7 15 10 10 11 14 14 6 7 17 13 19   3 13 9 6 13 13 14 10 11 12 16 17 13 10 15 15 19 19 11 11 15 11 13 9 13 20 8 18   14 18 23 23 23 15 19 20 14 11 7 18 16 15 22 28 20 24 22 25 17 20 39 24 26 25     25 33 25 25 25 33 15 29 18 29 18 12 18 23 17 24 28 22 16 20 33 23 18 23 26 23    15 24 16 16 16 16 17 15 15 16 14 11 9 23 17 13 13 18 12 19 20 30 20 20 15 21     19 16 18 20 23 19 15 10 11 15 19 13 22 22 18 19 16 19 23 16 10 25 23 20 21 20    31 19 19 18 15 22 18 14 13 21 18 19 22 19 16 17 21 14 20 26 18 26 22 19 26 19    20 22 15 13 24 23 15 21 21 21 27 18 22 19 24 17 22 16 18 23 10 12 3 5 3 3 0 0   0.190000 4.350 4.350 10.30      3502025           3           0  0 0 0 0 0 0 0 0 0 0 0 3 0 3 2 3 4 4 3 4 5 10 7 6 6 4 5 12 10 6 6 13 10 6 7 14    9 6 13 10 12 16 3 9 9 7 5 6 13 11 10 8 11 19 12 14 13 16 13 14 9 12 14 13 14     16 10 14 7 16 18 16 9 15 11 20 15 10 14 14 11 14 17 10 6 16 10 15 12 17 17 20    15 7 12 23 15 8 13 12 8 16 15 20 16 16 20 14 11 20 24 23 20 16 18 27 25 31 27    27 25 21 31 27 20 23 24 32 17 21 34 27 17 19 19 25 30 27 21 24 28 30 19 26 21    14 16 21 23 27 8 17 21 17 11 23 15 22 15 18 10 17 20 23 18 18 17 19 22 15 22     21 19 23 18 18 26 17 18 26 18 24 15 22 23 23 19 23 25 23 24 26 10 21 16 32 23    18 19 24 21 28 26 22 19 19 14 30 21 24 23 22 21 13 27 20 27 24 15 20 22 22 13    25 14 19 32 21 18 18 23 22 22 14 18 20 24 14 19 20 18 17 24 29 27 20 12 18 17    11 9 2 3 2 1 0   0.192000 4.400 4.400 10.40      3593938           3           0  0 0 0 0 0 0 0 0 0 0 1 0 1 1 2 3 4 7 8 1 5 6 8 3 7 5 4 9 8 8 7 7 9 7 9 9 15 5 7   8 15 14 9 9 13 8 8 15 10 7 10 9 10 14 7 8 18 16 17 11 14 15 13 8 15 8 15 18 16   16 22 12 8 16 13 10 13 13 10 21 11 10 16 16 13 13 17 16 20 23 13 22 16 14 15     22 19 22 15 22 24 16 16 16 19 12 15 16 17 20 18 19 26 17 23 18 32 20 28 36 22    25 30 29 31 36 24 24 21 29 24 32 29 30 23 34 19 33 34 25 20 31 27 24 16 14 21    20 13 24 17 28 13 24 16 26 15 26 21 11 15 20 13 20 18 25 23 18 24 26 22 16 22    14 13 16 20 24 25 19 29 20 15 20 16 25 26 21 22 17 24 22 21 17 23 23 15 19 30    23 17 21 19 18 21 26 14 29 24 20 33 19 15 20 23 28 19 23 25 15 19 17 31 23 18    29 26 25 14 24 25 18 19 19 24 35 31 23 23 14 15 19 11 20 19 24 17 16 9 10 12 3   2 2 0 1   0.194000 4.450 4.450 10.50      3712573           7           0  0 0 0 0 0 0 0 0 0 0 0 1 1 1 5 3 5 4 3 11 3 10 4 6 7 8 5 5 5 8 9 12 7 7 11 8 6    7 9 10 13 10 6 13 9 9 9 11 14 14 12 13 10 6 13 13 15 12 13 19 8 14 13 16 11 13   14 15 9 15 16 13 16 17 17 17 23 18 16 19 10 13 18 16 10 9 21 11 22 14 20 14 18   13 15 12 13 14 16 14 15 20 29 17 14 18 8 15 21 15 19 15 22 20 17 15 23 26 16     26 24 23 23 23 23 30 24 29 28 26 35 33 31 22 23 22 20 37 22 27 33 26 27 26 17    16 18 27 22 21 24 18 18 18 17 15 18 14 19 24 22 15 20 21 15 19 25 15 16 26 19    22 29 20 16 13 15 16 32 24 23 13 33 17 22 18 18 23 24 22 21 20 26 21 16 22 18    18 16 15 26 26 17 22 21 13 25 24 13 23 18 18 25 32 20 24 21 17 19 24 24 23 33    19 19 21 32 18 22 23 19 23 32 18 31 22 25 23 23 31 29 21 16 20 20 15 22 14 12    5 10 9 2 1 0 1   0.196000 4.500 4.500 10.60      3829518           3           0  0 0 0 0 0 0 0 0 0 1 2 2 1 6 2 6 5 9 3 5 6 8 6 3 8 10 7 11 9 4 8 9 5 11 10 13 9   16 13 10 9 5 12 9 15 10 13 9 12 18 14 19 9 13 14 12 13 21 17 17 18 16 13 12 16   14 18 10 15 15 16 11 15 22 17 19 17 11 12 26 12 17 19 18 21 20 27 17 18 19 21    14 19 16 12 16 21 20 18 8 17 17 13 13 18 15 19 15 19 20 28 21 29 27 27 34 24     26 31 25 24 16 17 23 23 30 28 18 28 32 28 37 18 26 18 16 33 21 31 21 20 22 19    20 25 18 18 20 11 17 20 22 23 14 14 17 18 20 25 20 19 20 22 19 16 33 25 21 21    24 18 16 22 29 22 16 27 26 28 21 20 22 17 25 23 20 23 18 16 19 26 22 21 22 23    15 20 19 17 23 19 20 15 22 18 22 26 23 23 31 17 29 18 13 15 19 18 24 22 28 22    17 23 24 26 21 23 25 24 29 26 18 41 24 29 22 27 23 28 16 30 24 18 23 19 17 18    21 17 14 8 2 5 2 0 0   0.198000 4.550 4.550 10.70      3950740           3           0  0 0 0 0 0 0 0 0 1 1 1 2 1 3 7 5 6 7 7 7 4 5 6 4 1 8 9 10 9 8 10 8 12 6 10 8 10   8 11 9 10 15 7 11 8 13 11 13 15 15 17 12 10 8 17 12 9 14 12 14 11 14 21 14 15    20 18 16 8 15 22 24 14 10 18 14 15 16 12 10 16 21 16 25 17 20 17 17 20 15 24     15 17 22 25 17 13 22 18 20 19 11 21 22 21 16 21 24 16 22 17 21 17 24 22 24 35    27 24 28 24 32 37 34 25 24 29 37 37 25 28 21 23 24 22 21 20 25 22 32 19 21 22    24 20 21 20 22 18 27 17 14 20 22 22 22 14 19 20 20 21 23 22 14 20 21 23 20 18    23 20 25 31 24 18 22 14 23 22 21 23 27 27 20 21 18 22 23 24 23 21 18 22 17 22    21 35 15 24 24 12 27 30 27 28 22 31 24 24 19 27 24 28 23 25 26 35 27 22 29 21    24 18 19 26 33 29 31 23 25 19 24 26 21 10 23 24 26 28 20 27 26 17 29 22 18 14    22 8 10 11 4 4 1 2 0   0.200000 4.600 4.600 10.80      4068161           5           0  0 0 0 0 0 0 0 0 0 1 1 0 1 5 5 2 9 3 11 6 9 8 7 7 8 3 3 13 10 8 7 5 8 13 8 7 14   12 10 7 15 13 13 11 12 12 14 12 13 12 10 15 11 14 7 16 15 8 15 13 15 13 18 13    17 21 15 12 13 13 17 18 18 18 16 19 20 17 14 17 24 13 12 18 19 19 13 21 18 26    21 23 16 14 18 19 13 33 13 19 20 14 20 23 14 26 19 22 21 21 16 27 30 25 28 22    32 21 30 27 31 21 30 22 27 27 31 27 21 17 38 41 17 21 20 19 30 24 27 20 20 21    30 20 19 19 31 25 24 13 21 23 19 24 33 24 17 20 17 12 25 23 18 24 11 24 25 22    33 20 11 22 31 21 20 26 27 21 26 24 14 23 23 20 20 26 28 10 20 27 24 22 17 27    28 20 23 23 33 20 24 26 32 33 29 21 25 24 17 18 19 27 26 20 24 26 24 24 26 21    19 24 21 36 32 18 33 33 20 23 25 33 19 27 25 27 24 27 21 21 23 28 18 27 25 19    24 15 17 12 15 7 2 1 0 0 ", "%f ", Inf);
 %! assert (rows (x) == n);
 
+## Test input validation
+%!error <Invalid call to sscanf> sscanf ()
+%!error <STRING must be a string> sscanf (1, "2")
+%!error <TEMPLATE must be a string> sscanf ("1", 2)
+%!error <Invalid call to sscanf> sscanf ("foo", "bar", 1, 2)
+
 %% Note use fprintf so output not sent to stdout
 %!test
 %! nm = tempname ();
--- a/test/jupyter-notebook/jupyter-notebook.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/jupyter-notebook/jupyter-notebook.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -28,8 +28,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
@@ -63,8 +62,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
@@ -102,8 +100,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
@@ -146,8 +143,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
--- a/test/leftdiv.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/leftdiv.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -30,8 +30,15 @@
 %#!assert (0 \ i, Inf)
 %#!assert (0 \ single (i), single (Inf))
 
-%!assert ([Inf, 0; 0, 0] \ [1; 1], zeros (2,1))
-%!assert ([Inf, 0; 0, 0] \ single ([1; 1]), zeros (2,1, "single"))
-%!assert ([Inf, 0; 0, 0] \ [i; 1], zeros (2,1))
-%!assert ([Inf, 0; 0, 0] \ single ([i; 1]), zeros (2,1, "single"))
-
+%!warning <matrix singular to machine precision>
+%! warning ('on', 'Octave:singular-matrix', 'local');
+%! assert ([Inf, 0; 0, 0] \ [1; 1], zeros (2,1));
+%!warning <matrix singular to machine precision>
+%! warning ('on', 'Octave:singular-matrix', 'local');
+%! assert ([Inf, 0; 0, 0] \ single ([1; 1]), zeros (2,1, "single"));
+%!warning <matrix singular to machine precision>
+%! warning ('on', 'Octave:singular-matrix', 'local');
+%! assert ([Inf, 0; 0, 0] \ [i; 1], zeros (2,1));
+%!warning <matrix singular to machine precision>
+%! warning ('on', 'Octave:singular-matrix', 'local');
+%! assert ([Inf, 0; 0, 0] \ single ([i; 1]), zeros (2,1, "single"));
--- a/test/line-continue.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/line-continue.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -33,34 +33,6 @@
 %! b];
 %! assert (y, x);
 
-## FIXME: Next 3 tests use '\' continuation outside of a double-quoted string
-##        This behavior is deprecated and will be removed at some point.
-##        When it does these
-%!test
-%! x = [1;2];
-%! y = [a... # comments here ok
-%! ;\
-%!
-%! b];
-%! assert (y, x);
-
-%!assert (1 + ...
-%! 2 - \# comments here ok
-%! 3 / ... # comments here ok
-%! -1,6);
-
-%!function y = f (a,...
-%!                b,  ...
-%!                c,  ...   % comments ok
-%!                x,  # continuation characters not required in parens
-%!                y,  \# but they should work too.
-%!                z)
-%!
-%!  y = 1;
-%!endfunction
-%!
-%!assert (f (), 1)
-
 ## String continuation using '\'
 %!assert (["abc\
 %! def"], "abc def")
--- a/test/mk-sparse-tst.sh	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/mk-sparse-tst.sh	Fri Jun 23 20:51:51 2023 +0200
@@ -28,15 +28,15 @@
 # Some tests are commented out because they are known to be broken!
 # Search for "# fails"
 
-# ./build-sparse-tests.sh preset
+# ./mk-sparse-tst.sh preset
 #    creates sparse.tst with preset tests.
 #    Use "test sparse.tst" from octave to run the tests.
 #
-# ./build-sparse-tests.sh random
+# ./mk-sparse-tst.sh random
 #    Creates sprandom.tst with randomly generated matrices.
 #    Use "test sprandom.tst" from octave to run the tests.
 
-# build-sparse-tests.sh generates tests for real and complex sparse matrices.
+# mk-sparse-tst.sh generates tests for real and complex sparse matrices.
 # Also, we want to run both fixed tests with known outputs (quick tests)
 # and longer tests with unknown outputs (thorough tests).  This requires
 # two sets of tests -- one which uses preset matrices and another which
@@ -117,14 +117,14 @@
     random) preset=false ;;
     preset) preset=true ;;
     '') preset=true ;;
-    *) echo "build-sparse-tests.sh random|preset" && exit 1 ;;
+    *) echo "mk-sparse-tst.sh random|preset" && exit 1 ;;
 esac
 
 # create initial file
 cat <<EOF
 ## !!! DO NOT EDIT !!!
 ## THIS IS AN AUTOMATICALLY GENERATED FILE
-## modify build-sparse-tests.sh to generate the tests you need.
+## modify mk-sparse-tst.sh to generate the tests you need.
 EOF
 
 
@@ -174,6 +174,33 @@
 gen_specific() {
 cat <<EOF
 
+%% error handling in constructor
+%!error <Invalid call> sparse ()
+%!error <Invalid call> sparse (1,2,3,4,5,6,7)
+%!warning <input array cast to double>
+%! warning ("on", "Octave:sparse:double-conversion", "local");
+%! s = sparse (single ([1 2]));
+%!error <wrong type argument 'uint8 matrix'>
+%! s = sparse (uint8 ([1 2]));
+%!error <M must be a non-negative integer> sparse ({1}, 2)
+%!error <N must be a non-negative integer> sparse (1, {2})
+%!error <dimensions M and N must be non-negative> sparse (-1, 2)
+%!error <dimensions M and N must be non-negative> sparse (1, -2)
+%!error <dimension mismatch> sparse (1,[2,3],[1,2,3])
+%!error <invalid option: foobar> sparse ([1,1],[1,1],[1,2],"foobar")
+%% negative subscripts are disallowed
+%!error <subscripts must be> sparse ([1,3],[1,-4],[3,5],2,2)
+%!error <subscripts must be> sparse ([1,3],[1,-4],[3,5i],2,2)
+%!error <M must be a non-negative integer> sparse ([1,1],[1,1],[1,2], {1}, 2)
+%!error <N must be a non-negative integer> sparse ([1,1],[1,1],[1,2], 1, {2})
+%!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], -1, 2)
+%!error <dimensions M and N must be non-negative> sparse ([1,1],[1,1],[1,2], 1, -2)
+%!warning <input array cast to double>
+%! warning ("on", "Octave:sparse:double-conversion", "local");
+%! s = sparse ([1,1],[1,1], single ([1,2]), 2, 2);
+%!error <wrong type argument 'uint8 matrix'>
+%! s = sparse ([1,1],[1,1], uint8 ([1,2]), 2, 2);
+
 %!test # segfault test from edd@debian.org
 %! n = 510;
 %! sparse (kron ((1:n)', ones (n,1)), kron (ones (n,1), (1:n)'), ones (n));
@@ -189,12 +216,6 @@
 %#!error inv ( sparse ([0,0;0,1+i]) );
 %#!error inv ( sparse ([0,0;0,0]  ) );
 
-%% error handling in constructor
-%!error sparse (1,[2,3],[1,2,3])
-%!error sparse ([1,1],[1,1],[1,2],3,3,"invalid")
-%!error sparse ([1,3],[1,-4],[3,5],2,2)
-%!error sparse ([1,3],[1,-4],[3,5i],2,2)
-%!error sparse (-1,-1,1)
 EOF
 }
 
@@ -251,7 +272,7 @@
 ##  end
 ##  The test log is appended to sprandomtest.log
 function [passes,total] = test_sprandom
-  warning ("untested --- fix the source in build-sparse-tests.sh");
+  warning ("untested --- fix the source in mk-sparse-tst.sh");
   disp ("appending test output to sprandomtest.log");
   fid = fopen ("sprandomtest.log", "at");
   test ("sprandom.tst", "normal", fid);
@@ -513,8 +534,8 @@
 %! wn2s = warning ("query", "Octave:num-to-str");
 %! warning ("off", "Octave:num-to-str");
 %! if (isreal (af))
-%!   assert (tolower (as), as);
-%!   assert (toupper (as), as);
+%!   assert (lower (as), as);
+%!   assert (upper (as), as);
 %! endif
 %! warning (wn2s.state, "Octave:num-to-str");
 
@@ -632,19 +653,35 @@
 %! assert(det(bs+speye(size(bs))), det(bf+eye(size(bf))), 100*eps*abs(det(bf+eye(size(bf)))));
 
 %!testif HAVE_UMFPACK
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [l,u] = lu (sparse ([1,1;1,1]));
 %! assert (l*u, [1,1;1,1], 10*eps);
 
 %!testif HAVE_UMFPACK
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [l,u] = lu (sparse ([1,1;1,1+i]));
 %! assert (l, sparse ([1,2,2],[1,1,2],1), 10*eps);
 %! assert (u, sparse ([1,1,2],[1,2,2],[1,1,1i]), 10*eps);
 
 %!testif HAVE_UMFPACK   # permuted LU
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [L,U] = lu (bs);
 %! assert (L*U, bs, 1e-10);
 
 %!testif HAVE_UMFPACK   # simple LU + row permutations
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [L,U,P] = lu (bs);
 %! assert (P'*L*U, bs, 1e-10);
 %! ## triangularity
@@ -745,10 +782,18 @@
     gen_matrixreshape_tests
     cat <<EOF
 %!testif HAVE_UMFPACK   # permuted LU
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [L,U] = lu (bs);
 %! assert (L*U, bs, 1e-10);
 
 %!testif HAVE_UMFPACK   # simple LU + row permutations
+%! ## Yes, we want to test lu with fewer than 4 output arguments
+%! ## and sparse input while also avoiding the warning.  So use
+%! ## warning ("off", ...) instead of additional outputs.
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [L,U,P] = lu (bs);
 %! assert (P'*L*U, bs, 1e-10);
 %! ## triangularity
--- a/test/parser.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/parser.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -61,6 +61,7 @@
 %! assert (!a .b, logical ([1 0]));
 %! assert (3*a .b, [0 3]);
 %! assert (a. b-1, [-1 0]);
+%! warning ('off', 'Octave:colon-nonscalar-argument', 'local');
 %! assert (a. b:3, 0:3);
 %! assert (a. b>0.5, logical ([0 1]));
 %! assert (a. b&0, logical ([0 0]));
--- a/test/publish/publish.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/publish/publish.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -29,8 +29,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
@@ -61,8 +60,7 @@
 %! visibility = get (0, "defaultfigurevisible");
 %! toolkit = graphics_toolkit ();
 %! unwind_protect
-%!   if (! __have_feature__ ("QT_OFFSCREEN")
-%!       || ! strcmp (graphics_toolkit (), "qt"))
+%!   if (! strcmp (graphics_toolkit (), "qt"))
 %!     try
 %!       graphics_toolkit ("gnuplot");
 %!     catch
--- a/test/range.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/range.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -31,7 +31,9 @@
 %!assert (full (9:-1:1), [ 9 8 7 6 5 4 3 2 1 ])
 %!assert (full (1:-1:9), zeros (1,0))
 %!assert (full (1:1:1), 1)
-%!assert (full (i:2i:10i), zeros (1,0))
+%!test
+%! warning ('off', 'Octave:colon-complex-argument', 'local');
+%! assert (full (i:2i:10i), zeros (1,0));
 
 ## Test mixing integer range with other types
 
--- a/test/struct.tst	Fri Jun 23 20:51:15 2023 +0200
+++ b/test/struct.tst	Fri Jun 23 20:51:51 2023 +0200
@@ -247,6 +247,7 @@
 %! y = x;
 %! assert (! isempty (y));
 %! assert (y, x);
+%! warning ('off', 'Octave:empty-index', 'local');
 %! z = x();
 %! assert (! isempty (z));
 %! assert (z, x);